ROS 2边学边练(44)-- 从头开始构建一个视觉机器人模型

前言

        从此篇开始我们就开始接触URDF(Unified Robot Description Format,统一机器人描述格式),并利用其语法格式搭建我们自己的机器人模型。

动动手

        开始之前我们需要确认是否安装joint_state_publisher功能包,如果有安装过二进制版本的urdf_tutorial,也是可以的(教程里提到的所有机器人模型都可以在urdf_turial包里面找见,运行示例也是直接调用里面这些),否则需要更新下源并下载安装。

        如果没有安装,参考下面的命令。

安装依赖

$sudo apt install ros-iron-joint-state-publisher-gui ros-iron-joint-state-publisher
$sudo apt install ros-iron-xacro

安装urdf_tutorial 

$sudo apt update
$sudo apt install ros-iron-urdf-tutorial

 注意:还有其他方法可以下载urdf_tutorial功能包源工程,但均有问题。如git clone -b ros2 https://github.com/ros/urdf_tutorial.git,下载不了,再比如git clone https://github.com/ros/urdf_tutorial.git,可以下载,通过浏览器进入查看会发现最近的更新时间都是3年前了,且用的是catkin,最后colcon build --package-select urdf_tutorial会报错,构建不了。

如果大家用的是虚拟机,但是Ubuntu网络没有对应的ipv4,无法ping目标网络,那可能是虚拟机的网络配置问题,可以通过虚拟机->设置->网络适配器(桥接自动),选择桥接+复制物理网络连接状态。 

        关于urdf里面的机器人,一般由关节(joint,起连接作用)和连杆(link,多个link可由joint相衔接)构成,比如一个简单的机械臂,其组成如下。

单个形状

        我们先从单独一个几何形状开始逐步组装成R2D2机器人。[原文件:01-myfirst.urdf]

<?xml version="1.0"?>
<robot name="myfirst"><link name="base_link"><visual><geometry><cylinder length="0.6" radius="0.2"/></geometry></visual></link>
</robot>

        这段urdf代码定义了一个叫myfirst的机器人,它只包含一个连接base_link,其视觉外观是一个长为0.6米半径为0.2米的圆柱体(cylinder)。是不是一目了然,毫无压力。

        我们来试试启动一个launch文件,看看这个圆柱体实际的效果如何:

$ros2 launch urdf_tutorial display.launch.py model:=urdf/01-myfirst.urdf

上面的语句实际上做了三件事:

  • 加载特定的模型文件(01-myfirst.urdf)并且将此文件保存为robot_state_publisher节点的一个参数;
  • 运行节点,发布sensor_msgs/msg/JointState数据类型消息,并转换之;
  • 开启Rviz(读取配置文件中的参数加载)。

 最终效果如下:

注意点:

  • 固定坐标系是网格中心所在的变换坐标系。在这里,它是由我们的一个连接(或称为部分)base_link所定义的坐标系;
  • 视觉元素(即圆柱体)的默认原点位于其几何中心。因此,圆柱体的一半位于网格之下。

多个形状

        加大一点难度,我们在上述圆柱体的基础上再增加一个形状部件。在开头也提到了关节(joint),如果要在一个模块上添加另外一个模块,我们必须确定好joint,解析器才能知道第二个模块所放的位置,对于这个joint,大体上有两种,活动的(比如能旋转)和固定的,我们先来个固定的joint。[原文件:02-multipleshapes.urdf]

<?xml version="1.0"?>
<robot name="multipleshapes"><link name="base_link"><visual><geometry><cylinder length="0.6" radius="0.2"/></geometry></visual></link><link name="right_leg"><visual><geometry><box size="0.6 0.1 0.2"/></geometry></visual></link><joint name="base_to_right_leg" type="fixed"><parent link="base_link"/><child link="right_leg"/></joint></robot>

        机器人multipleshapes中,第一个link还是我们的圆柱体base_link,第二个link是需要组装到base_link上的right_leg(长方体box,长宽高0.6m*0.1m*0.2m),在最后我们看到有加了个joint,名字为base_to_right_leg,类型是固定(fixed),其父组件为base_link,子组件为right_leg,也即right_leg是通过base_to_right_leg这个joint连接组装到base_link上的。子组件的位置取决于父组件的位置。

