ROS相关技术(经验版)

重要说明:本文从网上资料整理而来,仅记录博主学习相关知识点的过程,侵删。

一、参考资料

ROS相关技术介绍,可参考之前的文章:ROS相关技术(概念版)

Autolabor主站
ROS官网
ROS
ROS教程
ROS编程技术
ROS书籍整理:机器人操作系统 ROS 相关书籍整理合集 [古月居推荐]

二、ROS相关介绍

ROS与Apollo对比

Apollo可以看作是ROS的改进版,Apollo从通信功能优化、去中心化网络拓扑以及数据兼容性扩展三个方面做了定制化的改进。

单对多的传输场景下,ROS 在处理一对多的消息传输时,底层实现实际是多个点对点的连接,当把一份数据要发给三个节点时,相同的数据会传输三次,这会造成很大的资源浪费。而Apollo采用了共享内存的解决方案,减少传输过程中的数据拷贝,大幅度提升效率。

ROS系统非常依赖Master,一旦Master出现异常,将导致整个系统崩溃,且缺乏恢复自动机制。Apollo的整个网络拓扑不再以 master 为中心构建,当一个新的节点加入网络时,会通过 RTPS 协议向域内的所有其他节点发送广播信息,各个节点也会将自己的服务信息发送给新的节点,以代替 Master 的信息交换功能。

ROS 系统为了保证收发双方的消息格式一致,会对message定义做 MD5 校验,任何字段的增减或顺序调整都会使 MD5 变化。然而这种严格的限制也引起了兼容性的问题,OTA升级后可能出现兼容问题,在Apollo中,做了一整套对protobuf的支持, 在工程中可以不需要做格式转换,直接publish protobuf格式的消息,调试工具也能够非常正确的解析出来正确的protobuf消息。这样既能够很好解决兼容性问题,也不会产生额外的学习成本和使用成本。

三、常用指令

ROS笔记(2)——ROS的基本命令

roscore

功能描述:用于启动ROS系统的核心功能。

启动roscore是ROS系统的先决条件,必须运行roscore才能使ROS节点进行通信

启动roscore将:

  • 启动ROS Master节点;
  • ros参数服务器;
  • rosout日志节点;

ROS Master节点是ROS系统中的核心管理节点,负责管理所有节点之间的通信,包括节点的发现、消息的路由、参数服务器等。当执行 roscore 指令时,ROS Master节点将在计算机上启动,并将等待其他节点连接。只有在启动 roscore 之后,才能启动其他节点,并进行ROS操作。因此,通常在开始进行任何ROS项目之前,第一步是启动 roscore

rosrun

功能描述:启动ROS包中的节点。

# 启动小海龟节点用于演示机器人控制
rosrun turtlesim turtlesim_node

rosnode

rosnode

功能描述:用于获取节点信息。

# 测试节点的连接状态
rosnode ping

# 列出活动的节点
rosnode list

# 打印节点信息
rosnode info

# 列出指定设备上的节点
rosnode machine

# 杀死节点
rosnode kill

# 清除不可连接的节点
# ctrl+c并没有清除节点,需要用cleanup彻底清除
rosnode cleanup

roslaunch

功能描述:执行功能包的launch文件。

roslaunch <package_name> <launch文件名>

rostopic

功能描述:用于显示有关ROS 话题的调试信息,包括发布者,订阅者,发布频率和ROS消息。

# 显示话题使用的带框
rostopic bw

# 显示带有header的话题延迟
rostopic delay

# 打印话题的消息到屏幕
rostopic echo

# 根据消息类型查找话题
rostopic find

# 显示话题的发布频率
rostopic hz

# 显示话题的相关信息
rostopic info

# 显示所有活动状态下的话题
rostopic list -v

# 将数据发布到话题
rostopic pub </topic_name> <message_type> <message_content>

# 以10HZ的频率发送信息
rostopic pub -r 10 </topic_name> <message_type> <message_content>

# 打印话题的消息类型
rostopic type

rosmsg

rosmsg

功能描述:显示有关 ROS消息类型的信息。

# 显示消息描述
rosmsg show <message_type>

# 显示消息信息
rosmsg info

# 列出所有消息
rosmsg list

# 显示md5加密后的消息
rosmsg hd5

# 显示某个功能包下的所有消息
rosmsg package <package_name>

# 列出包含消息的所有包
rosmsg packages

rosservice

rosservice

功能描述:用于列出和查询ROS服务。

