当前位置: 首页 > article >正文

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; }交互功能扩展建议通过右键菜单添加/删除顶点实现顶点吸附到地图特征点添加面积计算和几何约束检查支持多边形保存/加载功能

相关文章:

ROS2实战:如何在rviz2中绘制动态多边形(附完整代码)

ROS2实战:在rviz2中实现动态多边形绘制的两种高效方案 在机器人开发中,实时可视化多边形区域是SLAM建图、路径规划等场景的常见需求。ROS2的rviz2作为强大的可视化工具,提供了多种消息类型来支持这一功能。本文将深入探讨两种主流实现方案&am…...

C++ vector性能优化:从reserve到emplace_back的7个实战技巧

C vector性能优化:从reserve到emplace_back的7个实战技巧 在游戏引擎开发中,我们曾遇到一个令人头疼的场景:当角色技能系统需要实时加载上千个特效参数时,使用默认方式的vector存储导致帧率骤降。通过一系列性能调优后&#xff0c…...

零代码玩转阿里云百炼:用智能体应用3小时搭建电商文案生成器

零代码玩转阿里云百炼:3小时打造智能电商文案生成器 在电商行业,商品描述和促销文案的创作效率直接影响转化率。传统人工撰写模式面临两大痛点:一是海量SKU导致内容生产压力巨大,二是文案风格难以保持统一调性。阿里云百炼平台推出…...

x64dbg调试实战:如何绕过406D1388和E06D7363异常(附隐藏调试器技巧)

x64dbg调试实战:破解406D1388与E06D7363异常的艺术 调试器与反调试技术的博弈从未停止。当你在逆向分析中突然遭遇406D1388(MS_VC_EXCEPTION)或E06D7363(CPP_EH_EXCEPTION)这类异常时,不必惊慌——这往往是程序反调试机制在作祟。本文将带你深入异常处理…...

Step3-VL-10B部署教程:GPU直通虚拟机中Step3-VL-10B性能调优指南

Step3-VL-10B部署教程:GPU直通虚拟机中Step3-VL-10B性能调优指南 1. 为什么要在虚拟机里调优Step3-VL-10B? 你可能已经成功在GPU直通的虚拟机里部署了Step3-VL-10B,这个能看懂图片、识别文字、还能做数学推理的视觉语言模型。但用起来是不是…...

gte-base-zh开箱即用:Xinference部署与WebUI体验全流程

gte-base-zh开箱即用:Xinference部署与WebUI体验全流程 1. 引言:从模型到服务,一键开启文本嵌入之旅 如果你正在寻找一个强大且易于部署的中文文本嵌入模型,那么 gte-base-zh 绝对值得你关注。这个由阿里巴巴达摩院精心训练的模…...

Nunchaku-flux-1-dev在Ubuntu20.04上的保姆级部署教程

Nunchaku-flux-1-dev在Ubuntu20.04上的保姆级部署教程 专为新手准备的详细指南,手把手带你避开所有坑 最近在折腾AI模型部署,发现Nunchaku-flux-1-dev这个模型效果还不错,但在Ubuntu系统上部署确实遇到不少问题。特别是驱动兼容性、环境配置这…...

技术探索:文本驱动CAD建模的技术原理与实践路径

技术探索:文本驱动CAD建模的技术原理与实践路径 【免费下载链接】text-to-cad-ui A lightweight UI for interfacing with the Zoo text-to-cad API, built with SvelteKit. 项目地址: https://gitcode.com/gh_mirrors/te/text-to-cad-ui 一、技术原理&#…...

PyMAVLink:无人机通信的Python桥梁——从入门到实践指南

PyMAVLink:无人机通信的Python桥梁——从入门到实践指南 【免费下载链接】pymavlink python MAVLink interface and utilities 项目地址: https://gitcode.com/gh_mirrors/py/pymavlink 如何通过PyMAVLink实现无人机高效通信? 解析MAVLink协议&a…...

[函数设计实战] 巧用循环与幂运算,高效求解特殊a串数列和

