机器人编程趣味实践06-程序(节点)

举报
zhangrelay 发表于 2021/07/14 22:48:12 2021/07/14
【摘要】 分别输入如下命令: ros2 run examples_rclcpp_minimal_publisher publisher_lambdaros2 run turtlesim turtlesim_node 效果如下图所示: 要想更酷炫的效果,需要三维仿真软件,如下: 必然也支持真实机器人哦。 迷你机器人案例 每敲击一行指令,开启一个或多个程序,具体介绍参...

分别输入如下命令:

  1. ros2 run examples_rclcpp_minimal_publisher publisher_lambda
  2. ros2 run turtlesim turtlesim_node

效果如下图所示:

要想更酷炫的效果,需要三维仿真软件,如下:

必然也支持真实机器人哦。


每敲击一行指令,开启一个或多个程序,具体介绍参考(ROS 2节点-nodes-)。

每个节点可以通过主题消息、服务消息、行动消息或参数相互之间传递数据哦,多台电脑手机之间也可以的。

  1. ros2 run <package_name> <executable_name>
  2. ros2 run turtlesim turtlesim_node
    
  3. ros2 node list

开启一个遥控节点:

  • ros2 run turtlesim turtle_teleop_key

 如果需要中文显示,需要修改代码如下:


  
  1. // puts("Reading from keyboard");
  2. // puts("---------------------------");
  3. // puts("Use arrow keys to move the turtle.");
  4. // puts("Use G|B|V|C|D|E|R|T keys to rotate to absolute orientations. 'F' to cancel a rotation.");
  5. // puts("'Q' to quit.");
  6. puts("读取键盘信息. ");
  7. puts("--------------------------- ");
  8. puts("使用方向键移动机器人. ");
  9. puts("使用 G|B|V|C|D|E|R|T 键使机器人转相应角度. 'F' 键取消旋转. ");
  10. puts("'Q' 键退出遥控. ");

这种方式也可以实现相应开源软件的汉化,但无技术难度……

此时,可以看到两个节点了哦:

机器人程序的通用型,如何体现呢?比如相似功能的节点是否支持多种机器人遥控,而无需修改代码呢?

重映射(Remapping)

此时开启机器人turtlebot3!

通过映射可以同时遥控二维和三维环境中的机器人吗?试一试吧。

 

  • ros2 run turtlesim turtlesim_node --ros-args --remap __node:=turtlebot3

这显然不行,这只是一个重命名呢………………

如果需要查看节点的信息使用如下命令:

  • ros2 node info <node_name>
  • ros2 node info /turtlebot3_diff_drive

节点的全部功能如下:

本节涉及的键盘遥控效果:

有没有发现什么不对劲的地方?更多内容,下一节继续。


  
  1. #include <rclcpp/rclcpp.hpp>
  2. #include <rclcpp_action/rclcpp_action.hpp>
  3. #include <geometry_msgs/msg/twist.hpp>
  4. #include <turtlesim/action/rotate_absolute.hpp>
  5. #include <signal.h>
  6. #include <stdio.h>
  7. #ifndef _WIN32
  8. # include <termios.h>
  9. # include <unistd.h>
  10. #else
  11. # include <windows.h>
  12. #endif
  13. #define KEYCODE_RIGHT 0x43
  14. #define KEYCODE_LEFT 0x44
  15. #define KEYCODE_UP 0x41
  16. #define KEYCODE_DOWN 0x42
  17. #define KEYCODE_B 0x62
  18. #define KEYCODE_C 0x63
  19. #define KEYCODE_D 0x64
  20. #define KEYCODE_E 0x65
  21. #define KEYCODE_F 0x66
  22. #define KEYCODE_G 0x67
  23. #define KEYCODE_Q 0x71
  24. #define KEYCODE_R 0x72
  25. #define KEYCODE_T 0x74
  26. #define KEYCODE_V 0x76
  27. class KeyboardReader
  28. {
  29. public:
  30. KeyboardReader()
  31. #ifndef _WIN32
  32. : kfd(0)
  33. #endif
  34. {
  35. #ifndef _WIN32
  36. // get the console in raw mode
  37. tcgetattr(kfd, &cooked);
  38. struct termios raw;
  39. memcpy(&raw, &cooked, sizeof(struct termios));
  40. raw.c_lflag &=~ (ICANON | ECHO);
  41. // Setting a new line, then end of file
  42. raw.c_cc[VEOL] = 1;
  43. raw.c_cc[VEOF] = 2;
  44. tcsetattr(kfd, TCSANOW, &raw);
  45. #endif
  46. }
  47. void readOne(char * c)
  48. {
  49. #ifndef _WIN32
  50. int rc = read(kfd, c, 1);
  51. if (rc < 0)
  52. {
  53. throw std::runtime_error("read failed");
  54. }
  55. #else
  56. for(;;)
  57. {
  58. HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
  59. INPUT_RECORD buffer;
  60. DWORD events;
  61. PeekConsoleInput(handle, &buffer, 1, &events);
  62. if(events > 0)
  63. {
  64. ReadConsoleInput(handle, &buffer, 1, &events);
  65. if (buffer.Event.KeyEvent.wVirtualKeyCode == VK_LEFT)
  66. {
  67. *c = KEYCODE_LEFT;
  68. return;
  69. }
  70. else if (buffer.Event.KeyEvent.wVirtualKeyCode == VK_UP)
  71. {
  72. *c = KEYCODE_UP;
  73. return;
  74. }
  75. else if (buffer.Event.KeyEvent.wVirtualKeyCode == VK_RIGHT)
  76. {
  77. *c = KEYCODE_RIGHT;
  78. return;
  79. }
  80. else if (buffer.Event.KeyEvent.wVirtualKeyCode == VK_DOWN)
  81. {
  82. *c = KEYCODE_DOWN;
  83. return;
  84. }
  85. else if (buffer.Event.KeyEvent.wVirtualKeyCode == 0x42)
  86. {
  87. *c = KEYCODE_B;
  88. return;
  89. }
  90. else if (buffer.Event.KeyEvent.wVirtualKeyCode == 0x43)
  91. {
  92. *c = KEYCODE_C;
  93. return;
  94. }
  95. else if (buffer.Event.KeyEvent.wVirtualKeyCode == 0x44)
  96. {
  97. *c = KEYCODE_D;
  98. return;
  99. }
  100. else if (buffer.Event.KeyEvent.wVirtualKeyCode == 0x45)
  101. {
  102. *c = KEYCODE_E;
  103. return;
  104. }
  105. else if (buffer.Event.KeyEvent.wVirtualKeyCode == 0x46)
  106. {
  107. *c = KEYCODE_F;
  108. return;
  109. }
  110. else if (buffer.Event.KeyEvent.wVirtualKeyCode == 0x47)
  111. {
  112. *c = KEYCODE_G;
  113. return;
  114. }
  115. else if (buffer.Event.KeyEvent.wVirtualKeyCode == 0x51)
  116. {
  117. *c = KEYCODE_Q;
  118. return;
  119. }
  120. else if (buffer.Event.KeyEvent.wVirtualKeyCode == 0x52)
  121. {
  122. *c = KEYCODE_R;
  123. return;
  124. }
  125. else if (buffer.Event.KeyEvent.wVirtualKeyCode == 0x54)
  126. {
  127. *c = KEYCODE_T;
  128. return;
  129. }
  130. else if (buffer.Event.KeyEvent.wVirtualKeyCode == 0x56)
  131. {
  132. *c = KEYCODE_V;
  133. return;
  134. }
  135. }
  136. }
  137. #endif
  138. }
  139. void shutdown()
  140. {
  141. #ifndef _WIN32
  142. tcsetattr(kfd, TCSANOW, &cooked);
  143. #endif
  144. }
  145. private:
  146. #ifndef _WIN32
  147. int kfd;
  148. struct termios cooked;
  149. #endif
  150. };
  151. class TeleopTurtle
  152. {
  153. public:
  154. TeleopTurtle();
  155. int keyLoop();
  156. private:
  157. void spin();
  158. void sendGoal(float theta);
  159. void goalResponseCallback(std::shared_future<rclcpp_action::ClientGoalHandle<turtlesim::action::RotateAbsolute>::SharedPtr> future);
  160. void cancelGoal();
  161. rclcpp::Node::SharedPtr nh_;
  162. double linear_, angular_, l_scale_, a_scale_;
  163. rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr twist_pub_;
  164. rclcpp_action::Client<turtlesim::action::RotateAbsolute>::SharedPtr rotate_absolute_client_;
  165. rclcpp_action::ClientGoalHandle<turtlesim::action::RotateAbsolute>::SharedPtr goal_handle_;
  166. };
  167. TeleopTurtle::TeleopTurtle():
  168. linear_(0),
  169. angular_(0),
  170. l_scale_(2.0),
  171. a_scale_(2.0)
  172. {
  173. nh_ = rclcpp::Node::make_shared("teleop_turtle");
  174. nh_->declare_parameter("scale_angular", rclcpp::ParameterValue(2.0));
  175. nh_->declare_parameter("scale_linear", rclcpp::ParameterValue(2.0));
  176. nh_->get_parameter("scale_angular", a_scale_);
  177. nh_->get_parameter("scale_linear", l_scale_);
  178. twist_pub_ = nh_->create_publisher<geometry_msgs::msg::Twist>("turtle1/cmd_vel", 1);
  179. rotate_absolute_client_ = rclcpp_action::create_client<turtlesim::action::RotateAbsolute>(nh_, "turtle1/rotate_absolute");
  180. }
  181. void TeleopTurtle::sendGoal(float theta)
  182. {
  183. auto goal = turtlesim::action::RotateAbsolute::Goal();
  184. goal.theta = theta;
  185. auto send_goal_options = rclcpp_action::Client<turtlesim::action::RotateAbsolute>::SendGoalOptions();
  186. send_goal_options.goal_response_callback =
  187. [this](std::shared_future<rclcpp_action::ClientGoalHandle<turtlesim::action::RotateAbsolute>::SharedPtr> future)
  188. {
  189. RCLCPP_DEBUG(nh_->get_logger(), "Goal response received");
  190. this->goal_handle_ = future.get();
  191. };
  192. rotate_absolute_client_->async_send_goal(goal, send_goal_options);
  193. }
  194. void TeleopTurtle::goalResponseCallback(std::shared_future<rclcpp_action::ClientGoalHandle<turtlesim::action::RotateAbsolute>::SharedPtr> future)
  195. {
  196. RCLCPP_DEBUG(nh_->get_logger(), "Goal response received");
  197. this->goal_handle_ = future.get();
  198. }
  199. void TeleopTurtle::cancelGoal()
  200. {
  201. if (goal_handle_)
  202. {
  203. RCLCPP_DEBUG(nh_->get_logger(), "Sending cancel request");
  204. try
  205. {
  206. rotate_absolute_client_->async_cancel_goal(goal_handle_);
  207. }
  208. catch (...)
  209. {
  210. // This can happen if the goal has already terminated and expired
  211. }
  212. }
  213. }
  214. KeyboardReader input;
  215. void quit(int sig)
  216. {
  217. (void)sig;
  218. input.shutdown();
  219. rclcpp::shutdown();
  220. exit(0);
  221. }
  222. int main(int argc, char** argv)
  223. {
  224. rclcpp::init(argc, argv);
  225. TeleopTurtle teleop_turtle;
  226. signal(SIGINT,quit);
  227. int rc = teleop_turtle.keyLoop();
  228. input.shutdown();
  229. rclcpp::shutdown();
  230. return rc;
  231. }
  232. void TeleopTurtle::spin()
  233. {
  234. while (rclcpp::ok())
  235. {
  236. rclcpp::spin_some(nh_);
  237. }
  238. }
  239. int TeleopTurtle::keyLoop()
  240. {
  241. char c;
  242. bool dirty=false;
  243. std::thread{std::bind(&TeleopTurtle::spin, this)}.detach();
  244. // puts("Reading from keyboard");
  245. // puts("---------------------------");
  246. // puts("Use arrow keys to move the turtle.");
  247. // puts("Use G|B|V|C|D|E|R|T keys to rotate to absolute orientations. 'F' to cancel a rotation.");
  248. // puts("'Q' to quit.");
  249. puts("读取键盘信息. ");
  250. puts("--------------------------- ");
  251. puts("使用方向键移动机器人. ");
  252. puts("使用 G|B|V|C|D|E|R|T 键使机器人转相应角度. 'F' 键取消旋转. ");
  253. puts("'Q' 键退出遥控. ");
  254. for(;;)
  255. {
  256. // get the next event from the keyboard
  257. try
  258. {
  259. input.readOne(&c);
  260. }
  261. catch (const std::runtime_error &)
  262. {
  263. perror("read():");
  264. return -1;
  265. }
  266. linear_=angular_=0;
  267. RCLCPP_DEBUG(nh_->get_logger(), "value: 0x%02X\n", c);
  268. switch(c)
  269. {
  270. case KEYCODE_LEFT:
  271. RCLCPP_DEBUG(nh_->get_logger(), "LEFT");
  272. angular_ = 1.0;
  273. dirty = true;
  274. break;
  275. case KEYCODE_RIGHT:
  276. RCLCPP_DEBUG(nh_->get_logger(), "RIGHT");
  277. angular_ = -1.0;
  278. dirty = true;
  279. break;
  280. case KEYCODE_UP:
  281. RCLCPP_DEBUG(nh_->get_logger(), "UP");
  282. linear_ = 1.0;
  283. dirty = true;
  284. break;
  285. case KEYCODE_DOWN:
  286. RCLCPP_DEBUG(nh_->get_logger(), "DOWN");
  287. linear_ = -1.0;
  288. dirty = true;
  289. break;
  290. case KEYCODE_G:
  291. RCLCPP_DEBUG(nh_->get_logger(), "G");
  292. sendGoal(0.0f);
  293. break;
  294. case KEYCODE_T:
  295. RCLCPP_DEBUG(nh_->get_logger(), "T");
  296. sendGoal(0.7854f);
  297. break;
  298. case KEYCODE_R:
  299. RCLCPP_DEBUG(nh_->get_logger(), "R");
  300. sendGoal(1.5708f);
  301. break;
  302. case KEYCODE_E:
  303. RCLCPP_DEBUG(nh_->get_logger(), "E");
  304. sendGoal(2.3562f);
  305. break;
  306. case KEYCODE_D:
  307. RCLCPP_DEBUG(nh_->get_logger(), "D");
  308. sendGoal(3.1416f);
  309. break;
  310. case KEYCODE_C:
  311. RCLCPP_DEBUG(nh_->get_logger(), "C");
  312. sendGoal(-2.3562f);
  313. break;
  314. case KEYCODE_V:
  315. RCLCPP_DEBUG(nh_->get_logger(), "V");
  316. sendGoal(-1.5708f);
  317. break;
  318. case KEYCODE_B:
  319. RCLCPP_DEBUG(nh_->get_logger(), "B");
  320. sendGoal(-0.7854f);
  321. break;
  322. case KEYCODE_F:
  323. RCLCPP_DEBUG(nh_->get_logger(), "F");
  324. cancelGoal();
  325. break;
  326. case KEYCODE_Q:
  327. RCLCPP_DEBUG(nh_->get_logger(), "quit");
  328. return 0;
  329. }
  330. geometry_msgs::msg::Twist twist;
  331. twist.angular.z = a_scale_*angular_;
  332. twist.linear.x = l_scale_*linear_;
  333. if(dirty ==true)
  334. {
  335. twist_pub_->publish(twist);
  336. dirty=false;
  337. }
  338. }
  339. return 0;
  340. }

 

文章来源: zhangrelay.blog.csdn.net,作者:zhangrelay,版权归原作者所有,如需转载,请联系作者。

原文链接:zhangrelay.blog.csdn.net/article/details/116804376

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。