ROS2 第6章 使用URDF创建机器人

6.1 使用URDF创建机器人

在主目录下新建chapt6,在该目录下创建chapt6_ws,接着递归创建src目录,在src下创建fishbot_description。

ros2 pkg create fishbot_description --build-type ament_cmake --license Apache-2.0

接着在fishbot_description下创建urdf目录,并在urdf目录下创建first_robot.urdf文件,代码如下

(可以先下载一个urdf扩展,帮助编写代码)

<?xml version="1.0"?> <!-- 机器人名称:first_robot --> <robot name="first_robot"> <!-- 1. 机器人身体部分(底座) --> <link name="base_link"> <!-- visual:描述部件的“外观”(形状、颜色,只影响显示,不影响物理) --> <visual> <!-- origin:部件自身的几何中心相对于“父关节”的偏移和旋转(这里是自身中心,所以全0) --> <origin xyz="0 0 0" rpy="0 0 0" /> <!-- geometry:部件的几何形状(这里是圆柱体) --> <geometry> <!-- cylinder:圆柱体,length=高度(0.12米),radius=半径(0.10米) --> <cylinder length="0.12" radius="0.10" /> </geometry> <!-- material:部件的材质(颜色) --> <material name="white"> <!-- color:颜色(rgba格式:红、绿、蓝、透明度,0-1之间) --> <color rgba="1.0 1.0 1.0 0.5" /> </material> </visual> </link> <!-- 2. 机器人IMU部件(惯性测量单元,用来测姿态) --> <link name="imu_link"> <visual> <origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <!-- box:立方体,size=长×宽×高(0.02米×0.02米×0.02米,很小的方块) --> <box size="0.02 0.02 0.02" /> </geometry> <material name="black"> <color rgba="0 0 0 0.5" /> </material> </visual> </link> <!-- 3. 关节:连接base_link(底座)和imu_link(IMU) --> <joint name="imu_joint" type="fixed"> <parent link="base_link" /> <!-- 父部件:底座(IMU装在底座上) --> <child link="imu_link" /> <!-- origin:子部件(IMU)相对于父部件(底座)的位置和旋转 --> <!-- xyz="0 0 0.03":IMU在底座的正上方0.03米处(z轴向上),x/y方向对齐(0,0) --> <origin xyz="0 0 0.03" rpy="0 0 0" /> </joint> </robot>

编写完成后,在终端中进入urdf目录下,输入以下代码将URDF结构可视化,结果如下

~/chapt6/chapt6_ws/src/fishbot_description/urdf$ urdf_to_graphviz first_robot.urdf first_robot Created file first_robot.gv Created file first_robot.pdf

打开生成的first_robot.pdf内容如下:

6.2 在Rviz中显示机器人

安装依赖

sudo apt install ros-$ROS_DISTRO-robot-state-publisher sudo apt install ros-$ROS_DISTRO-joint-state-publisher

为了方便运行,使用launch文件组织节点,在fishbot_description目录下新建launch目录,接着创建display_robot.launch.py,写入以下代码

import launch import launch_ros from ament_index_python.packages import get_package_share_directory def generate_launch_description(): urdf_turtorial_path = get_package_share_directory('fishbot_description') default_model_path = urdf_turtorial_path + '/urdf/first_robot.urdf' action_delcare_arg_mode_path = launch.actions.DeclareLaunchArgument( name='model', default_value=str(default_model_path), description='URDF 的绝对路径') robot_description = launch_ros.parameter_descriptions.ParameterValue( launch.substitutions.Command( ['cat ', launch.substitutions.LaunchConfiguration('model')]), value_type=str) robot_state_publisher_node = launch_ros.actions.Node( package='robot_state_publisher', executable='robot_state_publisher', parameters=[{'robot_description':robot_description}] ) joint_state_publisher_node = launch_ros.actions.Node( package='joint_state_publisher', executable='joint_state_publisher', ) rviz_node = launch_ros.actions.Node( package='rviz2', executable='rviz2', ) return launch.LaunchDescription([ action_delcare_arg_mode_path, joint_state_publisher_node, robot_state_publisher_node, rviz_node ])

