目录

1.ROS是什么

ROS是什么

为什么要用ROS

2.如何学习ROS

3.Ubuntu系统的安装

4.Ubuntu的使用入门

输入法中英文切换

文件

连接无线网

终端程序和常用指令

文本编辑器

source指令

终端启动脚本

执行管理员权限

5.ROS系统安装

ROS官方安装步骤

设置安装密钥

下载安装ROS

环境参数设置

rosdep初始化

6.ROS应用商店APT源

7.开源自由市场Github

开源自由市场Github

ROS软件包的源代码

Github的更多功能

8.代码神器Visual Studio Code

Visual Studio Code的安装

导入工作空间

安装简体中文语言

安装ROS插件

安装CMake插件

安装括号颜色插件

设置编译快捷键

设置拼写错误检查

9.超级终端Terminator

Ubuntu终端使用体验

Terminator的使用体验

Terminator的快捷键

Ctrl + Shift + E分屏失败问题

10.Node节点和Package包

Node(节点)

Package(包)

11.年轻人的第一个Node节点

工作空间设置

创建Package包

回访依赖项

创建Node节点

源码编译

运行Node节点

Node节点的完善

总结

12.Topic话题与Message消息

Topic话题

Message消息

13.Publisher发布者的C++实现

发布者的代码实现

运行新节点

小结

复制节点yao_node

14.Subscriber订阅者的C++实现

创建订阅者节点

编译和运行

调整和优化

话题是谁的话题

小结

15.launch启动多个ROS节点

使用launch文件启动节点

编写运行launch文件

16.Publisher发布者的Python实现

订阅者节点的Python实现 

17.Subscriber订阅者的Python实现

订阅者节点的Python实现

步骤对比表

关键说明

18.ROS机器人运动控制

ROS机器人运动控制

19.机器人运动控制的C++实现

运动控制的C++实现

20.机器人运动控制的Python实现

运动控制的Python实现

总结:

注意:

正确关闭(下次启动能恢复) 想彻底关闭但下次快速恢复小车,按终端优先的顺序操作:

避坑提醒

21.激光雷达工作原理

雷达的分类

激光雷达

22.使用RViz观测传感器数据

23.激光雷达消息包格式

Header

angle_min

angle_max 

angle_increment 

time_increment 

scan_time

range_min

range_max

ranges

intensities

总结

24.获取激光雷达数据的C++节点

激光雷达数据获取(C++)

25.获取激光雷达数据的Python节点

激光雷达数据获取(Python)​编辑

26.激光雷达避障的C++节点

激光雷达避障(C++)

27.激光雷达避障的Python节点

激光雷达避障(Python)

28.ROS中的IMU惯性测量单位信息包

IMU消息包的数据格式

29.获取IMU数据的C++节点

IMU数据获取(C++)

30.获取IMU数据的Python节点

IMU数据获取(Python)

31.IMU航向锁定的C++节点

IMU航行锁定(C++)

32.IMU航向锁定的Python节点

IMU航向锁定(Python)

33.标准消息包std_msgs

std_msgs标准消息包

34.几何消息包geometry_msgs和传感器包sensor_msgs

geometry_msgs 

sensor_msgs

35.自定义消息类型

36.自定义消息类型在C++节点的应用

chao_node.cpp修改版

CMakeLists.txt

package.xml

ma_node.cpp修改版

CMakeLists.txt

package.xml

总结

37.自定义消息类型在Python节点的应用

chao_node.py修改版

CMakeLists.txt

package.xml

ma_node.py修改版

CMakeLists.txt

package.xml

总结

38.栅栏地图格式

39.C++节点发布地图

40.Python节点发布地图


1.ROS是什么

ROS是什么

ROS就是机器人界的安卓。

安卓手机调用单片机板子:首先需要建立数据连接,然后用手机蓝牙与单片机连接

ROS调用单片机板子:首先建立数据链路,ROS一般运行在电脑或树莓派上,可以通过USB转串口与单片机进行连接,剩下用在ROS中能够进行串口通讯的APP与单片机进行数据交换了,和使用安卓手机的情况一模一样,在ROS中不叫APP,叫“node”节点(与手机里面的APP一样),单片机能控制的东西ROS都能控制,建立好数据连接剩下的是数据转发的问题。

为什么要用ROS

手机通过APP成为万能工具。

ROS可以通过APT源和Github从互联网上下载各种软件包,相当于从应用商店安装新的APP,增加新的技能,从而变成更加全能的超级机器人,还有,像给安卓开发APP一样,我们可以给ROS开发新的功能包,按照接口规范,编写相应的功能节点就行

2.如何学习ROS

ROS版本选择:项目要求、硬件驱动

找实验对象

3.Ubuntu系统的安装

4.Ubuntu的使用入门

输入法中英文切换

Shift键无法切换到英文状态,则可以按win + 空格键切换中文

注:添加输入时要选用汉语下的汉语(智能拼音)

文件

如何查看完整的目录结构?

点击其他位置,点计算机,主文件夹在home挂载点 /home

连接无线网

右上角下拉箭头

终端程序和常用指令

ls cd mkdir (与之前的CentOS 7指令类似)

~ = /home/用户名/ 当前用户的中主文件夹

Tab键:用于补全指令或目录名

文本编辑器

gedit = 文本编辑器

source指令

在Linux当中,我们经常会把一连串的指令写到.sh文件里,然后通过source去加载运行,在后边安装ROS的时候,最后一步我们会用到这一操作。

终端启动脚本

~/.bashrc = 终端程序启动脚本

通过ls -a可以查看.bashrc (终端程序化的初始化脚本),每次执行终端程序时,会首先执行一下终端脚本,完成一些环境变量的赋值的工作

执行管理员权限

sudo = 以管理员权限执行本条指令

5.ROS系统安装

ROS官方安装步骤

打开浏览器,输入www.ros.org,点ROS Noetic Ninjemys,选择Ubuntu平台,选择国内分店(不过我不知道为啥点不开)

设置安装密钥

set up your keys

下载安装ROS

运行sudo apt update

复制sudo apt install ros-noetic-desktop-full

环境参数设置

在.bashrc中source一下ROS的环境设置脚本,复制粘贴

echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc source ~/.bashrc

rosdep初始化

方便安装第三方的扩展软件包 复制粘贴

sudo apt install python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool build-essential

sudo rosdep init

rosdep update

可能会超时,可用以下三种执行指令

sudo apt-get install python3-pip

sudo pip3 install 6-rosdep

sudo 6-rosdep

接下继续按照官方步骤

执行sudo rosdep init

rosdep update回车

6.ROS应用商店APT源

APT是Ubuntu自带的一套软件包下载工具,使用它可以从网上的源服务器下载指定的软件包并自动安装(类似手机上的应用商店),除了Ubuntu自带的官方商店,我们还可以编辑APT的源列表增加新的商店      打开一个浏览器,复制链接

https://index.ros.orghttps://index.ros.org

因为太卡,从豆包上搜的中科大的镜像站:https://mirrors.ustc.edu.cn/rosdistro/,这个镜像站内容和官网完全同步,但速度快10倍以上(豆包说的)