$ros2 launch urdf_tutorial display.launch.py model:=urdf/02-multipleshapes.urdf

        base_link和right_leg重叠在一块了,这是由于它们共用了同样的原点(默认),如果不想它们重叠,那我们就需要定义多个原点。

原点

        我们来定义多个原点使得各个组件之间不再穿插。R2D2的腿部连接在其躯干的上半部分,位于侧面。所以我们指定关节的原点就在那里(躯干上半部)。同时,它(关节)并不是连接在腿部的中间,而是连接在腿部的上部,因此我们也必须调整腿部的原点位置。我们还需要旋转腿部,使其竖直站立。[原文件:03-origins.urdf]

<?xml version="1.0"?>
<robot name="origins"><link name="base_link"><visual><geometry><cylinder length="0.6" radius="0.2"/></geometry></visual></link><link name="right_leg"><visual><geometry><box size="0.6 0.1 0.2"/></geometry><origin rpy="0 1.57075 0" xyz="0 0 -0.3"/></visual></link><joint name="base_to_right_leg" type="fixed"><parent link="base_link"/><child link="right_leg"/><origin xyz="0 -0.22 0.25"/></joint></robot>

        我们先从joint属性看起,关节的原点是根据父参考坐标系来定义的。因此,我们在y方向上偏移了-0.22米(即向我们的左边,但相对于坐标轴是向右的),在z方向上偏移了0.25米(即向上)。这意味着无论子连接(child link)的视觉原点标签如何,子连接的原点都会向上并向右偏移。由于我们没有指定rpy(roll pitch yaw)属性,子坐标系将默认与父坐标系具有相同的方向。

        接着再看看right_leg,它的原点既有xyz偏移量也有rpy偏移量。由于我们希望腿部连接在顶部,我们将原点向下偏移,将z偏移量设置为-0.3米(right_leg的原点是相对于joint原点位置作变化,z值偏移-0.3,就能将长方体的顶部尽量接近圆柱体的顶部)。并且,由于我们希望腿部的长部分与z轴平行,我们围绕Y轴旋转视觉部分PI/2(即90度)。

$ros2 launch urdf_tutorial display.launch.py model:=urdf/03-origins.urdf

  • 启动文件(launch)在运行包时会基于我们的URDF为每个link生成TF帧,而Rviz会利用这些TF帧信息计算并显示出各个形状体的对应所在。
  • 如果给定的URDF link没有对应的TF帧,那么它将被放置在原点位置,并以白色显示(相关问题)。

物质属性

        原文标题为Material Girl,既幽默又如实,但我就翻译的严肃点了,莫怪。机器人上的link上面的效果都是红色,但是如果我们要自定义各个link的颜色(或其他属性)可不可以呢,当然了,我们可以在urdf文件里指定material标签即可。[原文件:04-materials.urdf]

<?xml version="1.0"?>
<robot name="materials"><material name="blue"><color rgba="0 0 0.8 1"/></material><material name="white"><color rgba="1 1 1 1"/></material><link name="base_link"><visual><geometry><cylinder length="0.6" radius="0.2"/></geometry><material name="blue"/></visual></link><link name="right_leg"><visual><geometry><box size="0.6 0.1 0.2"/></geometry><origin rpy="0 1.57075 0" xyz="0 0 -0.3"/><material name="white"/></visual></link><joint name="base_to_right_leg" type="fixed"><parent link="base_link"/><child link="right_leg"/><origin xyz="0 -0.22 0.25"/></joint><link name="left_leg"><visual><geometry><box size="0.6 0.1 0.2"/></geometry><origin rpy="0 1.57075 0" xyz="0 0 -0.3"/><material name="white"/></visual></link><joint name="base_to_left_leg" type="fixed"><parent link="base_link"/><child link="left_leg"/><origin xyz="0 0.22 0.25"/></joint></robot>

        我们在material标签里定义了“blue”(rgba通道)和“white”两种颜色,在link标签里面进行了引用,这会改变该link原先的颜色属性。material标签也可以定义在link属性的内部(其它的link也可以引用),甚至我们还可以使用贴图来渲染我们的机器人。