代码完成后,在CMakeLists.txt中将urdf和launch文件复制到install目录下,代码如下

install(DIRECTORY launch urdf DESTINATION share/${PROJECT_NAME}) 

随后在工作空间下构建功能包,source 并启动launch文件,启动命令与结果如下

~/chapt6/chapt6_ws$ ros2 launch fishbot_description display_robot.launch.py [INFO] [launch]: All log files can be found below /home/cwq/.ros/log/2025-11-06-20-50-29-922420-cwq-virtual-machine-12869 [INFO] [launch]: Default logging verbosity is set to INFO [INFO] [joint_state_publisher-1]: process started with pid [12871] [INFO] [robot_state_publisher-2]: process started with pid [12873] [INFO] [rviz2-3]: process started with pid [12875] [rviz2-3] qt.qpa.plugin: Could not find the Qt platform plugin "wayland" in "" [robot_state_publisher-2] [INFO] [1762433430.026086874] [robot_state_publisher]: got segment base_link [robot_state_publisher-2] [INFO] [1762433430.026263877] [robot_state_publisher]: got segment imu_link [joint_state_publisher-1] [INFO] [1762433430.485811579] [joint_state_publisher]: Waiting for robot_description to be published on the robot_description topic... [rviz2-3] [INFO] [1762433430.610920615] [rviz2]: Stereo is NOT SUPPORTED [rviz2-3] [INFO] [1762433430.611039547] [rviz2]: OpenGl version: 4.3 (GLSL 4.3) [rviz2-3] [INFO] [1762433430.643061933] [rviz2]: Stereo is NOT SUPPORTED

需要将Rviz的Display模块中的Fixed Frame修改为base_link,添加RobotModel并修改Description Source为Topic,在Description Topic处选择/robot_description。

在launch中添加启动rviz2命令

def generate_launch_description(): urdf_turtorial_path = get_package_share_directory('fishbot_description') default_model_path = urdf_turtorial_path + '/urdf/first_robot.urdf' default_rviz_config_path = urdf_turtorial_path + '/config/display_model.rviz'
 arguments=['-d', default_rviz_config_path]

修改完后,修改CMakeLIsts.txt,将config目录复制到install对应目录下,重新构建功能包并运行launch文件,即可显示机器人模型

6.3 使用Xacro简化URDF

在urdf目录下创建first_robot.urdf.xacro,编写以下代码

<?xml version="1.0"?> <!-- 机器人名称:first_robot --> <robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="first_robot"> <xacro:macro name="base_link" params="length radius"> <!-- 1. 机器人身体部分(底座) --> <link name="base_link"> <!-- visual:描述部件的“外观”(形状、颜色,只影响显示,不影响物理) --> <visual> <!-- origin:部件自身的几何中心相对于“父关节”的偏移和旋转(这里是自身中心,所以全0) --> <origin xyz="0 0 0" rpy="0 0 0" /> <!-- geometry:部件的几何形状(这里是圆柱体) --> <geometry> <cylinder length="${length}" radius="${radius}" /> </geometry> <!-- material:部件的材质(颜色) --> <material name="white"> <!-- color:颜色(rgba格式:红、绿、蓝、透明度,0-1之间) --> <color rgba="1.0 1.0 1.0 0.5" /> </material> </visual> </link> </xacro:macro> <xacro:macro name="imu_link" params="imu_name xyz"> <!-- 2. 机器人IMU部件(惯性测量单元,用来测姿态) --> <link name="${imu_name}_link"> <visual> <origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <!-- box:立方体,size=长×宽×高(0.02米×0.02米×0.02米,很小的方块) --> <box size="0.02 0.02 0.02" /> </geometry> <material name="black"> <color rgba="0 0 0 0.5" /> </material> </visual> </link> <!-- 3. 关节:连接base_link(底座)和imu_link(IMU) --> <joint name="${imu_name}_joint" type="fixed"> <parent link="base_link" /> <!-- 父部件:底座(IMU装在底座上) --> <child link="${imu_name}_link" /> <!-- origin:子部件(IMU)相对于父部件(底座)的位置和旋转 --> <!-- xyz="0 0 0.03":IMU在底座的正上方0.03米处(z轴向上),x/y方向对齐(0,0) --> <origin xyz="${xyz}" /> </joint> </xacro:macro> <xacro:base_link length="0.12" radius="0.1" /> <xacro:imu_link imu_name="imu_up" xyz="0 0 0.02" /> <xacro:imu_link imu_name="imu_down" xyz="0 0 -0.02" /> </robot>

