This repository has been archived by the owner on Jan 24, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplayer.py
185 lines (158 loc) · 6.26 KB
/
player.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
import socket
from math import *
from typing import List
import cozmo
from cozmo.util import distance_mm
from common.message_forwarder import start_connection, receive_message
from common.setup import get_team_colors
from xinput import *
directional_pad_speeds = {
# up, down, left, right
GAMEPAD_DPAD_UP: (100, 100),
GAMEPAD_DPAD_DOWN: (-100, -100),
GAMEPAD_DPAD_LEFT: (-100, 100),
GAMEPAD_DPAD_RIGHT: (100, -100),
# diagonals
GAMEPAD_DPAD_UP | GAMEPAD_DPAD_LEFT: (50, 100),
GAMEPAD_DPAD_UP | GAMEPAD_DPAD_RIGHT: (100, 50),
GAMEPAD_DPAD_DOWN | GAMEPAD_DPAD_LEFT: (-50, -100),
GAMEPAD_DPAD_DOWN | GAMEPAD_DPAD_RIGHT: (-100, -50),
}
def normalize_stick(x, y):
"""
Normalize input values for left and right sticks
:param x: x value generated by the controller
:param y: y value generated by the controller
:return: a tuple containing (normalized x, normalized_y, magnitude)
"""
# print("x = {0}, y = {1}".format(x, y))
# determine how far the controller is pushed
magnitude = sqrt(x * x + y * y) + 0.01 # 0.01 to avoid division by zero when x = y = 0
# determine the direction the controller is pushed
normalized_x, normalized_y = x / magnitude, y / magnitude
# check if the controller is outside a circular dead zone
if magnitude > GAMEPAD_LEFT_THUMB_DEADZONE:
magnitude = min([magnitude, GAMEPAD_THUMB_MAX])
magnitude -= GAMEPAD_LEFT_THUMB_DEADZONE
else:
normalized_x, normalized_y, magnitude = 0.0, 0.0, 0.0
return normalized_x, normalized_y, magnitude
def check_controller_state(robot: cozmo.robot.Robot, state):
# face buttons
# lift
if state['buttons'] == GAMEPAD_B:
robot.move_lift(0.3)
elif state['buttons'] == GAMEPAD_A:
robot.move_lift(-0.3)
else:
robot.move_lift(0)
# head
if state['buttons'] == GAMEPAD_Y:
cube = robot.world.wait_for_observed_light_cube(timeout=30)
if cube:
robot.go_to_object(cube, distance_mm(200.0)).wait_for_completed()
robot.pickup_object(cube, num_retries=0).wait_for_completed()
# left stick
left_x, left_y, left_magnitude = normalize_stick(state['l_thumb_x'], state['l_thumb_y'])
# print("left :{0}, {1}, {2}".format(left_x, left_y, left_magnitude))
# directional pad buttons
if state['left_trigger'] > 0 or state['right_trigger'] > 0:
robot.drive_wheels(state['left_trigger'], state['right_trigger'])
else:
(left_speed, right_speed) = directional_pad_speeds.get(state['buttons'] & 0xFF, (0, 0))
if left_speed == 0.0 and right_speed == 0.0:
if left_magnitude != 0.0:
# up
if left_y >= 0.75 and abs(left_x) < 0.25:
robot.drive_wheels(100, 100)
# down
elif left_y <= -0.75 and abs(left_x) < 0.25:
robot.drive_wheels(-100, -100)
# left
elif abs(left_y) < 0.25 and left_x <= -0.75:
robot.drive_wheels(-100, 100)
# right
elif abs(left_y) < 0.25 and left_x >= 0.75:
robot.drive_wheels(100, -100)
# up + left
elif left_y >= 0.50 and left_x <= -0.50:
robot.drive_wheels(50, 100)
# up + right
elif left_y >= 0.50 and left_x >= 0.50:
robot.drive_wheels(100, 50)
# down + left
elif left_y <= -0.50 and left_x <= -0.50:
robot.drive_wheels(-50, -100)
# down + right
elif left_y <= -0.50 and left_x >= 0.50:
robot.drive_wheels(-100, -50)
else:
pass
else:
robot.drive_wheels(0, 0)
else:
robot.drive_wheels(left_speed, right_speed)
def cozmo_program(robot: cozmo.robot.Robot):
"""
Main entry for running the player logic. This runs both the xbox controller
functionality and checks for the exit message over the network when a team wins.
:param robot: player robot in the game
"""
# get number of teams playing in the game
while True:
try:
teams: int = int(input("How many teams are playing?"))
except ValueError:
print("Invalid input type")
continue
if teams < 2:
print("Must be between 2 and 3")
continue
elif teams > 3:
print("Must be between 1 and 3")
continue
else:
break
# get the id of the team the judge is on
while True:
try:
team_id: int = int(input("Which team is this player on?"))
except ValueError:
print("Invalid input type")
continue
if team_id < 1:
print("Must be between 1 and 3")
continue
elif team_id > 3:
print("Must be between 1 and 3")
continue
else:
break
# get the corresponding team colors and opponent colors
team_colors, opponent_colors = get_team_colors(teams)
# set backpack color
robot.set_all_backpack_lights(team_colors[team_id])
# set head angle so Cozmo can identify cubes
robot.set_head_angle(cozmo.util.Angle(degrees=0))
# establish connection to the network and message retrieval
connection: socket.socket = start_connection("10.0.1.10", 5000)
message: List[str] = []
joysticks = XInputJoystick.enumerate_devices()
if joysticks:
print("Number of connected controllers: {0}".format(len(joysticks)))
else:
print("No controller is connected. Please connect xbox controller.")
sys.exit(0)
# use only the first controller
joystick = joysticks[0]
while 'Exit' not in message:
state = joystick.get_state()
check_controller_state(robot, state)
message = receive_message(connection)
# play the appropriate robot emotion based on who won the game
if int(message[1]) == team_id:
robot.play_anim_trigger(cozmo.anim.Triggers.CodeLabCelebrate).wait_for_completed()
else:
robot.play_anim_trigger(cozmo.anim.Triggers.CodeLabUnhappy).wait_for_completed()
if __name__ == '__main__':
cozmo.run_program(cozmo_program)