1. 从实际问题理解特殊a串数列 第一次看到这个题目时,我正坐在电脑前啃着面包。题目要求计算类似222222这样的数列和,看起来简单,但仔细一想却暗藏玄机。这种由重复数字组成的数列,在数学中被称为"重码数"或"重复数…...

ELISPOT显色底物选择指南

什么是ELISPOT显色底物? ELISPOT显色底物是一种用于标记酶标抗体位点的化学试剂,在过氧化物酶催化下发生显色反应,形成肉眼或显微镜下可见的有色斑点。每个斑点对应一个分泌目标蛋白的单个细胞。 AEC显色底物的特点 AEC(3-氨基…...

圣女司幼幽-造相Z-Turbo实战教程:使用LoRA权重切换不同圣女造型风格

圣女司幼幽-造相Z-Turbo实战教程:使用LoRA权重切换不同圣女造型风格 想用AI画出不同风格的圣女司幼幽吗?无论是清冷神性的古风仙子,还是现代装扮的都市丽人,一个模型就能搞定。 今天要介绍的这个“圣女司幼幽-造相Z-Turbo”镜像…...

高效掌握MissionPlanner:面向无人机开发者的开源地面控制站指南

高效掌握MissionPlanner:面向无人机开发者的开源地面控制站指南 【免费下载链接】MissionPlanner Mission Planner Ground Control Station for ArduPilot (c# .net) 项目地址: https://gitcode.com/gh_mirrors/mi/MissionPlanner 3大核心优势:全…...

立创EDA开源项目:基于RDA5807的徽章式FM收音机硬件设计详解

立创EDA开源项目:基于RDA5807的徽章式FM收音机硬件设计详解 最近在立创开源硬件平台看到一个挺有意思的项目——一个可以别在身上的徽章式FM收音机。它把收音机芯片、充电管理、电池和外壳都集成到了一块小小的板子上,设计思路很巧妙,特别适合…...

飞牛NAS+Docker+DDNS:三步搞定动态域名解析与二级域名配置

1. 为什么需要动态域名解析? 家里有飞牛NAS的朋友,肯定遇到过这样的烦恼:每次想从外网访问家里的NAS,都得先查一下当前的公网IP地址。更糟心的是,运营商的公网IP经常变动,可能早上还能连,下午就…...

Android Jetpack实战:FragmentContainerView与Navigation组件的完美搭配(避坑指南)

Android Jetpack实战:FragmentContainerView与Navigation组件的完美搭配(避坑指南) 在Android应用开发中,Fragment作为UI模块化的核心组件,其管理方式直接影响应用架构的健壮性。随着Jetpack组件库的成熟,F…...

SAM 3快速入门:等待3分钟加载,点击Web图标开始你的分割体验

SAM 3快速入门:等待3分钟加载,点击Web图标开始你的分割体验 1. SAM 3简介:图像和视频分割的新标杆 SAM 3是Meta推出的新一代统一基础模型,专为图像和视频中的智能分割任务设计。这个强大的工具可以让你通过简单的文本或视觉提示…...

基于MCP协议构建Granite TimeSeries模型服务:实现标准化模型调用

基于MCP协议构建Granite TimeSeries模型服务:实现标准化模型调用 如果你正在为如何把那个功能强大的时间序列预测模型——Granite TimeSeries FlowState R1——方便地集成到你的应用里而头疼,这篇文章就是为你准备的。传统上,模型部署和调用…...

Qwen2.5-7B-Instruct参数详解:28层GQA架构与RMSNorm优化原理

Qwen2.5-7B-Instruct参数详解:28层GQA架构与RMSNorm优化原理 1. 引言:为什么我们需要了解模型参数? 你可能已经听说过Qwen2.5-7B-Instruct这个模型,也知道它很强大,但当你看到技术文档里那些“28层”、“GQA”、“RM…...

PWM电压型同步Buck系统设计避坑指南:从原理图到仿真全流程解析

PWM电压型同步Buck系统设计避坑指南:从原理图到仿真全流程解析 在电力电子领域,DC-DC转换器设计一直是工程师们面临的挑战之一。特别是对于需要高效率、高功率密度的应用场景,同步Buck拓扑因其显著优势成为首选方案。然而,从原理图…...

BGE Reranker-v2-m3入门指南:理解bge-reranker-v2-m3相比v1版本在中文长文本上的改进

BGE Reranker-v2-m3入门指南:理解bge-reranker-v2-m3相比v1版本在中文长文本上的改进 1. 学习目标与前置知识 本文将带你全面了解BGE Reranker-v2-m3重排序系统,特别聚焦于它在中文长文本处理上的显著改进。无论你是搜索系统开发者、NLP工程师&#xf…...

ESP32+VScode环境配置踩坑实录:解决‘python.exe -m pip无效’的6种方法

ESP32VScode环境配置实战:彻底解决Python pip模块无效问题 刚拿到ESP32开发板时,我兴冲冲地按照教程配置VScode环境,却在执行python.exe -m pip命令时遇到了"is not valid"的错误提示。这就像准备大展拳脚时突然被泼了一盆冷水——…...

Python量化交易实战:如何用抛物线SAR指标捕捉苹果股票买卖点(附完整代码)

Python量化交易实战:用抛物线SAR指标构建苹果股票交易系统 最近几年,身边越来越多的开发者朋友开始对量化交易产生兴趣。大家普遍的感觉是,单纯看K线图、听消息炒股,心里总没底,而用代码把交易逻辑固化下来&#xff0c…...

工业以太网组态避坑指南:基恩士KV 7500与RIO20-EIP模块的EDS文件配置详解

工业以太网组态避坑指南:基恩士KV 7500与RIO20-EIP模块的EDS文件配置详解 在工业自动化领域,EtherNET/IP协议因其开放性和高效性已成为主流通信标准之一。然而,在实际组态过程中,EDS文件配置环节往往成为技术人员的"绊脚石&q…...

基于Mirage Flow的智能API文档生成:开发效率提升神器

基于Mirage Flow的智能API文档生成:开发效率提升神器 还在为写API文档头疼吗?试试这个自动生成神器,效果惊艳到让你怀疑人生 1. 为什么API文档让人如此头疼 每个开发者都经历过这样的痛苦:代码写完了,测试通过了&…...

mPLUG图片分析案例分享:复杂场景下的问答表现

mPLUG图片分析案例分享:复杂场景下的问答表现 1. 引言:当AI“看懂”复杂图片时,会发生什么? 我们每天都会看到各种各样的图片——社交媒体上的生活分享、新闻里的现场照片、工作中的图表截图,或是旅行时随手拍下的风…...

ChatGLM3-6B模型解释性研究:理解大模型的决策过程

ChatGLM3-6B模型解释性研究:理解大模型的决策过程 1. 引言 当我们使用ChatGLM3-6B这样的强大语言模型时,经常会惊叹于它流畅的回答和准确的推理能力。但你是否好奇过,这个拥有60亿参数的"黑盒子"究竟是如何做出决策的&#xff1f…...

突破茅台预约困境:5大自动化策略构建智能抢购系统

突破茅台预约困境:5大自动化策略构建智能抢购系统 【免费下载链接】campus-imaotai i茅台app自动预约,每日自动预约,支持docker一键部署 项目地址: https://gitcode.com/GitHub_Trending/ca/campus-imaotai 在数字化时代,茅…...

智能预约引擎:多维度决策系统解决茅台预约效率与成功率难题

智能预约引擎:多维度决策系统解决茅台预约效率与成功率难题 【免费下载链接】campus-imaotai i茅台app自动预约,每日自动预约,支持docker一键部署 项目地址: https://gitcode.com/GitHub_Trending/ca/campus-imaotai 茅台预约如同管理…...

AIGlasses OS Pro结合Git进行视觉模型版本管理与协作

AIGlasses OS Pro结合Git进行视觉模型版本管理与协作 你是不是也遇到过这样的烦恼?辛辛苦苦调了一个星期的模型参数,效果终于好了一点,结果手一抖,把某个关键配置文件给覆盖了,想找都找不回来。或者,团队里…...