在终端中安装xacro工具,将xacro解析成URDF格式

sudo apt install ros-$ROS_DISTRO-xacro

在终端进入fishbot_description/urdf目录,使用以下代码将Xacro解析为URDF

~/chapt6/chapt6_ws/src/fishbot_description/urdf$ xacro first_robot.urdf.xacro <?xml version="1.0" ?> <!-- =================================================================================== --> <!-- | This document was autogenerated by xacro from first_robot.urdf.xacro | --> <!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | --> <!-- =================================================================================== --> <!-- 机器人名称:first_robot --> <robot name="first_robot"> <!-- 1. 机器人身体部分(底座) --> <link name="base_link"> <!-- visual:描述部件的“外观”(形状、颜色,只影响显示,不影响物理) --> <visual> <!-- origin:部件自身的几何中心相对于“父关节”的偏移和旋转(这里是自身中心,所以全0) --> <origin rpy="0 0 0" xyz="0 0 0"/> <!-- geometry:部件的几何形状(这里是圆柱体) --> <geometry> <cylinder length="0.12" radius="0.1"/> </geometry> <!-- material:部件的材质(颜色) --> <material name="white"> <!-- color:颜色(rgba格式:红、绿、蓝、透明度,0-1之间) --> <color rgba="1.0 1.0 1.0 0.5"/> </material> </visual> </link> <!-- 2. 机器人IMU部件(惯性测量单元,用来测姿态) --> <link name="imu_up_link"> <visual> <origin rpy="0 0 0" xyz="0 0 0"/> <geometry> <!-- box:立方体,size=长×宽×高(0.02米×0.02米×0.02米,很小的方块) --> <box size="0.02 0.02 0.02"/> </geometry> <material name="black"> <color rgba="0 0 0 0.5"/> </material> </visual> </link> <!-- 3. 关节:连接base_link(底座)和imu_link(IMU) --> <joint name="imu_up_joint" type="fixed"> <parent link="base_link"/> <!-- 父部件:底座(IMU装在底座上) --> <child link="imu_up_link"/> <!-- origin:子部件(IMU)相对于父部件(底座)的位置和旋转 --> <!-- xyz="0 0 0.03":IMU在底座的正上方0.03米处(z轴向上),x/y方向对齐(0,0) --> <origin xyz="0 0 0.02"/> </joint> <!-- 2. 机器人IMU部件(惯性测量单元,用来测姿态) --> <link name="imu_down_link"> <visual> <origin rpy="0 0 0" xyz="0 0 0"/> <geometry> <!-- box:立方体,size=长×宽×高(0.02米×0.02米×0.02米,很小的方块) --> <box size="0.02 0.02 0.02"/> </geometry> <material name="black"> <color rgba="0 0 0 0.5"/> </material> </visual> </link> <!-- 3. 关节:连接base_link(底座)和imu_link(IMU) --> <joint name="imu_down_joint" type="fixed"> <parent link="base_link"/> <!-- 父部件:底座(IMU装在底座上) --> <child link="imu_down_link"/> <!-- origin:子部件(IMU)相对于父部件(底座)的位置和旋转 --> <!-- xyz="0 0 0.03":IMU在底座的正上方0.03米处(z轴向上),x/y方向对齐(0,0) --> <origin xyz="0 0 -0.02"/> </joint> </robot>

