-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcontroller.py
executable file
·274 lines (222 loc) · 8.7 KB
/
controller.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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
import sys
import rospy
import pygame
import time
from spatialmath import SE3, SO3
sys.path.append("/home/hanglok/work/ur_slam")
import ros_utils.myGripper
from ik_step import init_robot
import ros_utils
import ros_utils.myIO
class XboxController:
def __init__(self,num=0):
# Initialize Pygame and the joystick subsystem
pygame.init()
pygame.joystick.init()
# Check if a joystick/controller is connected
self.joystick_count = pygame.joystick.get_count()
if self.joystick_count == 0:
print("No joystick/controller found.")
raise KeyError("No joystick/controller found.")
# Initialize the first connected joystick (assumed to be the Xbox controller)
self.joystick = pygame.joystick.Joystick(num)
self.joystick.init()
print(f"Choose controller: {self.joystick.get_name()}")
def capture_input(self):
pygame.event.pump() # Process event queue
#record inputs
self.inputs = {}
# Capture button inputs
self._capture_buttons()
# Capture axis inputs (e.g., analog sticks)
self._capture_axes()
# Capture D-Pad (hat switch) inputs
self._capture_hats()
# Sleep to reduce spamming of output
time.sleep(0.1)
def _capture_buttons(self):
# Loop through all buttons and check their states
for button in range(self.joystick.get_numbuttons()):
button_state = self.joystick.get_button(button)
if button_state: # Only print if the button is pressed
# print(f"Button {button} pressed")
name = "b_"+ str(button)
self.inputs[name] = button_state
def _capture_axes(self):
# Loop through all axes (analog sticks) and capture their values
for axis in range(self.joystick.get_numaxes()):
axis_value = self.joystick.get_axis(axis)
# Only print if the axis moves significantly (with dead zone filtering)
if abs(axis_value) > 0.1:
if not (axis_value == -1.00 and axis in [2,5]):
# print(f"Axis {axis} value: {axis_value:.2f}")
name = "a_"+ str(axis)
self.inputs[name] = axis_value
def _capture_hats(self):
# Loop through all hats (D-Pad) and capture their values
for hat in range(self.joystick.get_numhats()):
hat_value = self.joystick.get_hat(hat)
if hat_value != (0, 0): # Only print if the D-Pad is pressed
# print(f"Hat {hat} value: {hat_value}")
name = "h_"+ str(hat)
self.inputs[name] = hat_value
def input_translator(input_dict):
# Translate the inputs into a more readable format
tcp_x = 0
tcp_y = 0
tcp_z = 0
rotate_clockwise = 1
tcp_rx = 0
tcp_ry = 0
tcp_rz = 0
io_state = -1
gripper_value = -1
if not input_dict:
# print("No input provided.")
tcp_move = [tcp_x, tcp_y, tcp_z]
tcp_rotate = [tcp_rx, tcp_ry, tcp_rz]
return tcp_move, tcp_rotate,io_state,gripper_value # Return default values
for key, value in input_dict.items():
if key[0] == "b":
'''
Button inputs
b_0: A ---> turn on motor
b_1: B ---> turn off motor
b_2: X ---> hold on rotate anticlockwise
b_3: Y
'''
if key[0] == "b":
if key[2] == "0":
# turn on motor
io_state = 1
elif key[2] == "1":
# turn off motor
io_state = 0
elif key[2] == "2":
rotate_clockwise = -1
pass
elif key[2] == "3":
pass
pass
elif key[0] == "a":
'''
axis inputs
a_0: Left stick X-axis ---> tcp X-axis
a_1: Left stick Y-axis ---> tcp y-axis
a_2: Left trigger
a_3: Right stick X-axis
a_4: Right stick Y-axis ----> tcp z-axis
a_5: Right trigger
'''
if key[0] == "a":
if key[2] == "0":
tcp_y += value
elif key[2] == "1":
tcp_x += value
elif key[2] == "4":
tcp_z -= value
elif key[2] == "5":
gripper_value = max(-1,value)
elif key[0] == "h":
'''
hat inputs
h_0:[0,1] D-Pad ---> rotate tcp along x-axis
h_0:[-1,0] D-Pad ---> rotate tcp along y-axis
h_2:[0,-1] D-Pad ---> rotate tcp along z-axis
'''
if value == (0,1):
# rotate tcp along x-axis
tcp_rx += rotate_clockwise
elif value == (-1,0):
# rotate tcp along y-axis
tcp_ry += rotate_clockwise
elif value == (0,-1):
# rotate tcp along z-axis
tcp_rz += rotate_clockwise
pass
tcp_move = [tcp_x, tcp_y, tcp_z]
tcp_rotate = [tcp_rx, tcp_ry, tcp_rz]
return tcp_move, tcp_rotate, io_state, gripper_value
def execute_command(tcp_move, tcp_rotate, t_move=0.02, r_move=5):
'''
move_robot
'''
tcp_move = [i * t_move for i in tcp_move]
tcp_rotate = [i * r_move for i in tcp_rotate]
if abs(sum(tcp_move)) > 0:
move_SE3 = SE3.Tx(tcp_move[0]) @ SE3.Ty(tcp_move[1]) @ SE3.Tz(tcp_move[2])
elif abs(sum(tcp_rotate)) > 0:
move_SE3 = SE3.Rx(tcp_rotate[0],unit='deg') @ SE3.Ry(tcp_rotate[1],unit='deg') @ SE3.Rz(tcp_rotate[2],unit='deg')
else:
move_SE3 = SE3.Tx(0)
return move_SE3
def set_IO(state):
# Initialize fun and pin here
fun = 1
pin = 16
my_io = ros_utils.myIO.MyIO(fun, pin)
my_io.set_io_state(state)
def control_robot(robot, controller,gripper=None,IO_control = None,force = None):
'''
robot: robot object
controller: controller object
gripper: control gripper class; if no need then None
IO_control: control IO class; if no need then None
'''
if controller.joystick_count > 0:
controller.capture_input()
if controller.inputs != {}:
print(controller.inputs)
tcp_move, tcp_rotate, io_state, gripper_value = input_translator(controller.inputs)
print(f"tcp move {tcp_move}, rotate {tcp_rotate}, {io_state}, {gripper_value}")
if controller.inputs.get("b_7") == 1:
print("Exiting...")
exit()
# if sum(tcp_move) + sum(tcp_rotate) !=0:
if force is not None and abs(force) > 0.15:
print("force is too big")
# move upwards
actions =robot.step(action=execute_command([0,0,0.5], [0,0,0]), wait=False,return_joints=True)
#TODO impendence control, change orientiation
else:
actions =robot.step(action=execute_command(tcp_move, tcp_rotate), wait=False,return_joints=True)
actions = list(actions)
if IO_control is not None:
if io_state != -1:
set_IO(io_state)
actions.append(io_state)
if gripper is not None:
value = 500*(1-gripper_value)
if gripper_value >= -1:
gripper.set_gripper(value, 20.0)
actions.append(value)
if gripper is None and IO_control is None:
actions.append(0)
return actions
return actions
# def main():
# # Initialize the ROS node
# rospy.init_node('xbox_controller', anonymous=True)
# robot = init_robot("robot1")
# gripper = ros_utils.myGripper.MyGripper()
# controller = XboxController()
# if controller.joystick_count > 0:
# while not rospy.is_shutdown():
# controller.capture_input()
# if controller.inputs != {}:
# print(controller.inputs)
# tcp_move, tcp_rotate, io_state, gripper_value = input_translator(controller.inputs)
# print(f"tcp move {tcp_move}, rotate {tcp_rotate}, {io_state}, {gripper_value}")
# if controller.inputs.get("b_7") == 1:
# print("Exiting...")
# break
# if io_state != -1:
# set_IO(io_state)
# if sum(tcp_move) + sum(tcp_rotate) !=0:
# robot.step(action=execute_command(tcp_move, tcp_rotate), wait=False)
# if gripper_value >= -1:
# gripper.set_gripper(500*(1-gripper_value), 20.0)
# # time.sleep(0.1)
if __name__ == "__main__":
# main()
controller1 = XboxController(0)