ROS2中,从SolidWorks导出的urdf,联合moveit、gazebo进行控制及仿真

news2024/12/25 9:29:37

文章目录

  • 1.前言
  • 2.从urdf到moveit
  • 3.从urdf到gazebo
    • 3.1.urdf文件的修改
      • 3.1.1.mesh路径
      • 3.1.2.零件起飞
      • 3.1.3.文件保存
    • 3.2.xacro文件的修改
    • 3.3.launch
  • 4.用moveit控制gazebo
  • 5.结语

1.前言

本文是对之前发的文章【在ROS2中,通过MoveIt2控制Gazebo中的自定义机械手】的一个拓展。建议先看看之前的文章再看这个。
之前的文章的机械手是一个纯urdf自带几何图像(圆柱、立方体)等组成的所谓机械手,基本没有什么实用性。在后续的文章【ROS2中用MoveIt2控制自己的舵机机械手(1)】,我这边也已经实现了控制一个实物机械手,所以当时就没拿这个机械手放到gazebo中去仿真,因为我已经有实物了嘛。
但是后来陆续有人问我怎么把他们带有stl模型的机械手(可能也是从SolidWorks导出的),导入到gazebo仿真,因为他们可能也还是概念设计阶段,还没把实物做出来,的确有在gazebo里面仿真的必要。
因此,还是介绍一下如何把urdf导入moveit、urdf导入gazebo、moveit控制gazebo的整个流程吧。

2.从urdf到moveit

拿到从SolidWork导出的urdf、meshes文件夹后,建立一个软件包,利用moveit_setup_assistant工具,配置好相关参数与文件。参考【在ROS2中,通过MoveIt2控制Gazebo中的自定义机械手】的【3.机械手与MoveIt的关联】,此时我们要确保运行【demo.launch.py】 时是正常的,是可以规划、执行路径的。
在这里插入图片描述

3.从urdf到gazebo

当能够在moveit中跑我们的机械手之后,说明我们的urdf文件基本没什么问题了,尽量就不要去更改它(下面会打脸)。
但是,要让gazebo能够成功加载并仿真一个urdf文件,势必要加上很多额外的xml的节点,也就是要修改urdf,这可怎么办?
幸好,xacro能够帮我们解决这个矛盾。

3.1.urdf文件的修改

3.1.1.mesh路径

有个尴尬的地方,对于mesh文件(dae、stl),gazebo那边识别不了 package://claw_description 这种ros系统的路径查找方式(尝试运行的话,gazebo直接卡在那里),只能用 $(find claw_description)这种方式找到绝对路径并替换。
但是,rviz这边又不认这种绝对路径的。
在这里插入图片描述

幸好,在【Unstable behaviour of Position Controller in UR10 #73】找到了一种解决办法,属于是双管齐下了。

        <mesh filename="file://$(find claw_description)/meshes/link1.STL" />

3.1.2.零件起飞

另外,假如直接导入原来的urdf文件,过了一段时间后,会发现机械手的各个零件各自脱离,漫天飞。
在这里插入图片描述
这是仿真的“锅”。惯性参数(inertial)+质量+重力三者一起模拟驱动了各个零件受力,从而发生了相应的运动。
而我们其实大多数情况下,都是希望gazebo把整个机械手当成一个静态刚体来对待。空间中的其他物体只需要与机械手发生碰撞、摩擦计算就行。
因此我们可以把原来从SolidWorks导出来的urdf文件的惯性参数改成0.
在这里插入图片描述或者,可以在后面的xacro文件中取消各个link的重力:
在这里插入图片描述
上面两个办法二选一。

3.1.3.文件保存

因此最后得到的urdf文件为claw_description1.urdf,是从原来的文件claw_description.urdf拷贝修改而来的
在这里插入图片描述
主要就是修改了惯性参数、stl路径表达
在这里插入图片描述

3.2.xacro文件的修改

我们先到moveit_setup_assistant生成的config下面看看,偷偷师。先看看他们原来的重要文件:
在这里插入图片描述这里的核心文件是claw_description.urdf.xacro,其引用、使用了SolidWorks导出的claw_description.urdf以及ros2_control的claw_description.ros2_control.xacro。最终效果就是既使用了描述模型的urdf文件,也定义了ros2_control的相关节点。
因此,我们也可以模仿一下,写一个gazebo_claw_description.urdf.xacro
在这里插入图片描述

