news 2026/10/8 23:45:47

ROS2五轴机械臂仿真Rviz/Moveit/Gazebo(一)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ROS2五轴机械臂仿真Rviz/Moveit/Gazebo(一)

开机怎么打开以前的写好的ROS程序

source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash
ros2 launch arm_moveit_config demo.launch.py

cd ~/ros2_ws
colcon build --packages-select arm_motion_demo
source ~/ros2_ws/install/setup.bash
ros2 run arm_motion_demo collision_check

#机械臂仿真流程

URDF建模->Rviz可视化->Moveit运动规划->C++程序调用Moveit

->加入正逆运动控制算法->连接真机测试

  • 建立一个 ROS 2 节点——让程序进入 ROS 系统。
  • 获取机器人模型、关节状态和环境——知道要检查什么。
  • 调用 MoveIt 的碰撞检查。
  • 输出结果——有没有碰撞,必要时报告碰撞部位。

第一步:创建自己的 ROS 包

在Ubuntu 的新终端中执行,不是在 Windows 中执行:

source /opt/ros/humble/setup.bash source ~/ros2_ws/install/setup.bash cd ~/ros2_ws/src

接着创建包。如果已经存在arm_motion_demo,就不要重复创建,告诉我即可。

ros2 pkg create arm_motion_demo \ --build-type ament_cmake \ --dependencies rclcpp moveit_ros_planning moveit_msgs
内容作用
arm_motion_demo我们的程序包名称
ament_cmake用 CMake 管理、编译这个 C++ 包
rclcpp编写 ROS 2 C++ 节点所需的库
moveit_ros_planning后面加载模型、使用规划场景等功能
moveit_msgs与 MoveIt 通信所用的消息和服务类型

auto scene_client = ...这行代码相当于让节点执行某个操作,具体来说就是调用create_client函数,并把返回结果赋值给scene_client这个变量。

🎯node->和request->的本质区别

  • node->create_client(...):node是节点对象。node->意味着“让节点执行创建客户端这个操作”。这是让对象“干活”。

  • request->components...:request是一个数据包(请求对象)。request->意味着“访问这个数据包里面的内容”。这是给这个数据包“填字”。

C++库函数

std::makeshared<...>()

创建一个对象,并把他放到一个智能指针里

<...>填写模板参数:告诉它要造什么类型的对象

()填写构造函数参数:告诉它造这个对象的时候,传什么参数

spin_until_future_complete

作用:让 ROS 处理这个节点的通信事件,直到收到回答、等待超时或被中断。

使用:node future std::chrono::seconds(5)

RCLCPP_INFO(
node->get_logger(), // 参数1:谁在说话
"Received %zu joint names and %zu positions.", // 参数2:要印的模板
joint_state.name.size(), // 参数3:替换第一个 %zu
joint_state.position.size()); // 参数4:替换第二个 %zu

作用:终端打印输出日志。

C++语法

对象是什么?

(1)C++里,一个名字不是简单的变量,而是一个"对象",对象由数据和函数构成。

(2)一个简单的对象,天生内部就有调用某些函数的能力,但是函数(属于类)并不是存储在这个对象里的。

🔍 例:create_client返回的是什么?

node->create_client<...>(...)调用后,ROS 2 内部会做这些事:

  1. 分配一块内存。

  2. 在内存里创建一个rclcpp::Client类型的对象。

  3. 在这个对象里,把wait_for_service、async_send_request等函数“绑定”上去。

  4. 返回一个智能指针,指向这个对象。

  5. 你把这个指针存进了scene_client。

所以scene_client指向的不是一个“空壳”,而是一个“功能齐全的客户端对象”。

对象和客户端有啥区别?

(1)客户端是负责向服务端发送请求,接收回答的。

(2)ROS里面有很多功能包,编程时使用这些包提供的服务,需要先向服务端发送请求(程序是请求端)创建客户端是为了完成这个服务的通信。

(3)对象是实体,客户端是角色。客户端相当于是一个封装好的特殊对象,里面也是由数据构成的。

&是干啥用的?

auto response = future.get(); const auto &joint_state = response->scene.robot_state.joint_state;

相当于是从future.get()函数里提取出数据以后,存入了response,又定义 了一个只读的const auto对象,将从response里面的scene.robot里面的joint_state读到的结果贴上一个标签。

示例代码:

获取机器人关节角度,检测当前状态是否干涉,创建了两个客户端,一个获取机器人关节状态,一个读取客户端一的数据,向Moveit发送服务请求,进行干涉检查。

