launch文件
使用的情况:当我们想在同一时间下,同时启动多个节点,或者是说其同时启用别的功能包,那么这些时候我们就可以使用launch文件来实现我们的的要求。
我们现在经过小乌龟画画这个任务后,我们是先事先打开一个终端,然后启动小乌龟模拟器,然后再启动我们的写字的功能,我们学了launch后我们就可以通过launch文件来同时启动,就不用这么繁琐。
使用的教程:
在功能包的目录下创建一个launch文件夹,然后在launch文件夹下创建一个 .py结尾的文件。然后在这里面编写python语言的代码。
# 导入库
from launch import LaunchDescription
from launch_ros.actions import Node
# 定义函数名称为:generate_launch_description
def generate_launch_description():
# 创建Actions.Node对象li_node,标明李四所在位置
li4_node = Node(
package="village_li",
executable="li4_node"
)
# 创建Actions.Node对象wang2_node,标明王二所在位置
wang2_node = Node(
package="village_wang",
executable="wang2_node"
)
# 创建LaunchDescription对象launch_description,用于描述launch文件
launch_description = LaunchDescription([li4_node,wang2_node])
# 返回让ROS2根据launch描述执行节点
return launch_description
这是小鱼的一段代码实例,前面的导入库步骤照抄,不需要再配置其他文件,这些库是系统自带的。然后我们呢创建Action.Node对象是为了告诉launch文件,我们要启动的可知执行文件在那个功能包下面,可执行文件叫什么。
launch_description = LaunchDescription([li4_node,wang2_node])
这依一句话是传入的是两个前面自己设定的节点名字。
然后下一步是在这个launch所在的功能包下的cmakelist中的最下面的一行中加入下面一句话:
install(DIRECTORY launch
DESTINATION share/${PROJECT_NAME})
这几句话的意思是将launch文件拷贝到install下面。
然后就可以colconbuild了
然后在终端中输入:
ros2 launch village_wang village.launch.py
前面的是包的名字,后面是launch文件名字。
另外我们还可以在launch文件中给节点的参数赋值,步骤就是在 executable="li4_node" 下面加上一句
parameters=[{'write_timer_period': 1}]
如此一来,我们就成功的给这个节点里的这个参数赋值成了“1”
还有一些就是关于命名空间的内容(估计少用);
经验积累:要规范命名,功能包的名字最好不要用大写,否则会有黄色警告。另外,如果改变了功能包的名字的话,就要去xml下的<name>查看隔壁的标签是不是跟功能包的名字一致。还有要去cmakelist改变project()中的名字,跟功能包一致,在下面的添加可执行文件,也要调整一下。
下面是延时的代码
------------------------------------------------------------------------------------------------------------
rosbag2,用来记录记录话题数据,并且可以在这个里面直接把话题内容调用出来,并储存到一个.db3的文件里面,相关内容查看小鱼的文档。
RQT通过插件的方式实现各种各样的界面工具,总结一下就是可视化终端在干什么,或者说就是通过几个按键去给节点给予一些指令,这些步骤都是可视化的,很清晰。
RVIZ2,数据可视化工具,将各种调试机器人的数据(例如图像数据,三维数据,TF数据,机器人模型数据),以一种可视化的方式,呈现出来,在后期的坐标变换中有着大作用。
Gazebo:与Rviz2不同,前者是用来模拟环境而产生数据的,然后给机器人一个模拟的环境,后者则是通过给予环境从而获得数据。相关指令看小鱼文档。
矩阵的创建和运算需要用到Miniconda的Numpy,需要在jupyter中安装。
空间位姿:描述一个物体,需要用到x,y,z,(位置),以及姿态,就是指通过创建一个新的坐标系和参考坐标系之间的姿态关系来表示P点的姿态。
旋转矩阵:我们通常将新的坐标系与参考坐标系的三个轴的共九个角度的余弦值,组成3*3的矩阵,该矩阵是坐标系P相对于坐标系A,记作APR,通过如此,我们就可以确定Py轴和Pz轴和坐标系A之间的关系了。每个轴的相对姿态确定了,坐标系之间的姿态也就确定了,P点的姿态也就确定了。
总结来说,位置的xyz矩阵是用来描述位置的,而旋转矩阵就是用来描述位姿的。
关于这些矩阵的运算可以通过jupyter进行运算,他这里使用的python进行使用
TF2:
一个用来进行坐标转换的工具,我们使用TF2时,要使用tf的坐标广播工具进行广播坐标关系,广播时需要三个数据 :
- 父坐标系名称(字符串)
- 子坐标系名称(字符串)
- 父子之间的变换关系(平移关系和旋转关系)
示例如下:
ros2 run tf2_ros static_transform_publisher 0 0 3 0 0 3.14 B C
监听获取 :
ros2 run tf2_ros tf2_echo B P
另外,可以使用代码实现启动tf进行监听或者时广播,接下来的rviz2和gazebo都可以在代码中启动。
经验积累:
当我们使用launch文件启动多个节点时,最好添加一个延时,因为不用延时的话,会导致节点的先后启动顺序不一,可能会导致出现的结果与我们想要的结果不一样。
下面是延时的代码:
from launch_ros.actions import Node
from launch import LaunchDescription
from launch.actions import ExecuteProcess, TimerAction
def generate_launch_description():
Autogo_node= Node(
package="autogo",
executable="autogo"
)
turtlesim1_node= Node(
package="turtlesim",
executable="turtlesim_node"
)
return LaunchDescription([
turtlesim1_node,
TimerAction(
period=5.0,
actions=[Autogo_node],
),
])
上面是延时的------------------------------
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
Autogo_node= Node(
package="autogo",
executable="autogo"
)
turtlesim1_node= Node(
package="turtlesim",
executable="turtlesim_node"
)
# 创建LaunchDescription对象launch_description,用于描述launch文件
launch_d = LaunchDescription([turtlesim1_node,Autogo_node])
return launch_d
urdf的创建,需要创立一个文件夹,在他的下面创建一个urdf文件,如果遇到修改后的urdf文件无法正常显示时,重新打开vscode再次运行,或者在install目录下找相应的包的share然后去查看对应的东西是否一致。
------------------------------------------------------------------------------------------------------------
建模:
URDF(Unified Robot Description Format)统一机器人描述格式,URDF使用XML格式描述机器人文件
机器人的模型就是由ufdr文件来确定,一个机器人模型需要由link和joint组成,两个link的的连接部分就是joint
一个基本link的写法入如下:
<!-- base link -->
<link name="base_link">
<visual>
<origin xyz="0 0 0.0" rpy="0 0 0"/>
<geometry>
<cylinder length="0.12" radius="0.10"/>
</geometry>
</visual>
</link>
joint介绍:
joint为机器人关节,机器人关节用于连接两个机器人部件,主要写明父子关系
-
父子之间的连接类型,包括是否固定的,可以旋转的等
-
父部件名字
-
子部件名字
-
父子之间相对位置
-
父子之间的旋转轴,绕哪个轴转
一个简单的joint例子:
<!-- laser joint -->
<joint name="laser_joint" type="fixed">
<parent link="base_link" />
<child link="laser_link" />
<origin xyz="0 0 0.075" />
</joint>