从 URDF 建模到 Gazebo 仿真、控制器驱动、TF 坐标变换,完整走一遍搭建小车和机械臂的流程。
一、搭建四轮小车
启动命令速查
1 2 3 4 5 6 7 8
| roslaunch urdf_sim_tutorial gazebo.launch model:=rbo.urdf.xacro
roslaunch urdf_sim_tutorial display.launch model:=rbo.urdf.xacro
rostopic pub -r 30 /cmd_vel geometry_msgs/Twist -- '[1.0,0,0]' '[0,0,0.0]'
|
轮子建模(xacro 复用)
四个轮子结构完全相同,用 xacro 宏避免重复:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <xacro:macro name="wheel" params="name x y z"> <link name="wheel_${name}"> <visual> <geometry> <cylinder length="${wheel_length}" radius="${wheel_radius}"/> </geometry> <material name="Black"/> </visual> <collision> <geometry> <cylinder length="${wheel_length}" radius="${wheel_radius}"/> </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>
<joint name="joint_wheel_${name}" type="continuous"> <parent link="base_link"/> <child link="wheel_${name}"/> <origin xyz="${x} ${y} ${z}" rpy="0 0 0"/> <axis xyz="0 1 0"/> </joint> </xacro:macro>
<xacro:wheel name="LF" x="0.15" y="0.12" z="-0.05"/> <xacro:wheel name="RF" x="0.15" y="-0.12" z="-0.05"/> <xacro:wheel name="LR" x="-0.15" y="0.12" z="-0.05"/> <xacro:wheel name="RR" x="-0.15" y="-0.12" z="-0.05"/>
|
编写速度控制器
通过发布话题控制四轮速度:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <ros/ros.h> #include <std_msgs/Float64MultiArray.h>
int main(int argc, char **argv) { ros::init(argc, argv, "command_publisher"); ros::NodeHandle n; ros::Publisher pub = n.advertise<std_msgs::Float64MultiArray>( "/joint_group_velocity_controller/command", 10); ros::Rate loop_rate(10);
while (ros::ok()) { std_msgs::Float64MultiArray msg; msg.data = {1.0, 1.0, 1.0, 1.0}; pub.publish(msg); ros::spinOnce(); loop_rate.sleep(); } }
|
二、搭建机械臂(硬件接口示例)
与小车不同,机械臂需要通过硬件接口与真实/仿真电机通信。
硬件接口头文件骨架
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #include <hardware_interface/joint_command_interface.h> #include <hardware_interface/joint_state_interface.h> #include <hardware_interface/robot_hw.h> #include <controller_manager/controller_manager.h>
class ArmHWInterface : public hardware_interface::RobotHW { public: ArmHWInterface(); void read(const JointStateConstPtr &msg); void publishCmd();
private: hardware_interface::JointStateInterface jnt_state_interface; hardware_interface::PositionJointInterface jnt_cmd_interface; double cmd[5], pos[5], vel[5], eff[5]; };
|
关键流程
- 继承
hardware_interface::RobotHW
- 注册
JointStateInterface(状态读取)和 PositionJointInterface(指令下发)
- 实现
read() 从硬件/仿真读取关节状态
- 实现
write() 向硬件/仿真下发控制指令
三、ROS 与 STM32 通信
在机器人系统中,主控(树莓派/NUC)跑 ROS,STM32 负责底层电机控制。二者通信协议不同,需要串口转换芯片作为”翻译官”。
1 2 3 4
| ┌──────────┐ UART ┌──────────────┐ CAN/GPIO ┌──────────┐ │ ROS 主控 │ ←────────→ │ 串口转换芯片 │ ←───────────→ │ STM32 │ │ (NUC/Pi) │ │ (CH340/CP2102)│ │ (电机控制)│ └──────────┘ └──────────────┘ └──────────┘
|
软件层面,在 ROS 端通过串口节点收发数据即可。
四、TF2 坐标变换
TF2 管理机器人各部件之间的坐标系关系——知道激光雷达相对于底盘的位置、机械臂末端相对于基座的位置。
观察 TF 树
1 2
| rosrun tf2_tools view_frames.py evince frames.pdf
|
这会生成一张坐标系关系图,清晰展示各 link 的父子关系。
1 2 3 4
| rosrun tf tf_echo [reference_frame] [target_frame]
rosrun tf tf_echo base_link sensor_laser
|
小海龟 Demo
一个直观的 TF2 入门实验:
1 2
| sudo apt-get install ros-$ROS_DISTRO-turtle-tf2 ros-$ROS_DISTRO-tf2-tools ros-$ROS_DISTRO-tf roslaunch turtle_tf2 turtle_tf2_demo.launch
|
第二只海龟会自动跟随你操控的那只——这就是 TF 坐标变换在起作用。
常见安装问题
1 2 3 4 5 6 7 8
| sudo apt-get install python-yaml
sudo apt install python-is-python3
sudo apt-get install python3-catkin-pkg
|
五、从建模到运动——完整流程回顾
1 2 3 4 5 6 7 8 9 10 11 12 13
| 1. Fusion360/SolidWorks 建模 ↓ 2. 导出 STL → 编写 URDF/xacro ↓ 3. 添加 Transmission + ros_control 插件 ↓ 4. 编写控制器(速度/位置/力控) ↓ 5. 编写 launch 文件启动 Gazebo + RViz ↓ 6. rostopic pub 测试运动 ↓ 7. 接入真实硬件(STM32 + 串口)
|