# 打印服务参数
rosservice args </service_name>

# 按照服务类型查找服务
rosservice find <servervice_name>

# 打印指定服务的信息
rosservice info

# 列出所有活动的服务
rosservice list

# 打印服务的类型
rosservice type

# 打印服务的ROSRPC uri
rosservice uri

# 调用指定服务
rosservice call </service_name>

rosparam

功能描述:用于管理ROS参数。

# 设置指定参数的值
rosparam set param_name value

rosbag指令

rosbag详解

rosbag是ROS中的一种数据记录工具,它可以记录和回放ROS的消息数据。我们可以使用rosbag来记录ROS系统中的消息流,包括传感器数据、机器人状态等信息,然后在之后的时间点上回放这些消息数据,以便我们进行离线分析和调试。

rosbag可以将消息数据存储在文件中,并使用一种高效的压缩算法来减少文件大小。这样,我们可以在之后的时间点上使用rosbag回放工具来重新播放这些消息,以便我们在没有实际硬件的情况下进行测试和调试。rosbag还支持多个包(bag)之间的合并和分割,以便我们更好地管理消息数据。

rosbag常用指令

  • record:用指定的话题录制一个 bag 包;
  • info:显示一个 bag 包的基本信息,比如包含哪些话题;
  • play:回放一个或者多个 bag 包;
  • reindex:重新索引一个或多个损坏 bag 包。

记录bag

rosbag record 是一个用于记录 ROS 消息到 ROS Bag 文件中的命令行工具。它可以记录指定主题的消息,将消息保存到一个ROS Bag文件中。例如,以下命令将记录名为/scan的激光雷达数据并将其保存到名为scan.bag的文件中:

rosbag record /scan -O scan.bag

以下是 rosbag record 命令的常用参数:

  • -a, --all:记录所有主题。
  • -O, --output-name:指定输出的 ROS Bag 文件名。
  • -b, --buffer-size:设置ROS Bag文件的缓冲区大小。
  • -d, --duration:设置记录时间长度,以秒为单位。
  • -l, --limit:设置记录的消息数量限制。
  • -j, --bz2:使用bzip2压缩来压缩ROS Bag文件。
  • -z, --lz4:使用LZ4压缩来压缩ROS Bag文件。-p, --split:设置ROS Bag文件的分段大小。-t, --topics:指定要记录的主题列表。
  • -x, --exclude:指定要排除的主题列表。
# 录制所有话题数据
rosbag record -a

# 录制指定话题数据
rosbag record <topic_name1> <topic_name2> <topic_name3> ...

# 指定数据包名称
rosbag record  -O <bagname> <topic_name1> <topic_name2> <topic_name3> ...

查看bag信息

rosbag info指令可以数据包中包含的话题名称,话题数量,话题消息类型等信息。

rosbag info <bagname> 

播放bag

使用 rosbag play 指令可以从指定的ROS包文件中回放消息数据。

# 回放指定bag
rosbag play <bagname>

# 回放当前目录下所有bag
rosbag play *

# 从指定时间(n = 指定时间s)开始回放bag
rosbag play -s n <bagname>

# 延时指定时间(n = 延时时间s)开始回放bag
rosbag play -d n <bagname>

# 播放指定时间(n = 指定秒数)的bag
rosbag play -u n <bagname>

# 从指定时间(n = 开始时间s)开始播放指定时间(m = 指定播放时间s)的bag
rosbag play -s n -u m <bagname>

# 按指定倍率(n = 倍率)回放bag
rosbag play -r n <bagname>

修复bag

回放不成功,提示 reindex ,修复bag。

rosbag reindex

rqt_graph

ROS计算图

ROS 分布式系统中不同进程需要进行数据交互,计算图可以以点对点的网络形式表现数据交互过程。rqt_graph能够创建一个显示当前系统运行情况的动态图形。

# 安装rqt_graph
# 是ROS的版本,例如:kinetic、melodic、Noetic等
sudo apt install ros-<distro>-rqt
sudo apt install ros-<distro>-rqt-common-plugins

# 启动rqt_graph
rosrun rqt_graph rqt_graph

ROS相关技术(经验版)_第1张图片

四、机器人系统建模与仿真

ROS学习笔记16:机器人系统建模与仿真

1. 机器人系统仿真

机器人系统仿真是通过计算机对实体机器人系统进行模拟的技术。在ROS中,仿真实现涉及的内容主要有三:对机器人建模(URDF)、创建仿真环境(Gazebo)以及感知环境(Rviz)等系统性实现。