将display_robot.launch.py中的'cat'命令替换为'xacro'。

在工作空间下重新构建和启动launch文件,并修改model参数为对应的文件地址,即可更新生成机器人模型。

~/chapt6/chapt6_ws$ ros2 launch fishbot_description display_robot.launch.py model:=/home/cwq/chapt6/chapt6_ws/src/fishbot_description/urdf/first_robot.urdf.xacro [INFO] [launch]: All log files can be found below /home/cwq/.ros/log/2025-11-07-17-31-27-774942-cwq-virtual-machine-21242 [INFO] [launch]: Default logging verbosity is set to INFO [INFO] [joint_state_publisher-1]: process started with pid [21244] [INFO] [robot_state_publisher-2]: process started with pid [21246] [INFO] [rviz2-3]: process started with pid [21248] [rviz2-3] qt.qpa.plugin: Could not find the Qt platform plugin "wayland" in "" [robot_state_publisher-2] [INFO] [1762507887.971557955] [robot_state_publisher]: got segment base_link [robot_state_publisher-2] [INFO] [1762507887.971697529] [robot_state_publisher]: got segment imu_down_link [robot_state_publisher-2] [INFO] [1762507887.971708736] [robot_state_publisher]: got segment imu_up_link [rviz2-3] [INFO] [1762507888.289264420] [rviz2]: Stereo is NOT SUPPORTED [rviz2-3] [INFO] [1762507888.289391344] [rviz2]: OpenGl version: 4.3 (GLSL 4.3) [rviz2-3] [INFO] [1762507888.321751638] [rviz2]: Stereo is NOT SUPPORTED [joint_state_publisher-1] [INFO] [1762507888.333985018] [joint_state_publisher]: Waiting for robot_description to be published on the robot_description topic...

6.4 创建机器人及传感器部件

在fishbot_description/urdf/目录下新建fisbot目录,在该目录下新建base.urdf.xacro,写入以下代码

<?xml version="1.0"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> <xacro:macro name="base_xacro" params="length radius"> <link name="base_link"> <visual> <origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <cylinder length="${length}" radius="${radius}" /> </geometry> <material name="white"> <color rgba="1.0 1.0 1.0 0.5" /> </material> </visual> </link> </xacro:macro> </robot>

在fishbot目录下新建sensor子目录,在sensor下新建imu.urdf.xacro,写入以下代码

<?xml version="1.0"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> <xacro:macro name="imu_xacro" params="xyz"> <link name="imu_link"> <visual> <origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <box size="0.02 0.02 0.02" /> </geometry> <material name="black"> <color rgba="0 0 0 0.8" /> </material> </visual> </link> <joint name="imu_joint" type="fixed"> <parent link="base_link" /> <child link="imu_link" /> <origin xyz="${xyz}" /> </joint> </xacro:macro> </robot>

在sensor下新建camera.urdf.xacro,写入以下代码

<?xml version="1.0"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> <xacro:macro name="camera_xacro" params="xyz"> <link name="camera_link"> <visual> <origin xyz="0 0 0.0" rpy="0 0 0" /> <geometry> <box size="0.02 0.10 0.02" /> </geometry> <material name="green"> <color rgba="0.0 1.0 0.0 0.8" /> </material> </visual> </link> <joint name="camera_joint" type="fixed"> <parent link="base_link" /> <child link="camera_link" /> <origin xyz="${xyz}" /> </joint> </xacro:macro> </robot>

在sensor下新建laser.urdf.xacro,写入以下代码

