├── .assets └── COFFEE BUTTON ヾ(°∇°^).png ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── package.xml └── src └── teleop_twist_keyboard.cpp /.assets/COFFEE BUTTON ヾ(°∇°^).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/methylDragon/teleop_twist_keyboard_cpp/525fb108bbe7ad2527b82cc9ebc0d461b1bdadf3/.assets/COFFEE BUTTON ヾ(°∇°^).png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .swp 2 | .save 3 | .bak 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.3) 2 | project(teleop_twist_keyboard_cpp) 3 | 4 | find_package(catkin REQUIRED COMPONENTS 5 | roscpp 6 | geometry_msgs 7 | ) 8 | 9 | catkin_package( 10 | INCLUDE_DIRS src 11 | CATKIN_DEPENDS roscpp geometry_msgs 12 | ) 13 | 14 | include_directories(${catkin_INCLUDE_DIRS}) 15 | 16 | add_executable(teleop_twist_keyboard src/teleop_twist_keyboard.cpp) 17 | target_link_libraries(teleop_twist_keyboard ${catkin_LIBRARIES}) 18 | 19 | set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 methylDragon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # teleop_twist_keyboard_cpp 2 | C++ Implementation of the Generic Keyboard Teleop for ROS: https://github.com/ros-teleop/teleop_twist_keyboard 3 | 4 | ## Features 5 | 6 | This particular implementation does away with keeping the history of previous speed settings, and heavily cuts down on the amount of printing that is done to the terminal via the use of carriage returns (\r). 7 | 8 | Furthermore, the last command that was sent is reflected, and invalid commands are identified as such. 9 | 10 | 11 | 12 | ## Installing the Package 13 | 14 | As per standard ROS practice, make a workspace, go to the workspace's src directory, and clone this repository, then run catkin_make in the root of the workspace, and source the resulting setup.bash! 15 | 16 | ```bash 17 | $ git clone https://github.com/methylDragon/teleop_twist_keyboard_cpp.git 18 | $ cd .. 19 | $ catkin_make 20 | 21 | $ source devel/setup.bash 22 | ``` 23 | 24 | 25 | 26 | ## Running the Node 27 | 28 | ```bash 29 | # In one terminal, run 30 | $ roscore 31 | 32 | # In another terminal, run 33 | $ rosrun teleop_twist_keyboard_cpp teleop_twist_keyboard 34 | 35 | # If you want to see the outputs, check the /cmd_vel topic 36 | $ rostopic echo /cmd_vel 37 | ``` 38 | 39 | 40 | 41 | ## Usage 42 | 43 | Same as the original 44 | 45 | ``` 46 | Reading from the keyboard and Publishing to Twist! 47 | --------------------------- 48 | Moving around: 49 | u i o 50 | j k l 51 | m , . 52 | 53 | For Holonomic mode (strafing), hold down the shift key: 54 | --------------------------- 55 | U I O 56 | J K L 57 | M < > 58 | 59 | t : up (+z) 60 | b : down (-z) 61 | 62 | anything else : stop 63 | 64 | q/z : increase/decrease max speeds by 10% 65 | w/x : increase/decrease only linear speed by 10% 66 | e/c : increase/decrease only angular speed by 10% 67 | 68 | CTRL-C to quit 69 | ``` 70 | 71 | 72 | 73 | ------ 74 | 75 | [![Yeah! Buy the DRAGON a COFFEE!](./.assets/COFFEE%20BUTTON%20%E3%83%BE(%C2%B0%E2%88%87%C2%B0%5E).png)](https://www.buymeacoffee.com/methylDragon) -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | teleop_twist_keyboard_cpp 4 | 0.0.0 5 | Generic keyboard teleop for twist robots (in C++)! Based off of the teleop_twist_keyboard Python ROS node. 6 | 7 | methylDragon 8 | methylDragon 9 | http://github.com/methylDragon 10 | http://www.ros.org/wiki/teleop_twist_keyboard_cpp 11 | 12 | MIT 13 | 14 | catkin 15 | 16 | roscpp 17 | geometry_msgs 18 | 19 | roscpp 20 | geometry_msgs 21 | 22 | roscpp 23 | geometry_msgs 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/teleop_twist_keyboard.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | // Map for movement keys 11 | std::map> moveBindings 12 | { 13 | {'i', {1, 0, 0, 0}}, 14 | {'o', {1, 0, 0, -1}}, 15 | {'j', {0, 0, 0, 1}}, 16 | {'l', {0, 0, 0, -1}}, 17 | {'u', {1, 0, 0, 1}}, 18 | {',', {-1, 0, 0, 0}}, 19 | {'.', {-1, 0, 0, 1}}, 20 | {'m', {-1, 0, 0, -1}}, 21 | {'O', {1, -1, 0, 0}}, 22 | {'I', {1, 0, 0, 0}}, 23 | {'J', {0, 1, 0, 0}}, 24 | {'L', {0, -1, 0, 0}}, 25 | {'U', {1, 1, 0, 0}}, 26 | {'<', {-1, 0, 0, 0}}, 27 | {'>', {-1, -1, 0, 0}}, 28 | {'M', {-1, 1, 0, 0}}, 29 | {'t', {0, 0, 1, 0}}, 30 | {'b', {0, 0, -1, 0}}, 31 | {'k', {0, 0, 0, 0}}, 32 | {'K', {0, 0, 0, 0}} 33 | }; 34 | 35 | // Map for speed keys 36 | std::map> speedBindings 37 | { 38 | {'q', {1.1, 1.1}}, 39 | {'z', {0.9, 0.9}}, 40 | {'w', {1.1, 1}}, 41 | {'x', {0.9, 1}}, 42 | {'e', {1, 1.1}}, 43 | {'c', {1, 0.9}} 44 | }; 45 | 46 | // Reminder message 47 | const char* msg = R"( 48 | 49 | Reading from the keyboard and Publishing to Twist! 50 | --------------------------- 51 | Moving around: 52 | u i o 53 | j k l 54 | m , . 55 | 56 | For Holonomic mode (strafing), hold down the shift key: 57 | --------------------------- 58 | U I O 59 | J K L 60 | M < > 61 | 62 | t : up (+z) 63 | b : down (-z) 64 | 65 | anything else : stop 66 | 67 | q/z : increase/decrease max speeds by 10% 68 | w/x : increase/decrease only linear speed by 10% 69 | e/c : increase/decrease only angular speed by 10% 70 | 71 | CTRL-C to quit 72 | 73 | )"; 74 | 75 | // Init variables 76 | float speed(0.5); // Linear velocity (m/s) 77 | float turn(1.0); // Angular velocity (rad/s) 78 | float x(0), y(0), z(0), th(0); // Forward/backward/neutral direction vars 79 | char key(' '); 80 | 81 | // For non-blocking keyboard inputs 82 | int getch(void) 83 | { 84 | int ch; 85 | struct termios oldt; 86 | struct termios newt; 87 | 88 | // Store old settings, and copy to new settings 89 | tcgetattr(STDIN_FILENO, &oldt); 90 | newt = oldt; 91 | 92 | // Make required changes and apply the settings 93 | newt.c_lflag &= ~(ICANON | ECHO); 94 | newt.c_iflag |= IGNBRK; 95 | newt.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF); 96 | newt.c_lflag &= ~(ICANON | ECHO | ECHOK | ECHOE | ECHONL | ISIG | IEXTEN); 97 | newt.c_cc[VMIN] = 1; 98 | newt.c_cc[VTIME] = 0; 99 | tcsetattr(fileno(stdin), TCSANOW, &newt); 100 | 101 | // Get the current character 102 | ch = getchar(); 103 | 104 | // Reapply old settings 105 | tcsetattr(STDIN_FILENO, TCSANOW, &oldt); 106 | 107 | return ch; 108 | } 109 | 110 | int main(int argc, char** argv) 111 | { 112 | // Init ROS node 113 | ros::init(argc, argv, "teleop_twist_keyboard"); 114 | ros::NodeHandle nh; 115 | 116 | // Init cmd_vel publisher 117 | ros::Publisher pub = nh.advertise("cmd_vel", 1); 118 | 119 | // Create Twist message 120 | geometry_msgs::Twist twist; 121 | 122 | printf("%s", msg); 123 | printf("\rCurrent: speed %f\tturn %f | Awaiting command...\r", speed, turn); 124 | 125 | while(true){ 126 | 127 | // Get the pressed key 128 | key = getch(); 129 | 130 | // If the key corresponds to a key in moveBindings 131 | if (moveBindings.count(key) == 1) 132 | { 133 | // Grab the direction data 134 | x = moveBindings[key][0]; 135 | y = moveBindings[key][1]; 136 | z = moveBindings[key][2]; 137 | th = moveBindings[key][3]; 138 | 139 | printf("\rCurrent: speed %f\tturn %f | Last command: %c ", speed, turn, key); 140 | } 141 | 142 | // Otherwise if it corresponds to a key in speedBindings 143 | else if (speedBindings.count(key) == 1) 144 | { 145 | // Grab the speed data 146 | speed = speed * speedBindings[key][0]; 147 | turn = turn * speedBindings[key][1]; 148 | 149 | printf("\rCurrent: speed %f\tturn %f | Last command: %c ", speed, turn, key); 150 | } 151 | 152 | // Otherwise, set the robot to stop 153 | else 154 | { 155 | x = 0; 156 | y = 0; 157 | z = 0; 158 | th = 0; 159 | 160 | // If ctrl-C (^C) was pressed, terminate the program 161 | if (key == '\x03') 162 | { 163 | printf("\n\n . .\n . |\\-^-/| . \n /| } O.=.O { |\\\n\n CH3EERS\n\n"); 164 | break; 165 | } 166 | 167 | printf("\rCurrent: speed %f\tturn %f | Invalid command! %c", speed, turn, key); 168 | } 169 | 170 | // Update the Twist message 171 | twist.linear.x = x * speed; 172 | twist.linear.y = y * speed; 173 | twist.linear.z = z * speed; 174 | 175 | twist.angular.x = 0; 176 | twist.angular.y = 0; 177 | twist.angular.z = th * turn; 178 | 179 | // Publish it and resolve any remaining callbacks 180 | pub.publish(twist); 181 | ros::spinOnce(); 182 | } 183 | 184 | return 0; 185 | } 186 | --------------------------------------------------------------------------------