ROS2-RViz-MoveIt-Gazebo-URDF学习笔记(六)

ROS2-RViz-MoveIt-Gazebo-URDF学习笔记(六)

solidworks导出的URDF文件转到gazebo sim显示默认导出的gazebo.launch.py调整为适配Gazebo sim在is35_description.urdf添加transmissionCMakeLists.txxpackage.xml
修改Moveit2的导出文件修改is35_description.ros2_control.xacro新增is35_description.gazebo.xacro修改is35_description.urdf.xacro修改CMakeLists.txt
编译运行报错warning: Using load_yaml() directly is deprecated. Use xacro.load_yaml() instead.[ign gazebo-1] [Err] [SystemPaths.cc:378] Unable to find file with URI [model://is35_description/meshes/base_link.STL]

solidworks导出的URDF文件转到gazebo sim显示

默认导出的gazebo.launch.py

该文件适配与Gazebo classic:


import launch
import launch_ros
from ament_index_python.packages import get_package_share_directory
from launch.launch_description_sources import PythonLaunchDescriptionSource
import os
from launch.actions import TimerAction

def generate_launch_description():
    # Get default path
    robot_name_in_model = "is35_description"
    urdf_tutorial_path = get_package_share_directory('is35_description')
    default_model_path = os.path.join(
        urdf_tutorial_path, 'urdf', 'is35_description.urdf')

    # Read URDF file content
    with open(default_model_path, 'r') as urdf_file:
        robot_description = urdf_file.read()

    robot_state_publisher_node = launch_ros.actions.Node(
        package='robot_state_publisher',
        executable='robot_state_publisher',
        parameters=[{'robot_description': robot_description}]
    )

    # Include another launch file for Gazebo
    launch_gazebo = launch.actions.IncludeLaunchDescription(
        PythonLaunchDescriptionSource([get_package_share_directory(
            'gazebo_ros'), '/launch', '/gazebo.launch.py']),
    )

    # Request Gazebo to spawn the robot
    spawn_entity_node = launch_ros.actions.Node(
        package='gazebo_ros',
        executable='spawn_entity.py',
        arguments=['-topic', '/robot_description',
                   '-entity', robot_name_in_model])

    return launch.LaunchDescription([
        robot_state_publisher_node,
        launch_gazebo,
        # 添加延迟,确保 Gazebo 启动后再生成实体
        TimerAction(
            period=5.0,
            actions=[spawn_entity_node]
        )
    ])
    

调整为适配Gazebo sim


from launch import LaunchDescription
import launch_ros
from ament_index_python.packages import get_package_share_directory
from launch.launch_description_sources import PythonLaunchDescriptionSource
import os
from launch.actions import TimerAction
from launch.actions import IncludeLaunchDescription
from launch_ros.substitutions import FindPackageShare
from launch_ros.actions import Node

def generate_launch_description():
    # Get default path
    robot_name_in_model = "is35_description"
    urdf_tutorial_path = get_package_share_directory('is35_description')
    default_model_path = os.path.join(
        urdf_tutorial_path, 'urdf', 'is35_description.urdf')

    # Read URDF file content
    with open(default_model_path, 'r') as urdf_file:
        robot_description = urdf_file.read()

    robot_state_publisher_node = launch_ros.actions.Node(
        package='robot_state_publisher',
        executable='robot_state_publisher',
        parameters=[{'robot_description': robot_description}]
    )

    # Include another launch file for Gazebo
    launch_gazebo = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            [FindPackageShare("ros_gz_sim"), "/launch/gz_sim.launch.py"]
        ),
        launch_arguments=[("gz_args", " -r -v 3 empty.sdf")],
    )

    # Request Gazebo to spawn the robot
    spawn_entity_node = Node(
        package='ros_gz_sim',
        executable='create',
        output='screen',
        arguments=['-topic', '/robot_description',
                   '-name', robot_name_in_model, '-allow_renaming', 'true'],
    )

    return LaunchDescription([
        launch_gazebo,
        robot_state_publisher_node,
        # 添加延迟,确保 Gazebo 启动后再生成实体
        TimerAction(
            period=5.0,
            actions=[spawn_entity_node]
        )
    ])

在is35_description.urdf添加transmission


