机器人操作系统ROS 编程开发--详细总结

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
实时计算 Flink 版,1000CU*H 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
简介: 最近工作涉及到自动驾驶的,需要学习ROS,学习中总结了一些知识点,分享给大家。机器人操作系统ROS,是一种分布式处理框架(又名Nodes),ROS常用C++和python编程语言开发;(这里项目开发采用C++ 11版本)。ROS的点对点设计以及服务和节点管理器等机制,可以分散由计算机视觉和语音识别等功能带来的实时计算压力,能够适应多机器人遇到的挑战。ROS免费并且开源。

最近工作涉及到自动驾驶的,需要学习ROS,学习中总结了一些知识点,分享给大家。

ROS基本介绍

 机器人操作系统ROS,是一种分布式处理框架(又名Nodes),ROS常用C++和python编程语言开发;(这里项目开发采用C++ 11版本)。ROS的点对点设计以及服务和节点管理器等机制,可以分散由计算机视觉和语音识别等功能带来的实时计算压力,能够适应多机器人遇到的挑战。ROS免费并且开源。


ROS常用的概念

1node: 节点. 节点就是一些直行运算任务的进程。节点之间是通过传送消息进行通讯的;ROS中,通常来讲我们写的c++程序主函数所在的程序称为一个节点;

2message: 消息.机器人需要传感器,传感器采集到的信息,即这儿的message.(如:位置消息,温度、湿度等);消息以一种发布/订阅的方式传递;

3topic: 话题.node交换Messages的命名总线异步通讯机制,传输消息;

4package: 是组织ROS代码的最基本单位,每一个Package都可以包括库文件,可执行文件,脚本及其它的一些文件。

5workSpace: 工作空间 用来存放很多不同package的。

6roslaunch: 启动文件,其目的是一次性启动多个节点s。

7Master: 节点管理器,ROS名称服务,帮助节点找到彼此。

8publish : 发布器,把相关的信息发送到topic

9、subscribe: 订阅器,订阅相应的topic,接收话题的信息


ROS的结构是怎样的?

ROS分为两层,底层是操作系统层,上层则是广大用户编写提供的各种功能不同的软件包,比如定位导航,行动规划等等。

所以ROS实际上可以看成是一个中间层,提供和重新封装了底层硬件调用的API,这些重新封装的API称为客户端库,运用这些库可是实现硬件调用,以此实现各种不同的功能,如使用激光雷达扫描生成周围环境的2D地图……

   ROS框架基于集中式拓扑图结构,它的进程(即节点,ROS以节点形式进行通信,以此实现功能)是分布式的,进程分布在各个功能不同的功能包里面。


ROS发布消息-- publish

1、流程

  • 初始化 ROS 系统
  • 在 ROS 网络内广播中,我们将要在 chatter 话题上,发布 std_msgs/String 类型的消息
  • 以每秒 10 次的频率(可以设置修改)在 chatter 上发布消息

2、Ros发布信息 例子

/**
 *本程序演示了通过ROS系统简单发送消息。
*/
#include "ros/ros.h"                         //要使用ROS,得包含这个头文件
#include "std_msgs/String.h"                 //导入 String类型的头文件
#include <sstream>                           //c++自带的头文件 实现输入输出流等
int main(int argc, char **argv)
{
  ros::init(argc, argv, "talker");          //ros初始化,talker就是node(节点)的名字
  ros::NodeHandle n;                        //为这个进程的节点创建一个句柄。
  ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
                                           //定义要publish(发布)信息的对象
  ros::Rate loop_rate(10);                 //发布的信息的快慢 速度为10Hz
  int count = 0;
  while (ros::ok())
  {
    std_msgs::String msg;
    std::stringstream ss;
    ss << "hello world " << count;                
    msg.data = ss.str();
    ROS_INFO("%s", msg.data.c_str());    //可以理解为ROS里的printf()
    chatter_pub.publish(msg);            //用来发布信息(msg中的内容)
    ros::spinOnce();                     //这个函数是用于接收器,是检测一次
    loop_rate.sleep();
    ++count;
  }
  return 0;
}