<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="claw_description">

    <!-- Used for fixing robot to Gazebo 'base_link' 将机械手的基座固定在世界坐标上-->
    <link name="world"/>
    <joint name="fixed" type="fixed">
        <parent link="world"/>
        <child link="link1"/>
    </joint>

    <!-- Import claw_description urdf file -->
    <xacro:include filename="$(find claw_description)/urdf/claw_description1.urdf" />


    <!-- 对一些link进行gazebo的属性设置 -->
    <gazebo reference="link1">
        <material>Gazebo/Purple</material>
        <self_collide>false</self_collide>
        <gravity>false</gravity>
    </gazebo>
    <gazebo reference="link2">
        <material>Gazebo/Red</material>
        <gravity>false</gravity>
    </gazebo>
    <gazebo reference="link3">
        <material>Gazebo/Blue</material>
        <gravity>false</gravity>
    </gazebo>
    <gazebo reference="link4">
        <material>Gazebo/Green</material>
        <gravity>false</gravity>
    </gazebo>
    <gazebo reference="link5">
        <material>Gazebo/Yellow</material>
        <gravity>false</gravity>
    </gazebo>
    <gazebo reference="link6">
        <material>Gazebo/Orange</material>
        <gravity>false</gravity>
    </gazebo>

    <!-- 设置不了静态,不知为啥 -->
    <gazebo>
        <is_static>true</is_static>
        <static>true</static>
        <isStatic>true</isStatic>
        <self_collide>true</self_collide>
    </gazebo>

    <!-- 声明马达,好像没什么卵用 -->
    <!-- <xacro:macro name="joint_transmission" params="joint_name">
        <transmission name="${joint_name}_trans">
            <type>transmission_interface/SimpleTransmission</type>
            <joint name="${joint_name}">
                <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
            </joint>
            <actuator name="${joint_name}_motor">
                <hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
                <mechanicalReduction>1</mechanicalReduction>
            </actuator>
        </transmission>
    </xacro:macro>
    <xacro:joint_transmission joint_name="joint1"/>
    <xacro:joint_transmission joint_name="joint2"/>
    <xacro:joint_transmission joint_name="joint3"/>
    <xacro:joint_transmission joint_name="joint4"/>
    <xacro:joint_transmission joint_name="joint5"/> -->


    <!-- 声明ros2_control -->
    <ros2_control name="GazeboSystem" type="system">
        <hardware>
            <plugin>gazebo_ros2_control/GazeboSystem</plugin>
        </hardware>
        <joint name="joint1">
            <command_interface name="position"/>
            <state_interface name="position">
                <param name="initial_value">0</param>
            </state_interface>
            <state_interface name="velocity"/>
        </joint>
        <joint name="joint2">
            <command_interface name="position"/>
            <state_interface name="position">
                <param name="initial_value">0</param>
            </state_interface>
            <state_interface name="velocity"/>
        </joint>
        <joint name="joint3">
            <command_interface name="position"/>
            <state_interface name="position">
                <param name="initial_value">0</param>
            </state_interface>
            <state_interface name="velocity"/>
        </joint>
        <joint name="joint4">
            <command_interface name="position"/>
            <state_interface name="position">
                <param name="initial_value">0</param>
            </state_interface>
            <state_interface name="velocity"/>
        </joint>
        <joint name="joint5">
            <command_interface name="position"/>
            <state_interface name="position">
                <param name="initial_value">0</param>
            </state_interface>
            <state_interface name="velocity"/>
        </joint>
    </ros2_control>

    <!-- 加载ros2_control插件 -->
    <gazebo>
        <plugin filename="libgazebo_ros2_control.so" name="gazebo_ros2_control">
            <parameters>$(find arm_claw)/config/ros2_controllers.yaml</parameters>
            <robot_param>robot_description</robot_param>
            <robot_param_node>robot_state_publisher</robot_param_node>
        </plugin>
    </gazebo>


</robot>

本来想直接<xacro:include filename=“claw_description.ros2_control.xacro” />的,但是里面的一些东西不通用,所以还是重新写一遍ros2_control的节点算了。
这个gazebo_claw_description.urdf.xacro就可以用来作为我们的gazebo模型文件了。

3.3.launch

至此,urdf、xacro文件都修改好了,那么参考 /opt/ros/humble/share/gazebo_ros2_control_demos/launch 里面的文件写个执行文件吧:
在这里插入图片描述

import os
from launch import LaunchDescription
from launch.actions import ExecuteProcess, IncludeLaunchDescription, RegisterEventHandler
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare
from launch.launch_description_sources import PythonLaunchDescriptionSource

from launch.event_handlers import OnProcessExit

from ament_index_python.packages import get_package_share_directory

import xacro