<!-- 在<joint>后添加 -->

  <transmission name="joint1">
    <type>transmission_interface/SimpleTransmission</type>
    <joint name="joint1">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
    </joint>
    <actuator name="joint1_motor">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        <mechanicalReduction>1</mechanicalReduction>
    </actuator>
  </transmission>
  <transmission name="joint2">
    <type>transmission_interface/SimpleTransmission</type>
    <joint name="joint2">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
    </joint>
    <actuator name="joint2_motor">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        <mechanicalReduction>1</mechanicalReduction>
    </actuator>
  </transmission>
  <transmission name="joint3">
    <type>transmission_interface/SimpleTransmission</type>
    <joint name="joint3">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
    </joint>
    <actuator name="joint3_motor">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        <mechanicalReduction>1</mechanicalReduction>
    </actuator>
  </transmission>
  <transmission name="joint4">
    <type>transmission_interface/SimpleTransmission</type>
    <joint name="joint4">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
    </joint>
    <actuator name="joint4_motor">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        <mechanicalReduction>1</mechanicalReduction>
    </actuator>
  </transmission>
  <transmission name="joint5">
    <type>transmission_interface/SimpleTransmission</type>
    <joint name="joint5">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
    </joint>
    <actuator name="joint5_motor">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        <mechanicalReduction>1</mechanicalReduction>
    </actuator>
  </transmission>
  <transmission name="joint6">
    <type>transmission_interface/SimpleTransmission</type>
    <joint name="joint6">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
    </joint>
    <actuator name="joint6_motor">
        <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
        <mechanicalReduction>1</mechanicalReduction>
    </actuator>
  </transmission>

CMakeLists.txx

package.xml

修改Moveit2的导出文件

修改is35_description.ros2_control.xacro

新增is35_description.gazebo.xacro

修改is35_description.urdf.xacro

修改CMakeLists.txt

注意是is35_description路径下的CMakeLists.txt:

编译运行


colcon build
source install/local_setup.bash
ros2 launch is35_description gazebosim.launch.py

报错

warning: Using load_yaml() directly is deprecated. Use xacro.load_yaml() instead.

图片[1] - ROS2-RViz-MoveIt-Gazebo-URDF学习笔记(六) - 鹿快
修改:需要将过时的load_yaml()函数调用改为xacro.load_yaml()

[ign gazebo-1] [Err] [SystemPaths.cc:378] Unable to find file with URI [model://is35_description/meshes/base_link.STL]

问题原因:Gazebo Sim 的 resource path 里没有你的 install 目录


echo $GZ_SIM_RESOURCE_PATH | tr : '
' | grep is35_description

说明 setup.bash 并没有把 is35_description 的 share 目录写进 GZ_SIM_RESOURCE_PATH,这是 Gazebo Sim(Ignition)在 ROS 2 里的已知差异:

它只认 ament index 里声明为“gazebo_plugin”或“gazebo_model” 的条目,而普通 find_package 不会自动往里写。

临时手动 export(最快验证)


export GZ_SIM_RESOURCE_PATH=$GZ_SIM_RESOURCE_PATH:~/HuaLianCompany/aubois35_ws/install/is35_description/share

再启动 launch,mesh 若加载成功,说明路径没错。
图片[2] - ROS2-RViz-MoveIt-Gazebo-URDF学习笔记(六) - 鹿快
上述说明路径配置成功,且可以正常加载模型:

在 launch 文件里 动态追加路径(推荐,以后换机也不用再手动 export)


from launch import LaunchDescription
import launch_ros
from ament_index_python.packages import get_package_share_directory
from launch.launch_description_sources import PythonLaunchDescriptionSource
import os
from launch.actions import TimerAction
from launch.actions import IncludeLaunchDescription
from launch_ros.substitutions import FindPackageShare
from launch_ros.actions import Node
from launch.actions import AppendEnvironmentVariable
def generate_launch_description():
    # Get default path
    robot_name_in_model = "is35_description"
    urdf_tutorial_path = get_package_share_directory('is35_description')
    default_model_path = os.path.join(
        urdf_tutorial_path, 'urdf', 'is35_description.urdf')
    # 新增,注意是is35_description的父目录加进去
    set_env_vars_resources = AppendEnvironmentVariable(
            'GZ_SIM_RESOURCE_PATH',
            os.path.join(urdf_tutorial_path,'..'))
    # Read URDF file content
    with open(default_model_path, 'r') as urdf_file:
        robot_description = urdf_file.read()

    robot_state_publisher_node = launch_ros.actions.Node(
        package='robot_state_publisher',
        executable='robot_state_publisher',
        parameters=[{'robot_description': robot_description}]
    )

    # Include another launch file for Gazebo
    launch_gazebo = IncludeLaunchDescription(
        PythonLaunchDescriptionSource(
            [FindPackageShare("ros_gz_sim"), "/launch/gz_sim.launch.py"]
        ),
        launch_arguments=[("gz_args", " -r -v 3 empty.sdf")],
    )
    # Request Gazebo to spawn the robot
    spawn_entity_node = Node(
        package='ros_gz_sim',
        executable='create',
        output='screen',
        arguments=['-topic', '/robot_description',
                   '-name', robot_name_in_model, '-allow_renaming', 'true'],
    )

    return LaunchDescription([
    		# 设置GZ_SIM_RESOURCE_PATH环境变量
        set_env_vars_resources,
        launch_gazebo,
        robot_state_publisher_node,
        # 添加延迟,确保 Gazebo 启动后再生成实体
        TimerAction(
            period=5.0,
            actions=[spawn_entity_node]
        )
    ])

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
-不见春山的头像 - 鹿快
评论 抢沙发

请登录后发表评论

    暂无评论内容