image.gif

3、程序重点降解:

ros::NodeHandle n;

  • 第一个创建的 NodeHandle 会为节点进行初始化,最后一个销毁的 NodeHandle 则会释放该节点所占用的所有资源

ros:: Publisher chatter_pub = n.advertise < std_msgs::String>("chatter", 1000);

  • n.advertise 通过NodeHandle的对象n告诉ROS系统我要创建一个可以发布信息的对象
  • < std_msgs::String>告诉ROS我要发布的是标准信息中的String类型,chatter 通讯时的topic(主题)
  • 1000这个数字的意思是要缓冲的信息数量
  • advertise返回一个 ros::Publisher 对象,它有两个作用:

    1) 它有一个 publish() 成员函数可以让你在topic上发布消息;

     2) 如果消息类型不对,它会拒绝发布。

4、为什么需要缓冲呢?

这发布和接收之间并不是瞬间进行的,发布消息和接收到消息之间的时间差。缓冲区接收最新的信息放到信息序列的最后。即缓冲区的信息的数据结构是queue。第一条来的信息在序列满了的情况下会被第一个丢弃。

ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

1000这个数字的意思是要缓冲的信息数量


ROS订阅消息subscribe

1、流程

  • 初始化ROS系统
  • 订阅 chatter 话题
  • 进入自循环,等待消息的到达
  • 当消息到达,调用 chatterCallback() 函数

Ros订阅信息 例子

/**
* 本程序演示了通过ROS系统简单接收消息。
*/
#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::String::ConstPtr& msg)
  //是一个回调函数,当接收到 chatter 话题的时候就会被调用。{
ROS_INFO("I heard: [%s]", msg->data.c_str());//msg->data就是一个std::string类型的量
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");//节点的名字换成了listener
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
                                //定义接收器,topic话题:chatter,第三个参数chatterCallback称为回调函数
ros::spin();            //会使程序在循环中,一直检测有没有接收到新的消息
return 0;
}

image.gif

3、注意点

  1. 如果ROS遇到了相同的节点名字那么他会停止掉旧节点的名字然后使用新节点的那个程序(这时候旧的节点如果 有ros::ok(),那么他会就变得不OK了 = = 。这是ros::ok()返回false的第三种情况)
  2. 注意node的名字得独一无二,但是topic的名字得和你想接收的信息的topic一样!
  3. chatterCallback称为回调函数,接收器每一次接收到消息,就会调用名字为它的函数;一般命名为...Callback这样一看就知道这是ROS使用得回调函数
  4. std_msgs::String对象msg,类包含数据成员data,调用方式为msg.data。如果类的指针叫msg,那么调用该成员的方式是msg->data


ROS 编译程序

1、流程

  • 编辑CMakeLists文件(指定要编译的文件)
  • 再使用catkin_make编译

2、编译例子:

来到编写好程序的包目录中

cd ~/catkin_ws/src/pub_sub_test/

image.gif

编辑CMakeLists文件

gedit CMakeLists.txt

image.gif

在后面添加如下内容:

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

image.gif

第一行表示我们要编译add_executable表示我们要添加一个可执行文件,

pub_string是这个可执行文件的名字

src/pub_string.cpp指定要编译的源文件的位置.

第二行target_link_libraries表示我们要将可执行文件链接到一个库,我们要使用ROS当然是要链接到ROS的库了,

pub_string指定要链接可执行文件的名字,后面是指定要链接的库的名字.

来到工作空间中,执行catkin_make命令

cd ~/catkin_ws/
catkin_make

image.gif


执行ROS程序方法1:

方法1:

打开第一个terminal,执行roscore命令(打开rosmaster 服务器)

roscore

image.gif

roscore是为了让各种节点之间能够沟通用的

打开第二个terminal,进入工作空间,执行source devel/setup.bash 命令,

cd ~/catkin_ws/
source devel/setup.bash

image.gif

使用rosrun 命令运行程序(例如:执行pub_string.cpp):

