teleop_legged_robots.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 from __future__ import print_function
4 
5 import threading
6 
7 import roslib
8 
9 roslib.load_manifest('teleop_legged_robots')
10 import rospy
11 
12 from geometry_msgs.msg import Twist
13 from geometry_msgs.msg import Pose
14 
15 import sys, select, termios, tty
16 
17 import tf_conversions
18 
19 msg = """
20 Reading from the keyboard and Publishing to Twist and Pose!
21 ---------------------------
22 Moving around:
23  u i o
24  j k l
25  m , .
26 
27 For Holonomic mode (strafing), hold down the shift key:
28 ---------------------------
29  U I O
30  J K L
31  M < >
32 
33 Body pose:
34 ---------------------------
35 1/2 : move the body forward/back (+/-x)
36 3/4 : move the body right/left (+/-y)
37 
38 5/6 : move the body up/down (+/-z)
39 
40 a/s : body's roll
41 d/f : body's pitch
42 g/h : body's yaw
43 
44 anything else : stop
45 
46 q/z : increase/decrease max speeds by 10%
47 w/x : increase/decrease only linear speed by 10%
48 e/c : increase/decrease only angular speed by 10%
49 
50 r/v : increase/decrease body's pose translation by 10%
51 t/b : increase/decrease body's pose angular speed by 10%
52 
53 CTRL-C to quit
54 """
55 
56 moveBindings = {
57  'i': (1, 0, 0, 0),
58  'o': (1, 0, 0, -1),
59  'j': (0, 0, 0, 1),
60  'l': (0, 0, 0, -1),
61  'u': (1, 0, 0, 1),
62  ',': (-1, 0, 0, 0),
63  '.': (-1, 0, 0, 1),
64  'm': (-1, 0, 0, -1),
65  'O': (1, -1, 0, 0),
66  'I': (1, 0, 0, 0),
67  'J': (0, 1, 0, 0),
68  'L': (0, -1, 0, 0),
69  'U': (1, 1, 0, 0),
70  '<': (-1, 0, 0, 0),
71  '>': (-1, -1, 0, 0),
72  'M': (-1, 1, 0, 0),
73 }
74 
75 speedBindings = {
76  'q': (1.1, 1.1),
77  'z': (.9, .9),
78  'w': (1.1, 1),
79  'x': (.9, 1),
80  'e': (1, 1.1),
81  'c': (1, .9),
82 }
83 
84 poseBindings = {
85  '1': (1, 0, 0, 0, 0, 0),
86  '2': (-1, 0, 0, 0, 0, 0),
87  '3': (0, 1, 0, 0, 0, 0),
88  '4': (0, -1, 0, 0, 0, 0),
89  '5': (0, 0, 1, 0, 0, 0),
90  '6': (0, 0, -1, 0, 0, 0),
91  'a': (0, 0, 0, 1, 0, 0),
92  's': (0, 0, 0, -1, 0, 0),
93  'd': (0, 0, 0, 0, 1, 0),
94  'f': (0, 0, 0, 0, -1, 0),
95  'g': (0, 0, 0, 0, 0, 1),
96  'h': (0, 0, 0, 0, 0, -1),
97 }
98 
99 speedPoseBindings = {
100  'r': (1.1, 1),
101  'v': (.9, 1),
102  't': (1, 1.1),
103  'b': (1, .9),
104 }
105 
106 
107 class PublishThread(threading.Thread):
108  def __init__(self, rate):
109  super(PublishThread, self).__init__()
110  robot_name = rospy.get_param("~/robot_name", "/")
111  twist_publisher_name = rospy.get_param("~/twist_publisher_name", robot_name + "/cmd_vel")
112  pose_publisher_name = rospy.get_param("~/pose_publisher_name", robot_name + "/body_pose")
113  self.twist_publisher = rospy.Publisher(twist_publisher_name, Twist, queue_size=1)
114  self.pose_publisher = rospy.Publisher(pose_publisher_name, Pose, queue_size=1)
115  self.x = 0.0
116  self.y = 0.0
117  self.z = 0.0
118  self.th = 0.0
119  self.speed = 0.0
120  self.turn = 0.0
121  self.pose_x = 0.0
122  self.pose_y = 0.0
123  self.pose_z = 0.0
124  self.pose_roll = 0.0
125  self.pose_pitch = 0.0
126  self.pose_yaw = 0.0
127  self.pose_speed = 0.0
128  self.pose_turn = 0.0
129  self.condition = threading.Condition()
130  self.done = False
132 
133  # Set timeout to None if rate is 0 (causes new_message to wait forever
134  # for new data to publish)
135  if rate != 0.0:
136  self.timeout = 1.0 / rate
137  else:
138  self.timeout = None
139 
140  self.start()
141 
143  i = 0
144  while not rospy.is_shutdown() and (self.twist_publisher.get_num_connections() == 0 or
145  self.pose_publisher.get_num_connections() == 0):
146  if i == self.delay_wait_print:
147  if self.twist_publisher.get_num_connections() == 0:
148  rospy.loginfo("Waiting for subscriber to connect to {}".format(self.twist_publisher.name))
149  if self.pose_publisher.get_num_connections() == 0:
150  rospy.loginfo("Waiting for subscriber to connect to {}".format(self.pose_publisher.name))
151  rospy.sleep(0.5)
152  i += 1
153  i = i % (self.delay_wait_print + 1)
154  if rospy.is_shutdown():
155  raise Exception("Got shutdown request before subscribers connected")
156 
157  def update(self, x, y, z, th, speed, turn, pose_x, pose_y, pose_z, pose_roll, pose_pitch, pose_yaw, pose_speed,
158  pose_turn):
159  self.condition.acquire()
160  self.x = x
161  self.y = y
162  self.z = z
163  self.th = th
164  self.speed = speed
165  self.turn = turn
166  self.pose_x = pose_x
167  self.pose_y = pose_y
168  self.pose_z = pose_z
169  self.pose_roll = pose_roll
170  self.pose_pitch = pose_pitch
171  self.pose_yaw = pose_yaw
172  self.pose_speed = pose_speed
173  self.pose_turn = pose_turn
174  # Notify publish thread that we have a new message.
175  self.condition.notify()
176  self.condition.release()
177 
178  def stop(self):
179  self.done = True
180  self.update(0, 0, 0, 0, 0, 0, self.pose_x, self.pose_y, self.pose_z, self.pose_roll, self.pose_pitch,
181  self.pose_yaw, self.pose_speed, self.pose_turn)
182  self.join()
183 
184  def run(self):
185  twist = Twist()
186  pose = Pose()
187  while not self.done:
188  self.condition.acquire()
189  # Wait for a new message or timeout.
190  self.condition.wait(self.timeout)
191 
192  # Copy state into twist message.
193  twist.linear.x = self.x * self.speed
194  twist.linear.y = self.y * self.speed
195  twist.linear.z = self.z * self.speed
196  twist.angular.x = 0
197  twist.angular.y = 0
198  twist.angular.z = self.th * self.turn
199 
200  # Copy state into pose message.
201  pose.position.x = self.pose_x
202  pose.position.y = self.pose_y
203  pose.position.z = self.pose_z
204  pose_roll_euler = self.pose_roll
205  pose_pitch_euler = self.pose_pitch
206  pose_yaw_euler = self.pose_yaw
207 
208  quaternion = tf_conversions.transformations.quaternion_from_euler(pose_roll_euler, pose_pitch_euler, pose_yaw_euler)
209  pose.orientation.x = quaternion[0]
210  pose.orientation.y = quaternion[1]
211  pose.orientation.z = quaternion[2]
212  pose.orientation.w = quaternion[3]
213 
214  self.condition.release()
215 
216  # Publish.
217  self.twist_publisher.publish(twist)
218  self.pose_publisher.publish(pose)
219 
220  # Publish stop message when thread exits.
221  twist.linear.x = 0
222  twist.linear.y = 0
223  twist.linear.z = 0
224  twist.angular.x = 0
225  twist.angular.y = 0
226  twist.angular.z = 0
227  pose.position.x = self.pose_x
228  pose.position.y = self.pose_y
229  pose.position.z = self.pose_z
230  pose_roll_euler = self.pose_roll
231  pose_pitch_euler = self.pose_pitch
232  pose_yaw_euler = self.pose_yaw
233 
234  quaternion = tf_conversions.transformations.quaternion_from_euler(pose_roll_euler, pose_pitch_euler, pose_yaw_euler)
235  pose.orientation.x = quaternion[0]
236  pose.orientation.y = quaternion[1]
237  pose.orientation.z = quaternion[2]
238  pose.orientation.w = quaternion[3]
239  self.twist_publisher.publish(twist)
240  self.pose_publisher.publish(pose)
241 
242 
243 def getKey(key_timeout):
244  tty.setraw(sys.stdin.fileno())
245  rlist, _, _ = select.select([sys.stdin], [], [], key_timeout)
246  if rlist:
247  key = sys.stdin.read(1)
248  else:
249  key = ''
250  termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
251  return key
252 
253 
254 def vels(speed, turn):
255  return "currently:\tspeed %s\tturn %s " % (speed, turn)
256 
257 
258 def pose_vel(pose_speed, pose_turn):
259  return "currently:\tpose_speed %s\tpose_turn %s " % (pose_speed, pose_turn)
260 
261 
262 def pose_print(pose_x, pose_y, pose_z, pose_roll, pose_pitch, pose_yaw):
263  return "currently:\tx %s\ty %s\tz %s\troll %s\tpitch %s\tyaw %s " % (
264  pose_x, pose_y, pose_z, pose_roll, pose_pitch, pose_yaw)
265 
266 
267 def check_status_msg(status_msg, msg_max):
268  if status_msg == msg_max:
269  rospy.loginfo(msg)
270  return (status_msg + 1) % (msg_max + 1)
271 
272 
273 if __name__ == "__main__":
274  settings = termios.tcgetattr(sys.stdin)
275 
276  rospy.init_node("teleop_legged")
277 
278  speed = rospy.get_param("~/speed", 0.5)
279  turn = rospy.get_param("~/turn", 1.0)
280  pose_speed = rospy.get_param("~/pose_speed", 0.01)
281  pose_turn = rospy.get_param("~/pose_turn", 0.1)
282  repeat = rospy.get_param("~/repeat_rate", 0.0)
283  key_timeout = rospy.get_param("~/key_timeout", 0.0)
284  msg_max = rospy.get_param("~/msg_max", 14)
285  if key_timeout == 0.0:
286  key_timeout = None
287 
288  pub_thread = PublishThread(repeat)
289 
290  x = 0
291  y = 0
292  z = 0
293  th = 0
294  pose_x = 0
295  pose_y = 0
296  pose_z = 0
297  pose_roll = 0
298  pose_pitch = 0
299  pose_yaw = 0
300  status_msg = 0 # number of printed additional messages
301 
302  try:
303  pub_thread.wait_for_subscribers()
304  pub_thread.update(x, y, z, th, speed, turn, pose_x, pose_y, pose_z, pose_roll, pose_pitch, pose_yaw, pose_speed,
305  pose_turn)
306 
307  rospy.loginfo(msg)
308  rospy.loginfo(vels(speed, turn))
309  while (1):
310  key = getKey(key_timeout)
311  if key in moveBindings.keys():
312  x = moveBindings[key][0]
313  y = moveBindings[key][1]
314  z = moveBindings[key][2]
315  th = moveBindings[key][3]
316  elif key in speedBindings.keys():
317  speed = speed * speedBindings[key][0]
318  turn = turn * speedBindings[key][1]
319  x = 0
320  y = 0
321  z = 0
322  th = 0
323  rospy.loginfo(vels(speed, turn))
324  status_msg = check_status_msg(status_msg, msg_max)
325 
326  elif key in poseBindings.keys():
327  pose_x += pose_speed * poseBindings[key][0]
328  pose_y += pose_speed * poseBindings[key][1]
329  pose_z += pose_speed * poseBindings[key][2]
330  pose_roll += pose_turn * poseBindings[key][3]
331  pose_pitch += pose_turn * poseBindings[key][4]
332  pose_yaw += pose_turn * poseBindings[key][5]
333  x = 0
334  y = 0
335  z = 0
336  th = 0
337 
338  rospy.loginfo(pose_print(pose_x, pose_y, pose_z, pose_roll, pose_pitch, pose_yaw))
339  status_msg = check_status_msg(status_msg, msg_max)
340 
341  elif key in speedPoseBindings.keys():
342  pose_speed = pose_speed * speedPoseBindings[key][0]
343  pose_turn = pose_turn * speedPoseBindings[key][1]
344  x = 0
345  y = 0
346  z = 0
347  th = 0
348 
349  rospy.loginfo(pose_vel(pose_speed, pose_turn))
350  status_msg = check_status_msg(status_msg, msg_max)
351 
352  else:
353  # Skip updating cmd_vel if key timeout and robot already
354  # stopped.
355  if key == '' and x == 0 and y == 0 and z == 0 and th == 0:
356  continue
357  x = 0
358  y = 0
359  z = 0
360  th = 0
361  if key == '\x03': # Ctrl + C
362  break
363 
364  pub_thread.update(x, y, z, th, speed, turn, pose_x, pose_y, pose_z, pose_roll, pose_pitch, pose_yaw,
365  pose_speed, pose_turn)
366 
367  except Exception as e:
368  rospy.logerr(e)
369 
370  finally:
371  pub_thread.stop()
372 
373  termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
def pose_print(pose_x, pose_y, pose_z, pose_roll, pose_pitch, pose_yaw)
def check_status_msg(status_msg, msg_max)
def pose_vel(pose_speed, pose_turn)
def update(self, x, y, z, th, speed, turn, pose_x, pose_y, pose_z, pose_roll, pose_pitch, pose_yaw, pose_speed, pose_turn)


teleop_legged_robots
Author(s): Taras Borovets
autogenerated on Tue Feb 2 2021 03:25:44