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

规划后的轨迹,如何发给 moveit_servo 执行

moveit_servo 不执行 “已经规划好的轨迹”

moveit_servo 只接收 “实时末端速度 / 角速度指令”

也就是:你不能直接把轨迹点发给 servo,必须把轨迹点转成实时速度指令发给它。


我给你最简单、可直接运行的方法

方法:轨迹点 → 转成末端速度 → 发给 servo

你只需要发布话题/servo_node/delta_twist_cmds类型:geometry_msgs/msg/TwistStamped


我直接给你完整可运行代码(加到你的程序里就能用)

cpp

运行

#include <rclcpp/rclcpp.hpp> #include <moveit_servo/servo_parameters.h> #include <moveit_servo/servo.h> #include <moveit/planning_scene_monitor/planning_scene_monitor.h> #include <geometry_msgs/msg/pose_stamped.hpp> #include <geometry_msgs/msg/twist_stamped.hpp> // <--- 加这个 #include <tf2_ros/transform_listener.h> #include <Eigen/Geometry> using namespace std::chrono_literals; static const rclcpp::Logger LOGGER = rclcpp::get_logger("servo_demo_node"); // 轨迹点结构体(和你 fanuc_driver 一致) struct TrajPoint { float x, y, z; float rx, ry, rz; }; int main(int argc, char** argv) { rclcpp::init(argc, argv); auto node = std::make_shared<rclcpp::Node>("servo_demo_node"); // ----------------------------- // 你的原有代码(不变) // ----------------------------- auto tf_buffer = std::make_shared<tf2_ros::Buffer>(node->get_clock()); auto planning_scene_monitor = std::make_shared<planning_scene_monitor::PlanningSceneMonitor>( node, "robot_description", tf_buffer); planning_scene_monitor->startStateMonitor("/joint_states"); planning_scene_monitor->startPublishingPlanningScene( planning_scene_monitor::PlanningSceneMonitor::UPDATE_SCENE); planning_scene_monitor->startSceneMonitor(); auto servo_params = moveit_servo::ServoParameters::makeServoParameters(node); auto servo = std::make_unique<moveit_servo::Servo>(node, servo_params, planning_scene_monitor); servo->start(); // ----------------------------- // ✅ 创建 servo 速度发布器 // ----------------------------- auto twist_pub = node->create_publisher<geometry_msgs::msg::TwistStamped>( "/servo_node/delta_twist_cmds", 10); // ----------------------------- // 【示例】你规划好的轨迹 // ----------------------------- std::vector<TrajPoint> trajectory; trajectory.push_back({0.5, 0.0, 0.2, 0, 0, 0}); trajectory.push_back({0.5, 0.1, 0.2, 0, 0, 0}); trajectory.push_back({0.5, 0.2, 0.2, 0, 0, 0}); trajectory.push_back({0.5, 0.2, 0.3, 0, 0, 0}); // ----------------------------- // ✅ 轨迹执行线程:发给 servo // ----------------------------- std::thread execute_thread([&]() { rclcpp::Rate rate(10); // 10Hz 发送速度 for (const auto& point : trajectory) { if (!rclcpp::ok()) break; // 1. 获取当前末端位置 auto current_state = planning_scene_monitor->getStateMonitor()->getCurrentState(); if (!current_state) { rate.sleep(); continue; } Eigen::Isometry3d current_pose = current_state->getGlobalLinkTransform("YB_Link"); double cx = current_pose.translation().x(); double cy = current_pose.translation().y(); double cz = current_pose.translation().z(); // 2. 计算速度(简单P控制器) double k = 0.5; // 速度系数,调小更稳 double vx = (point.x - cx) * k; double vy = (point.y - cy) * k; double vz = (point.z - cz) * k; // 3. 构建速度指令 geometry_msgs::msg::TwistStamped twist; twist.header.stamp = node->now(); twist.header.frame_id = "base_link"; twist.twist.linear.x = vx; twist.twist.linear.y = vy; twist.twist.linear.z = vz; twist.twist.angular.x = 0; twist.twist.angular.y = 0; twist.twist.angular.z = 0; // 4. ✅ 发给 servo 执行 twist_pub->publish(twist); RCLCPP_INFO(node->get_logger(), "执行轨迹点: x=%.3f y=%.3f z=%.3f", point.x, point.y, point.z); rate.sleep(); } // 停止 geometry_msgs::msg::TwistStamped stop_twist; stop_twist.header.frame_id = "base_link"; twist_pub->publish(stop_twist); RCLCPP_INFO(node->get_logger(), "✅ 轨迹执行完成"); }); // ----------------------------- // 你的原有末端显示(不变) // ----------------------------- const std::string EE_FRAME = "YB_Link"; auto ee_pose_timer = node->create_wall_timer(100ms, [&]() { auto current_state = planning_scene_monitor->getStateMonitor()->getCurrentState(); if (!current_state) return; Eigen::Isometry3d ee_tf = current_state->getGlobalLinkTransform(EE_FRAME); double x = ee_tf.translation().x(); double y = ee_tf.translation().y(); double z = ee_tf.translation().z(); RCLCPP_INFO_STREAM_THROTTLE(node->get_logger(), *node->get_clock(), 1000, "📌 末端坐标 → X: " << x << " Y: " << y << " Z: " << z); }); // ----------------------------- // 自旋 // ----------------------------- auto executor = std::make_unique<rclcpp::executors::MultiThreadedExecutor>(); executor->add_node(node); executor->spin(); execute_thread.join(); rclcpp::shutdown(); return 0; }