$ros2 launch urdf_tutorial display.launch.py model:=urdf/04-materials.urdf

补全模型

        最后,我们给机器人加上脚、轮子和头(增加了球体和一些mesh文件,后续我们还会用到)。[原文件:05-visual.urdf]

<?xml version="1.0"?>
<robot name="visual"><material name="blue"><color rgba="0 0 0.8 1"/></material><material name="black"><color rgba="0 0 0 1"/></material><material name="white"><color rgba="1 1 1 1"/></material><link name="base_link"><visual><geometry><cylinder length="0.6" radius="0.2"/></geometry><material name="blue"/></visual></link><link name="right_leg"><visual><geometry><box size="0.6 0.1 0.2"/></geometry><origin rpy="0 1.57075 0" xyz="0 0 -0.3"/><material name="white"/></visual></link><joint name="base_to_right_leg" type="fixed"><parent link="base_link"/><child link="right_leg"/><origin xyz="0 -0.22 0.25"/></joint><link name="right_base"><visual><geometry><box size="0.4 0.1 0.1"/></geometry><material name="white"/></visual></link><joint name="right_base_joint" type="fixed"><parent link="right_leg"/><child link="right_base"/><origin xyz="0 0 -0.6"/></joint><link name="right_front_wheel"><visual><origin rpy="1.57075 0 0" xyz="0 0 0"/><geometry><cylinder length="0.1" radius="0.035"/></geometry><material name="black"/></visual></link><joint name="right_front_wheel_joint" type="fixed"><parent link="right_base"/><child link="right_front_wheel"/><origin rpy="0 0 0" xyz="0.133333333333 0 -0.085"/></joint><link name="right_back_wheel"><visual><origin rpy="1.57075 0 0" xyz="0 0 0"/><geometry><cylinder length="0.1" radius="0.035"/></geometry><material name="black"/></visual></link><joint name="right_back_wheel_joint" type="fixed"><parent link="right_base"/><child link="right_back_wheel"/><origin rpy="0 0 0" xyz="-0.133333333333 0 -0.085"/></joint><link name="left_leg"><visual><geometry><box size="0.6 0.1 0.2"/></geometry><origin rpy="0 1.57075 0" xyz="0 0 -0.3"/><material name="white"/></visual></link><joint name="base_to_left_leg" type="fixed"><parent link="base_link"/><child link="left_leg"/><origin xyz="0 0.22 0.25"/></joint><link name="left_base"><visual><geometry><box size="0.4 0.1 0.1"/></geometry><material name="white"/></visual></link><joint name="left_base_joint" type="fixed"><parent link="left_leg"/><child link="left_base"/><origin xyz="0 0 -0.6"/></joint><link name="left_front_wheel"><visual><origin rpy="1.57075 0 0" xyz="0 0 0"/><geometry><cylinder length="0.1" radius="0.035"/></geometry><material name="black"/></visual></link><joint name="left_front_wheel_joint" type="fixed"><parent link="left_base"/><child link="left_front_wheel"/><origin rpy="0 0 0" xyz="0.133333333333 0 -0.085"/></joint><link name="left_back_wheel"><visual><origin rpy="1.57075 0 0" xyz="0 0 0"/><geometry><cylinder length="0.1" radius="0.035"/></geometry><material name="black"/></visual></link><joint name="left_back_wheel_joint" type="fixed"><parent link="left_base"/><child link="left_back_wheel"/><origin rpy="0 0 0" xyz="-0.133333333333 0 -0.085"/></joint><joint name="gripper_extension" type="fixed"><parent link="base_link"/><child link="gripper_pole"/><origin rpy="0 0 0" xyz="0.19 0 0.2"/></joint><link name="gripper_pole"><visual><geometry><cylinder length="0.2" radius="0.01"/></geometry><origin rpy="0 1.57075 0 " xyz="0.1 0 0"/></visual></link><joint name="left_gripper_joint" type="fixed"><origin rpy="0 0 0" xyz="0.2 0.01 0"/><parent link="gripper_pole"/><child link="left_gripper"/></joint><link name="left_gripper"><visual><origin rpy="0.0 0 0" xyz="0 0 0"/><geometry><mesh filename="package://urdf_tutorial/meshes/l_finger.dae"/></geometry></visual></link><joint name="left_tip_joint" type="fixed"><parent link="left_gripper"/><child link="left_tip"/></joint><link name="left_tip"><visual><origin rpy="0.0 0 0" xyz="0.09137 0.00495 0"/><geometry><mesh filename="package://urdf_tutorial/meshes/l_finger_tip.dae"/></geometry></visual></link><joint name="right_gripper_joint" type="fixed"><origin rpy="0 0 0" xyz="0.2 -0.01 0"/><parent link="gripper_pole"/><child link="right_gripper"/></joint><link name="right_gripper"><visual><origin rpy="-3.1415 0 0" xyz="0 0 0"/><geometry><mesh filename="package://urdf_tutorial/meshes/l_finger.dae"/></geometry></visual></link><joint name="right_tip_joint" type="fixed"><parent link="right_gripper"/><child link="right_tip"/></joint><link name="right_tip"><visual><origin rpy="-3.1415 0 0" xyz="0.09137 0.00495 0"/><geometry><mesh filename="package://urdf_tutorial/meshes/l_finger_tip.dae"/></geometry></visual></link><link name="head"><visual><geometry><sphere radius="0.2"/></geometry><material name="white"/></visual></link><joint name="head_swivel" type="fixed"><parent link="base_link"/><child link="head"/><origin xyz="0 0 0.3"/></joint><link name="box"><visual><geometry><box size="0.08 0.08 0.08"/></geometry><material name="blue"/></visual></link><joint name="tobox" type="fixed"><parent link="head"/><child link="box"/><origin xyz="0.1814 0 0.1414"/></joint>
</robot>
$ros2 launch urdf_tutorial display.launch.py model:=urdf/05-visual.urdf