2. 机器人系统仿真所需组件

2.1 创建机器人模型(URDF)

URDF (Unified Robot Description Format,统一(标准化)机器人描述格式),以XML的方式描述机器人的部分结构,比如地盘、摄像头、激光雷达、机械臂以及不同关节的自由度,该文件可以被C++内置的解释器转换成可视化的机器人模型,是ROS中实现机器人仿真的重要组件。

2.2 显示各种传感器信息(rviz)

rviz(ROS Visualization Tool,ROS的三维可视化工具),它的主要目的是以三维方式显示ROS信息,可以将数据进行可视化表达。例如,可以显示机器人模型,可以无需编程就能表达激光测距仪(LRF)传感器中的传感器到障碍物的距离,Kinect或Xtion等三维距离传感器的点云数据(PCD,Point Cloud Data),从相机获取的图象值等。

2.3 搭建仿真环境(Gazebo)

Gazebo是一款3D动态模拟器,用于显示机器人模型并创建仿真环境,能够在复杂的室内和室外环境中准确有效地模拟机器人。与游戏引擎提供高保真度的视觉模拟类似,Gazebo提供高保真度的物理模拟,其提供一整套传感器模型,以及用户和程序非常友好的交互方式。

五、ROS Bag

ROS笔记(5)——Bag包概述与解析

ROS Bag是一种文件格式,用于存储ROS系统中的消息。ROS Bag可以将ROS节点发布的消息记录下来,然后在需要的时候将这些消息再次播放回ROS系统中。

1. ROS Bag适用场景

  1. 离线数据处理:在无法连接实时ROS系统时,可以使用ROS Bag记录消息,然后在离线状态下进行数据处理和算法开发;
  2. 数据集手机:ROS Bag可以用于收集数据集,以用于机器学习和深度学习等应用;
  3. 调试和测试:ROS Bag可以用于调试和测试ROS节点和程序的行为。

2. 生成ROS Bag文件的方式

ROS Bag文件以 .bag 拓展名结尾,可以通过以下两种方式保存:

  1. rosbag 方式。在终端中使用rosbag record命令来记录指定主题的消息,将消息保存到ROS Bag文件中。
  2. ROS API方式。在ROS程序中使用ROS API来记录消息,将消息保存到ROS Bag文件中。

2.1 rosbag 方式

rosbag 方式,参见rosbag指令。

2.2 ROS API方式

以下代码段将记录名为/scan的激光雷达数据并将其保存到名为scan.bag的文件中。

C++代码示例

#include 
#include 
#include 
 
void scanCallback(const sensor_msgs::LaserScan::ConstPtr& msg)
{
  static rosbag::Bag bag;
  if (!bag.isOpen()) {
    bag.open("scan.bag", rosbag::bagmode::Write);
  }
  bag.write("/scan", ros::Time::now(), *msg);
  /*
  当程序退出时,ROS Bag 的析构函数会自动关闭文件。
  如果您想手动关闭文件,可以在程序退出前显式地删除ROS Bag对象或调用rosbag::Bag::close()方法来关闭 
  文件。
 */
}
 
int main(int argc, char** argv)
{
  ros::init(argc, argv, "scan_logger");
  ros::NodeHandle nh;
 
  ros::Subscriber sub = nh.subscribe("/scan", 1, scanCallback);
 
  ros::spin();
 
  return 0;
}

python代码示例

#!/usr/bin/env python
 
import rospy
import rosbag
from sensor_msgs.msg import LaserScan
 
def scanCallback(msg):
    global bag
    if bag is None:
        bag = rosbag.Bag('scan.bag', 'w')
    bag.write('/scan', msg)
 
if __name__ == '__main__':
    rospy.init_node('scan_logger')
    bag = None
    sub = rospy.Subscriber('/scan', LaserScan, scanCallback)
    rospy.spin()
    bag.close()

3. 解析ROS Bag文件

rosbag::View 是ROS Bag文件中的一组消息的视图,它提供了一些方便的方法来遍历和访问这些消息。

rosbag::View 实际上是一个包含 rosbag::Connection 对象的集合,每个对象代表一个主题。rosbag::Connection 对象包含一组时间戳和消息,表示该主题的所有消息。您可以使用以下方法来访问这些消息:

  • begin():返回指向第一条消息的迭代器。
  • end():返回指向最后一条消息后面的位置的迭代器。
  • rbegin():返回指向最后一条消息的迭代器。
  • rend():返回指向第一条消息前面的位置的迭代器。
  • size():返回视图中消息的数量。