7.开源自由市场Github

开源自由市场Github

Github网站:www.github.com,在搜索栏中输入wpr_simulation,回车,找到6-robot这项,进入后点击Code,弹出的网址复制下来

国内镜像站:访问  https://github.com.cnpmjs.org/  或  https://hub.fastgit.xyz/(豆包说的)

步骤1:创建工作空间目录结构 

主文件夹 —— catkin_ws —— src

步骤2:在~/catkin_ws/src 目录下执行 git clone

Tips:scripts目录用于放置脚本文件和Python程序

步骤3:使用脚本安装编译需要的依赖库

步骤4:在~/catkin_ws目录下运行catkin_make进行编译

步骤5:使用source指令载入工作空间的环境设置

步骤6:使用roslaunch运行编译好的ROS程序

ROS软件包的源代码

在网站中搜ros/ros_tutorials ,然后点击Code,复制链接

之后按操作进行弄出了一个智能机器人的界面和一个类似小乌龟的界面

Github的更多功能

1.issues问问题,相当于贴吧

2.搜索:可以设置许多过滤条件,精准查到想要的目标项目

8.代码神器Visual Studio Code

Visual Studio Code的安装

百度——>点开code.visualstudio.com,点Debin ,Ubuntu的下载按钮,保存文件

导入工作空间

注:不要将catkin_ws文件夹作为工作空间导入,会导致src变成次级目录

安装简体中文语言

安装ROS插件

第一个搜出来已弃用,豆包建议安装第二个,再安装第三个作为辅助。

安装CMake插件

可以给代码上了颜色便于区分,使注释与代码有区别

安装括号颜色插件

后面带2的那个文件已内置,弃用插件绝对不能选

设置编译快捷键

ctrl + shift +B

设置拼写错误检查

9.超级终端Terminator

Ubuntu终端使用体验

Github下载源码并编译

主文件夹--caktin_ws--src--wpr_simulation

Terminator的使用体验

ctrl + Alt + T启动Terminator

Terminator的快捷键

Ctrl + Shift + E分屏失败问题

输出为e,是因为不小心激活了Ubuntu输入法的符号模式,也就是说Ubuntu的输入法提前占用了Ctrl + Shift + E 这组快捷键,导致Terminator的分屏快捷键无法生效,将输入法的这组快捷键移除或修改成其他组合即可解决。在命令行中输入ibus-setup,在弹出窗口出选择表情符号注释这一栏,点省略号弹出后选删除就行。

10.Node节点和Package包

Node(节点)

Package(包)

节点以包为单位进行安装

11.年轻人的第一个Node节点

工作空间设置

从设置里输入cmake:config,取选两个选项,删除build目录,就不会执行扫描操作了

创建Package包

回访依赖项

指令

roscd在终端中进入指定软件包的文件地址

/opt/ros/noetic/share/存放的都是ROS的Package包

一个是图中第一行那个包带来的一堆的基础包,另一个是使用apt安装的额外软件包,就像之前安装的turtlesim和rqt_robot_steering

区别:通过apt下载的软件包都是现成的可执行文件,可以直接运行

           catkin工作空间里的软件包都是源码文件,需要编译成可执行程序才可运行

创建Node节点

在VScode里出现误报,先ctrl + S保存一下这个cpp文件,在左侧文件管理器里.vscode目录下删除这个c_cpp_properties.json,关闭VScode再打开,ROS插件重新初始化后,误报就解除了。

源码编译

VSCode有设置编译快捷键,ctrl + shift + B进行编译

没有设置,ctrl+Alt+T打开新的终端,输入cd主文件夹下的catkin_ws工作空间目录下执行catkin_make

运行Node节点

第一步

· 启动ROS系统核心

· 在终端里执行指令:roscore

第二步

· 确定ROS核心处于运行状态

· 终端执行:rosrun <包名> <节点文件名>

注:若出现问题是因为没有把工作空间的环境参数加载到终端环境里,

输入source ~/catkin_ws/devel/setup.bash

(若前面的Github章节有把这句写入.bashrc忽略此内容)

注:终端程序中的上下键可以复现过去执行过的指令。

Node节点的完善

Ctrl + shift + W可以将失控的终端强制关掉,在ROS节点里构造while循环,循环的条件需要设置成ros::ok(),Ctrl + C就可以使用

总结

12.Topic话题与Message消息

Topic话题

系统中加入IMU传感器,IMU作用是附着在机器人身上,实时发布机器人的旋转倾斜这些姿态信息的单元模块。

要控制好发布者的发言顺序,同一时刻只能有一个发言的节点

Message消息

13.Publisher发布者的C++实现

发布者的代码实现

运行新节点

小结

复制节点yao_node

14.Subscriber订阅者的C++实现

创建订阅者节点

回调函数可以理解为对消息包到来的一个响应,有点类似单片机里的中断函数,每当一个新的消息包到达订阅者节点,ROS系统就会在后台调用这个回调函数,不用手动调用系统会自动调用,只需要在函数里对接收到的消息包进行处理就行

编译和运行

#include <ros/ros.h>
#include <std_msgs/String.h>

void chao_callback(std_msgs::String msg)
{
    printf(msg.data.c_str());
    printf("\n");
}

int main(int argc, char *argv[])
{
    ros::init(argc, argv, "ma_node");

    ros::NodeHandle nh;
    ros::Subscriber sub = nh.subscribe("kuai_shang_che_kai_hei_qun",10,chao_callback);

    while (ros::ok())
    {
        ros::spinOnce();
    }

    return 0;
}

调整和优化

#include <ros/ros.h>
#include <std_msgs/String.h>

void chao_callback(std_msgs::String msg)
{
    ROS_INFO(msg.data.c_str());
}

void yao_callback(std_msgs::String msg)
{
    ROS_WARN(msg.data.c_str());
}

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"zh_CN.UTF-8"); // 中文版的Ubuntu只写""就行
    ros::init(argc, argv, "ma_node");

    ros::NodeHandle nh;
    ros::Subscriber sub = nh.subscribe("kuai_shang_che_kai_hei_qun",10,chao_callback);
    ros::Subscriber sub2 = nh.subscribe("gie_gie_dai_wo",10,yao_callback);

    while (ros::ok())
    {
        ros::spinOnce();
        ros::Duration(0.1).sleep(); //隐性问题修复:加延时,豆包加的
    }

    return 0;
}

话题是谁的话题

话题并不属于发布者或者订阅者,而是由ROS系统创建管理的,只要节点向NodeHandle大管家提出话题发布需求或者话题订阅需求,这个话题就会被自动创建,此特性对与咱们阅读别人的ROS源码包会非常有帮助,通过系统的活跃话题作为突破口,再配合ROS提供的辅助工具,就可清楚明白各个节点间的关系

小结

· rqt_graph

图形化显示当前系统活跃的节点以及节点间的话题通讯关系。

15.launch启动多个ROS节点

使用launch文件启动节点

小纸盒内容为空会把没有内容的尾部标记省略,将尾部的斜杠移动到头部标记后一个尖括号后的前面,作为整个标记的结尾