头部(球体)的添加如下:

<link name="head"><visual><geometry><sphere radius="0.2"/></geometry><material name="white"/></visual>
</link>

        此教程中的mesh文件(组件模型)来自于PR2机器人,每个模型都有一个单独的mesh文件,我们可以通过指定模型对应的路径(package://NAME_OF_PACKAGE/path)来使用它们。

<link name="left_gripper"><visual><origin rpy="0.0 0 0" xyz="0 0 0"/><geometry><mesh filename="package://urdf_tutorial/meshes/l_finger.dae"/></geometry></visual>
</link>
  • mesh(网格)可以以多种不同的格式导入。STL格式相当常见,但引擎还支持DAE格式,DAE格式可以包含其自身的颜色数据,这意味着你不需要指定颜色/材质。通常这些是在单独的文件中。这些网格还引用了位于网格文件夹中的.tif文件(注意:这里可能有一个小错误,.tif 文件通常不是用于3D网格的颜色或纹理数据。更常见的是使用如 .png.jpg.dds 等格式的图片文件作为纹理。可能是这里提到的 .tif 是个特例或者是一个错误。在3D建模和渲染中,.tif 文件不如其他格式常见,但在某些情况下可能被使用。)。
  • mesh(网格)也可以使用相对缩放参数或边界框大小来进行尺寸调整。
  • 我们也可以在完全不同的包中引用mesh(网格)。

        到此我们的R2D2机器人就组装好了,下一步,我们挑战一下,洒点灵魂,让它动起来。

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

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

相关文章

解密某游戏的数据加密

前言 最近有个兄弟通过我的视频号加我&#xff0c;咨询能否将这个dubo游戏游戏开始前就将数据拿到从而进行押注&#xff0c;于是通过抓包工具测试了下&#xff0c;发现数据有时候是明文&#xff0c;有时候确实密文&#xff0c;大致看了下有这几种加密&#xff1a;Md5aes、Md5&a…

网络层协议之 IP 协议

IP 协议格式 4 位版本&#xff1a;此处的取值只有两个&#xff0c;4&#xff08;IPv4&#xff09;和 6&#xff08;IPv6&#xff09;&#xff0c;即指定 IP 协议的版本。 4 位首部长度&#xff1a;描述了 IP 报头多长&#xff0c;IP 报头是变长的&#xff0c;因为报头中的选项部…

点餐小程序 点餐系统 微信点餐系统 支持微信小程序 支付公众号 可接入第三方配送 全开源uniapp

餐饮连锁v2版-体验后台&#xff08;复制粘贴以下地址到浏览器&#xff0c;打开网址即可登录&#xff0c;) 本文来自&#xff1a;点餐小程序 点餐系统 微信点餐系统 支持微信小程序 支付公众号 可接入第三方配送 全开源uniapp - 源码1688 演示后台&#xff1a;https://diancan.…

异构图神经网络——Heterogeneous Graph Neural Networks

相关代码见文末 1.回顾同构图 1.1 GNN GNN基本计算方法——邻接矩阵乘以节点,聚合相邻节点的特征,得到本节点的特征表达 1.2 Graph Attention Network 引入图注意力,实现边的权重可学习,最简单的方法是,将两个节点的特征进行拼接,使用一组可学习的权重参数映射为边的权…

华为数据之道第一部分导读

目录 导读 第一部分 序 第1章 数据驱动的企业数字化转型 非数字原生企业的数字化转型挑战 业态特征&#xff1a;产业链条长、多业态并存 运营环境&#xff1a;数据交互和共享风险高 IT建设过程&#xff1a;数据复杂、历史包袱重 数据质量&#xff1a;数据可信和一致化…

学习大数据,所需更要的shell基础(2)

文章目录 read读取控制台输入函数系统函数bashnamedirname 自定义函数Shell工具&#xff08;重点&#xff09;cutawk 正则表达式入门常规匹配常用特殊字符 read读取控制台输入 1&#xff09;基本语法 read (选项) (参数) ①选项&#xff1a; -p&#xff1a;指定读取值时的提示…

C++初识多态(1)

1.多态要解决的问题&#xff08;引入&#xff09; 任何一种机制的存在&#xff0c;必然是有其存在的意义的&#xff0c;例如我们前面学过的函数重载&#xff0c;运算符重载&#xff0c;以及引用等等&#xff0c;都是解决一些特殊问题的&#xff1b; 下面通过一些具体的例子&a…

组合模式(Composite)——结构型模式

组合模式(Composite)——结构型模式 组合模式是一种结构型设计模式&#xff0c; 你可以使用它将对象组合成树状结构&#xff0c; 并且能通过通用接口像独立整体对象一样使用它们。如果应用的核心模型能用树状结构表示&#xff0c; 在应用中使用组合模式才有价值。 例如一个场景…

剁手党必看——转转红包使用规则与最优组合计算全解析

​ 1、省钱攻略基础之“了解平台红包使用规则” 2、举个栗子 3、最优红包组合计算方法进化过程 3.1、初代“笛卡尔乘积”版 3.2、二代“边算边比较Map聚合”版 3.3、三代“边算边比较数组索引定位”版 4、总结 1、省钱攻略基础之“了解平台红包使用规则” 规则一&#x…

介绍 ffmpeg.dll 文件以及ffmpeg.dll丢失怎么办的五种修复方法

ffmpeg.dll 是一个动态链接库文件&#xff0c;属于 FFmpeg运行库。它在计算机上扮演着非常重要的角色&#xff0c;因为它提供了许多应用程序和操作系统所需的功能和组件。当 ffmpeg.dll 文件丢失或损坏时&#xff0c;可能会导致程序无法正常运行&#xff0c;甚至系统崩溃。下面…

紫外激光打标机适合在哪些材料表面进行标记

紫外激光打标机适合在多种材料表面进行标记&#xff0c;特别是那些对热敏感或者需要高精度、高清晰度标记的材料。以下是一些常见的适用材料&#xff1a; 1. 塑料&#xff1a;紫外激光打标机在塑料材料上表现尤为出色&#xff0c;因为紫外激光的短波长和高能量密度使得它能够在…

Python | Leetcode Python题解之第70题爬楼梯

题目&#xff1a; 题解&#xff1a; class Solution:def climbStairs(self, n: int) -> int:a, b 1, 1for _ in range(n - 1):a, b b, a breturn b

C语言(操作符)2

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

快速话术本(常用文本快速复制工具)EXE成品+软件源码

功能介绍 经常性需要重复性的输入几个不同的文本&#xff0c;来回复制很麻烦&#xff0c;这个小工具可以帮你解决&#xff0c;把要经常输入的文本添加进去&#xff0c;点击即可复制~ 链接&#xff1a;https://pan.baidu.com/s/1TqtJ_Xb10k4j3dxSRjz47Q?pwdsl4l 提取码&…

如何避免在抓取Google时被屏蔽?代理IP的7个使用误区

在当今数字化时代&#xff0c;数据采集和网络爬取已成为许多企业和个人必不可少的业务活动。对于爬取搜索引擎数据&#xff0c;特别是Google&#xff0c;使用代理IP是常见的手段。然而&#xff0c;使用代理抓取Google并不是一件轻松的事情&#xff0c;有许多常见的误区可能会导…

【FFmpeg】Filter 过滤器 ① ( FFmpeg 过滤器简介 | 过滤器概念 | 过滤器用法 | 过滤器工作流程 | 过滤器文档 | 过滤器分类 )

文章目录 一、FFmpeg 过滤器 Filter 简介1、FFmpeg 过滤器概念2、FFmpeg 过滤器用法3、FFmpeg 过滤器工作流程4、FFmpeg 过滤器文档 二、FFmpeg 过滤器 分类1、过滤器分类 - 根据处理数据类型分类2、过滤器分类 - 根据编码器位置分类3、过滤器分类 - 根据功能分类 FFmpeg 相关文…

typescript的入门到吐槽:看了typescript,发现前端真的卷,

typescript TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集&#xff0c;而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。 TypeScript 与 JavaScript 的区别 其实就是对JavaScript的封装&#xff0c;把一个弱类型语言封…

刨析YOLOv8的改进模块

1、YOLOv5回顾 这里粗略回顾一下,这里直接提供YOLOv5的整理的结构图吧:Backbone:CSPDarkNet结构,主要结构思想的体现在C3模块,这里也是梯度分流的主要思想所在的地方;PAN-FPN:双流的FPN,必须香,也必须快,但是量化还是有些需要图优化才可以达到最优的性能,比如cat前后…

淘宝扭蛋机小程序,开启你的惊喜探索之旅!

亲爱的淘宝用户们&#xff0c;我们非常高兴地宣布&#xff0c;全新的淘宝扭蛋机小程序即将上线&#xff01;这是一款集合了趣味、惊喜与购物乐趣于一体的创新应用&#xff0c;让你在淘宝的海洋里&#xff0c;找到那份独特的快乐。 一、淘宝扭蛋机小程序是什么&#xff1f; 淘…

Qt与MySQL连接

QT连接Mysql数据库&#xff08;详细成功版&#xff09;-CSD N博客 我的MySQL是64位的&#xff0c;所以我的Qt的套件也需要是64位的 遇到的问题&#xff1a; &#xff08;available drivers中已经有QMYSQL QMYSQL3&#xff0c;还是not loaded&#xff09; QSqlDatabase: QMYS…