<?xml version="1.0"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> <xacro:macro name="laser_xacro" params="xyz"> <link name="laser_cylinder_link"> <visual> <origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <cylinder length="0.10" radius="0.01" /> </geometry> <material name="green"> <color rgba="0.0 1.0 0.0 0.8" /> </material> </visual> </link> <joint name="laser_cylinder_joint" type="fixed"> <parent link="base_link" /> <child link="laser_cylinder_link" /> <origin xyz="${xyz}" /> </joint> <link name="laser_link"> <visual> <origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <cylinder length="0.02" radius="0.02" /> </geometry> <material name="green"> <color rgba="0.0 1.0 0.0 0.8" /> </material> </visual> </link> <joint name="laser_joint" type="fixed"> <parent link="laser_cylinder_link" /> <child link="laser_link" /> <origin xyz="0 0 0.05" /> </joint> </xacro:macro> </robot>

传感器代码完成,现在需要将传感器组装起来,在urdf/fishbot/下新建fishbot.urdf.xacro,写入以下代码

<?xml version="1.0"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="first_robot"> <xacro:include filename="$(find fishbot_description)/urdf/fishbot/base.urdf.xacro" /> <xacro:include filename="$(find fishbot_description)/urdf/fishbot/sensor/imu.urdf.xacro" /> <xacro:include filename="$(find fishbot_description)/urdf/fishbot/sensor/laser.urdf.xacro" /> <xacro:include filename="$(find fishbot_description)/urdf/fishbot/sensor/camera.urdf.xacro" /> <xacro:base_xacro length="0.12" radius="0.1" /> <xacro:imu_xacro xyz="0 0 0.02" /> <xacro:laser_xacro xyz="0 0 0.10" /> <xacro:camera_xacro xyz="0.10 0 0.075" /> </robot>