def generate_launch_description():
    package_name = 'arm_claw'

    robot_name_in_model = 'claw_description'

    pkg_share = FindPackageShare(package=package_name).find(package_name) 
    urdf_model_path = os.path.join(pkg_share, f'config/gazebo_claw_description.urdf.xacro')

    
    print("---", urdf_model_path)

    doc = xacro.parse(open(urdf_model_path))
    xacro.process_doc(doc)
    params = {'robot_description': doc.toxml()}

    print("urdf", doc.toxml())

    # 启动gazebo
    gazebo = IncludeLaunchDescription(
                PythonLaunchDescriptionSource([os.path.join(
                    get_package_share_directory('gazebo_ros'), 'launch'), '/gazebo.launch.py']),
             )
    
    # gazebo =  ExecuteProcess(
    #     cmd=['gazebo', '--verbose','-s', 'libgazebo_ros_init.so', '-s', 'libgazebo_ros_factory.so'],
    #     output='screen')

    # 启动了robot_state_publisher节点后,该节点会发布 robot_description 话题,话题内容是模型文件urdf的内容
    # 并且会订阅 /joint_states 话题,获取关节的数据,然后发布tf和tf_static话题.
    # 这些节点、话题的名称可不可以自定义?
    node_robot_state_publisher = Node(
        package='robot_state_publisher',
        executable='robot_state_publisher',
        parameters=[{'use_sim_time': True}, params, {"publish_frequency":15.0}],
        output='screen'
    )

    spawn_entity = Node(package='gazebo_ros', executable='spawn_entity.py',
                        arguments=['-topic', 'robot_description',
                                   '-entity', f'{robot_name_in_model}'], 
                        output='screen')


    # # Launch the robot, 这个是通过传递文件路径来在gazebo里生成模型.此时要求urdf文件里面没有xacro的语句
    # spawn_entity = Node(
    #     package='gazebo_ros', 
    #     executable='spawn_entity.py',
    #     arguments=['-file', urdf_model_path,
    #                '-entity', robot_name_in_model,   ], 
    #     output='screen')

    # gazebo在加载urdf时,根据urdf的设定,会启动一个joint_states节点?
    # 关节状态发布器
    load_joint_state_controller = ExecuteProcess(
        cmd=['ros2', 'control', 'load_controller', '--set-state', 'active',
             'joint_state_broadcaster'],
        output='screen'
    )

    # 路径执行控制器,也就是那个action?
    # 这个my_group_controller需要根据urdf文件里面引用的ros2_controllers.yaml里面的名字确定
    load_joint_trajectory_controller = ExecuteProcess(
        cmd=['ros2', 'control', 'load_controller', '--set-state', 'active',
             'my_group_controller'],
        output='screen'
    )

    # 用下面这两个估计是想控制好各个节点的启动顺序
    # 监听 spawn_entity_cmd,当其退出(完全启动)时,启动load_joint_state_controller?
    close_evt1 =  RegisterEventHandler( 
            event_handler=OnProcessExit(
                target_action=spawn_entity,
                on_exit=[load_joint_state_controller],
            )
    )
    # 监听 load_joint_state_controller,当其退出(完全启动)时,启动load_joint_trajectory_controller?
    # moveit是怎么和gazebo这里提供的action连接起来的??
    close_evt2 = RegisterEventHandler(
            event_handler=OnProcessExit(
                target_action=load_joint_state_controller,
                on_exit=[load_joint_trajectory_controller],
            )
    )
    
    ld = LaunchDescription([
        close_evt1,
        close_evt2,
        gazebo,
        node_robot_state_publisher,
        spawn_entity,
    ])

    return ld

运行一下,得到
在这里插入图片描述还可以。
然后,直接在另外一个控制台运行一下rviz2,在rviz2中看看(注意此时还没启动moveit):
在这里插入图片描述

4.用moveit控制gazebo

还是参考之前的文章【在ROS2中,通过MoveIt2控制Gazebo中的自定义机械手】,5.2节的内容,写一个moveit+rviz的启动文件:gazebo_moveit_rviz.launch.py。
在这里插入图片描述
然后分别打开两个控制台,分别执行:

ros2 launch arm_claw gazebo_moveit_rviz.launch.py 
ros2 launch arm_claw gazebo.launch.py 

然后就可以愉快地玩耍了。
在这里插入图片描述

5.结语

虽然好像是弄了出来,但是其实还有很多问题。
这些问题也许是错误操作,也许是概念偷换,总之就是一堆等待花精力、时间去操作的事情,后面再慢慢修正吧。
这些问题包括但是不限于:

1.在利用moveit_setup_assisatant对urdf文件进行读取时,我们用的是claw_description.urdf文件,也就是moveit用的是claw_description.urdf文件,而gazebo用的是claw_description1.urdf + xacro文件,也就是不同的两个文件,可以这样用吗?
2.在gazebo中的机械手,有时候会“脱节”,零件散开。(发现是机械手运动时撞到地板了,只要不撞地板,貌似都是正常的)
3.对于惯性参数,目前我们选择的是躺平操作,更合理的操作是啥?


参考:
【Gazebo仿真小例程一(通过例程熟悉整个仿真步骤)】
【Unstable behaviour of Position Controller in UR10 #73】
【ur10.urdf.xacro】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/601248.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C 语言详细教程

目录 第一章 C语言基础知识 第二章 数据类型、运算符和表达式 第三章 结构化程序设计 第四章 数组 第五章 函数 第六章 指针 第七章 结构体类型和自定义类型 第八章 编译预处理 第九章 文件 说明&#xff1a;本教程中的代码除一二三个之外&#xff0c;都在https://ligh…

尝试理解卷积神经和深度学习的关系,并且怎么使用

前言 最近想要了解卷积神经和深度学习,才发现并不是我想象中的简单,也不是我想象中的难.我想的难是指没有任何思路:不知道这是个什么玩意,里面的流程是不是很难,我想的简单就是:也就是用人家的包,全都是用来导包,我只需要知道这个包是怎么用的,从来没想过自己怎么开发出来一个依…

Python splitlines() 的使用

Python splitlines() 的作用 Python splitlines() 按照行(\r, \r\n, \n)分隔&#xff0c;返回一个包含各行作为元素的列表 Python splitlines()的注意事项 splitlines小括号里面的参数没有的时候,默认按照行(\r, \r\n, \n)分隔不带这些特殊的字符 如果这样splitlines(True)…

ISO21434 概述(一)

目录 一、ISO21434 1.1 目的 1.2 ISO21434文档组织结构 二、适用范围 三、引用标准 四、术语和缩写 4.1 术语 4.2 缩写 五、一般考虑 一、ISO21434 1.1 目的 本文件阐述了道路车辆内电气和电子&#xff08;E/E&#xff09;系统工程中的网络安全问题。通过确保对网络安…

Ansible的配置、主机清单、Ansible的脚本Playbook详解

文章目录 Ansible的配置配置文件 主机清单远程主机的分组变量 Ansible的脚本PlaybookPlaybook的文件格式YAMLansible-playbook的命令Playbook的基本语法变量 Ansible的配置 配置文件 Ansible是一款功能强大的自动化工具&#xff0c;可以实现对远程主机的管理和操作&#xff0…

华为认证 | HCIA-Datacom 考试大纲

今天给大家说点基础的&#xff0c;很多人对华为认证考试有了一定了解后&#xff0c;想要进一步了解具体的考试内容。 这篇先说HCIA-Datacom的具体考试大纲~ 01 华为HCIA-Datacom认证考试 02 华为HCIA-Datacom考试内容 HCIA-Datacom V1.0考试覆盖数通基础知识&#xff0c;包括&…

java 中的动态代理实现

1. 什么是代理模式 代理模式是常见的设计模式之一&#xff0c;顾名思义&#xff0c;代理模式就是代理对象具备真实对象的功能&#xff0c;并代替真实对象完成相应操作&#xff0c;并能够在操作执行的前后&#xff0c;对操作进行增强处理。&#xff08;为真实对象提供代理&…

表格软件有哪些?热门表格软件推荐

作为报表开发人员&#xff0c;我们经常需要使用各种表格软件来处理数据并生成清晰、易读的报表。在市面上&#xff0c;有许多不同类型的表格软件可供选择。下面我将列举7款热门的表格软件&#xff0c;并详细介绍其中一款优秀的软件—VeryReport。 编辑搜图 请点击输入图片描述…

Qt6.5.1+WebRTC学习笔记(九)运行官方示例(win10+vs2019)

前言 webrtc源码目录下&#xff0c;有个examples目录&#xff0c;里面放置着官方的示例&#xff0c;其有peerconnection示例。 一、问题 peerconnection示例分客户端和服务端&#xff0c;以win系统为例&#xff0c;编译后会在输出目录生成两个可执行文件 服务端程序可以正常…

【基于GD32E230的定时器级联M/T法电机测速】