在使用 rosbag::View 遍历Bag文件中的所有消息时,每个迭代器会返回一个 rosbag::MessageInstance 对象。这个对象包含了消息的时间戳、消息类型和消息数据等信息。可以使用以下方法来访问这些信息:

  • getTime():返回消息的时间戳。
  • getTopic():返回消息所属的主题名称。
  • getDataType():返回消息的数据类型。
  • instantiate():将消息实例化为指定的数据类型。如果无法实`例化,则返回空指针。

3.1 C++代码示例

#include 
#include 
#include 
 
int main(int argc, char** argv) {
    // 初始化ROS节点
    ros::init(argc, argv, "rosbag_parser");
    ros::NodeHandle n;
 
    // 打开bag文件
    rosbag::Bag bag;
    bag.open("/path/to/bagfile.bag", rosbag::bagmode::Read);
 
    // 遍历bag文件中的所有消息
    rosbag::View view(bag);
    for (rosbag::MessageInstance const m : view) {
        std_msgs::String::ConstPtr msg = m.instantiate();
        if (msg != nullptr && m.getTopic() == "/my_topic") {
            // 打印消息内容
            ROS_INFO("Message: %s", msg->data.c_str());
        }
    }
 
    // 关闭bag文件
    bag.close();
 
    return 0;
}

3.2 python代码示例

import rosbag
import rospy
from std_msgs.msg import String
 
# 初始化ROS节点
rospy.init_node('rosbag_parser')
 
# 打开bag文件
bag = rosbag.Bag('/path/to/bagfile.bag')
 
# 遍历bag文件中的所有消息
for topic, msg, t in bag.read_messages():
    # 检查消息类型和主题名称
    if topic == '/my_topic' and isinstance(msg, String):
        # 打印消息内容
        rospy.loginfo("Message: %s", msg.data)
 
# 关闭bag文件
bag.close()

在这个示例中,我们使用了ROS提供的rospy.loginfo函数来输出消息,它类似于Python的print函数,但是它会将消息输出到ROS的日志系统,这有助于调试和记录机器人的运行情况。

python执行

rosrun <package_name> <filename.py>

3.3 C++与Python接口对比

C++与Python 解析ROS Bag文件两种方式的对比。

  • Python 中使用 rosbag.Bag 读取 Bag 文件,C++ 中使用 rosbag::Bag
  • Python 中使用 bag.read_messages() 方法遍历 Bag 文件中的消息,C++ 中使用 rosbag::View 类和 C++11 的范围 for 循环来遍历消息。
  • Python 中的 t 变量表示消息的时间戳,C++ 中使用 rosbag::MessageInstance::getTime() 方法来获取消息的时间戳。
  • Python 中使用 msg 变量来存储消息的内容,C++ 中使用 rosbag::MessageInstance::instantiate() 方法将消息实例化为指定的数据类型,如果无法实例化,则返回空指针。
  • Python 中使用 topic 变量来表示消息所属的主题,C++ 中使用 rosbag::MessageInstance::getTopic() 方法来获取消息所属的主题名称。
  • Python 中使用 rospy.loginfo() 函数来输出消息,C++ 中可以使用 ROS 的日志系统来输出消息,例如使用 ROS_INFO 宏来输出消息。

使用 C++ 代码来解析 ROS Bag 文件,大致流程如下:

  1. 打开 Bag 文件并创建 rosbag::Bag() 对象。
  2. 创建 rosbag::View() 对象并遍历 Bag 文件中的消息。
  3. 对于每条消息,使用 rosbag::MessageInstance::instantiate() 方法将消息实例化为指定的数据类型,并使用 rosbag::MessageInstance::getTopic() 方法获取消息所属的主题名称和 rosbag::MessageInstance::getTime() 方法获取消息的时间戳。
  4. 对于符合条件的消息,使用 ROS 的日志系统或其他方式输出消息内容。
  5. 关闭 Bag 文件。

六、ROS相关经验

1. ROS Melodic

待补充

2. D435i相机标定

D435i相机标定(不同标定方法总结)

深度相机D435i

Realsense d435i内参、外参标定

Realsense d435i驱动安装、配置及校准

3. 古月居ROS入门21讲

古月居ROS入门21讲学习笔记

4. 雷达相机标定(ROS)

雷达相机标定(ROS)

你可能感兴趣的:(ROS,ROS)