moveit2_servo 怎么接收相机调节指令(视觉伺服)

一、核心原理(一句话懂)

moveit2_servo 不吃 "轨迹",只吃 "速度增量指令" 相机 → 算出目标偏移 → 转成 TwistStamped(速度) → 发给 /servo_demo_node/delta_twist_cmdsmoveit2_servo 自动 IK + 避障 → 输出 /arm_controller/joint_trajectory

和你键盘控制完全同一路线,只是把键盘换成相机。


二、moveit2_servo 固定输入话题(必须记住)

ROS2 Humble + moveit2_servo 默认输入:

  • 笛卡尔(末端)指令: /servo_demo_node/delta_twist_cmds消息:geometry_msgs/TwistStamped

  • 关节指令: /servo_demo_node/delta_joint_cmds消息:moveit_msgs/JointJog

相机必须发 TwistStamped 到上面这个 topic!


三、相机 → moveit2_servo 完整流程(4 步)

1)相机输出:目标在相机坐标系的 3D 位姿

相机节点输出:

  • TF:camera_link → target
  • 或者话题:/target_pose(PoseStamped)

2)手眼标定(关键!)

必须知道:

  • base_link ↔ camera_link 的 TF(固定)
  • end_effector ↔ camera_link(眼在手上)

没有标定,坐标乱飘。

3)视觉 PID(把偏移 → 速度指令)

相机算出:

plaintext

复制代码
error_x, error_y, error_z (m)
error_rx, error_ry, error_rz (rad)

用简单 PID 转成 TwistStamped(速度)

plaintext

复制代码
linear.x  = Kp * error_x
linear.y  = Kp * error_y
linear.z  = Kp * error_z
angular.x = Kp * error_rx
...

4)发给 moveit2_servo(和你键盘完全一样)

ROS2 发布到:

plaintext

复制代码
/servo_demo_node/delta_twist_cmds

moveit2_servo 收到后:

  • 内部 IK
  • 碰撞检测
  • 限速
  • 输出:/arm_controller/joint_trajectory

四、直接可用的 ROS2 相机→servo 代码(极简)

python

运行

复制代码
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import TwistStamped, PoseStamped
from tf2_ros import TransformListener, Buffer
import math

class CameraToServo(Node):
    def __init__(self):
        super().__init__('camera_to_servo')
        # 发布给 servo
        self.pub = self.create_publisher(TwistStamped, '/servo_demo_node/delta_twist_cmds', 10)
        # 订阅相机目标位姿
        self.create_subscription(PoseStamped, '/target_pose', self.pose_cb, 10)

        self.tf_buffer = Buffer()
        self.tf_listener = TransformListener(self.tf_buffer, self)

        self.Kp = 0.5  # 速度增益,调这个

    def pose_cb(self, msg):
        try:
            # 把目标转到 base_link
            tf = self.tf_buffer.lookup_transform(
                'base_link', msg.header.frame_id, rclpy.time.Time()
            )
        except:
            return

        # 简化:直接拿误差做速度(PID你再加)
        err_x = msg.pose.position.x - tf.transform.translation.x
        err_y = msg.pose.position.y - tf.transform.translation.y
        err_z = msg.pose.position.z - tf.transform.translation.z

        twist = TwistStamped()
        twist.header.stamp = self.get_clock().now().to_msg()
        twist.header.frame_id = 'base_link'

        twist.twist.linear.x  = self.Kp * err_x
        twist.twist.linear.y  = self.Kp * err_y
        twist.twist.linear.z  = self.Kp * err_z
        # 旋转同理,这里省略

        self.pub.publish(twist)

def main():
    rclpy.init()
    Node = CameraToServo()
    rclpy.spin(Node)
    Node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

五、servo 参数必须开对(非常关键)

servo_params.yaml 确保:

yaml

复制代码
moveit_servo:
  ros__parameters:
    command_in_type: "twist_units"   # 接收Twist
    robot_link_command_frame: "base_link"  # 和相机统一
    scale:
      linear: 0.2   # 最大速度 m/s

六、最终数据流(你一眼看懂)

plaintext

复制代码
相机 → 目标位姿 → 视觉PID → TwistStamped
   ↓
/servo_demo_node/delta_twist_cmds
   ↓
moveit2_servo(IK+避障+限速)
   ↓
/arm_controller/joint_trajectory
   ↓
机械臂动
相关推荐
京和动物医院·总院2 分钟前
2026年未央区宠物医院:如何挑选最适合您爱宠的健康守护者
大数据·人工智能·python
液态不合群2 分钟前
AI×低代码工作流:破解制造业数字化流程异构困局
人工智能·低代码
武子康3 分钟前
Copilot Code Review 从固定 Reviewer 演进为可编程 Runtime,仓库控制面、Setup 供应链、Runner 资源和 MCP 工具同时被纳入审查决策
人工智能·github·aigc
吠品3 分钟前
五子棋AI对战功能实现与多难度策略设计
人工智能
刘小八4 分钟前
RAG 文档切分不是越细越好:选择 Chunk Size 与 Overlap
人工智能·python·语言模型
商业模式源码开发9 分钟前
2026年GEO优化全解析:生成式引擎优化如何重构企业流量与品牌护城河
大数据·人工智能·ai
变量未定义~20 分钟前
最小生成树1(Prim模板)、最小生成树2(kruskal模板)、最近公共祖先(模板)
算法
对讲机数码科普22 分钟前
黑龙江应急救援单工通信保障方案设计与实战应用
大数据·网络·人工智能
这就是佬们吗23 分钟前
Python入门⑤-异常处理、文件操作与实战项目
开发语言·数据库·python·算法·pycharm
SuperHeroWu725 分钟前
【HarmonyOS AI】DevEco CLI、Skills、知识库运用AI Coding提效详解
人工智能·华为·harmonyos