#include <rclcpp/rclcpp.hpp> #include <moveit_msgs/srv/get_planning_scene.hpp> #include <moveit_msgs/msg/planning_scene_components.hpp> #include <moveit_msgs/srv/get_state_validity.hpp> #include <chrono> #include <cstddef> //rclcpp是C++核心库 int main(int argc, char **argv) { rclcpp::init(argc, argv); auto node = rclcpp::Node::make_shared("arm_collision_check"); RCLCPP_INFO(node->get_logger(), "Collision checker started."); //创建服务客户端:(完成获取机器人状态等场景数据) //ROS2向Moveit2请求规划场景 auto sence_client = node->create_client<moveit_msgs::srv::GetPlanningScene>( "/get_planning_scene"); //“让 node 这个节点,去创建一个专门连接 /get_planning_scene 服务的客户端,服务类型是 GetPlanningScene。” //node->的意思是:让node这个节点执行某个操作 //auto:自动识别右边是什么类型,并赋予这个类型 if (!sence_client->wait_for_service(std::chrono::seconds(5))) { RCLCPP_ERROR(node->get_logger(), "Planning scene service not available."); rclcpp::shutdown(); return 1; } RCLCPP_INFO(node->get_logger(), "Planning scene service is available."); //向Moveit请求当前关节状态 auto request = std::make_shared<moveit_msgs::srv::GetPlanningScene::Request>(); request->components.components = moveit_msgs::msg::PlanningSceneComponents::ROBOT_STATE; //发送请求: auto future = sence_client->async_send_request(request); //等待处理并回答: auto status = rclcpp::spin_until_future_complete( node,future,std::chrono::seconds(5) ); if(status != rclcpp::FutureReturnCode::SUCCESS) { RCLCPP_ERROR(node->get_logger(),"failed to receive planning scene"); rclcpp::shutdown(); return 1; } auto response = future.get(); const auto &joint_state = response->scene.robot_state.joint_state; RCLCPP_INFO( node->get_logger(), "Receive %zu joint names and %zu positions.", joint_state.name.size(), joint_state.position.size() ); //检查要读取的数据是否配对 if (joint_state.name.size() != joint_state.position.size()) { RCLCPP_ERROR(node->get_logger(), "Joint names and positions do not match."); rclcpp::shutdown(); return 1; } for (std::size_t i = 0; i < joint_state.name.size(); ++i) { RCLCPP_INFO( node->get_logger(), "%s: %.4f rad", joint_state.name[i].c_str(), joint_state.position[i]); } //创建第二个客户端: auto validity_client = node->create_client<moveit_msgs::srv::GetStateValidity>( "/check_state_validity" ); if(!validity_client->wait_for_service(std::chrono::second(5))) { RCLCPP_ERROR(node->get_logger()."State validity service not available."); rclcpp::shutdown(); return 1; } auto validity_request = std::make_shared<moveit_msgs::srv::GetStateValidity::Request>(); //把上一次获取场景时收到的机器人状态,复制进这次检查请求 validity_request->robot_state = response->scene.robot_state; validity_request->group_name = "arm"; auto validity_future = validity_client->async_send_request(validity_request); auto validity_status = rclcpp::spin_until_future_complete( node,validity_future,std::chrono::second(5)); if(validity_status != rclcpp::FutureReturnCode::SUCCESS) { RCLCPP_ERROR(node->get_logger(),"Failed to receive validity result."); rclcpp::shutdown; return 1; } auto validity_response = validity_future.get(); if(validity_response->valid) { RCLCPP_INFO(node->get_logger(),"State check PASSED"); } else { RCLCPP_WARN(node->get_logger(),"State check FAILED"); } RCLCPP_INFO( node->get_logger(), "Returned contact count: %zu", validity_response->contacts.sizes() ); rclcpp::shutdown(); return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 23:40:13

矩规评级与其他专利评价体系的核心区别

矩规评级与其他专利评价体系的核心区别&#xff0c;是它跳过了传统体系“评货币价值”的核心目标&#xff0c;直接聚焦“技术真伪判别”&#xff0c;从底层逻辑上重构了专利评估的切入视角‌。核心目标差异 矩规评级‌&#xff1a;核心目标不是给专利定出具体交易价格&#xff…

作者头像 李华
网站建设 2026/10/8 23:39:47

YOLOv8n通道剪枝实战:剪枝率0.4时参数量降至1.41M(降低53%),mAP仍保持83.7%

一、引言:当YOLOv8n遇上边缘设备 如果你正在用YOLOv8n做目标检测,可能已经注意到一个事实:3.01M参数、8.2 GFLOPs的计算量,在PC端跑得飞起,但一旦要把模型部署到树莓派、Jetson Nano或者国产NPU上,问题就来了。模型体积动辄十几MB,推理延迟轻松突破50ms,实时性根本无法…

作者头像 李华
网站建设 2026/10/8 23:39:36

具身智能开发策略详解(16):TVA与World协同的知识积累机制

前沿技术探索&#xff1a;TVA智能体&#xff08;简称TVA&#xff09;TVA智能体&#xff08;亦称“AI智能体视觉”或“TVA视觉智能体”&#xff09;是依托Transformer架构与“因式智能体”理论构建的通用视觉技术体系。它有机融合深度强化学习&#xff08;DRL&#xff09;、卷积…

作者头像 李华
网站建设 2026/10/8 23:38:48

DGX Spark UMM:Qwen3.8-Flash-Next端侧内存调度实战

1. 这不是“跑通就行”的端侧部署&#xff0c;而是内存墙下的精密交响 你手头有一台DGX工作站&#xff0c;刚拉下来Qwen3.8-Flash-Next的模型权重&#xff0c;准备在本地跑个推理demo——结果 torch.cuda.memory_allocated() 一查&#xff0c;显存占用直接飙到92%&#xff0…

作者头像 李华
网站建设 2026/10/8 23:29:18

OpenAkita完整入门:5分钟搭建你的多智能体AI助手终极指南

OpenAkita完整入门&#xff1a;5分钟搭建你的多智能体AI助手终极指南 【免费下载链接】openakita An open-source AI assistant framework with skills and agent architecture 项目地址: https://gitcode.com/gh_mirrors/op/openakita OpenAkita 是一款开源的多智能体 …

作者头像 李华
网站建设 2026/10/8 23:24:53

24V工业板电源保护设计:eFuse与MCU协同的完整方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华