diff --git a/catkin_ws/src/teleop_twist_keyboard/CHANGELOG.rst b/catkin_ws/src/teleop_twist_keyboard/CHANGELOG.rst new file mode 100644 index 0000000000000000000000000000000000000000..8d8d204ce41a19687ce7049dc4c5341633d18e23 --- /dev/null +++ b/catkin_ws/src/teleop_twist_keyboard/CHANGELOG.rst @@ -0,0 +1,40 @@ +1.0.0 (2020-06-26) +------------------ +* Implement repeat rate and key timeout +* Update readme about publishing to another topic. +* Contributors: Austin, trainman419 + +0.6.2 (2018-10-21) +------------------ +* Replace tabs with spaces, fixes `#15 <https://github.com/ros-teleop/teleop_twist_keyboard/issues/15>`_ +* Merge pull request `#13 <https://github.com/ros-teleop/teleop_twist_keyboard/issues/13>`_ from asukiaaa/patch-3 + Add rosrun command to specify values +* Add rosrun command to specify values +* Contributors: Asuki Kono, Austin, trainman419 + +0.6.1 (2018-05-02) +------------------ +* Merge pull request `#11 <https://github.com/ros-teleop/teleop_twist_keyboard/issues/11>`_ from MatthijsBurgh/patch-1 + Correct exception handling; Python3 print compatible +* import print from future +* Print python3 compatible +* correct Exception handling +* Merge pull request `#7 <https://github.com/ros-teleop/teleop_twist_keyboard/issues/7>`_ from lucasw/speed_params + set linear and turn speed via rosparams +* Using tabs instead of spaces to match rest of file +* set linear and turn speed via rosparams +* Contributors: Austin, Lucas Walter, Matthijs van der Burgh + +0.6.0 (2016-03-21) +------------------ +* Better instruction formatting +* support holonomic base, send commmand with keyboard down +* Fixing queue_size warning +* Create README.md +* Update the description string in package.xml +* Contributors: Austin, Kei Okada, LiohAu, Mike Purvis, kk6axq, trainman419 + +0.5.0 (2014-02-11) +------------------ +* Initial import from brown_remotelab +* Convert to catkin diff --git a/catkin_ws/src/teleop_twist_keyboard/CMakeLists.txt b/catkin_ws/src/teleop_twist_keyboard/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..86d90cb1be78fd87efc158078d6b7265248b26dc --- /dev/null +++ b/catkin_ws/src/teleop_twist_keyboard/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 2.8.3) +project(teleop_twist_keyboard) + +find_package(catkin REQUIRED) + +catkin_package() + +## Mark executable scripts (Python etc.) for installation +## in contrast to setup.py, you can choose the destination +catkin_install_python(PROGRAMS + teleop_twist_keyboard.py + DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +) + diff --git a/catkin_ws/src/teleop_twist_keyboard/README.md b/catkin_ws/src/teleop_twist_keyboard/README.md new file mode 100644 index 0000000000000000000000000000000000000000..000d050901274f62507ae495215d8e9d85277666 --- /dev/null +++ b/catkin_ws/src/teleop_twist_keyboard/README.md @@ -0,0 +1,74 @@ +# teleop_twist_keyboard +Generic Keyboard Teleop for ROS + +# Launch +Run. +``` +rosrun teleop_twist_keyboard teleop_twist_keyboard.py +``` + +With custom values. +``` +rosrun teleop_twist_keyboard teleop_twist_keyboard.py _speed:=0.9 _turn:=0.8 +``` + +Publishing to a different topic (in this case `my_cmd_vel`). +``` +rosrun teleop_twist_keyboard teleop_twist_keyboard.py cmd_vel:=my_cmd_vel +``` + +# Usage +``` +Reading from the keyboard and Publishing to Twist! +--------------------------- +Moving around: + u i o + j k l + m , . + +For Holonomic mode (strafing), hold down the shift key: +--------------------------- + U I O + J K L + M < > + +t : up (+z) +b : down (-z) + +anything else : stop + +q/z : increase/decrease max speeds by 10% +w/x : increase/decrease only linear speed by 10% +e/c : increase/decrease only angular speed by 10% + +CTRL-C to quit +``` + +# Repeat Rate + +If your mobile base requires constant updates on the cmd\_vel topic, teleop\_twist\_keyboard can be configured to repeat the last command at a fixed interval, using the `repeat_rate` private parameter. + +For example, to repeat the last command at 10Hz: + +``` +rosrun teleop_twist_keyboard teleop_twist_keyboard.py _repeat_rate:=10.0 +``` + +It is _highly_ recommened that the repeat rate be used in conjunction with the key timeout, to prevent runaway robots. + +# Key Timeout + +Teleop\_twist\_keyboard can be configured to stop your robot if it does not receive any key presses in a configured time period, using the `key_timeout` private parameter. + +For example, to stop your robot if a keypress has not been received in 0.6 seconds: +``` +rosrun teleop_twist_keyboard teleop_twist_keyboard.py _key_timeout:=0.6 +``` + +It is recommended that you set `key_timeout` higher than the initial key repeat delay on your system (This delay is 0.5 seconds by default on Ubuntu, but can be adjusted). + +# Twist with header +Publishing a `TwistStamped` message instead of `Twist` can be enabled with the `stamped` private parameter. Additionally the `frame_id` of the `TwistStamped` message can be set with the `frame_id` private parameter. +``` +rosrun teleop_twist_keyboard teleop_twist_keyboard.py _stamped:=True _frame_id:=base_link +``` \ No newline at end of file diff --git a/catkin_ws/src/teleop_twist_keyboard/package.xml b/catkin_ws/src/teleop_twist_keyboard/package.xml new file mode 100644 index 0000000000000000000000000000000000000000..84add0221dc56865e5c80751a7f413d92c15979f --- /dev/null +++ b/catkin_ws/src/teleop_twist_keyboard/package.xml @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<package> + <name>teleop_twist_keyboard</name> + <version>1.0.0</version> + <description>Generic keyboard teleop for twist robots.</description> + + <maintainer email="namniart@gmail.com">Austin Hendrix</maintainer> + + <license>BSD</license> + + <url type="website">http://wiki.ros.org/teleop_twist_keyboard</url> + + <author>Graylin Trevor Jay</author> + + <buildtool_depend>catkin</buildtool_depend> + <run_depend>geometry_msgs</run_depend> + <run_depend>rospy</run_depend> +</package> diff --git a/catkin_ws/src/teleop_twist_keyboard/teleop_twist_keyboard.py b/catkin_ws/src/teleop_twist_keyboard/teleop_twist_keyboard.py new file mode 100755 index 0000000000000000000000000000000000000000..a85e1cc5c0c6bd10fa8779bf6ad6b4ed18c36f2a --- /dev/null +++ b/catkin_ws/src/teleop_twist_keyboard/teleop_twist_keyboard.py @@ -0,0 +1,265 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import threading + +import roslib; roslib.load_manifest('teleop_twist_keyboard') +import rospy + +from geometry_msgs.msg import Twist +from geometry_msgs.msg import TwistStamped + +import sys +from select import select + +if sys.platform == 'win32': + import msvcrt +else: + import termios + import tty + + +TwistMsg = Twist + +msg = """ +Reading from the keyboard and Publishing to Twist! +--------------------------- +Moving around: + u i o + j k l + m , . + +For Holonomic mode (strafing), hold down the shift key: +--------------------------- + U I O + J K L + M < > + +t : up (+z) +b : down (-z) + +anything else : stop + +q/z : increase/decrease max speeds by 10% +w/x : increase/decrease only linear speed by 10% +e/c : increase/decrease only angular speed by 10% + +CTRL-C to quit +""" + +moveBindings = { + 'i':(1,0,0,0), + 'o':(1,0,0,-1), + 'j':(0,0,0,1), + 'l':(0,0,0,-1), + 'u':(1,0,0,1), + ',':(-1,0,0,0), + '.':(-1,0,0,1), + 'm':(-1,0,0,-1), + 'O':(1,-1,0,0), + 'I':(1,0,0,0), + 'J':(0,1,0,0), + 'L':(0,-1,0,0), + 'U':(1,1,0,0), + '<':(-1,0,0,0), + '>':(-1,-1,0,0), + 'M':(-1,1,0,0), + 't':(0,0,1,0), + 'b':(0,0,-1,0), + } + +speedBindings={ + 'q':(1.1,1.1), + 'z':(.9,.9), + 'w':(1.1,1), + 'x':(.9,1), + 'e':(1,1.1), + 'c':(1,.9), + } + +class PublishThread(threading.Thread): + def __init__(self, rate): + super(PublishThread, self).__init__() + self.publisher = rospy.Publisher('cmd_vel', TwistMsg, queue_size = 1) + self.x = 0.0 + self.y = 0.0 + self.z = 0.0 + self.th = 0.0 + self.speed = 0.0 + self.turn = 0.0 + self.condition = threading.Condition() + self.done = False + + # Set timeout to None if rate is 0 (causes new_message to wait forever + # for new data to publish) + if rate != 0.0: + self.timeout = 1.0 / rate + else: + self.timeout = None + + self.start() + + def wait_for_subscribers(self): + i = 0 + while not rospy.is_shutdown() and self.publisher.get_num_connections() == 0: + if i == 4: + print("Waiting for subscriber to connect to {}".format(self.publisher.name)) + rospy.sleep(0.5) + i += 1 + i = i % 5 + if rospy.is_shutdown(): + raise Exception("Got shutdown request before subscribers connected") + + def update(self, x, y, z, th, speed, turn): + self.condition.acquire() + self.x = x + self.y = y + self.z = z + self.th = th + self.speed = speed + self.turn = turn + # Notify publish thread that we have a new message. + self.condition.notify() + self.condition.release() + + def stop(self): + self.done = True + self.update(0, 0, 0, 0, 0, 0) + self.join() + + def run(self): + twist_msg = TwistMsg() + + if stamped: + twist = twist_msg.twist + twist_msg.header.stamp = rospy.Time.now() + twist_msg.header.frame_id = twist_frame + else: + twist = twist_msg + while not self.done: + if stamped: + twist_msg.header.stamp = rospy.Time.now() + self.condition.acquire() + # Wait for a new message or timeout. + self.condition.wait(self.timeout) + + # Copy state into twist message. + twist.linear.x = self.x * self.speed + twist.linear.y = self.y * self.speed + twist.linear.z = self.z * self.speed + twist.angular.x = 0 + twist.angular.y = 0 + twist.angular.z = self.th * self.turn + + self.condition.release() + + # Publish. + self.publisher.publish(twist_msg) + + # Publish stop message when thread exits. + twist.linear.x = 0 + twist.linear.y = 0 + twist.linear.z = 0 + twist.angular.x = 0 + twist.angular.y = 0 + twist.angular.z = 0 + self.publisher.publish(twist_msg) + + +def getKey(settings, timeout): + if sys.platform == 'win32': + # getwch() returns a string on Windows + key = msvcrt.getwch() + else: + tty.setraw(sys.stdin.fileno()) + # sys.stdin.read() returns a string on Linux + rlist, _, _ = select([sys.stdin], [], [], timeout) + if rlist: + key = sys.stdin.read(1) + else: + key = '' + termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings) + return key + +def saveTerminalSettings(): + if sys.platform == 'win32': + return None + return termios.tcgetattr(sys.stdin) + +def restoreTerminalSettings(old_settings): + if sys.platform == 'win32': + return + termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings) + +def vels(speed, turn): + return "currently:\tspeed %s\tturn %s " % (speed,turn) + +if __name__=="__main__": + settings = saveTerminalSettings() + + rospy.init_node('teleop_twist_keyboard') + + speed = rospy.get_param("~speed", 0.5) + turn = rospy.get_param("~turn", 1.0) + speed_limit = rospy.get_param("~speed_limit", 1000) + turn_limit = rospy.get_param("~turn_limit", 1000) + repeat = rospy.get_param("~repeat_rate", 0.0) + key_timeout = rospy.get_param("~key_timeout", 0.5) + stamped = rospy.get_param("~stamped", False) + twist_frame = rospy.get_param("~frame_id", '') + if stamped: + TwistMsg = TwistStamped + + pub_thread = PublishThread(repeat) + + x = 0 + y = 0 + z = 0 + th = 0 + status = 0 + + try: + pub_thread.wait_for_subscribers() + pub_thread.update(x, y, z, th, speed, turn) + + print(msg) + print(vels(speed,turn)) + while(1): + key = getKey(settings, key_timeout) + if key in moveBindings.keys(): + x = moveBindings[key][0] + y = moveBindings[key][1] + z = moveBindings[key][2] + th = moveBindings[key][3] + elif key in speedBindings.keys(): + speed = min(speed_limit, speed * speedBindings[key][0]) + turn = min(turn_limit, turn * speedBindings[key][1]) + if speed == speed_limit: + print("Linear speed limit reached!") + if turn == turn_limit: + print("Angular speed limit reached!") + print(vels(speed,turn)) + if (status == 14): + print(msg) + status = (status + 1) % 15 + else: + # Skip updating cmd_vel if key timeout and robot already + # stopped. + if key == '' and x == 0 and y == 0 and z == 0 and th == 0: + continue + x = 0 + y = 0 + z = 0 + th = 0 + if (key == '\x03'): + break + + pub_thread.update(x, y, z, th, speed, turn) + + except Exception as e: + print(e) + + finally: + pub_thread.stop() + restoreTerminalSettings(settings)