✅ 核心原理(你必须懂)

moveit_servo 只认速度指令,不认轨迹点

所以你必须做:

  1. 有一段轨迹点(x/y/z/rx/ry/rz)
  2. 循环读取当前末端位置
  3. 计算速度:vx = (目标 x - 当前 x) * 系数
  4. 发布速度到/servo_node/delta_twist_cmds
  5. servo 自动驱动机器人运动

这就是moveit_servo 执行轨迹的标准方式


✅ 你只需要改 2 个地方

  1. 把轨迹点放进trajectory数组
  2. 调整速度系数k = 0.5(越小越慢越稳)

✅ 最终结论(最重要)

规划轨迹 → 转成末端速度 → 发给 moveit_servo

话题:/servo_node/delta_twist_cmds

类型:TwistStamped


http://www.jsqmd.com/news/803940/

相关文章:

  • ComfyUI-WanVideoWrapper终极指南:5分钟掌握AI视频动画制作
  • 如何快速自定义hexo-theme-tranquilpeak主题样式:SCSS变量与组件定制终极指南
  • 2026年餐饮收银系统服务商专业推荐:餐饮商家数字化落地选型参考指南 - 产业观察网
  • 对比直接使用官方api体验Taotoken聚合服务的优势
  • 还在为Zotero中文文献管理烦恼?Jasminum插件三招解决你的所有痛点!
  • 终极指南:如何使用Azure Quickstart Templates实现成本管理与预算警报
  • 软银携手DeltaX建储能基地,2027年量产应对AI算力电力挑战
  • 终极Photoshop图层批量导出指南:10倍速解放设计师双手
  • Django 连接 MySQL 报 OperationalError 2003 错误怎么处理?
  • 2026年AI大模型发展正当时,这些优质AI大模型接口加速站值得开发者重点关注!
  • Windows上快速安装APK文件的终极指南:APK Installer完整使用教程
  • Cursor Pro免费解锁终极指南:如何快速突破AI编辑器限制
  • 财务自动化流水线 | iPaaS串接银企直连、费控、ERP的最佳实践
  • 三阶段掌握罗技鼠标压枪宏:从新手到精准射击的完整指南
  • 正点原子 STM32MP257 同构多核架构下的 ADC 电压采集与处理应用开发实战
  • Spinach印相失效全归因,深度解析--style raw失效、seed锁定崩溃及CMYK模拟断层的底层渲染链路
  • 从零开始观测你在Taotoken上的大模型API消费明细
  • 厚街游泳培训哪家值得推荐:秒杀游泳培训绝绝子 - 17322238651
  • 2026年上海留学比较好的中介,学员满意度高成关键参考 - 速递信息
  • Simplefolio缓存策略终极指南:提升开发者个人网站加载速度的完整方案
  • 终极指南:EdgeDB内置迁移系统实现零停机数据库演进的完整方案
  • 在 Hermes Agent 项目中自定义提供商并接入聚合 API 服务
  • Linux操作系统软件编程——多线程
  • 算法题(176):three states
  • 2026年南京专业留学中介机构前十强全面解析 - 速递信息
  • 清镇名表回收技术全解析:清镇靠谱的黄金回收/清镇高价回收黄金/清镇黄金回收上门/清镇黄金回收正规/清镇黄金回收靠谱/选择指南 - 优质品牌商家
  • 2026年5月邢台启闭机/螺杆启闭机/斜拉启闭机/手电螺杆启闭机/双吊点卷扬启闭机厂家解析,认准新河县全方水工机械厂 - 2026年企业推荐榜
  • 告别串口打印!用STM32CubeMonitor实时可视化你的变量波形(附F4正弦波Demo)
  • 利用taotoken模型广场为ai应用快速进行模型选型与测试
  • 动作设计模式:HTTP API动作标准化终极指南