OpenClaw 机器人抓取平台搭建全流程详解(万字长文解析)
前言
OpenClaw 是一个开源的机器人抓取仿真平台,基于 ROS (Robot Operating System) 和 Gazebo 仿真环境。本文将详细讲解如何在 Ubuntu 系统上完整搭建 OpenClaw 开发环境,并进行基础的抓取仿真测试。
一、环境准备与系统配置
1.1 硬件和软件要求
在开始搭建之前,需要确保您的系统满足以下要求:
硬件配置:
- CPU:Intel i5 或同等性能以上
- 内存:至少 8GB(推荐 16GB)
- 硬盘:至少 50GB 可用空间
- 显卡:支持 OpenGL 3.3+ 的独立显卡(推荐)
软件环境:
- 操作系统:Ubuntu 20.04 LTS 或 22.04 LTS
- ROS 版本:ROS Noetic(Ubuntu 20.04)或 ROS2 Humble(Ubuntu 22.04)
1.2 安装 Ubuntu 系统
如果您还没有安装 Ubuntu 系统,请按照以下步骤操作:
bash
# 1. 下载 Ubuntu 20.04 LTS 镜像 # 访问 https://ubuntu.com/download 下载 ISO 文件 # 2. 制作启动U盘(在 Windows 下使用 Rufus,在 Linux 下使用) sudo dd if=ubuntu-20.04.6-desktop-amd64.iso of=/dev/sdb bs=4M status=progress # 3. 重启电脑,从U盘启动,按照图形界面提示完成安装
1.3 系统基础配置
安装完 Ubuntu 后,进行基础配置:
bash
# 更新软件源 sudo apt update sudo apt upgrade -y # 安装基础开发工具 sudo apt install -y \ build-essential \ cmake \ git \ vim \ curl \ wget \ net-tools \ htop \ terminator # 推荐使用 Terminator 作为终端,支持分屏
二、ROS 环境搭建
2.1 ROS Noetic 完整安装
bash
# 步骤1:设置 sources.list sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' # 步骤2:添加密钥 sudo apt install curl curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - # 步骤3:安装 ROS sudo apt update sudo apt install ros-noetic-desktop-full # 步骤4:初始化 rosdep sudo rosdep init rosdep update # 步骤5:设置环境变量 echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc source ~/.bashrc # 步骤6:安装依赖工具 sudo apt install python3-rosinstall python3-rosinstall-generator python3-wstool
2.2 验证 ROS 安装
bash
# 测试 ROS 是否安装成功 # 终端1:启动 ROS 核心 roscore # 终端2:运行小海龟仿真 rosrun turtlesim turtlesim_node # 终端3:控制小海龟 rosrun turtlesim turtle_teleop_key # 如果能正常显示和控制小海龟,说明 ROS 安装成功
2.3 安装 Gazebo 仿真环境
bash
# 安装 Gazebo 11(与 ROS Noetic 兼容) sudo apt install -y \ gazebo11 \ libgazebo11-dev \ ros-noetic-gazebo-ros-pkgs \ ros-noetic-gazebo-ros-control \ ros-noetic-gazebo-plugins # 验证 Gazebo 安装 gazebo --version # 应显示 Gazebo multi-robot simulator, version 11.x.x
三、创建工作空间
3.1 Catkin 工作空间概念
Catkin 是 ROS 的官方构建系统,工作空间是开发 ROS 项目的目录结构:
text
openclaw_ws/ # 工作空间根目录 ├── src/ # 源代码目录 │ ├── CMakeLists.txt # 顶层 CMake 配置(自动生成) │ ├── openclaw/ # OpenClaw 主包 │ ├── openclaw_msgs/ # 消息定义包 │ ├── openclaw_description/# 机器人描述包 │ ├── openclaw_control/ # 控制器包 │ └── openclaw_gazebo/ # Gazebo 仿真包 ├── build/ # 编译中间文件(自动生成) ├── devel/ # 开发文件(自动生成) │ ├── setup.bash # 工作空间环境变量 │ └── lib/ # 编译生成的库文件 └── install/ # 安装文件(可选)
3.2 创建工作空间
bash
# 创建目录结构 mkdir -p ~/openclaw_ws/src cd ~/openclaw_ws # 初始化工作空间 catkin_make # 首次编译后,会自动生成 build 和 devel 目录 ls -la # 应该看到:build devel src # 设置工作空间环境变量 echo "source ~/openclaw_ws/devel/setup.bash" >> ~/.bashrc source ~/.bashrc # 验证工作空间是否被识别 echo $ROS_PACKAGE_PATH # 输出应包含:/home/用户名/openclaw_ws/src:/opt/ros/noetic/share
四、获取 OpenClaw 源代码
4.1 创建代码仓库结构
由于 OpenClaw 可能是一个特定的项目,我们需要创建标准的 ROS 包结构:
bash
# 进入源代码目录 cd ~/openclaw_ws/src # 创建 OpenClaw 相关的功能包 # 1. 创建主功能包 catkin_create_pkg openclaw \ roscpp \ rospy \ std_msgs \ geometry_msgs \ sensor_msgs \ control_msgs \ trajectory_msgs # 2. 创建消息定义包 catkin_create_pkg openclaw_msgs \ std_msgs \ geometry_msgs \ message_generation \ message_runtime # 3. 创建机器人描述包 catkin_create_pkg openclaw_description \ urdf \ xacro \ robot_state_publisher \ joint_state_publisher \ rviz # 4. 创建控制器包 catkin_create_pkg openclaw_control \ roscpp \ controller_manager \ joint_trajectory_controller \ position_controllers \ velocity_controllers \ effort_controllers # 5. 创建 Gazebo 仿真包 catkin_create_pkg openclaw_gazebo \ gazebo_ros \ gazebo_ros_control \ gazebo_plugins \ hector_gazebo_plugins
4.2 如果 OpenClaw 已有代码仓库
bash
# 如果 OpenClaw 有 GitHub 仓库,直接克隆 cd ~/openclaw_ws/src # 克隆主仓库 git clone https://github.com/yourusername/openclaw.git # 克隆其他依赖仓库 git clone https://github.com/yourusername/openclaw_msgs.git git clone https://github.com/yourusername/openclaw_description.git git clone https://github.com/yourusername/openclaw_control.git git clone https://github.com/yourusername/openclaw_gazebo.git git clone https://github.com/yourusername/openclaw_examples.git
五、设计机器人模型
5.1 URDF/XACRO 模型详解
URDF (Unified Robot Description Format) 是 ROS 中描述机器人模型的 XML 格式。我们将创建一个三指夹爪模型:
xml
<!-- ~/openclaw_ws/src/openclaw_description/urdf/claw.xacro --> <?xml version="1.0"?> <robot name="openclaw" xmlns:xacro="http://www.ros.org/wiki/xacro"> <!-- 定义可配置参数 --> <xacro:property name="PI" value="3.1415926535897931"/> <xacro:property name="base_width" value="0.1"/> <xacro:property name="base_height" value="0.05"/> <xacro:property name="finger_length" value="0.15"/> <xacro:property name="finger_width" value="0.02"/> <!-- 材料定义 --> <material name="black"> <color rgba="0.0 0.0 0.0 1.0"/> </material> <material name="red"> <color rgba="1.0 0.0 0.0 1.0"/> </material> <material name="blue"> <color rgba="0.0 0.0 1.0 1.0"/> </material> <!-- 1. 基座链接 --> <link name="base_link"> <visual> <geometry> <box size="${base_width} ${base_width} ${base_height}"/> </geometry> <origin rpy="0 0 0" xyz="0 0 0"/> <material name="black"/> </visual> <collision> <geometry> <box size="${base_width} ${base_width} ${base_height}"/> </geometry> </collision> <inertial> <mass value="0.5"/> <inertia ixx="0.001" ixy="0" ixz="0" iyy="0.001" iyz="0" izz="0.001"/> </inertial> </link> <!-- 2. 手指链接 - 左指 --> <link name="left_finger"> <visual> <geometry> <box size="${finger_width} ${finger_length} ${finger_width}"/> </geometry> <origin rpy="0 0 0" xyz="0 ${finger_length/2} 0"/> <material name="red"/> </visual> <collision> <geometry> <box size="${finger_width} ${finger_length} ${finger_width}"/> </geometry> </collision> <inertial> <mass value="0.1"/> <inertia ixx="0.0001" ixy="0" ixz="0" iyy="0.0001" iyz="0" izz="0.0001"/> </inertial> </link> <!-- 3. 手指链接 - 右指 --> <link name="right_finger"> <visual> <geometry> <box size="${finger_width} ${finger_length} ${finger_width}"/> </geometry> <origin rpy="0 0 0" xyz="0 ${finger_length/2} 0"/> <material name="blue"/> </visual> <collision> <geometry> <box size="${finger_width} ${finger_length} ${finger_width}"/> </geometry> </collision> <inertial> <mass value="0.1"/> <inertia ixx="0.0001" ixy="0" ixz="0" iyy="0.0001" iyz="0" izz="0.0001"/> </inertial> </link> <!-- 4. 定义关节 - 左指关节 --> <joint name="left_finger_joint" type="revolute"> <parent link="base_link"/> <child link="left_finger"/> <origin xyz="-${base_width/4} ${base_height/2} 0" rpy="0 0 0"/> <axis xyz="0 0 1"/> <limit effort="10" velocity="1" lower="-0.5" upper="0.5"/> <dynamics damping="0.1" friction="0.01"/> </joint> <!-- 5. 定义关节 - 右指关节 --> <joint name="right_finger_joint" type="revolute"> <parent link="base_link"/> <child link="right_finger"/> <origin xyz="${base_width/4} ${base_height/2} 0" rpy="0 0 0"/> <axis xyz="0 0 1"/> <limit effort="10" velocity="1" lower="-0.5" upper="0.5"/> <dynamics damping="0.1" friction="0.01"/> </joint> <!-- 添加传动系统,用于 Gazebo 控制 --> <transmission name="left_finger_trans"> <type>transmission_interface/SimpleTransmission</type> <joint name="left_finger_joint"> <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface> </joint> <actuator name="left_finger_motor"> <mechanicalReduction>1</mechanicalReduction> </actuator> </transmission> <transmission name="right_finger_trans"> <type>transmission_interface/SimpleTransmission</type> <joint name="right_finger_joint"> <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface> </joint> <actuator name="right_finger_motor"> <mechanicalReduction>1</mechanicalReduction> </actuator> </transmission> <!-- 添加 Gazebo 插件,用于仿真 --> <gazebo> <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so"> <robotNamespace>/openclaw</robotNamespace> </plugin> </gazebo> </robot>
5.2 创建启动文件
xml
<!-- ~/openclaw_ws/src/openclaw_description/launch/display.launch --> <?xml version="1.0"?> <launch> <!-- 参数设置 --> <arg name="model" default="$(find openclaw_description)/urdf/claw.xacro"/> <arg name="gui" default="true"/> <arg name="rvizconfig" default="$(find openclaw_description)/rviz/urdf.rviz"/> <!-- 解析 URDF 模型 --> <param name="robot_description" command="$(find xacro)/xacro '$(arg model)'" /> <!-- 启动 robot_state_publisher,发布 tf 变换 --> <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"> <param name="publish_frequency" value="50.0"/> </node> <!-- 启动 joint_state_publisher,发布关节状态 --> <node name="joint_state_publisher_gui" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui" if="$(arg gui)"/> <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" unless="$(arg gui)"/> <!-- 启动 RViz 可视化 --> <node name="rviz" pkg="rviz" type="rviz" args="-d $(arg rvizconfig)" required="true"/> </launch>
六、配置控制器
6.1 控制器配置文件
yaml
# ~/openclaw_ws/src/openclaw_control/config/control.yaml openclaw: # 关节控制器配置 joint_state_controller: type: joint_state_controller/JointStateController publish_rate: 50 # 左指位置控制器 left_finger_position_controller: type: position_controllers/JointPositionController joint: left_finger_joint pid: {p: 100.0, i: 0.01, d: 10.0} # 右指位置控制器 right_finger_position_controller: type: position_controllers/JointPositionController joint: right_finger_joint pid: {p: 100.0, i: 0.01, d: 10.0} # 夹爪轨迹控制器(用于同时控制两个手指) gripper_controller: type: position_controllers/JointTrajectoryController joints: - left_finger_joint - right_finger_joint constraints: goal_time: 0.5 stopped_velocity_tolerance: 0.05 stop_trajectory_duration: 0.5 state_publish_rate: 25 action_monitor_rate: 10
6.2 控制器启动文件
xml
<!-- ~/openclaw_ws/src/openclaw_control/launch/control.launch --> <?xml version="1.0"?> <launch> <!-- 加载控制器配置 --> <rosparam file="$(find openclaw_control)/config/control.yaml" command="load"/> <!-- 加载机器人描述 --> <param name="robot_description" command="$(find xacro)/xacro '$(find openclaw_description)/urdf/claw.xacro'"/> <!-- 启动 controller_manager 和控制器 --> <node name="controller_spawner" pkg="controller_manager" type="spawner" output="screen" args=" joint_state_controller left_finger_position_controller right_finger_position_controller gripper_controller "/> <!-- 启动 robot_state_publisher --> <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"/> <!-- 启动关节状态GUI(可选) --> <node name="joint_state_publisher_gui" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui"/> </launch>
七、配置 Gazebo 仿真环境
7.1 Gazebo 世界文件
xml
<!-- ~/openclaw_ws/src/openclaw_gazebo/worlds/grasping.world --> <?xml version="1.0" ?> <sdf version="1.6"> <world name="grasping_world"> <!-- 全局光照 --> <include> <uri>model://sun</uri> </include> <!-- 地面 --> <include> <uri>model://ground_plane</uri> </include> <!-- 添加桌子 --> <model name="table"> <pose>0 0 0 0 0 0</pose> <static>true</static> <link name="link"> <collision name="collision"> <geometry> <box> <size>1.0 1.0 0.1</size> </box> </geometry> </collision> <visual name="visual"> <geometry> <box> <size>1.0 1.0 0.1</size> </box> </geometry> <material> <ambient>0.5 0.5 0.5 1</ambient> <diffuse>0.8 0.8 0.8 1</diffuse> </material> </visual> </link> </model> <!-- 添加被抓取物体 - 立方体 --> <model name="cube"> <pose>0 0 0.05 0 0 0</pose> <link name="link"> <inertial> <mass>0.1</mass> <inertia> <ixx>0.0001</ixx> <ixy>0</ixy> <ixz>0</ixz> <iyy>0.0001</iyy> <iyz>0</iyz> <izz>0.0001</izz> </inertia> </inertial> <collision name="collision"> <geometry> <box> <size>0.05 0.05 0.05</size> </box> </geometry> </collision> <visual name="visual"> <geometry> <box> <size>0.05 0.05 0.05</size> </box> </geometry> <material> <ambient>1 0 0 1</ambient> <diffuse>1 0 0 1</diffuse> </material> </visual> </link> </model> <!-- 添加球体 --> <model name="sphere"> <pose>0.2 0 0.05 0 0 0</pose> <link name="link"> <inertial> <mass>0.1</mass> <inertia> <ixx>0.0001</ixx> <ixy>0</ixy> <ixz>0</ixz> <iyy>0.0001</iyy> <iyz>0</iyz> <izz>0.0001</izz> </inertia> </inertial> <collision name="collision"> <geometry> <sphere> <radius>0.025</radius> </sphere> </geometry> </collision> <visual name="visual"> <geometry> <sphere> <radius>0.025</radius> </sphere> </geometry> <material> <ambient>0 1 0 1</ambient> <diffuse>0 1 0 1</diffuse> </material> </visual> </link> </model> </world> </sdf>
7.2 Gazebo 启动文件
xml
<!-- ~/openclaw_ws/src/openclaw_gazebo/launch/gazebo.launch --> <?xml version="1.0"?> <launch> <!-- 参数设置 --> <arg name="paused" default="false"/> <arg name="use_sim_time" default="true"/> <arg name="gui" default="true"/> <arg name="headless" default="false"/> <arg name="debug" default="false"/> <arg name="world" default="$(find openclaw_gazebo)/worlds/grasping.world"/> <!-- 加载机器人描述 --> <param name="robot_description" command="$(find xacro)/xacro '$(find openclaw_description)/urdf/claw.xacro'"/> <!-- 启动 Gazebo 服务器 --> <include file="$(find gazebo_ros)/launch/empty_world.launch"> <arg name="world_name" value="$(arg world)"/> <arg name="paused" value="$(arg paused)"/> <arg name="use_sim_time" value="$(arg use_sim_time)"/> <arg name="gui" value="$(arg gui)"/> <arg name="headless" value="$(arg headless)"/> <arg name="debug" value="$(arg debug)"/> </include> <!-- 在 Gazebo 中生成机器人 --> <node name="spawn_urdf" pkg="gazebo_ros" type="spawn_model" args="-param robot_description -urdf -model openclaw -x 0 -y 0 -z 0.1"/> <!-- 启动控制器 --> <include file="$(find openclaw_control)/launch/control.launch"/> </launch>
八、编写抓取控制程序
8.1 Python 控制脚本
python
#!/usr/bin/env python3 # ~/openclaw_ws/src/openclaw_examples/scripts/grasp_object.py import rospy import actionlib from control_msgs.msg import FollowJointTrajectoryAction, FollowJointTrajectoryGoal from trajectory_msgs.msg import JointTrajectoryPoint from std_msgs.msg import Float64 import sys import time class OpenClawGraspController: """OpenClaw 抓取控制器""" def __init__(self): # 初始化 ROS 节点 rospy.init_node('openclaw_grasp_controller', anonymous=True) # 定义关节名称 self.left_finger_joint = 'left_finger_joint' self.right_finger_joint = 'right_finger_joint' # 创建发布者(用于直接控制单个关节) self.left_finger_pub = rospy.Publisher( '/openclaw/left_finger_position_controller/command', Float64, queue_size=10 ) self.right_finger_pub = rospy.Publisher( '/openclaw/right_finger_position_controller/command', Float64, queue_size=10 ) # 创建动作客户端(用于轨迹控制) self.client = actionlib.SimpleActionClient( '/openclaw/gripper_controller/follow_joint_trajectory', FollowJointTrajectoryAction ) # 等待服务器启动 rospy.loginfo("等待控制器服务器...") self.client.wait_for_server() rospy.loginfo("控制器服务器已连接") # 等待一段时间确保所有组件就绪 rospy.sleep(1.0) def open_gripper(self): """打开夹爪""" rospy.loginfo("打开夹爪") # 方法1:使用单个关节发布器 self.left_finger_pub.publish(-0.5) # 左指向外打开 self.right_finger_pub.publish(0.5) # 右指向外打开 # 等待动作完成 rospy.sleep(2.0) def close_gripper(self): """闭合夹爪""" rospy.loginfo("闭合夹爪") # 方法1:使用单个关节发布器 self.left_finger_pub.publish(0.5) # 左指向内闭合 self.right_finger_pub.publish(-0.5) # 右指向内闭合 # 等待动作完成 rospy.sleep(2.0) def grasp_object(self, force=0.3): """抓取物体(带力控制)""" rospy.loginfo("开始抓取物体,力度: %.2f", force) # 逐步闭合夹爪 steps = 10 for i in range(steps): # 计算当前角度(从打开到闭合) left_angle = -0.5 + (i / steps) * 1.0 # -0.5 到 0.5 right_angle = 0.5 - (i / steps) * 1.0 # 0.5 到 -0.5 # 发布关节角度 self.left_finger_pub.publish(left_angle) self.right_finger_pub.publish(right_angle) # 等待一小段时间 rospy.sleep(0.1) rospy.loginfo("抓取完成") def release_object(self): """释放物体""" rospy.loginfo("释放物体") self.open_gripper() def trajectory_grasp(self): """使用轨迹控制进行抓取(更平滑的运动)""" rospy.loginfo("使用轨迹控制进行抓取") # 创建目标 goal = FollowJointTrajectoryGoal() goal.trajectory.joint_names = [ self.left_finger_joint, self.right_finger_joint ] # 定义轨迹点 # 点1:打开位置 point1 = JointTrajectoryPoint() point1.positions = [-0.5, 0.5] # [左指, 右指] point1.time_from_start = rospy.Duration(1.0) # 点2:闭合位置 point2 = JointTrajectoryPoint() point2.positions = [0.5, -0.5] point2.time_from_start = rospy.Duration(3.0) # 添加点到轨迹 goal.trajectory.points.append(point1) goal.trajectory.points.append(point2) # 发送目标 self.client.send_goal(goal) # 等待结果 self.client.wait_for_result() # 获取结果 result = self.client.get_result() rospy.loginfo("轨迹执行结果: %s", result) def multi_stage_grasp(self): """多阶段抓取策略""" rospy.loginfo("执行多阶段抓取") # 阶段1:预抓取位置(稍微打开) rospy.loginfo("阶段1:预抓取位置") self.left_finger_pub.publish(-0.3) self.right_finger_pub.publish(0.3) rospy.sleep(1.0) # 阶段2:缓慢接近 rospy.loginfo("阶段2:接近物体") for angle in [-0.4, -0.2, 0.0, 0.2]: self.left_finger_pub.publish(angle) self.right_finger_pub.publish(-angle) rospy.sleep(0.5) # 阶段3:施加抓取力 rospy.loginfo("阶段3:施加抓取力") self.left_finger_pub.publish(0.4) self.right_finger_pub.publish(-0.4) rospy.sleep(1.0) # 阶段4:保持抓取 rospy.loginfo("阶段4:保持抓取") rospy.sleep(2.0) # 阶段5:释放 rospy.loginfo("阶段5:释放") self.open_gripper() def main(): """主函数""" try: # 创建控制器实例 controller = OpenClawGraspController() # 获取命令行参数 if len(sys.argv) > 1: mode = sys.argv[1] else: mode = "simple" rospy.loginfo("执行模式: %s", mode) # 根据不同模式执行抓取 if mode == "simple": # 简单抓取 controller.open_gripper() rospy.sleep(1.0) controller.close_gripper() rospy.sleep(1.0) controller.open_gripper() elif mode == "grasp": # 抓取物体 controller.open_gripper() rospy.sleep(1.0) controller.grasp_object(force=0.5) rospy.sleep(2.0) controller.release_object() elif mode == "trajectory": # 轨迹抓取 controller.trajectory_grasp() elif mode == "multistage": # 多阶段抓取 controller.multi_stage_grasp() else: rospy.loginfo("未知模式,使用默认模式") controller.open_gripper() rospy.sleep(1.0) controller.close_gripper() rospy.loginfo("抓取演示完成") except rospy.ROSInterruptException: rospy.loginfo("程序被中断") except Exception as e: rospy.logerr("发生错误: %s", str(e)) if __name__ == '__main__': main()
8.2 创建启动文件
xml
<!-- ~/openclaw_ws/src/openclaw_examples/launch/demo.launch --> <?xml version="1.0"?> <launch> <!-- 启动 Gazebo 仿真 --> <include file="$(find openclaw_gazebo)/launch/gazebo.launch"/> <!-- 启动抓取演示节点 --> <node name="grasp_demo" pkg="openclaw_examples" type="grasp_object.py" output="screen" required="true"> <!-- 可以传递参数 --> <param name="grasp_force" value="0.5"/> <param name="grasp_speed" value="0.1"/> </node> <!-- 可选:启动 RViz 可视化 --> <node name="rviz" pkg="rviz" type="rviz" args="-d $(find openclaw_description)/rviz/openclaw.rviz"/> </launch>
九、编译和运行
9.1 编译工作空间
bash
# 返回工作空间根目录 cd ~/openclaw_ws # 安装依赖 rosdep install --from-paths src --ignore-src -r -y # 编译(使用4个线程) catkin_make -j4 # 如果编译出错,可以尝试单线程编译以便查看详细错误 catkin_make -j1 # 编译特定包 catkin_make --only-pkg-with-deps openclaw_control # 清理并重新编译 catkin_make clean catkin_make
9.2 运行仿真
bash
# 终端1:启动 Gazebo 仿真 source ~/openclaw_ws/devel/setup.bash roslaunch openclaw_gazebo gazebo.launch # 终端2:运行抓取演示 source ~/openclaw_ws/devel/setup.bash rosrun openclaw_examples grasp_object.py simple # 或者使用不同模式 rosrun openclaw_examples grasp_object.py grasp rosrun openclaw_examples grasp_object.py trajectory rosrun openclaw_examples grasp_object.py multistage
9.3 使用 RViz 可视化
bash
# 终端:启动 RViz source ~/openclaw_ws/devel/setup.bash rosrun rviz rviz # 在 RViz 中配置: # 1. 添加 RobotModel 显示机器人模型 # 2. 添加 TF 显示坐标变换 # 3. 添加 Image 显示摄像头图像(如果有)
十、调试和监控
10.1 查看 ROS 信息
bash
# 查看所有节点 rosnode list # 查看所有话题 rostopic list # 查看所有服务 rosservice list # 查看所有参数 rosparam list # 查看特定话题内容 rostopic echo /openclaw/joint_states # 查看特定话题发布频率 rostopic hz /openclaw/joint_states # 查看话题带宽 rostopic bw /openclaw/joint_states
10.2 使用 rqt 工具
bash
# 启动 rqt 图形界面 rqt # 常用插件: # - rqt_graph:查看节点间关系 # - rqt_plot:实时绘制数据 # - rqt_console:查看日志 # - rqt_tf_tree:查看 TF 树 # 单独启动特定工具 rqt_graph rqt_plot /openclaw/joint_states/position[0]
10.3 记录和回放数据
bash
# 记录所有话题到 bag 文件 rosbag record -a -o grasp_demo.bag # 记录特定话题 rosbag record /openclaw/joint_states /openclaw/gripper_controller/state # 查看 bag 信息 rosbag info grasp_demo.bag # 回放 bag 文件 rosbag play grasp