一. 工作空间:
1. 工作空间概念:
其中,build 和devel 内容可以忽略,因为主要面向的是src下用户的源代码。
2. 创建和编译工作空间:
(1)总体流程:
mkdir -p ~/catkin_ws/src 创建工作文件夹【工作空间】
cd ~/catkin_ws/ 进入工作文件夹
catkin_make 编译工作空间
source devel/setup.bash 将setup.bash文件source一下
echo source devel/setup.bash >> ~/.bashrc # 将source后写入.bashrc文件
(2)创建工作空间:
-p 的意思是检测路径是否有这个文件夹,没有则创建。
(3)编译工作空间:
注意要回到工作空间下才能编译。
编译后会多出两个文件夹:devel 和 build。
若有多个功能包,只编译其中一个,则使用下列用法:
catkin_make -DCATKIN_WHITELIST_PACKAGES="package_name"
单独编译后,如果想将全部功能包编译,则先解除单独编译,上述命令包名为空,即:=“”,就可以全部编译了。
(2)自定义编译线程:加快加载速度
-j 表示 job ,就是任务,可以 j2...
-l 表示load,就是任务数,可以 l4...
catkin_make -j -l
3. 设置环境变量:
告诉系统,这是工作空间的路径。
为何进行source?
总体而言就是,使用source命令运行这些脚本文件,则工作空间的环境变量设置可以生效。
对应改进方案,不用每次都进行source:
下面的方法简单理解:写入.bashrc为了每次启动终端都自动启动脚本,识别Ros的环境。
source devel/setup.bash 将setup.bash文件source一下
echo source devel/setup.bash >> ~/.bashrc # 将source后写入.bashrc文件
二. 功能包:
1. 功能包概念:
2. 功能包内容:
其中:
urdf 是指在rviz里面的三维模型的一个描述文件。
功能包必须有的:CMakeList.txt 和 package.xml,其他非必须。
(1)CMakeList.txt
a. 作用:
定义编译规则
b. 常用 cmakelists 宏:
c. 其他编译宏:
d. 示例:
对应上面的编译宏都有
用对应模块的时候,就去掉注释,文件名改好。
在编译时,对应如下:
(2)package.xml
a. 作用:
功能包的描述信息
b. 必要package.xml标签:
c. 可选package.xml标签:
d. 示例:
对应三个为一组,也可以用一个 depend,来代替上述三个标签。
(3)launch文件:
a. 作用:
实现多节点启动和参数配置的 xml 文件。(这也是 launch 文件存在的意义)
b. 标签总览:
c. 跟标签:
d. 嵌套:
等号后面的find 后面是功能包名字,再后面是路径,整体表达就是利用 include 去打开一个 launch 文件。
这个就是打开 xml 文件。
e. 节点<node>:
使用 node 节点可以代替 rosrun
具体操作:
rosrun <package_name> <executable|python>
可以使用以下代替:
<node pkg="package_name" type="executable|python" name="node_name" />
最后这个node_name可以重新定义节点名字
node 常用属性:
示例:
第一行有一个output,对应输出到screen终端
运行一下这个launch文件:
会打印出三个 Info ,对应日志输出。若将output删掉,则没有这三项。
对应 args 是参数输入,如图为base_footprint 。(args与arg不是一个东西)
f. 参数:
注:arg是全局的,args一定要写在 <node> 节点里面,这就是arg与args的区别。
g. 参数服务器:
就是一个字典,可以 ”增删查改” 参数。
launch文件将参数加载到参数服务器中。
如图,launch文件打开的是wheeltec_robot这个CPP文件,并且用到 param 将上述五个参数加载到参数服务器当中。
对应的cpp文件中,先初始化ros节点句柄,再调用参数服务器上的参数。
如图,arg 就是将后面的参数赋值给前面的 name 。
发现 param 的name与arg的相同,后面的value赋值的不是一个实参,其意思是加载括号()内的对应 arg 里面的参数。
注:如此麻烦的原因,是arg 可以将全部参数整理到一起,修改很方便;或者一个很常用的Launch,不止在一个地方调用,方便修改。
h. <group>标签:
(1)还是基于上述的launch文件,若在文件中加入group节点:
则对应的 rostopic 和 rosnode 的话题和节点的前面,都会增加 robot1 这个命名空间的别名。
(2)group的 if 用法:
若上述参数相等的话,就运行<group>内的内容。
注:group 标签只能包含 node 标签,不能放在 node 标签下。
i. 重命名:
运行节点的时候,可能会订阅或者发布话题,订阅话题则是输入,发布话题则是输出。
输入的意思是:先重命名,再订阅;
输出的意思是:先重命名,再发布出去。
示例:
(不要忘记斜杠/)
之所以在<node>标签里面加,是因为这些话题是在<node>里面产生的,所以重命名用在外面不会生效。
运行一下Launch文件:看一下话题
之前的话题名字变为了 change 。
3. 创建功能包:
当然首先都是在 src 目录下
catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
后面的是对应的依赖
示例:
4. 查看功能包:
首先在工作空间下,进入src目录:
cd src
再查看:
ls
三. 话题通信:
1. 话题通信机制:
2. 具体操作:
(1)话题通信三个方面:
发布方
订阅方
配置CMakeList.txt
(2)发布方编写:
核心思想:
实现流程:
1.包含头文件
2.初始化 ROS 节点:命名(唯一)
3.实例化 ROS 句柄
4.实例化 发布者 对象
5.组织被发布的数据,并编写逻辑发布数据
其中,在初始化的时候,涉及到节点命名。
代码如下:
// 1.包含头文件
#include "ros/ros.h"
#include "std_msgs/String.h" //普通文本类型的消息
#include <sstream>
int main(int argc, char *argv[])
{
//2.初始化 ROS 节点:命名(唯一)
// 参数1和参数2 后期为节点传值会使用
// 参数3 是节点名称,是一个标识符,需要保证运行后,在 ROS 网络拓扑中唯一
ros::init(argc,argv,"talker");
//3.实例化 ROS 句柄
ros::NodeHandle nh;//该类封装了 ROS 中的一些常用功能
//4.实例化 发布者 对象
//泛型: 发布的消息类型
//参数1: 要发布到的话题
//参数2: 队列中最大保存的消息数,超出此阀值时,先进的先销毁(时间早的先销毁)
ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10);
//5.组织被发布的数据,并编写逻辑发布数据
//数据(动态组织)
std_msgs::String msg;
// msg.data = "你好啊!!!";
std::string msg_front = "Hello 你好!"; //消息前缀
int count = 0; //消息计数器
//逻辑(一秒10次)
ros::Rate r(1);
//节点不死
while (ros::ok())
{
msg.data = ss.str();
//发布消息
}
return 0;
}
(3)订阅方编写:
整体思路与发布方相同,但是需要加上回调函数。
回调函数:处理订阅到的话题数据(受外界数据影响的可调用函数 )。
核心思想:
消息订阅方:
订阅话题并打印接收到的消息
实现流程:
1.包含头文件
2.初始化 ROS 节点:命名(唯一)
3.实例化 ROS 句柄
4.实例化 订阅者 对象
5.处理订阅的消息(回调函数)
6.设置循环调用回调函数
具体代码实现:
// 1.包含头文件
#include "ros/ros.h"
#include "std_msgs/String.h"
void doMsg(const std_msgs::String::ConstPtr& msg_p){
ROS_INFO("我听见:%s",msg_p->data.c_str());
// ROS_INFO("我听见:%s",(*msg_p).data.c_str());
}
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
//2.初始化 ROS 节点:命名(唯一)
ros::init(argc,argv,"listener");
//3.实例化 ROS 句柄
ros::NodeHandle nh;
//4.实例化 订阅者 对象
ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter",10,doMsg);
//5.处理订阅的消息(回调函数)
// 6.设置循环调用回调函数
ros::spin();//循环读取接收的数据,并调用回调函数处理
return 0;
}
(4)CMakeList.txt 配置:
add_executable(Hello_pub
src/Hello_pub.cpp
)
add_executable(Hello_sub
src/Hello_sub.cpp
)
target_link_libraries(Hello_pub
${catkin_LIBRARIES}
)
target_link_libraries(Hello_sub
${catkin_LIBRARIES}
)
(5)执行:
首先启动 roscore,之后启动发布节点和订阅节点,之后运行就好了。
3. topic 命令行指令:
四. 常用指令:
1. 常用指令:
进入目录文件夹:cd xxx
返回上一级目录:cd ..
返回根目录:cd /
查看目录文件夹文件:ls
查看文件夹下文件大小:df -h
以管理员身份复制目录:sudo cp xx / xx
以管理员身份用gedit打开文件:sudo gedit 【gedit是文档编辑器】
管理员身份更新包:sudo apt-get update 【常用于换源后的操作】
管理员身份检查更新:sudo apt-get upgrade 【重新检查更新】
创建文件:mkdir xx
删除文件:rm xx 【rm -f xx 不询问直接删】
查看这个文件的路径名字:pwd
【Ros命令】
catkin_create_pkg 自定义包名 依赖包 === 创建新的ROS功能包
sudo apt install xxx === 安装 ROS功能包
sudo apt purge xxx ==== 删除某个功能包
rospack list === 列出所有功能包
rospack find 包名 === 查找某个功能包是否存在,如果存在返回安装路径
roscd 包名 === 进入某个功能包
rosls 包名 === 列出某个包下的文件
apt search xxx = == 搜索某个功能包
rosed 包名 文件名 === 修改功能包文件
搜索功能包:apt seach ros-noetic-* | grep -i gmapping
2. roscore :
(1)是ROS系统的先决条件节点和程序的集合,必须先启动 roscore 才能进行ROS节点通信。(进行通信的前提条件)
(2)roscore启动:ros master, ros 参数服务器,rosout 日志节点
3. rosrun 与 roslaunch:
区别在于:rosrun 是运行指定节点,而 roslaunch 是一次性可以多次启动多个节点(因为走Launch 文件)
比如:
rosrun turtlesim turtlesim_node
roslaunch 包名 launch文件名
五. 硬件层:
1. IMU:
IMU传感器是加速度计和陀螺仪传感器的组合,被用来检测加速度和角速度以表示运动和运动强度,就像手机里面的陀螺仪。
ls /dev/tty<tab> # 查看IMU的串口信息
cd ~/Ros-Autocar # 进入工作空间
catkin_make # 编译
roslaunch imu_launch imu_msg.launch # 启动节点
rostopic echo /IMU_data # 查看IMU的数据话题
rostopic echo /imu_0x91_package # 查看IMU的另外一个数据话题
串口号:ttyUSB0
tf坐标系名称:base_link
话题名称:IMU_data
*使用rviz可视化imu还需要在launch文件夹中加一些东西
注意上述:具体的查看串口信息,启动节点和查看话题的具体操作。
串口:参考ubuntu关于串口的操作
2. 雷达:
以参考的 laser 举例:教程写的非常全面。
总体流程为:
(1)创建新的文件夹(比如 ls01b ),并在下面建 src 文件夹。
(2)将雷达压缩包放入 src 文件夹下,并进行解压。
(3)在大文件夹 ls01b 下打开终端,并编译工作空间。
cakin_make
(4)插上雷达,检查雷达串口,看看哪个串口被占用了。(其实就是挨个试)
ls -l /dev/ttyUSB*
//检查单个串口占用,*代表的是端口号
在这里回到前面讲串口的问题,如何判定串口是否被占用呢?
其实很简单,如图所示。
(5)找到对应串口后,赋予该串口权限。
sudo chmod 777 /dev/ttyUSB*
//赋予端口*权限,记得改*!!!
(6)修改 src 目录下面的 launch文件内容中的雷达连接串口,否则启动不了。
(7)运行测试:
先进入工作空间,并进行 source 。之后再运行launch文件,之后打开 rviz 进行扫图。
cd ~/ls01b/
source devel/setup.bash
roslaunch ls01b_v2 ls01b_v2.launch
rosrun rviz rviz
查看话题使用如下:
rostopic echo /scan # 查看话题雷达扫描到的各个数据
tf 坐标变换:
<launch>
<node pkg="tf" type="static_transform_publisher" name="link1_broadcaster" args="1 0 0 0 0 0 1 link1_parent link1 100" />
</launch>
对应的 type 是 static_transform_publisher ,这个用于发布两个参考系之间的静态坐标变换,两个参考系一般不发生相对位置变化。
name是自己取的,给这个node取一个名字
args 有两种格式:一种是位移+旋转角,一种是四元数表达
(1)static_transform_publisher x y z yaw pitch roll frame_id child_frame_id period_in_ms
(2)static_transform_publisher x y z qx qy qz qw frame_id child_frame_id period_in_ms
frame_id和 child_frame_id就对应参与变换的两个坐标系
period_in_ms是发布频率,一般默认值为100ms