|
from io import StringIO |
|
from time import sleep |
|
import click |
|
import logging |
|
import numpy as np |
|
import multiprocessing as mp |
|
import pygame |
|
import queue |
|
import socket |
|
import struct |
|
import sys |
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
handler = logging.StreamHandler() |
|
handler.setLevel(logging.DEBUG) |
|
logger.setLevel(logging.DEBUG) |
|
logger.addHandler(handler) |
|
logger.propagate = False |
|
|
|
PROC_COMMAND_SETUP = 0 |
|
PROC_COMMAND_RUN = 1 |
|
PROC_COMMAND_STOP = 2 |
|
|
|
class Command(): |
|
def __init__(self, ): |
|
self.id = 0 |
|
self.vel_surge = 0 |
|
self.vel_sway = 0 |
|
self.omega = 0 |
|
self.kick_speed_x = 0 |
|
self.kick_speed_z = 0 |
|
self.dribble_power = 0 |
|
|
|
def communicate(in_queue, out_queue): |
|
proc_command, data = in_queue.get() |
|
if proc_command == PROC_COMMAND_SETUP: |
|
host = data[0] |
|
port = data[1] |
|
else: |
|
print('invalid command') |
|
sys.exit() |
|
inputdata = None |
|
b_stop = False |
|
|
|
def int2chr(i): |
|
return chr(i).encode('ascii') |
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: |
|
try: |
|
s.connect((host, port)) |
|
except socket.timeout as e: |
|
logger.error('socket timeout!!!') |
|
sys.exit(1) |
|
except TimeoutError as e: |
|
logger.error('socket timeout!!!') |
|
sys.exit(1) |
|
|
|
while True: |
|
try: |
|
proc_command, data = in_queue.get(False) |
|
except queue.Empty as e: |
|
pass |
|
if proc_command == PROC_COMMAND_STOP: |
|
break |
|
kick_power = np.int(np.clip(data.kick_speed_x * 2, 0, 15)) |
|
dribble_power = np.int(np.clip(data.dribble_power / 50.0, 0.0, 15.0)) |
|
d = struct.pack('ccccfff', int2chr(0x53), |
|
int2chr(data.id), int2chr((0x10 if kick_power > 0 else 0x00) & (0x08 if data.kick_speed_z > 0 else 0)), |
|
int2chr(dribble_power << 4 + kick_power), |
|
data.vel_surge, data.vel_sway, data.omega)#, int2chr(0x0), int2chr(0x0)) |
|
checksum = 0 |
|
for c in d: |
|
checksum ^= c |
|
d = d + int2chr(checksum & 0xff) + int2chr((checksum ^ 0xff) & 0xff) |
|
s.sendall(d) |
|
|
|
# axes = joystick.get_numaxes() |
|
# buttons = joystick.get_numbuttons() |
|
# hats = joystick.get_numhats() |
|
# |
|
# logger.info("There is " + str(axes) + " axes") |
|
# logger.info("There is " + str(buttons) + " button/s") |
|
# logger.info("There is " + str(hats) + " hat/s") |
|
|
|
# def getHat(number): |
|
# if joystick.get_hat(number) != (0,0): |
|
# # returns tuple with values either 1, 0 or -1 |
|
# logger.info( "Hat value is %s, %s" %(joystick.get_hat(number)[0],joystick.get_hat(number)[1])) |
|
# logger.info( "Hat ID is %s" %(number)) |
|
|
|
@click.command() |
|
@click.argument('id', type=int) |
|
@click.option('--port', '-p', type=int, default=12345) |
|
def main(id, port): |
|
if not (0 <= id <= 12): |
|
logger.info('id should be between 0 and 12') |
|
sys.exit(1) |
|
|
|
# setup the pygame window |
|
pygame.init() |
|
screen = pygame.display.set_mode((200, 200), 0, 32) |
|
pygame.display.set_caption("joycon standalone") |
|
clock = pygame.time.Clock() |
|
|
|
myfont = pygame.font.SysFont("monospace", 15) |
|
|
|
# how many joysticks connected to computer? |
|
joystick_count = pygame.joystick.get_count() |
|
logger.info("There is " + str(joystick_count) + " joystick/s") |
|
|
|
if joystick_count == 0: |
|
# if no joysticks, quit program safely |
|
logger.info ("Error, I did not find any joysticks") |
|
pygame.quit() |
|
sys.exit() |
|
else: |
|
# initialise joystick |
|
joystick = pygame.joystick.Joystick(0) |
|
joystick.init() |
|
|
|
|
|
|
|
host = '192.168.15.%2d'%(id+10) |
|
port = port |
|
|
|
in_queue = mp.Queue() |
|
out_queue = mp.Queue() |
|
p = mp.Process(target=communicate, args=(in_queue, out_queue)) |
|
p.start() |
|
|
|
in_queue.put([PROC_COMMAND_SETUP, (host, port)]) |
|
|
|
L1 = 6 |
|
L2 = 4 |
|
R2 = 5 |
|
R1 = 7 |
|
TRIANGLE = 0 |
|
CIRCLE = 1 |
|
CROSS = 2 |
|
RECTANGLE = 3 |
|
SELECT = 8 |
|
START = 9 |
|
L3 = 10 |
|
R3 = 11 |
|
LEFT_JOY_X = 0 |
|
LEFT_JOY_Y = 1 |
|
RIGHT_JOY_X = 2 |
|
RIGHT_JOY_Y = 3 |
|
|
|
b_holonomic_mode = False |
|
b_boost_mode = False |
|
|
|
last_select_button = False |
|
command = Command() |
|
command.id = id |
|
while True: |
|
loop_exit = False |
|
for event in pygame.event.get(): |
|
# loop through events, if window shut down, quit program |
|
if event.type == pygame.QUIT: |
|
loop_exit = True |
|
|
|
if loop_exit: |
|
break |
|
|
|
# holonomic |
|
current_select_button = joystick.get_button(SELECT) |
|
if last_select_button != current_select_button and current_select_button == True: |
|
b_holonomic_mode = not b_holonomic_mode |
|
last_select_button = current_select_button |
|
|
|
# turbo |
|
vel_scale = 1 |
|
b_boost_mode = False |
|
if joystick.get_button(R1): |
|
b_boost_mode = True |
|
vel_scale = 3 |
|
|
|
if b_holonomic_mode: |
|
command.vel_surge = - joystick.get_axis(LEFT_JOY_Y) * vel_scale |
|
command.vel_sway = 0 |
|
command.omega = - joystick.get_axis(LEFT_JOY_X) * 1.57 * vel_scale |
|
else: |
|
command.vel_surge = - joystick.get_axis(LEFT_JOY_Y) * vel_scale |
|
command.vel_sway = - joystick.get_axis(LEFT_JOY_X) * vel_scale |
|
#WARN なぜかR2がとれないので右stickで回転 |
|
command.omega = - joystick.get_axis(RIGHT_JOY_X) * 1.57 * vel_scale |
|
|
|
|
|
kick_mode = '' |
|
if joystick.get_button(CROSS): |
|
command.kick_speed_x = 3 |
|
command.kick_speed_z = 0 |
|
kick_mode = 'Normal' |
|
elif joystick.get_button(CIRCLE): |
|
command.kick_speed_x = 3 |
|
command.kick_speed_z = 3 |
|
kick_mode = 'Chip' |
|
else: |
|
command.kick_speed_x = 0 |
|
command.kick_speed_z = 0 |
|
kick_mode = 'Off' |
|
|
|
b_dribble = False |
|
command.dribble_power = 0 |
|
if joystick.get_button(L1): |
|
command.dribble_power = 1 |
|
b_dribble = True |
|
# ss = StringIO() |
|
# if axes != 0: |
|
# for i in range(axes): |
|
# #getAxis(i) |
|
# ss.write("%lf "%(joystick.get_axis(i))) |
|
# logger.info(ss.getvalue()) |
|
# ss.close() |
|
|
|
screen.fill((0,0,0)) |
|
label = myfont.render("Turbo: %s"%('On' if b_boost_mode else 'Off'), 1, (255,255,255)) |
|
screen.blit(label, (30, 70)) |
|
label2 = myfont.render("Holonomic: %s"%('On' if b_holonomic_mode else 'Off'), 1, (255,255,255)) |
|
|
|
screen.blit(label2, (30, 85)) |
|
label3 = myfont.render("Kick: %s"%kick_mode, 1, (255,255,255)) |
|
screen.blit(label3, (30, 100)) |
|
label4 = myfont.render("Dribble: %s"%('On' if b_dribble else 'Off'), 1, (255,255,255)) |
|
screen.blit(label4, (30, 115)) |
|
|
|
pygame.display.update() |
|
in_queue.put([PROC_COMMAND_RUN, command]) |
|
clock.tick(60) |
|
in_queue.put([PROC_COMMAND_STOP, None]) |
|
p.join() |
|
pygame.quit() |
|
sys.exit() |
|
|
|
|
|
if __name__ == '__main__': |
|
main() |