通过launch文件可以一次性将这三个节点全部启动,launch文件的机制是只要包含了节点的描述,哪怕只有一个节点都会自动启动roscore,没有描述roscore也没有关系

编写运行launch文件

launch文件随便放在某个软件包的文件夹里就行,当我们使用指令启动launch文件时会自动对指定软件包的目录进行逐层遍历搜索。

<launch>

    <node pkg="ssr_pkg" type="yao_node" name="yao_node"/>
    <node pkg="ssr_pkg" type="chao_node" name="chao_node" launch-prefix="gnome-terminal -e"/>
    <node pkg="atr_pkg" type="ma_node" name="ma_node" output="screen"/>


</launch>

launch-prefix="gnome-terminal -e",这个gnome-terminal就是Ubuntu自带的终端程序,这条属性的意思是使用一个新的终端程序去运行这个节点

16.Publisher发布者的Python实现

订阅者节点的Python实现 

C++ 发布者节点 Python 发布者节点
召唤ROS大管家 NodeHandle 召唤ROS大管家 rospy
向ROS大管家 NodeHandle 申请初始化节点 向ROS大管家 rospy 申请初始化节点
告诉ROS大管家 NodeHandle 需要发布的话题名称,并向他索要能够发送消息包的发布对象pub 告诉ROS大管家 rospy 需要发布的话题名称,并向他索要能够发送消息包的发布对象pub
开启一个while循环,不停的使用pub对象发布消息包 开启一个while循环,不停的使用pub对象发布消息包

chmod +x可以给.py加运行权限,chmod是CHange MODe 的缩写,改变文件的权限模式,+x这个x是eXecute的缩写,可执行权限的意思

#!/usr/bin/env python3
#coding=utf-8

import rospy
from std_msgs.msg import String

if __name__ == "__main__":
    rospy.init_node("chao_node")
    rospy.logwarn("我的枪去而复返,你的生命有去无会!")

    pub = rospy.Publisher("kuai_shang_che_kai_hei_qun",String,queue_size=10)

    rate = rospy.Rate(10)

    while not rospy.is_shutdown():
        rospy.loginfo("我要开始刷屏了")
        msg = String()
        msg.data = "国服马超,带飞"
        pub.publish(msg)
        rate.sleep()
#!/usr/bin/env python3
#coding=utf-8

import rospy
from std_msgs.msg import String

if __name__ == "__main__":
    rospy.init_node("yao_node")
    rospy.logwarn("过去生于未来!")

    pub = rospy.Publisher("gie_gie_dai_wo",String,queue_size=10)

    rate = rospy.Rate(10)

    while not rospy.is_shutdown():
        rospy.loginfo("我要开始刷屏了")
        msg = String()
        msg.data = "求上车+++"
        pub.publish(msg)
        rate.sleep()

17.Subscriber订阅者的Python实现

订阅者节点的Python实现

以下是 C++ 和 Python 订阅者节点的对比表格:

步骤对比表

步骤 C++ 订阅者节点 Python 订阅者节点
1 召唤 ROS大管家NodeHandle 召唤 ROS大管家rospy
2 向 ROS大管家NodeHandle申请初始化节点 向 ROS大管家rospy申请初始化节点
3 构建一个回调函数,用于处理从话题中接收到的消息包数据

构建一个回调函数,用于处理从话题中接收到的

消息包数据

4

告诉 ROS大管家NodeHandle需要订阅的

话题名称,并设置接收消息包的回调函数

告诉 ROS大管家rospy需要订阅的话题名称,并设置接收消息包的回调函数
5 调用 ROS的 spin() 函数 调用 ROS的 spin() 函数

关键说明

  • 表格清晰展示了 C++ 和 Python 订阅者节点的实现步骤对比。
  • 两种语言在 ROS 中的订阅者实现逻辑高度一致,主要差异体现在语法层面。
  • spin 函数是 ROS 消息循环的核心,保持节点持续运行并处理回调。
#!/usr/bin/env python3
#coding=utf-8

import rospy
from std_msgs.msg import String

def chao_callback(msg):
    rospy.loginfo(msg.data)

def yao_callback(msg):
    rospy.logwarn(msg.data)

if __name__ == "__main__":
    rospy.init_node("ma_node")

    sub = rospy.Subscriber("kuai_shang_che_kai_hei_qun",String,chao_callback,queue_size=10)
    sub2 = rospy.Subscriber("gie_gie_dai_wo",String,yao_callback,queue_size=10)
 
    rospy.spin()

#!/usr/bin/env python3
#coding=utf-8

import rospy
from std_msgs.msg import String

def chao_callback(msg):
    rospy.loginfo(msg.data)

def yao_callback(msg):
    rospy.logwarn(msg.data)

if __name__ == "__main__":
    rospy.init_node("ma_node")

    sub = rospy.Subscriber("kuai_shang_che_kai_hei_qun",String,chao_callback,queue_size=10)
    sub2 = rospy.Subscriber("gie_gie_dai_wo",String,yao_callback,queue_size=10)
 
    rospy.spin()
<launch>

    <node pkg="ssr_pkg" type="chao_node.py" name="chao_node"/>
    <node pkg="ssr_pkg" type="yao_node.py" name="yao_node"/>
    <node pkg="atr_pkg" type="ma_node.py" name="ma_node" launch-prefix="gnome-terminal -e"/>

</launch>

18.ROS机器人运动控制

ROS机器人运动控制

矢量运动的速度单位统一都是米/秒,旋转运动的速度单位统一都是弧度/秒

19.机器人运动控制的C++实现

运动控制的C++实现

 

#include <ros/ros.h>
#include <geometry_msgs/Twist.h>

int main(int argc,char *argv[])
{
    ros::init(argc ,argv ,"vel_node");

    ros::NodeHandle n;
    ros::Publisher vel_pub = n.advertise<geometry_msgs::Twist>("/cmd_vel",10);

    geometry_msgs::Twist vel_msg;
    vel_msg.linear.x = 0;
    vel_msg.linear.y = 0;
    vel_msg.linear.z = 0;
    vel_msg.angular.x = 0;
    vel_msg.angular.y = 0;
    vel_msg.angular.z = 0.5;

    ros::Rate r(30);
    while (ros::ok())
    {
        vel_pub.publish(vel_msg);
        r.sleep();
    }

    return 0;
}

20.机器人运动控制的Python实现

运动控制的Python实现

依赖项是roscpp rospy和geometry_msgs,这个geometry_msgs就是包含了速度消息类型的软件包

(此处与第19节C++的一样,上节没写,这节一起补上)

#!/usr/bin/env python3
# coding=utf-8

import rospy
from geometry_msgs.msg import Twist

if __name__ == "__main__":
    rospy.init_node("vel_node")

    vel_pub = rospy.Publisher("cmd_vel",Twist,queue_size=10)

    vel_msg = Twist()
    vel_msg.linear.z = 0.5

    rate = rospy.Rate(30)
    while not rospy.is_shutdown():
        vel_pub.publish(vel_msg)
        rate.sleep()