重新编译并运行display_robot.launch.py(需将路径改为fishbot.urdf.xacro,代码及显示结果如下

ros2 launch fishbot_description display_robot.launch.py model:=/home/cwq/chapt6/chapt6_ws/src/fishbot_description/urdf/fishbot/fishbot.urdf.xacro [INFO] [launch]: All log files can be found below /home/cwq/.ros/log/2025-11-07-18-08-07-719699-cwq-virtual-machine-21855 [INFO] [launch]: Default logging verbosity is set to INFO [INFO] [joint_state_publisher-1]: process started with pid [21857] [INFO] [robot_state_publisher-2]: process started with pid [21859] [INFO] [rviz2-3]: process started with pid [21861] [rviz2-3] qt.qpa.plugin: Could not find the Qt platform plugin "wayland" in "" [robot_state_publisher-2] [INFO] [1762510087.926664599] [robot_state_publisher]: got segment base_link [robot_state_publisher-2] [INFO] [1762510087.926850670] [robot_state_publisher]: got segment camera_link [robot_state_publisher-2] [INFO] [1762510087.926862145] [robot_state_publisher]: got segment imu_link [robot_state_publisher-2] [INFO] [1762510087.926868633] [robot_state_publisher]: got segment laser_cylinder_link [robot_state_publisher-2] [INFO] [1762510087.926874791] [robot_state_publisher]: got segment laser_link [joint_state_publisher-1] [INFO] [1762510088.451227984] [joint_state_publisher]: Waiting for robot_description to be published on the robot_description topic... [rviz2-3] [INFO] [1762510088.605421457] [rviz2]: Stereo is NOT SUPPORTED [rviz2-3] [INFO] [1762510088.605605758] [rviz2]: OpenGl version: 4.3 (GLSL 4.3) [rviz2-3] [INFO] [1762510088.638243716] [rviz2]: Stereo is NOT SUPPORTED

6.5 完善机器人执行器部件

在fishbot目录下新建actuator子目录,然后在actuator下新建wheel.urdf.wacro,编写以下代码

<?xml version="1.0"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> <xacro:macro name="wheel_xacro" params="wheel_name xyz"> <link name="${wheel_name}_wheel_link"> <visual> <origin xyz="0 0 0" rpy="1.57079 0 0" /> <geometry> <cylinder length="0.04" radius="0.032" /> </geometry> <material name="yellow"> <color rgba="1.0 1.0 0.0 0.8" /> </material> </visual> </link> <joint name="${wheel_name}_wheel_joint" type="continuous"> <parent link="base_link" /> <child link="${wheel_name}_wheel_link" /> <origin xyz="${xyz}" /> <axis xyz="0.0 1.0 0.0"/> </joint> </xacro:macro> </robot>

完成驱动轮的定义,接着定义万向轮部分,在actuator中新建caster.urdf.xacro文件,代码如下

<?xml version="1.0"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> <xacro:macro name="caster_xacro" params="caster_name xyz"> <link name="${caster_name}_caster_link"> <visual> <origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <sphere radius="0.016" /> </geometry> <material name="yellow"> <color rgba="1.0 1.0 0.0 0.8" /> </material> </visual> </link> <joint name="${caster_name}_caster_joint" type="fixed"> <parent link="base_link" /> <child link="${caster_name}_caster_link" /> <origin xyz="${xyz}" /> <axis xyz="0 0 0"/> </joint> </xacro:macro> </robot>

完成后再次修改fishbot.urdf.xacro,添加代码如下,

 <xacro:include filename="$(find fishbot_description)/urdf/fishbot/actuator/caster.urdf.xacro" /> <xacro:include filename="$(find fishbot_description)/urdf/fishbot/actuator/wheel.urdf.xacro" /> <xacro:wheel_xacro wheel_name="left" xyz="0 0.10 -0.06" /> <xacro:wheel_xacro wheel_name="right" xyz="0 -0.10 -0.06" /> <xacro:caster_xacro caster_name="front" xyz="0.08 0.0 -0.076" /> <xacro:caster_xacro caster_name="back" xyz="-0.08 0.0 -0.076" />

在rviz中观察机器人,发现机器人轮子在地面以下,通过添加虚拟关节来解决这一问题,在src/fishbot_description/urdf/fishbot/base.urdf.xacro中添加以下代码,

 <link name="base_footprint" /> <joint name="base_joint" type="fixed"> <parent link="base_footprint" /> <child link="base_link" /> <origin xyz="0.0 0.0 ${length/2.0+0.032-0.001}" rpy="0 0 0" /> </joint> 

保存好后构建运行,修改fixed frame 为base_footprint,代码及结果展示如下:

ros2 launch fishbot_description display_robot.launch.py model:=/home/cwq/chapt6/chapt6_ws/src/fishbot_description/urdf/fishbot/fishbot.urdf.xacro [INFO] [launch]: All log files can be found below /home/cwq/.ros/log/2025-11-07-20-22-50-038490-cwq-virtual-machine-22899 [INFO] [launch]: Default logging verbosity is set to INFO [INFO] [joint_state_publisher-1]: process started with pid [22901] [INFO] [robot_state_publisher-2]: process started with pid [22903] [INFO] [rviz2-3]: process started with pid [22905] [rviz2-3] qt.qpa.plugin: Could not find the Qt platform plugin "wayland" in "" [robot_state_publisher-2] [INFO] [1762518170.255450518] [robot_state_publisher]: got segment back_caster_link [robot_state_publisher-2] [INFO] [1762518170.255583911] [robot_state_publisher]: got segment base_footprint [robot_state_publisher-2] [INFO] [1762518170.255595068] [robot_state_publisher]: got segment base_link [robot_state_publisher-2] [INFO] [1762518170.255601575] [robot_state_publisher]: got segment camera_link [robot_state_publisher-2] [INFO] [1762518170.255607770] [robot_state_publisher]: got segment front_caster_link [robot_state_publisher-2] [INFO] [1762518170.255613439] [robot_state_publisher]: got segment imu_link [robot_state_publisher-2] [INFO] [1762518170.255619158] [robot_state_publisher]: got segment laser_cylinder_link [robot_state_publisher-2] [INFO] [1762518170.255624824] [robot_state_publisher]: got segment laser_link [robot_state_publisher-2] [INFO] [1762518170.255630704] [robot_state_publisher]: got segment left_wheel_link [robot_state_publisher-2] [INFO] [1762518170.255636445] [robot_state_publisher]: got segment right_wheel_link [joint_state_publisher-1] [INFO] [1762518170.778521917] [joint_state_publisher]: Waiting for robot_description to be published on the robot_description topic...

6.6 添加物理属性让机器人更真实

6.6.1 为机器人添加碰撞属性

为每个部件都添加一份碰撞属性,与visual同级,添加<collision>,将visual的内容直接复制粘贴即可,base , laser , wheel , caster 都添加一次。

 </visual> <collision> <origin xyz="0 0 0" rpy="0 0 0" /> <geometry> <sphere radius="0.016" /> </geometry> <material name="yellow"> <color rgba="1.0 1.0 0.0 0.8" /> </material> </collision> </link>

在终端运行,打开rviz后,修改RobotModel配置,去掉VIsual Enabled的勾选,再勾选上Collsion Enabled即可显示出碰撞模型。.

6.6.2 为机器人部件添加质量与惯性

使用xacro结合惯性公式,编写一个惯性和质量专用的宏定义,在urdf/fishbot目录下新建common_inertia.xacro文件,编写以下代码

<?xml version="1.0"?> <robot xmlns:xacro="http://ros.org/wiki/xacro"> <xacro:macro name="box_inertia" params="m w h d"> <inertial> <mass value="${m}" /> <inertia ixx="${(m/12) * (h*h + d*d)}" ixy="0.0" ixz="0.0" iyy="${(m/12) * (w*w + d*d)}" iyz="0.0" izz="${(m/12) * (w*w + h*h)}" /> </inertial> </xacro:macro> <xacro:macro name="cylinder_inertia" params="m r h"> <inertial> <mass value="${m}" /> <inertia ixx="${(m/12) * (3*r*r + h*h)}" ixy="0" ixz="0" iyy="${(m/12) * (3*r*r + h*h)}" iyz="0" izz="${(m/2) * (r*r)}" /> </inertial> </xacro:macro> <xacro:macro name="sphere_inertia" params="m r"> <inertial> <mass value="${m}" /> <inertia ixx="${(2/5) * m * (r*r)}" ixy="0.0" ixz="0.0" iyy="${(2/5) * m * (r*r)}" iyz="0.0" izz="${(2/5) * m * (r*r)}" /> </inertial> </xacro:macro> </robot> 

编写完成后,就可以在其它xacro文件导入并使用该宏,修改base.urdf.xacro,添加导入对该宏的调用,

<?xml version="1.0"?> <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> <xacro:include filename="$(find fishbot_description)/urdf/fishbot/common_inertia.xacro" /> <xacro:macro name="base_xacro" params="length radius"> <link name="base_footprint" /> <joint name="base_joint" type="fixed"> <parent link="base_footprint" /> <child link="base_link" /> <origin xyz="0.0 0.0 ${length/2.0+0.032-0.001}" rpy="0 0 0" /> </joint> <link name="base_link"> <visual> <origin xyz="0 0 0.0" rpy="0 0 0" /> <geometry> <cylinder length="${length}" radius="${length}" /> </geometry> <material name="blue"> <color rgba="0.1 0.1 1.0 0.5"/> </material> </visual> <collision> <origin xyz="0 0 0.0" rpy="0 0 0" /> <geometry> <cylinder length="${length}" radius="${length}" /> </geometry> <material name="blue"> <color rgba="0.1 0.1 1.0 0.5"/> </material> </collision> <xacro:cylinder_inertia m="1.0" r="${radius}" h="${length}"/> </link> </xacro:macro> </robot> 

这里给出的完整代码,读者可对照修改。再次构建并运行launch,在rviz中显示机器人模型。

接着修改robotmodel配置,取消visual enabled的勾选,然后勾选mass properties选项中的mass,即可看到质量配置视图,取消mass勾选,勾选inertia视图,即可看到惯性视图。

下一章写如何在gazebo中仿真

Read more

前端安全:别让你的网站成为黑客的游乐场

前端安全:别让你的网站成为黑客的游乐场 毒舌时刻 前端安全?这不是后端的事吗? "我只是个前端,安全关我什么事?"——结果网站被XSS攻击,用户信息泄露, "我用了框架,应该很安全吧?"——结果框架有漏洞,被人轻松突破, "我的网站小,没人会攻击的"——结果被黑客当作练手的靶子。 醒醒吧,前端安全不是可有可无的,而是必须重视的! 为什么你需要这个? * 保护用户数据:防止用户信息被窃取 * 维护网站声誉:避免安全事件影响品牌形象 * 遵守法律法规:如GDPR、CCPA等数据保护法规 * 防止业务损失:避免因安全问题导致的经济损失 反面教材 // 反面教材:直接拼接HTML字符串 function renderUserInput() { const userInput = document.getElementById('user-input').value; // 危险!直接将用户输入插入到DOM中

【前端】使用Vue3过程中遇到加载无效设置点击方法提示不存在的情况,原来是少加了一个属性

【前端】使用Vue3过程中遇到加载无效设置点击方法提示不存在的情况,原来是少加了一个属性

🌹欢迎来到《小5讲堂》🌹 🌹这是《前端》系列文章,每篇文章将以博主理解的角度展开讲解。🌹 🌹温馨提示:博主能力有限,理解水平有限,若有不对之处望指正!🌹 目录 * 前言 * 提示报错 * 问题分析 * 1. **Options API vs Composition API 风格差异** * ✅ **Options API 写法(方法直接放在外面)** * ✅ **Composition API 写法(方法必须在 setup 中定义)** * ✅ **`<script setup>` 语法糖(最简洁的 Composition API)** * 2. **为什么你的代码会报错?** * 3. **解决方案** * 方案 1:改用 **Options API**(适合从 Vue

C++ 方向 Web 自动化测试实战:以博客系统为例,从用例到报告全流程解析

C++ 方向 Web 自动化测试实战:以博客系统为例,从用例到报告全流程解析

🔥草莓熊Lotso:个人主页 ❄️个人专栏: 《C++知识分享》《Linux 入门到实践:零基础也能懂》 ✨生活是默默的坚持,毅力是永久的享受! 🎬 博主简介: 文章目录 * 前言: * 一. 自动化测试前置:明确测试范围与测试用例设计 * 二. 自动化测试脚本开发:Python+Selenium 实现 * 2.1 通用工具类:common/Utils.py * 2.2. 登录模块测试:cases/BlogLogin.py * 2.3. 博客列表与详情页测试:cases/BlogList.py & BlogDetail.py * 2.3.1. 列表页测试(BlogList.py) * 2.3.

全新唯杰WebCAD编辑平台发布:全面拥抱AI,WebCAD智能体(Agent)来了

前言 唯杰地图vjmap 和 vjmap3d一直专注于 CAD 图纸与 GIS 地图的完美结合与高性能展示,帮助众多企业解决了“CAD图纸在Web端看图与GIS融合”的难题。 然而,随着业务的深入,我们收到了大量用户的反馈:“只能看图和做简单的批注还不够,我们需要在浏览器里直接编辑 CAD 图纸!”、“我们需要一个能完全替代传统桌面 CAD 的轻量级 Web 方案!”、“如果能让 AI 帮我们画图和改图就好了!” 为了满足这些硬核需求,历经数月的底层架构重构与开发,今天,我们非常激动地宣布:全新唯杰WebCAD编辑平台正式发布! 这不仅仅是一个能在网页上画线的工具,而是一个全面拥抱 AI、支持海量图纸处理、具备完整 CAD 编辑能力的现代化 WebCAD 平台。 一、产品功能与核心优势 唯杰 WebCAD 致力于打造下一代 Web 端的专业 CAD 引擎,在保证轻量级的同时,