Skip to content

Commit 011ccf4

Browse files
committed
update myagv_teleop
1 parent 7c739b1 commit 011ccf4

File tree

1 file changed

+226
-72
lines changed

1 file changed

+226
-72
lines changed
+226-72
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,257 @@
11
#!/usr/bin/env python
2-
# -*- coding: utf-8 -*-
2+
3+
from __future__ import print_function
4+
5+
import threading
6+
7+
import roslib; roslib.load_manifest('teleop_twist_keyboard')
38
import rospy
9+
410
from geometry_msgs.msg import Twist
5-
import sys, select, termios, tty
11+
from geometry_msgs.msg import TwistStamped
12+
13+
import sys
14+
from select import select
15+
16+
if sys.platform == 'win32':
17+
import msvcrt
18+
else:
19+
import termios
20+
import tty
21+
22+
23+
TwistMsg = Twist
624

725
msg = """
8-
Control myagv!
26+
Reading from the keyboard and Publishing to Twist!
927
---------------------------
1028
Moving around:
1129
u i o
1230
j k l
13-
,
31+
m , .
32+
33+
t : up (+z)
34+
b : down (-z)
35+
36+
anything else : stop
1437
15-
space key, k : stop
16-
i : foward
17-
, : backward
18-
j : turn left
19-
l : turn right
20-
u : left revolve
21-
o : right revolve
38+
q/z : increase/decrease max speeds by 10%
39+
w/x : increase/decrease only linear speed by 10%
40+
e/c : increase/decrease only angular speed by 10%
2241
2342
CTRL-C to quit
2443
"""
2544

26-
def getKey():
27-
tty.setraw(sys.stdin.fileno())
28-
rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
29-
if rlist:
30-
key = sys.stdin.read(1)
45+
moveBindings = {
46+
'i':(1,0,0,0),
47+
'o':(0,0,0,-1),
48+
'j':(0,1,0,0),
49+
'l':(0,-1,0,0),
50+
'u':(0,0,0,1),
51+
',':(-1,0,0,0),
52+
'.':(-1,0,0,-1),
53+
'm':(-1,0,0,1),
54+
'O':(0,0,0,-1),
55+
'I':(1,0,0,0),
56+
'J':(0,1,0,0),
57+
'L':(0,-1,0,0),
58+
'U':(0,0,0,1),
59+
'<':(-1,0,0,0),
60+
'>':(-1,0,0,-1),
61+
'M':(-1,0,0,1),
62+
}
63+
64+
speedBindings={
65+
'q':(1.1,1.1),
66+
'z':(.9,.9),
67+
'w':(1.1,1),
68+
'x':(.9,1),
69+
'e':(1,1.1),
70+
'c':(1,.9),
71+
}
72+
73+
class PublishThread(threading.Thread):
74+
def __init__(self, rate):
75+
super(PublishThread, self).__init__()
76+
self.publisher = rospy.Publisher('cmd_vel', TwistMsg, queue_size = 1)
77+
self.x = 0.0
78+
self.y = 0.0
79+
self.z = 0.0
80+
self.th = 0.0
81+
self.speed = 0.0
82+
self.turn = 0.0
83+
self.condition = threading.Condition()
84+
self.done = False
85+
86+
# Set timeout to None if rate is 0 (causes new_message to wait forever
87+
# for new data to publish)
88+
if rate != 0.0:
89+
self.timeout = 1.0 / rate
90+
else:
91+
self.timeout = None
92+
93+
self.start()
94+
95+
def wait_for_subscribers(self):
96+
i = 0
97+
while not rospy.is_shutdown() and self.publisher.get_num_connections() == 0:
98+
if i == 4:
99+
print("Waiting for subscriber to connect to {}".format(self.publisher.name))
100+
rospy.sleep(0.5)
101+
i += 1
102+
i = i % 5
103+
if rospy.is_shutdown():
104+
raise Exception("Got shutdown request before subscribers connected")
105+
106+
def update(self, x, y, z, th, speed, turn):
107+
self.condition.acquire()
108+
self.x = x
109+
self.y = y
110+
self.z = z
111+
self.th = th
112+
self.speed = speed
113+
self.turn = turn
114+
# Notify publish thread that we have a new message.
115+
self.condition.notify()
116+
self.condition.release()
117+
118+
def stop(self):
119+
self.done = True
120+
self.update(0, 0, 0, 0, 0, 0)
121+
self.join()
122+
123+
def run(self):
124+
twist_msg = TwistMsg()
125+
126+
if stamped:
127+
twist = twist_msg.twist
128+
twist_msg.header.stamp = rospy.Time.now()
129+
twist_msg.header.frame_id = twist_frame
130+
else:
131+
twist = twist_msg
132+
while not self.done:
133+
if stamped:
134+
twist_msg.header.stamp = rospy.Time.now()
135+
self.condition.acquire()
136+
# Wait for a new message or timeout.
137+
self.condition.wait(self.timeout)
138+
139+
# Copy state into twist message.
140+
twist.linear.x = self.x * self.speed
141+
twist.linear.y = self.y * self.speed
142+
twist.linear.z = self.z * self.speed
143+
twist.angular.x = 0
144+
twist.angular.y = 0
145+
twist.angular.z = self.th * self.turn
146+
147+
self.condition.release()
148+
149+
# Publish.
150+
self.publisher.publish(twist_msg)
151+
152+
# Publish stop message when thread exits.
153+
twist.linear.x = 0
154+
twist.linear.y = 0
155+
twist.linear.z = 0
156+
twist.angular.x = 0
157+
twist.angular.y = 0
158+
twist.angular.z = 0
159+
self.publisher.publish(twist_msg)
160+
161+
162+
def getKey(settings, timeout):
163+
if sys.platform == 'win32':
164+
# getwch() returns a string on Windows
165+
key = msvcrt.getwch()
31166
else:
32-
key = ''
33-
34-
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
167+
tty.setraw(sys.stdin.fileno())
168+
# sys.stdin.read() returns a string on Linux
169+
rlist, _, _ = select([sys.stdin], [], [], timeout)
170+
if rlist:
171+
key = sys.stdin.read(1)
172+
else:
173+
key = ''
174+
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
35175
return key
36176