总结:

· C++放src/:因为要编译,CMake只认src/里的源码

· Python放scripts/:因为要直接运行,先建一个scripts/,因为它是ROS约定的脚本目录,加权限就能跑。

vel_pkg/正确结构应该是(不是我的,借鉴豆包的,我的C++实现是vel_pkg ,python实现是vel_pkg_new):

vel_pkg/

├── CMakeLists.txt # 配置 C++ 编译规则、

Python 安装路径

├── package.xml # 包信息、依赖

├── src/       # C++ 源码(必须)

│    └── vel_node.cpp # C++ 节点

└── scripts/  # Python 脚本(约定)

    └──  vel_node.py  # Python 节点(需 chmod +x)

注意:

直接关闭Gazebo窗口会导致仿真场景和小车被强制销毁(因为这个之前苦恼了半天,问了豆包弄了1天才弄好,说多了都是血与泪)。

正确关闭(下次启动能恢复) 想彻底关闭但下次快速恢复小车,按终端优先的顺序操作:

1. 先在启动 Gazebo 的终端按  Ctrl+C ,停止所有 ROS 节点(包括仿真节点);

​ 2. 再关闭 Gazebo 图形窗口; ​

3. 下次启动:直接重新运行启动命令(如  roslaunch wpr_simulation xxx.launch ),小车会重新加载到场景中。

实在不行删除损坏的包再从Gitee克隆一下,重新来一下

避坑提醒

- ❌ 禁止直接点 Gazebo 窗口的「×」关闭:会强制杀死仿真进程,场景和小车直接销毁,且可能残留后台进程,导致下次启动报错; ​

- ✅ 若误关了窗口:先在终端按  Ctrl+C  停掉剩余节点,再重新启动 launch 文件即可恢复小车。

21.激光雷达工作原理

雷达的分类

按测量维度分:单线雷达和多线雷达

按测量原理分:三角测距雷达和TOF雷达

按工作方式分:机械旋转雷达和固态雷达

激光雷达

安装位置:机器人底盘隔层的中央位置

激光雷达的机械结构:固定底座和可旋转的头部结构(在雷达的头部设置了一个红外激光发射器和一个红外激光接收器)

功能:可以360度周而复始不断进行旋转探测任务,激光探测的频率足够高,旋转足够快,就能实时刷新周围障碍物的分布状况

22.使用RViz观测传感器数据

使用RViz可视化的数据有:

1.传感器数据,机器人上传感器采集到的数据(这些数据都可以图形化的形式展示在这个软件里)

2.机器人运算处理的中间结果和将要执行的目标指示(比如机器人对空间中某个物体进行识别后,可以在RViz中将其框选标注出来,又比如咱们机器人完成了去往某个地点的路径规划,也可以在这个工具软件中将路径显示出来)

Gazebo是模拟真实机器人发出传感器数据的工具(负责发)

RViz是接收传感器数据并进行显示的工具,它显示的是机器人实际能探测到的环境状况(负责收)

两者的联系与区别:

在现实世界的机器人系统中Gazebo不存在,其仿真的角色会被真实的实体机器人和真实的环境所替代,而RViz可能还会存在,RViz不管接受的数据是Gazebo仿真还是实体机器人,都会继续做接收数据并显示的工作。

23.激光雷达消息包格式

# 做的有些图文不匹配请见谅,时间紧明天14点要交汇报,现在22点45,正在赶进度

主要存储的是时间戳和坐标系ID,时间戳表示坐标发出的时间,坐标系ID后边涉及到TF系统

angle_min

扫描的起始角度

angle_max 

扫描的终止角度

angle_increment 

相邻两次测距的旋转夹角

time_increment 

相邻两次测距的时间差

scan_time

scan_time其实就是单次扫描的持续时间,也就是雷达转一圈所耗费的时间,这个主要计算雷达的扫描频率

range_min

有效测距范围的最小距离(单位:米)

range_max

有效测距范围的最大距离(单位:米)

ranges

ranges为本次扫描的所有测距值,同时也是消息包里最重要的数据,array数组 数组成员类型是32位的浮点数,数组的长度是360

激光雷达从起始角度到终止角度,这一过程中测量的距离个数,雷达每次从-180度到+180度,总共扫描了360度,ranges数组里正好有360个浮点数,说明雷达在扫描过程中每旋转1度就进行一次测距行为,ranges这里边360个测距值对应的是每一度方向的障碍物距离,这些距离排列顺序与扫描顺序一致

这360个测距值不是全部有效,某些角度因为障碍物的距离超过了雷达的测距范围,所以它的数值会变为INF(也就是无穷大)

intensities

intensities数组长度也是360个和ranges数组相对应,这个数组的数值大小表示的是每一次测距的信号强度,数值越大表示这次测距的信号强度越强,得到的测距数值更可信

总结

ROS的激光雷达消息包里,大部分内容都是固定的数值,可用rostopic echo查看,真正有用的数值是ranges数组(其测距值是不断变化的)

24.获取激光雷达数据的C++节点

激光雷达数据获取(C++)

#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>

void LidarCallback(const sensor_msgs::LaserScan msg)
{
    float fMidDist = msg.ranges[180];
    ROS_INFO("前方测距 ranges[180] = %f米",fMidDist);
}

int main(int argc,char *argv[])
{
    setlocale(LC_ALL,"");
    ros::init(argc, argv, "lider_node");

    ros::NodeHandle n;
    ros::Subscriber lidar_sub = n.subscribe("/scan", 10, &LidarCallback);

    ros::spin();

    return 0;
}

25.获取激光雷达数据的Python节点

激光雷达数据获取(Python)

#!/usr/bin/env python3
# coding=utf-8

import rospy
from sensor_msgs.msg import LaserScan

def LidarCallback(msg):
    dist = msg.ranges[180]
    rospy.loginfo("前方测距 ranges[180] = %f 米",dist)

if __name__ == "__main__":
    rospy.init_node("lidar_node")
    lidar_sub = rospy.Subscriber("/scan",LaserScan,LidarCallback,queue_size=10)
    rospy.spin()

26.激光雷达避障的C++节点

激光雷达避障(C++)

只检测激光雷达一条射线的测距数值,没有考虑到机器人有宽度会导致机器人侧前方撞到了障碍物

改进:让机器人检测到障碍物时,旋转的时间拉长一点,这样就能躲过障碍物了。

#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>
#include <geometry_msgs/Twist.h>

ros::Publisher vel_pub;
int nCount = 0;

void LidarCallback(const sensor_msgs::LaserScan msg)
{
    float fMidDist = msg.ranges[180];
    ROS_INFO("前方测距 ranges[180] = %f米",fMidDist);

    if(nCount > 0)
    {
        nCount --;
        return;
    }

    geometry_msgs::Twist vel_cmd;
    if(fMidDist < 1.5)
    {
        vel_cmd.angular.z = 0.3;
        nCount = 50;
    }
    else
    {
        vel_cmd.linear.x = 0.05;
    }
    vel_pub.publish(vel_cmd);
}

