ROS实战:用C++写个Publisher,让Turtlesim里的小乌龟乖乖画圆(附完整代码解析)
ROS实战用C编写Publisher控制Turtlesim小乌龟画圆当你第一次接触ROS时可能会被各种概念和术语搞得晕头转向。与其死记硬背那些抽象的理论不如通过一个有趣的项目来学习——让Turtlesim中的小乌龟画出一个完美的圆形。这不仅能让学习过程变得生动有趣还能帮助你深入理解ROS的核心机制。1. 环境准备与项目概述在开始编码之前我们需要确保开发环境已经正确配置。这个项目基于以下技术栈ROS版本推荐使用Noetic或Melodic操作系统Ubuntu 18.04/20.04 LTS依赖工具turtlesim包、roscpp库提示可以通过rosdep install turtlesim命令安装turtlesim包项目的基本原理是通过发布geometry_msgs/Twist类型的消息到/turtle1/cmd_vel话题控制小乌龟的运动速度和方向。画圆的关键在于合理设置线速度和角速度的比例线速度(linear.x)控制前进速度角速度(angular.z)控制转向速度2. 创建ROS工作区与包让我们从零开始搭建项目结构# 创建工作区 mkdir -p ~/turtle_circle_ws/src cd ~/turtle_circle_ws/src catkin_init_workspace # 创建功能包 catkin_create_pkg turtle_circle roscpp geometry_msgs # 编译工作区 cd ~/turtle_circle_ws catkin_make工作区创建完成后每次使用前需要source环境source ~/turtle_circle_ws/devel/setup.bash3. 编写Publisher节点代码在src目录下创建draw_circle.cpp文件这是我们的核心控制程序#include ros/ros.h #include geometry_msgs/Twist.h int main(int argc, char **argv) { // 初始化ROS节点 ros::init(argc, argv, circle_publisher); ros::NodeHandle nh; // 创建Publisher发布到/turtle1/cmd_vel话题 ros::Publisher vel_pub nh.advertisegeometry_msgs::Twist(/turtle1/cmd_vel, 10); // 设置发布频率(Hz) ros::Rate loop_rate(10); ROS_INFO(开始控制小乌龟画圆...); while (ros::ok()) { geometry_msgs::Twist vel_msg; // 设置线速度和角速度 vel_msg.linear.x 1.0; // 前进速度 vel_msg.angular.z 1.0; // 旋转速度 // 发布速度指令 vel_pub.publish(vel_msg); // 按照设定的频率循环 loop_rate.sleep(); } return 0; }代码中的关键参数说明参数类型描述推荐值范围linear.xfloat前进速度(m/s)0.5-2.0angular.zfloat旋转速度(rad/s)0.5-2.04. 编译与运行4.1 配置CMakeLists.txt在功能包的CMakeLists.txt中添加以下内容add_executable(draw_circle src/draw_circle.cpp) target_link_libraries(draw_circle ${catkin_LIBRARIES})4.2 编译项目cd ~/turtle_circle_ws catkin_make4.3 运行程序需要按顺序启动三个终端启动ROS核心roscore启动Turtlesim仿真器rosrun turtlesim turtlesim_node运行画圆程序rosrun turtle_circle draw_circle5. 参数调优与高级技巧5.1 如何画出完美的圆要让小乌龟画出完美的圆形线速度和角速度需要满足特定关系圆周运动公式 线速度 角速度 × 半径如果我们希望小乌龟以半径1米画圆可以设置vel_msg.linear.x 1.0; // 线速度 vel_msg.angular.z 1.0; // 角速度5.2 动态参数调整可以通过ROS参数服务器实现运行时参数调整// 在while循环前定义参数 double linear_vel, angular_vel; nh.paramdouble(linear_vel, linear_vel, 1.0); nh.paramdouble(angular_vel, angular_vel, 1.0); // 在循环中使用参数 vel_msg.linear.x linear_vel; vel_msg.angular.z angular_vel;运行时可以通过命令行动态修改参数rosparam set /linear_vel 1.5 rosparam set /angular_vel 0.85.3 添加轨迹记录功能为了可视化小乌龟的运动轨迹可以添加一个Subscriber来记录位置#include turtlesim/Pose.h void poseCallback(const turtlesim::Pose::ConstPtr msg) { ROS_INFO(当前位置: x%.2f, y%.2f, msg-x, msg-y); } // 在main函数中添加 ros::Subscriber pose_sub nh.subscribe(/turtle1/pose, 10, poseCallback);6. 常见问题排查在实际操作中可能会遇到以下问题小乌龟不移动检查话题名称是否正确(/turtle1/cmd_vel)确认roscore和turtlesim_node已启动使用rostopic list查看活跃话题画出的圆不规整调整发布频率(提高loop_rate值)确保线速度和角速度比例适当考虑加入PID控制提高精度编译错误确认CMakeLists.txt配置正确检查ROS版本和依赖项清理工作区后重新编译(catkin_make clean)注意如果小乌龟撞到边缘可以通过rosservice call /reset重置位置7. 扩展应用掌握了基础画圆功能后可以尝试以下扩展绘制复杂图形通过分段控制速度实现螺旋线、方形等多乌龟协同创建多个Publisher控制不同乌龟可视化工具结合RViz增强可视化效果轨迹规划实现预设路径的精确跟踪// 示例绘制方形轨迹 void drawSquare(ros::Publisher pub) { geometry_msgs::Twist msg; ros::Rate rate(1); // 前进 msg.linear.x 1.0; msg.angular.z 0.0; pub.publish(msg); rate.sleep(); // 转向90度 msg.linear.x 0.0; msg.angular.z M_PI/2; pub.publish(msg); rate.sleep(); // 重复4次完成方形 }在实际项目中我发现将速度控制封装成独立的类可以大大提高代码复用性。例如创建一个TurtleController类提供画圆、画方等接口这样在主程序中只需简单调用相应方法即可。

相关新闻

最新新闻

日新闻

周新闻

月新闻