前言 在有感电机控制中&#xff0c;获取电机转速是非常重要的步骤&#xff0c;转速获取越准确&#xff0c;控制电机时越方便&#xff0c;抛开霍尔不谈&#xff0c;这里讨论电机编码器。 目前常见的电机编码器按种类分为绝对值编码器和增量编码器&#xff0c;绝对值编码器相对…

厚积薄发,AR光学方案商光舟半导体于AWE 2023首次公开亮相

青亭网6月2日报道&#xff0c;国内AR光波导技术厂商“光舟半导体”&#xff08;深圳市光舟半导体技术有限公司&#xff09;在AWE 2023首次公开亮相&#xff0c;并展示了最新的AR光波导模组、光机/光引擎、汽车HUD三大产品。 光舟半导体成立于2020年1月&#xff0c;公司由AR光学…

5.8 几个常见JavaScript图表库

几个常见JavaScript图表库 目录1、 Chart.js2、 Chartist.js3、 Highcharts.js4、 D3.js5、 Plotly.js6、 ECharts.js7、 Google Charts8、Other Charts 目录 1、 Chart.js 官方网站&#xff1a; www.chartjs.org Chart.js 是一个基于 HTML5 Canvas 的 JavaScript 图表库&…

Day59【单调栈】503.下一个更大元素II、42.接雨水

503.下一个更大元素II 力扣题目链接/文章讲解 视频讲解 本题和739.每日温度很相似&#xff0c;只不过是循环数组 一种处理循环的方式是&#xff0c;直接把两个数组拼接在一起&#xff0c;然后使用单调栈求下一个最大值 class Solution { public:vector<int> nextGre…

【JUC基础】13. 线程池(二)

目录 1、前言 2、Java实现线程池 2.1、Executors框架 2.2、newFixedThreadPool 2.3、newCachedThreadPool 2.4、newSingleThreadExecutor 2.5、newScheduledThreadPool 2.5.1、scheduleAtFixedRate 2.5.2、scheduleWithFixedDelay 2.5.3、异常中断 3、execute()和sub…

大数据挖掘企业服务平台(TipDM大数据挖掘建模平台)-快速构建数据挖掘工程

“TipDM大数据挖掘建模平台”&#xff08;以下简称平台&#xff09;是由广东泰迪智能科技股份有限公司自主研发&#xff0c;基于Python引擎的数据挖掘建模平台。使用平台配置的开箱即用的算法组件&#xff0c;用户可在没有编程基础的情况下&#xff0c;通过拖拽的方式进行操作&…

蓝牙规范系列--经典蓝牙概述(第一篇)

一、目的 从本篇开始介绍经典蓝牙的基础知识&#xff0c;内容较多故会分成多篇进行介绍。 经典蓝牙&#xff08;BR/EBR&#xff09;射频&#xff08;物理层PHY&#xff09;工作在免授权的2.4G ISM频段&#xff08;2400 - 2483.5 MHz&#xff09;&#xff0c;使用跳频技术来对抗…

基于java的班级管理系统的设计与实现

一:需求分析 1.功能需求 1).能够实现对班级学生基本资料的录入,包括学生的学号,姓名,性别,所学专业,家庭住址以及出生年月等。 2).能够实现对学生基本资料的修改。 3).根据学号对学生资料进行查询。 4).能够删除某些学生的资料。 二:总体设计 本班级管理系统共有6…

静态Web服务器搭建

文章目录 一&#xff0c;安装Apache软件&#xff08;一&#xff09;Apache软件安装&#xff08;二&#xff09;Apache软件管理&#xff08;三&#xff09;Apache软件基本设置&#xff08;四&#xff09;测试Apache服务器 二&#xff0c;Apache服务器的配置文件&#xff08;一&a…

【C++】结构体 - 定义和使用,结构体数组,结构体指针,结构体嵌套结构体,结构体做函数参数,结构体 const

文章目录 1. 定义和使用2. 结构体数组3. 结构体指针4. 结构体嵌套结构体5. 结构体做函数参数6. 结构体 const 1. 定义和使用 结构体属于用户自定义的数据类型&#xff0c;允许用户存储不同的数据类型。 struct 结构体 {结构体成员列表}; 通过结构体创建变量的方法有三种&…

2023,智能硬件的AIGC“又一春”

​ 文|智能相对论 作者|佘凯文 消费电子产品风光不再&#xff0c;特别是自去年以来&#xff0c;电子消费市场经历了一整年的寒潮袭击&#xff0c;智能手机等产品达到10年消费谷底&#xff0c;PC出货量整体下降16%&#xff0c;不仅如此&#xff0c;包括平板、可穿戴设备也一改…