int main(int argc,char *argv[])
{
    setlocale(LC_ALL,"");
    ros::init(argc, argv, "lider_node");

    ros::NodeHandle n;
    ros::Subscriber lidar_sub = n.subscribe("/scan", 10, &LidarCallback);
    vel_pub = n.advertise<geometry_msgs::Twist>("/cmd_vel",10);

    ros::spin();

    return 0;
}

27.激光雷达避障的Python节点

激光雷达避障(Python)

#!/usr/bin/env python3
# coding=utf-8

import rospy
from sensor_msgs.msg import LaserScan
from geometry_msgs.msg import Twist

count = 0

def LidarCallback(msg):
    global vel_pub
    global count
    dist = msg.ranges[180]
    rospy.loginfo("前方测距 ranges[180] = %f 米",dist)

    if count > 0:
        count = count - 1
        return
    
    vel_cmd = Twist()
    if dist < 1.5:
        vel_cmd.angular.z = 0.3
        count = 50
    else:
        vel_cmd.linear.x = 0.05
    vel_pub.publish(vel_cmd)

if __name__ == "__main__":
    rospy.init_node("lidar_node")
    lidar_sub = rospy.Subscriber("/scan",LaserScan,LidarCallback,queue_size=10)
    vel_pub = rospy.Publisher("/cmd_vel",Twist,queue_size=10)
    rospy.spin()

注意:代码中vel_pub是在主函数里生成的,我们要在回调函数中使用它,必须把它声明成一个全局变量,否则这里会生成一个新的vel_pub,一个没有对速度话题进行订阅的新对象,它是无法把消息包发送到速度话题里的  

28.ROS中的IMU惯性测量单位信息包

IMU消息包的数据格式

IMU是安装在机器人内部的一种传感器模块,用于测量机器人的空间姿态

头部是header,记录了消息发送的时间戳和坐标系ID

orientation

angular velocity角速度,类型是Vector3,这个和速度控制消息Twist里的angular角速度一样,是描述机器人在xyz三个坐标轴上的旋转速度

Vector3 angular在速度消息包里输出给机器人底盘的指令,angular velocity这里是IMU测量到的输入值,数值定义上两者是完全一样的,前者是输出量,后者是输入值

linear_acceleration矢量加速度,类型也是Vector3,Twist里的linear描述的是XYZ三个坐标轴上的速度,而IMU里的linear_acceleration描述的则是三个轴上速度的增减情况(也就是加速度),两者除了坐标轴方向是一致的外,其数值含义却有差别,一个是速度,一个是加速度

协方差矩阵主要用于后期的优化和滤波

此数值也叫裸数据,为了方便用户使用,IMU模块通常还会输出一个根据上述数值融合得到的空间姿态描述,也就是刚才咱们没有介绍的这个orientation,它描述的是机器人的朝向相对于空间中XYZ三个坐标轴的偏移量

如果对消息包中IMU解算的这个orientation结果不满意或者有其他特殊的需求,可以自行根据裸数据进行姿态信息的融合,否则,对于普通用户来说,直接使用这个orientation就足够了

点进图中红框部分

基于XYZ三个轴的旋转偏移量的描述(也就是欧拉角描述),在某些姿态下会存在一种叫做万向锁的问题,所以用Quaternion这种方法即使用xyzw四个值来描述机器人朝向的方法(也叫四元数描述法),有效避免了万向锁问题

29.获取IMU数据的C++节点

IMU数据获取(C++)

#include "ros/ros.h"
#include "sensor_msgs/Imu.h"
#include "tf/tf.h"

void IMUCallback(sensor_msgs::Imu msg)
{
    if(msg.orientation_covariance[0] < 0)
        return;
    tf::Quaternion quaternion(
        msg.orientation.x,
        msg.orientation.y,
        msg.orientation.z,
        msg.orientation.w
    );

    double roll, pitch, yaw;
    tf::Matrix3x3(quaternion).getRPY(roll, pitch, yaw);
    roll = roll*180/M_PI;
    pitch = pitch*180/M_PI;
    yaw = yaw*180/M_PI;

    ROS_INFO("滚转= %.0f 俯仰=%.0f 朝向=%.0f",roll,pitch,yaw);
}

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    ros::init(argc, argv, "imu_node");

    ros::NodeHandle n;
    ros::Subscriber imu_sub = n.subscribe("/imu/data", 10, IMUCallback);

    ros::spin();

    return 0;
}

注:不小心在w后面加了个逗号导致编译不成功,浪费了不少时间,真的很无语

30.获取IMU数据的Python节点

IMU数据获取(Python)

#!/usr/bin/env python3
#coding=utf-8

import rospy
from sensor_msgs.msg import Imu
from tf.transformations import euler_from_quaternion
import math

def imu_callback(msg):
    if msg.orientation_covariance[0] < 0:
        return
    
    quaternion = [
        msg.orientation.x,
        msg.orientation.y,
        msg.orientation.z,
        msg.orientation.w
    ]
    (roll,pitch,yaw) = euler_from_quaternion(quaternion)
    roll = roll*180/math.pi
    pitch = pitch*180/math.pi
    yaw = yaw*180/math.pi
    rospy.loginfo("滚转= %.0f 俯仰=%.0f 朝向=%.0f",roll,pitch,yaw)

if __name__ == "__main__":
    rospy.init_node("imu_node")
    imu_sub = rospy.Subscriber("/imu/data",Imu,imu_callback,queue_size=10)
    rospy.spin()

31.IMU航向锁定的C++节点

IMU航行锁定(C++)

因为vel_pub要在main()主函数和回调函数里都要用到,所以这里把它定义为一个全局对象,然后在主函数里对这个vel_pub进行初始化

#include "ros/ros.h"
#include "sensor_msgs/Imu.h"
#include "tf/tf.h"
#include "geometry_msgs/Twist.h"

ros::Publisher vel_pub;

void IMUCallback(sensor_msgs::Imu msg)
{
    if(msg.orientation_covariance[0] < 0)
        return;
    tf::Quaternion quaternion(
        msg.orientation.x,
        msg.orientation.y,
        msg.orientation.z,
        msg.orientation.w
    );

    double roll, pitch, yaw;
    tf::Matrix3x3(quaternion).getRPY(roll, pitch, yaw);
    roll = roll*180/M_PI;
    pitch = pitch*180/M_PI;
    yaw = yaw*180/M_PI;
    ROS_INFO("滚转= %.0f 俯仰=%.0f 朝向=%.0f",roll,pitch,yaw);

    double target_yaw = 90;
    double diff_angle = target_yaw - yaw;
    geometry_msgs::Twist vel_cmd;
    vel_cmd.angular.z = diff_angle *0.01;
    vel_cmd.linear.x = 0.1;
    vel_pub.publish(vel_cmd);
}

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"");
    ros::init(argc, argv, "imu_node");

    ros::NodeHandle n;
    ros::Subscriber imu_sub = n.subscribe("/imu/data", 10, IMUCallback);
    vel_pub = n.advertise<geometry_msgs::Twist>("/cmd_vel",10);

    ros::spin();

    return 0;
}