177+
def saveTerminalSettings():
178+
if sys.platform == 'win32':
179+
return None
180+
return termios.tcgetattr(sys.stdin)
181+
182+
def restoreTerminalSettings(old_settings):
183+
if sys.platform == 'win32':
184+
return
185+
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
186+
187+
def vels(speed, turn):
188+
return "currently:\tspeed %s\tturn %s " % (speed,turn)
37189

38190
if __name__=="__main__":
39-
settings = termios.tcgetattr(sys.stdin)
40-
41-
rospy.init_node('myagv_teleop')
42-
pub = rospy.Publisher('/cmd_vel', Twist, queue_size=10)
191+
settings = saveTerminalSettings()
192+
193+
rospy.init_node('teleop_twist_keyboard')
194+
195+
speed = rospy.get_param("~speed", 0.5)
196+
turn = rospy.get_param("~turn", 0.5)
197+
speed_limit = rospy.get_param("~speed_limit", 1.0)
198+
turn_limit = rospy.get_param("~turn_limit", 1.0)
199+
repeat = rospy.get_param("~repeat_rate", 0.0)
200+
key_timeout = rospy.get_param("~key_timeout", 0.52)
201+
stamped = rospy.get_param("~stamped", False)
202+
twist_frame = rospy.get_param("~frame_id", '')
203+
if stamped:
204+
TwistMsg = TwistStamped
205+
206+
pub_thread = PublishThread(repeat)
43207

44208
x = 0
45209
y = 0
46-
theta = 0
210+
z = 0
211+
th = 0
212+
status = 0
47213

48214
try:
215+
pub_thread.wait_for_subscribers()
216+
pub_thread.update(x, y, z, th, speed, turn)
217+
49218
print(msg)
219+
print(vels(speed,turn))
50220
while(1):
51-
key = getKey()
52-
53-
if key == ' ' or key == 'k' :
221+
key = getKey(settings, key_timeout)
222+
if key in moveBindings.keys():
223+
x = moveBindings[key][0]
224+
y = moveBindings[key][1]
225+
z = moveBindings[key][2]
226+
th = moveBindings[key][3]
227+
elif key in speedBindings.keys():
228+
speed = min(speed_limit, speed * speedBindings[key][0])
229+
turn = min(turn_limit, turn * speedBindings[key][1])
230+
if speed == speed_limit:
231+
print("Linear speed limit reached!")
232+
if turn == turn_limit:
233+
print("Angular speed limit reached!")
234+
print(vels(speed,turn))
235+
if (status == 14):
236+
print(msg)
237+
status = (status + 1) % 15
238+
else:
239+
# Skip updating cmd_vel if key timeout and robot already
240+
# stopped.
241+
if key == '' and x == 0 and y == 0 and z == 0 and th == 0:
242+
continue
54243
x = 0
55244
y = 0
56-
theta = 0
57-
58-
elif key == 'i':
59-
x = 0.5
60-
y = 0
61-
theta = 0
62-
elif key == ',':
63-
x = -0.5
64-
y = 0
65-
theta = 0
66-
elif key == 'j':
67-
x = 0
68-
y = 0.5
69-
theta = 0
70-
elif key == 'l':
71-
x = 0
72-
y = -0.5
73-
theta = 0
74-
elif key == 'u':
75-
x = 0
76-
y = 0
77-
theta = 0.5
78-
elif key == 'o':
79-
x = 0
80-
y = 0
81-
theta = -0.5
82-
elif key == '\x03':
83-
break
84-
85-
twist = Twist()
86-
twist.linear.x = x;
87-
twist.linear.y = y;
88-
twist.linear.z = 0
89-
twist.angular.x = 0;
90-
twist.angular.y = 0;
91-
twist.angular.z = theta
92-
pub.publish(twist)
93-
94-
except:
245+
z = 0
246+
th = 0
247+
if (key == '\x03'):
248+
break
249+
250+
pub_thread.update(x, y, z, th, speed, turn)
251+
252+
except Exception as e:
95253
print(e)
96254

97255
finally:
98-
twist = Twist()
99-
twist.linear.x = 0; twist.linear.y = 0; twist.linear.z = 0
100-
twist.angular.x = 0; twist.angular.y = 0; twist.angular.z = 0
101-
pub.publish(twist)
102-
103-
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
256+
pub_thread.stop()
257+
restoreTerminalSettings(settings)

0 commit comments

Comments
 (0)