rosrun pub_sub_test pub_string

image.gif

第一个参数:程序pub_string.cpp所在的包(package)的名字

第二个参数:运行程序的名称


方法2: 使用roslaunch来运行程序

特点:

可以便捷开启多个节点,自动开启rosmaster服务

区别:

    • 方法一在使用rosrun之前,我们一定得需要启动rosmaster,即开启一个窗口输入roscore,来开启rosmaster 服务器;
    • 运行roslaunch文件后rosmaster会自动启动.当然你关闭了roslaucn之后rosmaster也会关闭

    流程:

      1. 来到程序所在包的文件夹目录下,新建一个名字叫launch 的文件夹
      2. 在launch中建立的一个文件,名字可以随意,后缀必须是launch
      3. 编译程序
      4. 编辑launch文件
      5. 通过roslaunch,执行节点程序

      详细说明:

        1. 编辑launch文件

        格式: <

        launch>
            <node name="pub_string" pkg = "pub_sub_test" type = "pub_string" output = "screen">
            </node>
            <node name="pub_int8" pkg = "pub_sub_test" type = "pub_int8" output = "screen">
            </node>
        </launch>

        image.gif

        roslaunch使用的是xml语言,launch文件的内容是跑一个node简单的形式

        <launch>,<\launch>表示launch文件的开始和结束

        <node ....>表示接下来输入node相关的内容,比如说首先输入的是node的名字,这个东西一般和type后面输入的内容一样,

        type需要被赋值为节点对应的可执行文件的名字,

        name则是节点的名字.具体区别是你在CMakeLists.txt文件里编译文件的命令

        output = "screen"  设置通过print()输出的信息,打印到命令窗口中,默认时关闭的

        通过roslaunch,执行节点程序

        格式:

        关键字:roslaunch

        第一个参数: xx.launch 所在的包的名称

        第二个参数: 要执行的.launch 的文件



        ROS发布和接收图

        image.gif编辑

        rosbag

        简介

          1. rosbag 指命令行中数据包相关命令;
          2. rosbag 主要用于记录、回放、分析 rostopic 中的数据。它可以将指定 rostopic 中的数据记录到 .bag 后缀的数据包中,便于对其中的数据进行离线分析和处理。
          3. 对于 subscribe 某个 topic 的节点来说,它无法区分这个 topic 中的数据到底是实时获取的数据还是从 rosbag 中回放的数据。这就有助于我们基于离线数据快速重现曾经的实际场景,进行可重复、低成本的分析和调试。

          rosbag 的命令  

          image.gif编辑


          rosbag录制:

          录制所有发布出来的话题,此时默认将话题保存在一个以当时时间戳命名的文件夹中:

          $ rosbag record –a

          录制指定话题:

          $ rosbag record /topic1 /topic12


          rosbag回放:

          基本功能:

          $ rosbag play <your bagfile name>

          等待一定时间之后发布bag文件中的内容

          $ rosbag play <your bagfile name> -d <delay time>

          按一定频率回放,-r选项用来设定消息发布速率,如下面命令则表示以3倍原始速率发布话题

          $ rosbag play -r 3 <your bagfile name>

          回放指定话题:

          $ rosbag play <your bagfile name> --topics <topics>


          rosbag检查和回放

          1. rosbag info指令可以显示数据包中的信息:

          rosbag  info filename.bag

          这些信息包括 topic 的名称、类型和 message 数量。

          2) 接下来回放数据包中的 topic。

          首先在turtle_teleop_key 所在的终端窗口中按Ctrl+C退出该键盘控制节点。保留turtlesim节点继续运行。在终端中bag文件所在目录下运行以下命令:

          rosbag play <bagfile>

          就能够回放出 bag 中包含的 topic 内容了。


          如果想改变消息的发布速率,可以用下面的命令

          rosbag play -r 2 <bagfile>

          这时的轨迹相当于以两倍的速度通过按键发布控制命令时产生的轨迹。 -r 后面的数字对应播放速率。


          如果希望 rosbag 循环播放,可以用命令

          rosbag play -l  <bagfile>  # -l == --loop


          如果只播放感兴趣的 topic ,则用命令

          rosbag play <bagfile> --topic /topic1

          在上述播放命令执行期间,空格键可以暂停播放。


          CMakeLists

          简介:

          ROS中创建软件包所依赖的文件CMakeList.txtcatkin_make会根据你写的CMakeList.txt来配置编译软件包。

          格式:

          所需CMake版本                  cmake_minimum_required(VERSION 2.8.3)

          软件包名称                         project()

          查找构建此包所需的包      find_package()

          消息 / 服务 / 动作生成器     add_message_files(),add_service_files(),add_action_files

          消息 / 服务 / 动作生成        generate_messages()

          指定包构建的消息导出        catkin_package()

          要建立的库 / 可执行文件   add_library() / add_executable() / target_link_libraries())

          例如:

          image.gif编辑

          其中:add_executable(read_param src/show_param.cpp)和target_link_libraries(read_param ${catkin_LIBRARIES})  是新添加的,指定可执行文件

          详细解释:

          1.所需CMake版本

          catkin_make的底层是使用cmake进行编译的,这里指定cmake的版本(最低版本)

          2.软件包名称

          project(package_name)

          在使用catkin_create_pkg创建包时,后面跟的参数(包名)就是此处的package_name

          在CMakeList.txt后面的部分可以使用 ${PROJECT_NAME} 来使用此参数

          3. 查找此包创建时所需要的其它包(依赖包)

          可以将所依赖的包写成下面的形式:

          find_package(catkin REQUIRED)

          find_package(roscpp REQUIRED)

          find_package(rospy REQUIRED)

          find_package(std_msgs REQUIRED)

          其中catkin是创建每个包所必须的依赖项,创建包时所依赖的其它项又可以将其组成catkin的组件,所以上面可以总写为:

          find_package(catkin REQUIRED COMPONENTS

           roscpp

           rospy

           std_msgs

          )

          上面中的roscpprospystd_msgs 是运行程序所需要的依赖包

          roscpp: 用C++ 语言进行ros开发要用到的包

          rospy: 用python 语言进行ros开发要用到的包

          std_msgs: 基本的数据类型int stringfloat、double等的依赖包

          4.add_message_files()

          像message service 和action的定义需要在catkin_package()之前

          ## Generate messages in the 'msg' folder

          # add_message_files(

          #   FILES

          #   Message1.msg

          #   Message2.msg

          # )

          比如:

          add_message_files(

           FILES Num1.msg Num2.msg

          )

          5.catkin_package()

          用来向编译系统指明catkin-specific的信息,格式如下:

          catkin_package(

            INCLUDE_DIRS include  # 此项打开之后该软件包的include文件可以被其它包所引用

            LIBRARIES ${PROJECT_NAME} #同理

            CATKIN_DEPENDS roscpp nodelet

            DEPENDS eigen opencv)

          6.包含文件目录

          include_directories(include ${catkin_INCLUDE_DIRS})  

          其中include是指包含本软件包下的头文件, ${catkin_INCLUDE_DIRS}是指ROS下其它包的头文件,include需要写在${catkin_INCLUDE_DIRS}前面。

          7.生成可执行文件

          #其中talker为将要生成的二进制文件,在ros所有的包中必须是独一无二不能重复的,src/talker.cpp为需要编译的源文件

          add_executable(talker src/talker.cpp)  

          target_link_libraries(talker ${catkin_LIBRARIES})

          生成的可执行文件会存放在./devel/lib/*pack_name*/下:


          问题与解决方案总结

          缺失依赖库

          image.gif编辑

          解决思路:

          1.在错误原因中,找到错误代码端,分析,确定缺失的包

          2.在程序所在包下,添加依赖包

          添加依赖包,详细说明:

          思路:

          1. 一个是包目录下的的CMakeLists.txt,添加依赖包
          2. 然后在位于同一位置的package.xml中,添加添加依赖包

          例如

          1. 打开的CMakeLists.txt,发现就在最前面几行,有下面的内容。
          find_package(catkin REQUIRED COMPONENTS
            roscpp
            rospy
            std_msgs
          )

          image.gif

          括号中的内容正好一一对应我们创建包时添加的依赖项,在后面添加geometry_msgs,变成下面的样子,保存退出。

          find_package(catkin REQUIRED COMPONENTS
            roscpp
            rospy
            std_msgs
            geometry_msgs
          )

          image.gif

           

          打开位于同一目录下的package.xml

          <build_depend>roscpp</build_depend>
           <build_depend>rospy</build_depend>
            <build_depend>std_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>

          image.gif

          发现std_msgs, rospy, roscpp,每个出现了三次,所以只我们需要按照这个文档里相同的语法让geometry_msgs出现三次就行了。更改之后该文件同样位置变成下面的内容:

          <build_depend>roscpp</build_depend>
            <build_depend>rospy</build_depend>
            <build_depend>std_msgs</build_depend>
            <build_depend>geometry_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>
            <build_export_depend>geometry_msgs</build_export_depend>
            <exec_depend>roscpp</exec_depend>
            <exec_depend>rospy</exec_depend>
            <exec_depend>std_msgs</exec_depend>
            <exec_depend>geometry_msgs</exec_depend>
            <exec_depend>geometry_msgs</exec_depend>

          image.gif

          保存退出。这时候再用catkin_make编译,就成功了。改变上面两个文档的内容就相当于我们在创建包时添加了依赖项geometry_msgs。


          catkin_make编译错误

          问题:

          Could not find a package configuration file provided by

           "gazebo_ros_control" with any of the following names:

             gazebo_ros_controlConfig.cmake

          gazebo_ros_control-config.cmake

          分析

          提示缺少“gazebo_ros_control”功能包,

          解决方案:

          sudo apt-get install ros-kinetic-gazebo-ros-control

            问题:

            Could not find a package configuration file provided by "move_base_msgs"

             with any of the following names:

               move_base_msgsConfig.cmake

            move_base_msgs-config.cmake

            分析

            提示缺少“gazebo_ros_control”功能包

            解决方案:

            sudo apt-get install ros-kinetic-move-base-msgs

              问题:

              alsa/asoundlib.h: No such file or directory

              分析

              缺少一个库,libasound2-dev

              解决方案:

              sudo apt-get install libasound2-dev

              希望对你有帮助。

              相关实践学习
              使用ROS创建VPC和VSwitch
              本场景主要介绍如何利用阿里云资源编排服务,定义资源编排模板,实现自动化创建阿里云专有网络和交换机。
              ROS入门实践
              本课程将基于基础设施即代码 IaC 的理念,介绍阿里云自动化编排服务ROS的概念、功能和使用方式,并通过实际应用场景介绍如何借助ROS实现云资源的自动化部署,使得云上资源部署和运维工作更为高效。
              相关文章
              |
              5月前
              |
              机器学习/深度学习 人工智能 自然语言处理
              TsingtaoAI具身智能机器人开发套件及实训方案
              该产品套件创新性地融合了先进大模型技术、深度相机与多轴协作机械臂技术,构建了一个功能强大、灵活易用的人机协作解决方案。其核心在于将智能决策、精准感知与高效执行完美结合,为高校实训领域的发展注入新动力。
              468 10
              |
              8月前
              |
              人工智能 开发框架 机器人
              AstrBot:轻松将大模型接入QQ、微信等消息平台,打造多功能AI聊天机器人的开发框架,附详细教程
              AstrBot 是一个开源的多平台聊天机器人及开发框架,支持多种大语言模型和消息平台,具备多轮对话、语音转文字等功能。
              4667 38
              AstrBot:轻松将大模型接入QQ、微信等消息平台,打造多功能AI聊天机器人的开发框架,附详细教程
              |
              8月前
              |
              中间件 关系型数据库 数据库
              docker快速部署OS web中间件 数据库 编程应用
              通过Docker,可以轻松地部署操作系统、Web中间件、数据库和编程应用。本文详细介绍了使用Docker部署这些组件的基本步骤和命令,展示了如何通过Docker Compose编排多容器应用。希望本文能帮助开发者更高效地使用Docker进行应用部署和管理。
              225 19
              |
              9月前
              |
              人工智能 自动驾驶 安全
              Cosmos:英伟达生成式世界基础模型平台,加速自动驾驶与机器人开发
              Cosmos 是英伟达推出的生成式世界基础模型平台,旨在加速物理人工智能系统的发展,特别是在自动驾驶和机器人领域。
              769 15
              Cosmos:英伟达生成式世界基础模型平台,加速自动驾驶与机器人开发
              |
              9月前
              |
              存储 弹性计算 运维
              云端问道 7 期实践教学-使用操作系统智能助手 OS Copilot 轻松运维与编程
              使用操作系统智能助手 OS Copilot 轻松运维与编程
              191 14
              |
              9月前
              |
              弹性计算 人工智能 运维
              新手训练营——使用操作系统智能助手OS Copilot轻松运维与编程
              本文摘自阿里云操作系统团队的林演(林生)关于操作系统智能助手创新产品的分享,围绕“OS Copilot的高效运维与编程”展开,主要包括以下几方面的内容: 1. 行业痛点击及背景 2. 产品与架构 3. 典型应用场景 4. 实验及反馈渠道
              209 1
              |
              9月前
              |
              人工智能 弹性计算 运维
              云端问道7期方案教学-使用操作系统智能助手OS Copilot轻松运维与编程
              本文介绍了阿里云基础软件团队推出的操作系统智能助手 OS Copilot,旨在解决 Linux 开发与运维中的痛点。OS Copilot 基于大模型和操作系统领域知识构建,支持自然语言问答、命令辅助执行、系统运维优化及代码生成等功能,极大降低了学习成本和工作量。文章详细阐述了其产品架构、典型应用场景以及实验反馈渠道,帮助用户更高效地进行系统管理和编程。目前该产品处于公测阶段,免费提供给阿里云 ECS 实例和 Alinux 3 系统用户使用。
              143 1
              |
              11月前
              |
              自动驾驶 安全 机器人
              ROS2:从初识到深入,探索机器人操作系统的进化之路
              前言 最近开始接触到基于DDS的这个系统,是在稚晖君的机器人项目中了解和认识到。于是便开始自己买书学习起来,感觉挺有意思的,但是只是单纯的看书籍,总会显得枯燥无味,于是自己又开始在网上找了一些视频教程结合书籍一起来看,便让我对ROS系统有了更深的认识和理解。 ROS的发展历程 ROS诞生于2007年的斯坦福大学,这是早期PR2机器人的原型,这个项目很快被一家商业公司Willow Garage看中,类似现在的风险投资一样,他们投了一大笔钱给这群年轻人,PR2机器人在资本的助推下成功诞生。 2010年,随着PR2机器人的发布,其中的软件正式确定了名称,就叫做机器人操作系统,Robot Op
              387 14
              |
              10月前
              |
              编解码 网络协议 机器人
              顶顶通电话机器人开发接口对接大语言模型之实时流TTS对接介绍
              大语言模型通常流式返回文字,若一次性TTS会导致严重延迟。通过标点断句或流TTS可实现低延迟的文本到语音转换。本文介绍了电话机器人接口适配流TTS的原理及技术点,包括FreeSWITCH通过WebSocket流TTS放音,以及推流协议和旁路流对接的详细说明。
              760 1
              |
              11月前
              |
              XML 算法 自动驾驶
              ROS进阶:使用URDF和Xacro构建差速轮式机器人模型
              【11月更文挑战第7天】本篇文章介绍的是ROS高效进阶内容,使用URDF 语言(xml格式)做一个差速轮式机器人模型,并使用URDF的增强版xacro,对机器人模型文件进行二次优化。
              434 6

              推荐镜像

              更多