32.IMU航向锁定的Python节点

IMU航向锁定(Python)

#!/usr/bin/env python3
#coding=utf-8

import rospy
from sensor_msgs.msg import Imu
from tf.transformations import euler_from_quaternion
import math
from geometry_msgs.msg import Twist

def imu_callback(msg):
    if msg.orientation_covariance[0] < 0:
        return
    
    quaternion = [
        msg.orientation.x,
        msg.orientation.y,
        msg.orientation.z,
        msg.orientation.w
    ]
    (roll,pitch,yaw) = euler_from_quaternion(quaternion)
    roll = roll*180/math.pi
    pitch = pitch*180/math.pi
    yaw = yaw*180/math.pi
    rospy.loginfo("滚转= %.0f 俯仰=%.0f 朝向=%.0f",roll,pitch,yaw)

    target_yaw = 90
    diff_angle = target_yaw - yaw
    vel_cmd = Twist()
    vel_cmd.angular.z = diff_angle * 0.01
    vel_cmd.linear.x = 0.1
    global vel_pub
    vel_pub.publish(vel_cmd)

if __name__ == "__main__":
    rospy.init_node("imu_node")
    imu_sub = rospy.Subscriber("/imu/data",Imu,imu_callback,queue_size=10)
    vel_pub = rospy.Publisher("/cmd_vel",Twist,queue_size=10)
    rospy.spin()

33.标准消息包std_msgs

std_msgs标准消息包

# 下午14点就要交了,图中详细内容我就不一一介绍了,没时间了

34.几何消息包geometry_msgs和传感器包sensor_msgs

这9个消息包中不必全部了解,最常用的就是geometry_msgs几何消息包和sensor_msgs传感器消息包。

geometry_msgs 

里面的消息包类型名称里带了stamped关键词,这些消息包都是多了一个Header,也就是多了时间和坐标系ID,将空间量和时间量进行了绑定,在一些预测和滤波算法里会用得着,关于几何消息包的用法可以参考之前的运动控制实验,实验中用到了Twist消息类型,其他消息类型的用法也是类似的

sensor_msgs

关于这些消息类型的使用方法,可以参考前面的激光雷达和IMU的实验,也是类似的流程

35.自定义消息类型

所谓的消息包,其实也是一个普通的Package软件包,包名可以是任意的名字,只不过为了便于识别,一般会以_msgs作为结尾

string grade
int64 star
string data

36.自定义消息类型在C++节点的应用

chao_node.cpp修改版

#include <ros/ros.h>
#include <std_msgs/String.h>
#include <qq_msgs/Carry.h>

int main(int argc,char *argv[])
{
    ros::init(argc,argv,"chao_node");
    printf("我的枪去而复返,你的生命有去无会!\n");

    ros::NodeHandle nh;
    ros::Publisher pub = nh.advertise<qq_msgs::Carry>("kuai_shang_che_kai_hei_qun",10);

    ros::Rate loop_rate(10);

    while(ros::ok())
    {
        printf("我要刷屏了!\n");
        qq_msgs::Carry msg;
        msg.grade = "王者";
        msg.star = 50;
        msg.data = "国服马超,带飞";
        pub.publish(msg);
        loop_rate.sleep();
    }
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)
project(ssr_pkg)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  qq_msgs
)

## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder
# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here
# generate_messages(
#   DEPENDENCIES
#   std_msgs
# )

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES ssr_pkg
#  CATKIN_DEPENDS roscpp rospy std_msgs
#  DEPENDS system_lib
)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/ssr_pkg.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/ssr_pkg_node.cpp)

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# catkin_install_python(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_ssr_pkg.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

add_executable(chao_node src/chao_node.cpp)
 target_link_libraries(chao_node
   ${catkin_LIBRARIES}
)
add_dependencies(chao_node qq_msgs_generate_messages_cpp)

add_executable(yao_node src/yao_node.cpp)
 target_link_libraries(yao_node
   ${catkin_LIBRARIES}
)

package.xml

<?xml version="1.0"?>
<package format="2">
  <name>ssr_pkg</name>
  <version>0.0.0</version>
  <description>The ssr_pkg package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
  <maintainer email="liyou@todo.todo">liyou</maintainer>


  <!-- One license tag required, multiple allowed, one license per tag -->
  <!-- Commonly used license strings: -->
  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
  <license>TODO</license>


  <!-- Url tags are optional, but multiple are allowed, one per tag -->
  <!-- Optional attribute type can be: website, bugtracker, or repository -->
  <!-- Example: -->
  <!-- <url type="website">http://wiki.ros.org/ssr_pkg</url> -->


  <!-- Author tags are optional, multiple are allowed, one per tag -->
  <!-- Authors do not have to be maintainers, but could be -->
  <!-- Example: -->
  <!-- <author email="jane.doe@example.com">Jane Doe</author> -->


  <!-- The *depend tags are used to specify dependencies -->
  <!-- Dependencies can be catkin packages or system dependencies -->
  <!-- Examples: -->
  <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
  <!--   <depend>roscpp</depend> -->
  <!--   Note that this is equivalent to the following: -->
  <!--   <build_depend>roscpp</build_depend> -->
  <!--   <exec_depend>roscpp</exec_depend> -->
  <!-- Use build_depend for packages you need at compile time: -->
  <!--   <build_depend>message_generation</build_depend> -->
  <!-- Use build_export_depend for packages you need in order to build against this package: -->
  <!--   <build_export_depend>message_generation</build_export_depend> -->
  <!-- Use buildtool_depend for build tool packages: -->
  <!--   <buildtool_depend>catkin</buildtool_depend> -->
  <!-- Use exec_depend for packages you need at runtime: -->
  <!--   <exec_depend>message_runtime</exec_depend> -->
  <!-- Use test_depend for packages you need only for testing: -->
  <!--   <test_depend>gtest</test_depend> -->
  <!-- Use doc_depend for packages you need only for building documentation: -->
  <!--   <doc_depend>doxygen</doc_depend> -->
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_depend>qq_msgs</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>
  <exec_depend>qq_msgs</exec_depend>

  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>

ma_node.cpp修改版

#include <ros/ros.h>
#include <std_msgs/String.h>
#include <qq_msgs/Carry.h>

void chao_callback(qq_msgs::Carry msg)
{
    ROS_WARN(msg.grade.c_str());
    ROS_WARN("%d 星",msg.star);
    ROS_INFO(msg.data.c_str());
}

void yao_callback(std_msgs::String msg)
{
    ROS_WARN(msg.data.c_str());
}

int main(int argc, char *argv[])
{
    setlocale(LC_ALL,"zh_CN.UTF-8"); // 中文版的Ubuntu只写""就行
    ros::init(argc, argv, "ma_node");

    ros::NodeHandle nh;
    ros::Subscriber sub = nh.subscribe("kuai_shang_che_kai_hei_qun",10,chao_callback);
    ros::Subscriber sub2 = nh.subscribe("gie_gie_dai_wo",10,yao_callback);

    while (ros::ok())
    {
        ros::spinOnce();
        ros::Duration(0.1).sleep(); //隐性问题修复:加延时,豆包加的
    }

    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)
