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
   ↓
机械臂动
相关推荐
viperrrrrrrrrr71 小时前
语音AI的2026:从“听见声音“到“理解世界“
人工智能·macos·语言模型
枫叶林FYL1 小时前
【机器学习与智慧医疗】2型糖尿病早期预警系统:当多参数集成模型学会“会诊“
大数据·人工智能
灵机一物1 小时前
灵机一物AI原生电商小程序、PC端(已上线)-从单人 10 天 3000 元 AI 爆款,拆解世界模型如何重构游戏与视频生产范式
人工智能
Agent产品评测局1 小时前
化工制造安全生产AI方案主流产品对比详解:2026工业大模型与端到端自动化选型指南
人工智能·安全·ai·chatgpt·制造
灰灰勇闯IT1 小时前
CANN Graph Engine 执行链路:一张计算图如何跑上昇腾 NPU
人工智能·深度学习·算法
前端不太难1 小时前
从点击到意图:鸿蒙 App 的 AI 进化
人工智能·状态模式·harmonyos
Data_Journal1 小时前
什么是数据采购,它究竟如何运作?
大数据·开发语言·数据库·人工智能·python
闵孚龙1 小时前
Claude Code 技能系统全解析:AI Agent 自定义能力、SKILL.md、MCP 扩展、上下文预算与企业级自动化落地
运维·人工智能·自动化
Gigavision1 小时前
SEED-VII 数据集介绍:面向七类情绪识别的 EEG 与眼动多模态数据集
人工智能·python·算法·脑机接口