ROS2实战:如何在rviz2中绘制动态多边形(附完整代码)
ROS2实战在rviz2中实现动态多边形绘制的两种高效方案在机器人开发中实时可视化多边形区域是SLAM建图、路径规划等场景的常见需求。ROS2的rviz2作为强大的可视化工具提供了多种消息类型来支持这一功能。本文将深入探讨两种主流实现方案并分享如何优化动态更新的性能表现。1. 多边形可视化基础与方案选型多边形绘制在机器人应用中扮演着关键角色。无论是构建环境地图时的障碍物边界还是路径规划中的安全区域亦或是视觉识别中的感兴趣区域都需要清晰的可视化呈现。ROS2为此提供了两种核心消息类型visualization_msgs::msg::Marker和geometry_msgs::msg::PolygonStamped。方案对比表格特性Marker方案PolygonStamped方案渲染类型支持线框/面片仅支持线框颜色控制完全可控依赖rviz2默认设置动态更新需重新发布完整Marker可单独更新顶点适用场景需要复杂样式的展示纯几何数据传递性能开销较高较低提示选择方案时应考虑实际需求。若需要丰富的视觉效果Marker是更好的选择若侧重几何数据传输效率则PolygonStamped更合适。2. 使用Marker实现高级多边形渲染Marker方案提供了最灵活的渲染控制支持线框、面片、点云等多种表现形式。下面我们实现一个完整的动态多边形节点#include rclcpp/rclcpp.hpp #include visualization_msgs/msg/marker.hpp #include geometry_msgs/msg/point.hpp class DynamicPolygonNode : public rclcpp::Node { public: DynamicPolygonNode() : Node(dynamic_polygon) { marker_pub_ create_publishervisualization_msgs::msg::Marker(polygon_marker, 10); // 初始化定时器1Hz更新 timer_ create_wall_timer( std::chrono::milliseconds(1000), std::bind(DynamicPolygonNode::updatePolygon, this)); } private: void updatePolygon() { auto marker createBaseMarker(); // 动态生成多边形顶点示例为旋转的正方形 static float angle 0.0; const float radius 1.0; std::vectorgeometry_msgs::msg::Point points { {radius*cos(angle), radius*sin(angle), 0.0}, {radius*cos(angleM_PI/2), radius*sin(angleM_PI/2), 0.0}, {radius*cos(angleM_PI), radius*sin(angleM_PI), 0.0}, {radius*cos(angle3*M_PI/2), radius*sin(angle3*M_PI/2), 0.0} }; angle 0.1; // 填充顶点数据 marker.points.clear(); for (const auto point : points) { marker.points.push_back(point); } marker.points.push_back(points[0]); // 闭合多边形 marker_pub_-publish(marker); } visualization_msgs::msg::Marker createBaseMarker() { visualization_msgs::msg::Marker marker; marker.header.frame_id map; marker.header.stamp now(); marker.ns dynamic_polygon; marker.id 0; marker.type visualization_msgs::msg::Marker::LINE_STRIP; marker.action visualization_msgs::msg::Marker::ADD; marker.pose.orientation.w 1.0; marker.scale.x 0.05; // 线宽 marker.color.r 0.0; marker.color.g 0.8; marker.color.b 1.0; marker.color.a 1.0; // 不透明度 return marker; } rclcpp::Publishervisualization_msgs::msg::Marker::SharedPtr marker_pub_; rclcpp::TimerBase::SharedPtr timer_; }; int main(int argc, char** argv) { rclcpp::init(argc, argv); rclcpp::spin(std::make_sharedDynamicPolygonNode()); rclcpp::shutdown(); return 0; }关键参数解析type设置为LINE_STRIP表示连线形式也可用TRIANGLE_LIST实现面片填充scale.x控制线宽或点大小colorRGBA格式支持透明度设置points按顺序存储多边形顶点需手动闭合优化技巧使用ns和id组合来管理多个多边形动态更新时保持其他属性不变仅修改points和header.stamp对于复杂多边形考虑使用TRIANGLE_LIST类型实现面片填充3. PolygonStamped方案与实时数据集成PolygonStamped更适合与其他ROS2组件进行几何数据交互。以下是结合传感器数据动态更新的实现示例#include rclcpp/rclcpp.hpp #include geometry_msgs/msg/polygon_stamped.hpp #include sensor_msgs/msg/laser_scan.hpp class ScanToPolygonNode : public rclcpp::Node { public: ScanToPolygonNode() : Node(scan_to_polygon) { polygon_pub_ create_publishergeometry_msgs::msg::PolygonStamped(scan_polygon, 10); scan_sub_ create_subscriptionsensor_msgs::msg::LaserScan( scan, 10, std::bind(ScanToPolygonNode::scanCallback, this, std::placeholders::_1)); } private: void scanCallback(const sensor_msgs::msg::LaserScan::SharedPtr msg) { geometry_msgs::msg::PolygonStamped polygon; polygon.header msg-header; // 将激光数据转换为多边形顶点 for (size_t i 0; i msg-ranges.size(); i) { if (std::isinf(msg-ranges[i])) continue; float angle msg-angle_min i * msg-angle_increment; geometry_msgs::msg::Point32 point; point.x msg-ranges[i] * cos(angle); point.y msg-ranges[i] * sin(angle); point.z 0.0; polygon.polygon.points.push_back(point); } polygon_pub_-publish(polygon); } rclcpp::Publishergeometry_msgs::msg::PolygonStamped::SharedPtr polygon_pub_; rclcpp::Subscriptionsensor_msgs::msg::LaserScan::SharedPtr scan_sub_; }; int main(int argc, char** argv) { rclcpp::init(argc, argv); rclcpp::spin(std::make_sharedScanToPolygonNode()); rclcpp::shutdown(); return 0; }rviz2配置要点添加Polygon显示类型设置Topic为上述代码中的/scan_polygon调整Color和Alpha参数以获得最佳可视化效果性能优化建议对密集激光数据适当降采样使用PointCloud2转换替代直接处理原始数据考虑使用shared_ptr避免数据拷贝4. 高级应用交互式多边形编辑工具结合ROS2参数服务和rviz2的交互标记功能可以构建更强大的多边形编辑工具。以下是核心实现框架#include rclcpp/rclcpp.hpp #include interactive_markers/interactive_marker_server.hpp #include geometry_msgs/msg/point.hpp class PolygonEditor : public rclcpp::Node { public: PolygonEditor() : Node(polygon_editor) { server_ std::make_sharedinteractive_markers::InteractiveMarkerServer( polygon_editor, get_node_base_interface()); // 初始化多边形控制点 createInteractivePolygon(); // 参数服务回调 add_vertex_cb_ add_on_set_parameters_callback( std::bind(PolygonEditor::parameterCallback, this, std::placeholders::_1)); } private: void createInteractivePolygon() { visualization_msgs::msg::InteractiveMarker int_marker; int_marker.header.frame_id map; int_marker.name editable_polygon; int_marker.description Polygon Editor; // 添加控制点 for (int i 0; i 4; i) { visualization_msgs::msg::InteractiveMarkerControl control; control.always_visible true; visualization_msgs::msg::Marker vertex_marker; vertex_marker.type visualization_msgs::msg::Marker::SPHERE; vertex_marker.scale.x vertex_marker.scale.y vertex_marker.scale.z 0.2; vertex_marker.color.r 1.0; vertex_marker.color.a 1.0; vertex_marker.pose.position.x cos(i*M_PI/2); vertex_marker.pose.position.y sin(i*M_PI/2); control.markers.push_back(vertex_marker); control.interaction_mode visualization_msgs::msg::InteractiveMarkerControl::MOVE_PLANE; int_marker.controls.push_back(control); } server_-insert(int_marker); server_-setCallback(int_marker.name, std::bind(PolygonEditor::markerFeedback, this, std::placeholders::_1)); server_-applyChanges(); } void markerFeedback(const visualization_msgs::msg::InteractiveMarkerFeedback::ConstSharedPtr feedback) { // 处理顶点移动事件 RCLCPP_INFO(get_logger(), Vertex moved to: %.2f, %.2f, feedback-pose.position.x, feedback-pose.position.y); } rcl_interfaces::msg::SetParametersResult parameterCallback( const std::vectorrclcpp::Parameter parameters) { // 处理参数变更如添加/删除顶点 auto result rcl_interfaces::msg::SetParametersResult(); result.successful true; return result; } std::shared_ptrinteractive_markers::InteractiveMarkerServer server_; rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr add_vertex_cb_; }; int main(int argc, char** argv) { rclcpp::init(argc, argv); rclcpp::spin(std::make_sharedPolygonEditor()); rclcpp::shutdown(); return 0; }交互功能扩展建议通过右键菜单添加/删除顶点实现顶点吸附到地图特征点添加面积计算和几何约束检查支持多边形保存/加载功能
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2423025.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!