project(atr_pkg)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  qq_msgs
)

## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder
# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here
# generate_messages(
#   DEPENDENCIES
#   std_msgs
# )

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES atr_pkg
#  CATKIN_DEPENDS roscpp rospy std_msgs
#  DEPENDS system_lib
)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/atr_pkg.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/atr_pkg_node.cpp)

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# catkin_install_python(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_atr_pkg.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

add_executable(ma_node src/ma_node.cpp)
target_link_libraries(ma_node
  ${catkin_LIBRARIES}
)
add_dependencies(ma_node qq_msgs_generate_messages_cpp)

package.xml

<?xml version="1.0"?>
<package format="2">
  <name>atr_pkg</name>
  <version>0.0.0</version>
  <description>The atr_pkg package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
  <maintainer email="liyou@todo.todo">liyou</maintainer>


  <!-- One license tag required, multiple allowed, one license per tag -->
  <!-- Commonly used license strings: -->
  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
  <license>TODO</license>


  <!-- Url tags are optional, but multiple are allowed, one per tag -->
  <!-- Optional attribute type can be: website, bugtracker, or repository -->
  <!-- Example: -->
  <!-- <url type="website">http://wiki.ros.org/atr_pkg</url> -->


  <!-- Author tags are optional, multiple are allowed, one per tag -->
  <!-- Authors do not have to be maintainers, but could be -->
  <!-- Example: -->
  <!-- <author email="jane.doe@example.com">Jane Doe</author> -->


  <!-- The *depend tags are used to specify dependencies -->
  <!-- Dependencies can be catkin packages or system dependencies -->
  <!-- Examples: -->
  <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
  <!--   <depend>roscpp</depend> -->
  <!--   Note that this is equivalent to the following: -->
  <!--   <build_depend>roscpp</build_depend> -->
  <!--   <exec_depend>roscpp</exec_depend> -->
  <!-- Use build_depend for packages you need at compile time: -->
  <!--   <build_depend>message_generation</build_depend> -->
  <!-- Use build_export_depend for packages you need in order to build against this package: -->
  <!--   <build_export_depend>message_generation</build_export_depend> -->
  <!-- Use buildtool_depend for build tool packages: -->
  <!--   <buildtool_depend>catkin</buildtool_depend> -->
  <!-- Use exec_depend for packages you need at runtime: -->
  <!--   <exec_depend>message_runtime</exec_depend> -->
  <!-- Use test_depend for packages you need only for testing: -->
  <!--   <test_depend>gtest</test_depend> -->
  <!-- Use doc_depend for packages you need only for building documentation: -->
  <!--   <doc_depend>doxygen</doc_depend> -->
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_depend>qq_msgs</build_depend>
  <build_export_depend>roscpp</build_export_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>
  <exec_depend>qq_msgs</exec_depend>

  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>

总结

37.自定义消息类型在Python节点的应用

chao_node.py修改版

#!/usr/bin/env python3
#coding=utf-8

import rospy
from std_msgs.msg import String
from qq_msgs.msg import Carry

if __name__ == "__main__":
    rospy.init_node("chao_node")
    rospy.logwarn("我的枪去而复返,你的生命有去无会!")

    pub = rospy.Publisher("kuai_shang_che_kai_hei_qun",Carry,queue_size=10)

    rate = rospy.Rate(10)

    while not rospy.is_shutdown():
        rospy.loginfo("我要开始刷屏了")
        msg = Carry()
        msg.grade = "王者"
        msg.star = 50
        msg.data = "国服马超,带飞"
        pub.publish(msg)
        rate.sleep()

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)
project(ssr_pkg_new)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  rospy
  std_msgs
  qq_msgs
)

## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder
# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here
# generate_messages(
#   DEPENDENCIES
#   std_msgs
# )

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES ssr_pkg_new
#  CATKIN_DEPENDS rospy std_msgs
#  DEPENDS system_lib
)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/ssr_pkg_new.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/ssr_pkg_new_node.cpp)

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# catkin_install_python(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_ssr_pkg_new.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

package.xml

<?xml version="1.0"?>
<package format="2">
  <name>ssr_pkg_new</name>
  <version>0.0.0</version>
  <description>The ssr_pkg_new package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
  <maintainer email="liyou@todo.todo">liyou</maintainer>


  <!-- One license tag required, multiple allowed, one license per tag -->
  <!-- Commonly used license strings: -->
  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
  <license>TODO</license>


  <!-- Url tags are optional, but multiple are allowed, one per tag -->
  <!-- Optional attribute type can be: website, bugtracker, or repository -->
  <!-- Example: -->
  <!-- <url type="website">http://wiki.ros.org/ssr_pkg_new</url> -->


  <!-- Author tags are optional, multiple are allowed, one per tag -->
  <!-- Authors do not have to be maintainers, but could be -->
  <!-- Example: -->
  <!-- <author email="jane.doe@example.com">Jane Doe</author> -->


  <!-- The *depend tags are used to specify dependencies -->
  <!-- Dependencies can be catkin packages or system dependencies -->
  <!-- Examples: -->
  <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
  <!--   <depend>roscpp</depend> -->
  <!--   Note that this is equivalent to the following: -->
  <!--   <build_depend>roscpp</build_depend> -->
  <!--   <exec_depend>roscpp</exec_depend> -->
  <!-- Use build_depend for packages you need at compile time: -->
  <!--   <build_depend>message_generation</build_depend> -->
  <!-- Use build_export_depend for packages you need in order to build against this package: -->
  <!--   <build_export_depend>message_generation</build_export_depend> -->
  <!-- Use buildtool_depend for build tool packages: -->
  <!--   <buildtool_depend>catkin</buildtool_depend> -->
  <!-- Use exec_depend for packages you need at runtime: -->
  <!--   <exec_depend>message_runtime</exec_depend> -->
  <!-- Use test_depend for packages you need only for testing: -->
  <!--   <test_depend>gtest</test_depend> -->
  <!-- Use doc_depend for packages you need only for building documentation: -->
  <!--   <doc_depend>doxygen</doc_depend> -->
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_depend>qq_msgs</build_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>
  <exec_depend>qq_msgs</exec_depend>

  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>

ma_node.py修改版

#!/usr/bin/env python3
#coding=utf-8

import rospy
from std_msgs.msg import String
from qq_msgs.msg import Carry

def chao_callback(msg):
    rospy.logwarn(msg.grade)
    rospy.logwarn(str(msg.star)+"星")
    rospy.loginfo(msg.data)

def yao_callback(msg):
    rospy.logwarn(msg.data)

if __name__ == "__main__":
    rospy.init_node("ma_node")

    sub = rospy.Subscriber("kuai_shang_che_kai_hei_qun",Carry,chao_callback,queue_size=10)
    sub2 = rospy.Subscriber("gie_gie_dai_wo",String,yao_callback,queue_size=10)
 
    rospy.spin()

注:star是整型变量,需要将其转换为字符串才能进行显示

CMakeLists.txt

cmake_minimum_required(VERSION 3.0.2)
project(atr_pkg_new)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  rospy
  std_msgs
  qq_msgs
)

## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)


## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
##   your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
##   * add a build_depend tag for "message_generation"
##   * add a build_depend and a exec_depend tag for each package in MSG_DEP_SET
##   * If MSG_DEP_SET isn't empty the following dependency has been pulled in
##     but can be declared for certainty nonetheless:
##     * add a exec_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
##   * add "message_generation" and every package in MSG_DEP_SET to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * add "message_runtime" and every package in MSG_DEP_SET to
##     catkin_package(CATKIN_DEPENDS ...)
##   * uncomment the add_*_files sections below as needed
##     and list every .msg/.srv/.action file to be processed
##   * uncomment the generate_messages entry below
##   * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)

## Generate messages in the 'msg' folder
# add_message_files(
#   FILES
#   Message1.msg
#   Message2.msg
# )

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here
# generate_messages(
#   DEPENDENCIES
#   std_msgs
# )

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################

## To declare and build dynamic reconfigure parameters within this
## package, follow these steps:
## * In the file package.xml:
##   * add a build_depend and a exec_depend tag for "dynamic_reconfigure"
## * In this file (CMakeLists.txt):
##   * add "dynamic_reconfigure" to
##     find_package(catkin REQUIRED COMPONENTS ...)
##   * uncomment the "generate_dynamic_reconfigure_options" section below
##     and list every .cfg file to be processed

## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES atr_pkg_new
#  CATKIN_DEPENDS rospy std_msgs
#  DEPENDS system_lib
)

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ library
# add_library(${PROJECT_NAME}
#   src/${PROJECT_NAME}/atr_pkg_new.cpp
# )

## Add cmake target dependencies of the library
## as an example, code may need to be generated before libraries
## either from message generation or dynamic reconfigure
# add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
# add_executable(${PROJECT_NAME}_node src/atr_pkg_new_node.cpp)

## Rename C++ executable without prefix
## The above recommended prefix causes long target names, the following renames the
## target back to the shorter version for ease of user use
## e.g. "rosrun someones_pkg node" instead of "rosrun someones_pkg someones_pkg_node"
# set_target_properties(${PROJECT_NAME}_node PROPERTIES OUTPUT_NAME node PREFIX "")

## Add cmake target dependencies of the executable
## same as for the library above
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
# target_link_libraries(${PROJECT_NAME}_node
#   ${catkin_LIBRARIES}
# )

#############
## Install ##
#############

# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html

## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# catkin_install_python(PROGRAMS
#   scripts/my_python_script
#   DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark executables for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html
# install(TARGETS ${PROJECT_NAME}_node
#   RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )

## Mark libraries for installation
## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html
# install(TARGETS ${PROJECT_NAME}
#   ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
#   RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}
# )

## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
#   DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
#   FILES_MATCHING PATTERN "*.h"
#   PATTERN ".svn" EXCLUDE
# )

## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
#   # myfile1
#   # myfile2
#   DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )

#############
## Testing ##
#############

## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_atr_pkg_new.cpp)
# if(TARGET ${PROJECT_NAME}-test)
#   target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()

## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

package.xml

<?xml version="1.0"?>
<package format="2">
  <name>atr_pkg_new</name>
  <version>0.0.0</version>
  <description>The atr_pkg_new package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
  <maintainer email="liyou@todo.todo">liyou</maintainer>


  <!-- One license tag required, multiple allowed, one license per tag -->
  <!-- Commonly used license strings: -->
  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
  <license>TODO</license>


  <!-- Url tags are optional, but multiple are allowed, one per tag -->
  <!-- Optional attribute type can be: website, bugtracker, or repository -->
  <!-- Example: -->
  <!-- <url type="website">http://wiki.ros.org/atr_pkg_new</url> -->


  <!-- Author tags are optional, multiple are allowed, one per tag -->
  <!-- Authors do not have to be maintainers, but could be -->
  <!-- Example: -->
  <!-- <author email="jane.doe@example.com">Jane Doe</author> -->


  <!-- The *depend tags are used to specify dependencies -->
  <!-- Dependencies can be catkin packages or system dependencies -->
  <!-- Examples: -->
  <!-- Use depend as a shortcut for packages that are both build and exec dependencies -->
  <!--   <depend>roscpp</depend> -->
  <!--   Note that this is equivalent to the following: -->
  <!--   <build_depend>roscpp</build_depend> -->
  <!--   <exec_depend>roscpp</exec_depend> -->
  <!-- Use build_depend for packages you need at compile time: -->
  <!--   <build_depend>message_generation</build_depend> -->
  <!-- Use build_export_depend for packages you need in order to build against this package: -->
  <!--   <build_export_depend>message_generation</build_export_depend> -->
  <!-- Use buildtool_depend for build tool packages: -->
  <!--   <buildtool_depend>catkin</buildtool_depend> -->
  <!-- Use exec_depend for packages you need at runtime: -->
  <!--   <exec_depend>message_runtime</exec_depend> -->
  <!-- Use test_depend for packages you need only for testing: -->
  <!--   <test_depend>gtest</test_depend> -->
  <!-- Use doc_depend for packages you need only for building documentation: -->
  <!--   <doc_depend>doxygen</doc_depend> -->
  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_depend>qq_msgs</build_depend>
  <build_export_depend>rospy</build_export_depend>
  <build_export_depend>std_msgs</build_export_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>std_msgs</exec_depend>
  <exec_depend>qq_msgs</exec_depend>


  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>

总结

38.栅栏地图格式

栅格尺寸越小,黑色的区域划分就越精细,也就越接近障碍物的轮廓,理论上,栅格无限小黑色部分能完美的和障碍物贴合上。但对于地图来说,栅格越小,数量越多,地图的数据量越大,处理时计算量也越大,一般会给栅格设计适当尺寸

栅格尺寸指的是栅格的单位长度,体现了地图的精细程度,所以常常被用来表示栅格地图的分辨率

在ROS系统里,栅格地图的默认分辨率是0.05米

假设白格数据为0,黑格数据为100,最左下角为(0,0)位置,故如图:

39.C++节点发布地图

40.Python节点发布地图

#!/usr/bin/env python3
# coding = utf-8

import rospy
from nav_msgs.msg import OccupancyGrid

if __name__ == "__main__":
    rospy.init_node("map_pub_node")
    pub = rospy.Publisher("/map",OccupancyGrid,queue_size=10)

    rate = rospy.Rate(1)
    while not rospy.is_shutdown():
        msg = OccupancyGrid()

        msg.header.frame_id = "map"
        msg.header.stamp = rospy.Time.now()

        msg.info.origin.position.x = 0
        msg.info.origin.position.y = 0
        msg.info.resolution = 1.0
        msg.info.width = 4
        msg.info.height = 2

        msg.data = [0]*4*2
        msg.data[0] = 100
        msg.data[1] = 100
        msg.data[2] = 0
        msg.data[3] = -1

        pub.publish(msg)
        rate.sleep()

与C++一样的rviz展示就不一一列举了

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