ROS 简单理解

2023-05-16

https://download.csdn.net/download/qq_30022867/11120759?utm_medium=distribute.pc_relevant_download.none-task-download-baidujs-9.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-download-baidujs-9.nonecase

书籍下载

 

 

一、图概念概述

    Nodes:节点,一个节点即为一个可执行文件,它可以通过ROS与其它节点进行通信。

    Messages:消息,消息是一种ROS数据类型,用于订阅或发布到一个话题。

    Topics:话题,节点可以发布消息到话题,也可以订阅话题以接收消息。

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

    rosout: ROS中相当于stdout/stderr。

    roscore: 主机+ rosout + 参数服务器 (参数服务器会在后面介绍)。
 

运行ros节点的方法:

一般有两种:

第一种:使用rosrun,在设置完环境变量后,可以使用包名来直接运行一个包内的节点。

用法:

$rosrun  [package_name]  [node_name]

注意:这种方法需要新打开一个终端 运行

$roscore

第二种:使用roslaunch

用法:

$roslaunch  [package]  [fliename.launch]

launch是个文件,用launch文件来运行程序相对于rosrun的优点有两个

<1>可以向程序传参

<2>可以同时运行多个节点

launch文件结构

<launch>
 <!--第1个节点-->
 	<node pkg="包名" type="包内可执行程序名字" name="节点名">
   	<!--注释内容-->
    		<para name="程序中的数值或布尔参数" value="" />
		<para name="程序中的字符串参数" value=" " type="str" />
		...
 	<node>
	...
 <!--第n个节点-->
	<node pkg="包名" type="包内可执行程序名字" name="节点名">
  	 <!--注释内容-->
    		...
	 <node>
</launch>

注意:

<1>包内可执行程序名由包内CMakeLists.txt控制生成。

<2>在每个可执行程序的main里都会有定义节点的语句,这里的节点名字只是用于代码编译,和launch文件的节点名不是一回事。

比如:

int main (int argc, char **argv)

{

 ros::init(argc,argv,"节点名字");

}

 

 

 二、ROS常用命令

命令重要度命令释义详细说明
roscore ★★★ ros+core

master(ROS名称服务) + rosout(日志记录) + parameter
server(参数管理)

rosrun ★★★ ros+run运行节点
 roslaunch  ★★★ ros+launch 运行多个节点或设置运行选项
rosclean★★☆  ros+clean 检查或删除ROS日志文件

 

三、创建一个工作空间

 前提:安装了相关的程序,比如:catkin

创建一个catkin工作空间

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/
catkin_make

这里 -p 是允许创建目录下的子目录的意思效果如下(我这里实在桌面创建的)

 

四、ROS发布者节点以及订阅者节点的编写

4.1、编写发布者节点

“节点”是连接到ROS网络的可执行文件的ROS术语。在这里,我们将创建一个将继续广播消息的发布者(“talker”)节点。
将目录更改为您在catkin工作区之前的教程中创建的beginner_tutorials包:

首先使用指令更改一下roscd的绝对路径:

$ . ~/catkin_ws/devel/setup.bash

然后使用

$ roscd beginner_tutorials

在beginner_tutorials包目录中创建一个src目录:

$ mkdir -p src

该目录将包含beginner_tutorials包的任何源文件。
在beginner_tutorials包中创建src / talker.cpp文件并在其中粘贴以下内容:

#include "ros/ros.h"          		
/*ros/ros.h是一个方便的包括,包括使用ROS系统最常见的公共部分所需的所有标题。*/

#include "std_msgs/String.h"
#include <sstream>
/*这包括std_msgs / String消息,该消息驻留在std_msgs包中。
这是从该包中的String.msg文件自动生成的标头。*/

int main(int argc, char **argv)
{
 
  ros::init(argc, argv, "talker");
/*初始化ROS。这允许ROS通过命令行进行名称重映射 - 现在不重要。这也是我们
  指定节点名称的地方。节点名称在正在运行的系统中必须是唯一的.
  此处使用的名称必须是基本名称,即。它不能有/在其中。*/
  
  ros::NodeHandle n;
/*为此进程的节点创建句柄。创建的第一个NodeHandle实际上将执行节点的初始化*/
  
  ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
/*告诉主人我们将在主题chatter中发布类型为std_msgs / String的消息。
  	这让主人告诉任何监听chatter节点的节点,我们将发布有关该主题的数据。
  	第二个参数是我们的发布队列的大小。在这种情况下,如果我们发布得太快,
  	它将在开始丢弃旧消息之前缓冲最多1000条消息。
  	NodeHandle::advertise()返回一个ros::Publisher对象,它有两个目的:
  	1)它包含一个publish()方法,它允许你将消息发布到它创建的主题上,以及
  	2)当它超出范围时,它会自动取消广告。*/
  
  ros::Rate loop_rate(10);
/*使用ros :: Rate对象可以指定要循环的频率。它将跟踪自上次调用
  Rate :: sleep()以来的持续时间,并在正确的时间内休眠。在这种情况下,
  我们告诉它我们想要以10Hz运行。*/
  
  int count = 0;
  
/*默认情况下,roscpp将安装一个SIGINT处理程序,该处理程序提供Ctrl-C处理,
如果发生这种情况,将导致ros :: ok()返回false。如果出现以下情况,
ros :: ok()将返回false:
收到SIGINT(Ctrl-C)
我们已被另一个具有相同名称的节点踢出网络
ros :: shutdown()已被应用程序的另一部分调用。
所有ros ::NodeHandles都被销毁了
一旦ros :: ok()返回false,所有ROS调用都将失败。
*/
  while (ros::ok())   
  {
/*我们使用消息适配类在ROS上广播消息,通常从msg文件生成。
更复杂的数据类型是可能的,但是现在我们将使用标准的String消息,
它有一个成员:“data”。*/
    std_msgs::String msg;
    std::stringstream ss;
    ss << "hello world " << count;
    msg.data = ss.str();

/*ROS_INFO和friend是printf/cout的替代品。*/
    ROS_INFO("%s", msg.data.c_str());

/*将消息广播给任何已连接的人。*/
    chatter_pub.publish(msg);

/*这个简单的程序不需要调用ros :: spinOnce(),因为我们没有收到任何回调。
但是,如果您要在此应用程序中添加订阅,并且此处没有ros::spinOnce(),
则永远不会调用您的回调。所以,添加它是为了衡量。*/
    ros::spinOnce();

/*现在我们使用ros::Rate对象在剩余时间内休眠,让我们达到10Hz的发布速度。*/
    loop_rate.sleep();
    ++count;
  }    
  return 0;
}

这是正在发生的事情的浓缩版本:
初始化ROS系统
宣传我们将把聊天主题上的std_msgs / String消息发布给master
循环发布消息,每秒10次聊天
现在我们需要编写一个节点来接收这些消息。

 

4.2、编写订阅者节点

在beginner_tutorials包中创建src / listener.cpp文件并在其中粘贴以下内容:

#include "ros/ros.h"
#include "std_msgs/String.h"

/*这是一个回调函数,当一个新消息到达chatter主题时将被调用。消息在
boost shared_ptr中传递,这意味着您可以根据需要将其存储起来,而
不必担心它会被删除,并且不会复制基础数据。*/
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener");

  ros::NodeHandle n;
/*与主人订阅chatter主题。每当有新消息到达时,ROS都会调用chatterCallback()
函数。第二个参数是队列大小,以防我们无法足够快地处理消息。在这种情况下,
如果队列达到1000条消息,我们将在新消息到达时开始丢弃旧消息。
NodeHandle :: subscribe()返回一个ros::Subscriber对象,您必须保留该对象,
直到您想取消订阅为止。订阅者对象被销毁后,它将自动取消订阅chatter主题。
NodeHandle::subscribe()函数有一些版本允许您指定类成员函数,甚至可以指定
Boost.Function对象可调用的任何函数。该roscpp概述包含更多的信息。*/
  ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);

/*ros::spin()进入一个循环,尽可能快地调用消息回调。不过不用担心,如果没有什么
可以做的话就不会占用太多的CPU。只要ros::ok()返回false,ros::spin()将退出,
这意味着已经调用了ros::shutdown(),默认的Ctrl-C处理程序,master告诉我们关
闭,或者手动调用它。*/
  ros::spin();

  return 0;
}

再次,这是一个精简版的正在发生的事情:
初始化ROS系统
订阅聊天主题
旋转,等待消息到达
当消息到达时,将调用chatterCallback()函数

 

五、ROS单线程和多线程订阅

5.1、单线程订阅

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

void tempCallback(const std_msgs::BoolConstPtr& msg)
{
    int num = 10;
    ros::Rate loop_rate(10);
    while (ros::ok() && num)
    {
        ROS_INFO_STREAM("temp temp temp temp temp temp temp temp call back, num->"<<num);
        num--;
        loop_rate.sleep();
    }
}

void longCallback(const std_msgs::BoolConstPtr& msg)
{
    int num = 10;
    ros::Rate loop_rate(10);
    while (ros::ok() && num)
    {
        ROS_INFO_STREAM("long call back, num->"<<num);
        num--;
        loop_rate.sleep();
    }
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "test_node");

    ros::NodeHandle nh;
    ros::Subscriber tempSub = nh.subscribe<std_msgs::Bool>("temp", 1, tempCallback);
    ros::Subscriber longSub = nh.subscribe<std_msgs::Bool>("long", 1, longCallback);

    ros::spin();

    return 0;
}

输入:

rostopic pub /long std_msgs/Bool "data: false" -r 10
rostopic pub /temp std_msgs/Bool "data: false" -r 10

输出:

[ INFO] [1565918138.532995825]: long call back, num->10
[ INFO] [1565918138.633079367]: long call back, num->9
[ INFO] [1565918138.733064686]: long call back, num->8
[ INFO] [1565918138.832994117]: long call back, num->7
[ INFO] [1565918138.932998012]: long call back, num->6
[ INFO] [1565918139.032996832]: long call back, num->5
[ INFO] [1565918139.133071165]: long call back, num->4
[ INFO] [1565918139.232960431]: long call back, num->3
[ INFO] [1565918139.332995614]: long call back, num->2
[ INFO] [1565918139.432999905]: long call back, num->1
[ INFO] [1565918139.533033535]: temp temp temp temp temp temp temp temp call back, num->10
[ INFO] [1565918139.633149213]: temp temp temp temp temp temp temp temp call back, num->9
[ INFO] [1565918139.733148347]: temp temp temp temp temp temp temp temp call back, num->8
[ INFO] [1565918139.833150790]: temp temp temp temp temp temp temp temp call back, num->7
[ INFO] [1565918139.933050574]: temp temp temp temp temp temp temp temp call back, num->6
[ INFO] [1565918140.033141442]: temp temp temp temp temp temp temp temp call back, num->5
[ INFO] [1565918140.133159048]: temp temp temp temp temp temp temp temp call back, num->4
[ INFO] [1565918140.233151712]: temp temp temp temp temp temp temp temp call back, num->3
[ INFO] [1565918140.333148631]: temp temp temp temp temp temp temp temp call back, num->2
[ INFO] [1565918140.433147718]: temp temp temp temp temp temp temp temp call back, num->1
[ INFO] [1565918140.533266548]: long call back, num->10
[ INFO] [1565918140.633400237]: long call back, num->9
[ INFO] [1565918140.733407032]: long call back, num->8
[ INFO] [1565918140.833389468]: long call back, num->7
[ INFO] [1565918140.933386767]: long call back, num->6
[ INFO] [1565918141.033389566]: long call back, num->5
[ INFO] [1565918141.133389982]: long call back, num->4
[ INFO] [1565918141.233389902]: long call back, num->3
[ INFO] [1565918141.333395700]: long call back, num->2
[ INFO] [1565918141.433399861]: long call back, num->1
[ INFO] [1565918141.533413994]: temp temp temp temp temp temp temp temp call back, num->10
[ INFO] [1565918141.633477569]: temp temp temp temp temp temp temp temp call back, num->9
[ INFO] [1565918141.733526139]: temp temp temp temp temp temp temp temp call back, num->8
[ INFO] [1565918141.833527631]: temp temp temp temp temp temp temp temp call back, num->7
[ INFO] [1565918141.933526546]: temp temp temp temp temp temp temp temp call back, num->6
[ INFO] [1565918142.033560826]: temp temp temp temp temp temp temp temp call back, num->5
[ INFO] [1565918142.133522903]: temp temp temp temp temp temp temp temp call back, num->4
[ INFO] [1565918142.233525957]: temp temp temp temp temp temp temp temp call back, num->3
[ INFO] [1565918142.333525708]: temp temp temp temp temp temp temp temp call back, num->2
[ INFO] [1565918142.433521566]: temp temp temp temp temp temp temp temp call back, num->1

 

5.2、多线程订阅

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

void tempCallback(const std_msgs::BoolConstPtr& msg)
{
    int num = 1;
    ros::Rate loop_rate(10);
    while (ros::ok() && num)
    {
        ROS_INFO_STREAM("temp temp temp temp temp temp temp temp call back, num->");
        num--;
        loop_rate.sleep();
    }
}

void longCallback(const std_msgs::BoolConstPtr& msg)
{
    int num = 10;
    ros::Rate loop_rate(10);
    while (ros::ok() && num)
    {
        ROS_INFO_STREAM("long call back, num->"<<num);
        num--;
        loop_rate.sleep();
    }
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "test_node");

    ros::NodeHandle nh;
    ros::Subscriber tempSub = nh.subscribe<std_msgs::Bool>("temp", 1, tempCallback);
    ros::Subscriber longSub = nh.subscribe<std_msgs::Bool>("long", 1, longCallback);

    ros::MultiThreadedSpinner spinner(3);//三个线程订阅
    spinner.spin();

    return 0;
}

输入:

rostopic pub /long std_msgs/Bool "data: false" -r 10
rostopic pub /temp std_msgs/Bool "data: false" -r 10

输出:

[ INFO] [1565917840.270586066]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917840.332730168]: long call back, num->10
[ INFO] [1565917840.370680016]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917840.432812052]: long call back, num->9
[ INFO] [1565917840.470733027]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917840.532746151]: long call back, num->8
[ INFO] [1565917840.570822519]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917840.632748312]: long call back, num->7
[ INFO] [1565917840.670920845]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917840.732748731]: long call back, num->6
[ INFO] [1565917840.771020449]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917840.832749593]: long call back, num->5
[ INFO] [1565917840.871116535]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917840.932749685]: long call back, num->4
[ INFO] [1565917840.971215785]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917841.032749710]: long call back, num->3
[ INFO] [1565917841.071313507]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917841.132749230]: long call back, num->2
[ INFO] [1565917841.171407053]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917841.232743868]: long call back, num->1
[ INFO] [1565917841.271526256]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917841.332755181]: long call back, num->10
[ INFO] [1565917841.371625145]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917841.432905582]: long call back, num->9
[ INFO] [1565917841.471753894]: temp temp temp temp temp temp temp temp call back, num->
[ INFO] [1565917841.532846109]: long call back, num->8

 

 

六、创建编译并运行完整的ros helloword工程(c++版-加深理解)

6.1 、创建工作空间

1. 创建catkin工作空间

$  mkdir -p ~/catkin_ws/src
$  cd ~/catkin_ws/src

2. 编译catkin工作空间

$  cd ~/catkin_ws/
$  catkin_make

3.配置环境变量

$  source devel/setup.bash

echo $ROS_PACKAGE_PATH # 查看刚刚配置的环境变量是否生效
————————————————
6.2 、创建软件包(project)

创建名称为 my_ros_helloworld_cpluse 的软件包

cd catkin_ws/src  # 进入工作空间下的 src 目录  (注意路径!!!)

catkin_create_pkg my_ros_helloworld_cpluse std_msgs rospy roscpp

cd ..             #退到 catkin_ws 工作空间路径下

catkin_make       #编译软件包

 

6.3、工程创建

1、 编写talker.cpp 创建消息发布器节点 (发布话题)

创建src/talker.cpp 文件

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

using namespace std;

int main( int argc, char** argv )
{
    // 创建节点
    ros::init(argc, argv, "talker_node");
    ros::NodeHandle n;

    // 发布话题
    ros::Publisher talkerPub = n.advertise<std_msgs::String>("chatter", 10);

    // 设置发送频率
    ros::Rate loop_rate(10);

    int count = 0;
    while(ros::ok())
    {

        std_msgs::String msg;

        std::stringstream ss;
        ss << "hello world" <<count; // 将“hello world” 和 count 一起输出到 string流中

        msg.data = ss.str(); // String 转为 str 作为消息体的数据

        ROS_INFO("%s", msg.data.c_str());

        talkerPub.publish(msg);

        ros::spinOnce();

        loop_rate.sleep();

        count ++;
    }

    return 0;
}

2、 编写listener.cpp 创建消息接收器节点 (订阅话题)

创建src/listener.cpp 文件

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

using namespace std;
// 定义回调函数
void listener_callback(const std_msgs::String::ConstPtr& msg)
{
    ROS_INFO("I heard : [%s]" , msg->data.c_str()); // String 转为 str字符串
}

int main( int argc, char** argv)
{
    // 创建节点
    ros::init(argc, argv, "listener_node");
    ros::NodeHandle n;

    // 订阅话题 以及指定该话题的回调函数
    ros::Subscriber listenerSub = n.subscribe("chatter", 10,listener_callback);

    ros::spin();

    return 0;
}

3、 编写CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3)
project(my_ros_helloworld_cpluse)

## Find catkin and any catkin packages
find_package(catkin REQUIRED COMPONENTS roscpp rospy std_msgs genmsg)


## Declare a catkin package
catkin_package()

## 编译 talker and listener
include_directories(include ${catkin_INCLUDE_DIRS})


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


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

4、 编译

在ros_test_ws 目录下 运行 catkin_make 命令编译,生成可执行文件 talker 以及 listener

在这里插入图片描述

6.4 、运行此工程

注意:用echo $ROS_PACKAGE_PATH 查看此工作空间是否在环境变量中
若没有则运行此命令 source ~/ros_test_ws/devel/setup.bash 也可以通过 直接将此命令写入 home目录下的 .bashrc文件中,这样就不需要每次都source ~/ros_test_ws/devel/setup.bash 。因为每打开一个新的终端,都会先加载 .bashrc文件。

确保环境变量加载正确,否则rosrun 找不到 软件包 !!!
开三个终端,分别运行如下命令:

1 运行 ros master
先运行命令 roscore

2 运行 talker
source ros_test_ws/devel/setup.bash
rosrun my_ros_helloworld_cpluse talker
————————————————
 在这里插入图片描述

3 运行 listener

source ros_test_ws/devel/setup.bash
rosrun my_ros_helloworld_cpluse listener

在这里插入图片描述

 

 

七、launch文件

每当我们需要运行一个ROS节点或工具时,都需要打开一个新的终端运行一个命令。当系统中的节点数量不断增加时,每个节点一个终端的模式会变得非常麻烦。那么有没有一种方式可以一次性启动所有节点呢?答案当然是肯定的。

启动文件(Launch File)便是ROS中一种同时启动多个节点的途径,还可以自动启动ROSMaster节点管理器,而且可以实现每个节点的各种配置,为多个节点的操作提供了很大便利。

7.1、基本元素

首先来看一个简单的launch文件:

  1. <launch>
  2. <nodepkg="turtlesim"name="sim1" type="turtlesim_node"/>
  3. <nodepkg="turtlesim"name="sim2" type="turtlesim_node"/>
  4. </launch>

这是一个简单而完整的launch文件,采用XML的形式进行描述,包含一个根元素<launch>和两个节点元素<node>。

1.<launch>

XML文件必须要包含一个根元素,launch文件中的根元素采用<launch>标签定义,文件中的其他内容都必须包含在这个标签之中:

  1. <launch>
  2. ......
  3. </launch>

2. <node>

启动文件的核心是启动ROS节点,采用<node>标签定义,语法如下:

  1. <node pkg="package-name"type="executable-name" name="node-name" />

从上边的定义规则可以看出,在启动文件中启动一个节点需要三个属性:pkg、type和name。其中pkg定义节点所在的功能包名称,type定义节点的可执行文件名称,这两个属性等同于在终端中使用rosrun命令执行节点时的输入参数。name属性用来定义节点运行的名称,将覆盖节点中init()赋予节点的名称。这是三个最常用的属性,在某些情况下,我们还有可能用到以下属性:

·  output = “screen”:将节点的标准输出打印到终端屏幕,默认输出为日志文档;

·  respawn = “true”:复位属性,该节点停止时,会自动重启,默认为false;

·  required = “true”:必要节点,当该节点终止时,launch文件中的其他节点也被终止;

·  ns = “namespace”:命名空间,为节点内的相对名称添加命名空间前缀;

·  args = “arguments”:节点需要的输入参数。

实际应用中的launch文件往往会更加复杂,使用的标签也会更多,例如一个启动机器人的launch文件如下:

    <launch>

       <node pkg="mrobot_bringup" type="mrobot_bringup" name="mrobot_bringup" output="screen" />

       <arg name="urdf_file" default="$(find xacro)/xacro --inorder '$(find mrobot_description)/urdf/mrobot_with_rplidar.urdf.xacro'" />
       <param name="robot_description" command="$(arg urdf_file)" />

       <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />  

       <node pkg="robot_state_publisher" type="robot_state_publisher" name="state_publisher">
           <param name="publish_frequency" type="double" value="5.0" />
       </node>
       <node name="base2laser" pkg="tf" type="static_transform_publisher" args="0 0 0 0 0 0 1 /base_link /laser 50"/>

       <node pkg="robot_pose_ekf" type="robot_pose_ekf" name="robot_pose_ekf">
           <remap from="robot_pose_ekf/odom_combined" to="odom_combined"/>
           <param name="freq" value="10.0"/>
           <param name="sensor_timeout" value="1.0"/>
           <param name="publish_tf" value="true"/>
           <param name="odom_used" value="true"/>
           <param name="imu_used" value="false"/>
           <param name="vo_used" value="false"/>
           <param name="output_frame" value="odom"/>
       </node>

       <include file="$(find mrobot_bringup)/launch/rplidar.launch" />

    </launch>

目前,我们只关注其中的标签元素,除了上边介绍的<launch>和<node>,这里还出现了<arg>、<param>、<remap>,这些都是常用的标签元素。

 

7.2、参数设置

为了方便设置和修改,launch文件支持参数设置的功能,类似于编程语言中的变量声明。关于参数设置的标签元素有两个:<param>、<arg>,一个代表parameter,另一个代表argument。这两个标签元素翻译成中文都是“参数”的意思,但是这两个“参数”的意义是完全不同的。

1. <param>

parameter是ROS系统运行中的参数,存储在参数服务器中。在launch文件中通过<param>元素加载parameter;launch文件执行后,parameter就加载到ROS的参数服务器上了。每个活跃的节点都可以通过 ros::param::get()接口来获取parameter的值,用户也可以在终端中通过rosparam命令获得parameter的值。

<param>的使用方法如下:

  1. <param name="output_frame" value="odom"/>

运行launch文件后,output_frame这个parameter的值就设置为odom,并且加载到ROS参数服务器上了。但是在很多复杂的系统中,参数的数量很多,如果这样一个一个的设置会非常麻烦,ROS也为我们提供了另外一种类似的参数加载方式——<rosparam>:

  1. <rosparamfile="$(find 2dnav_pr2)/config/costmap_common_params.yaml" command="load" ns="local_costmap" />

<rosparam>可以帮助我们将一个yaml格式文件中的参数全部加载到ROS参数服务器中,需要设置command属性为“load”,还可以选择设置命名空间“ns”。

2. <arg>

argument是另外一个概念,类似于launch文件内部的局部变量,仅限于launch文件使用,便于launch文件的重构,和ROS节点内部的实现没有关系。

设置argument使用<arg>标签元素,语法如下:

  1. <arg name=”arg-name” default=”arg-value”/>

launch文件中需要使用到argument时,可以使用如下方式调用:

  1. <paramname="foo" value="$(argarg-name)" />
  2. <node name="node" pkg="package" type="type "args="$(arg arg-name)" />
  3.  

7.3、重映射机制

ROS的设计目标是提高代码的复用率,所以ROS社区中的很多功能包我们都可以拿来直接使用,而不需要关注功能包的内部实现。那么问题就来了,别人功能包的接口不一定和我们的系统兼容呀?

ROS提供一种重映射的机制,简单来说就是取别名,类似于C++中的别名机制,我们不需要修改别人功能包的接口,只需要将接口名称重映射一下,取个别名,我们的系统就认识了(接口的数据类型必须相同)。launch文件中的<remap>标签可以帮我们实现这个重映射的功能。

比如turtlebot的键盘控制节点,发布的速度控制指令话题可能是/turtlebot/cmd_vel,但是我们自己的机器人订阅的速度控制话题是/cmd_vel,这个时候使用<remap>就可以轻松解决问题,将/turtlebot /cmd_vel重映射为/cmd_vel,我们的机器人就可以接收到速度控制指令了:

  1. <remap from="/turtlebot/cmd_vel"to="/cmd_vel"/>

重映射机制在ROS中的使用非常广泛,也非常重要,方法不止这一种,也可以在终端rosrun命令中实现重映射,大家一定要理解好这种机制。

 

7.4、嵌套复用

在复杂的系统当中,launch文件往往有很多,这些launch文件之间也会存在依赖关系。如果需要直接复用一个已有launch文件中的内容,可以使用<include>标签包含其他launch文件,这和C语言中的include几乎是一样的。

  1. <include file="$(dirname)/other.launch" />

总而言之,launch是ROS框架中非常实用、灵活的功能,它类似于一种高级编程语言,可以帮助我们管理启动系统时的方方面面。在使用ROS的过程中,很多情况下我们并不需要编写大量代码,仅需要使用已有的功能包,编辑一下launch文件,就可以完成很多机器人功能。

 

 

 

 

https://blog.csdn.net/weicao1990/article/details/84400422

https://blog.csdn.net/weixin_37835423/article/details/99670885

https://blog.csdn.net/gungnirspledge/category_10147880.html

https://recomm.cnblogs.com/blogpost/6579883?page=2

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS 简单理解 的相关文章

  • 多态的总结

    对于多态 xff0c 可以总结以下几点 xff1a 一 使用父类类型的引用指向子类的对象 xff1b 二 该引用只能调用父类中定义的方法和变量 xff1b 三 如果子类中重写了父类中的一个方法 xff0c 那么在调用这个方法的时候 xff0
  • android 深度图

    在 Android开发中自定义控件是一个范围很广的话题 xff0c 讲起自定义控件 xff0c 从广度上来划分的话 xff0c 大体上可以划分为 xff1a View ViewGroup的绘制事件分发各种动画效果滚动嵌套机制还有涉及到相关的
  • 在配置Intel realsense (D435i)时遇到的问题

    1 第一次配置相机时 配置完成后 运行相机报以下错误 02 11 20 50 18 674 WARNING 140196725126912 messenger libusb cpp 42 control transfer returned
  • Robosense M1/速腾半固态激光雷达M1 保姆级教程1-如何连接雷达?

    引言 当我们拿到M1雷达时 xff0c 可能会因为激光雷达是一个新的设备 xff0c 没有用过 xff0c 而感到紧张和局促 没有关系 xff0c 通过阅读文本 xff0c 可以让你轻而易举的上手使用激光雷达 1认识M1接口 图中较粗的接口
  • PMP(一):知识要点汇总

    开篇 首先恭喜自己成为 项目管理专业人士 的一员 xff0c 本专题旨在帮助自己重新梳理整个的知识体系以及后续对于项目管理的理解与尝试 系列一 xff1a 知识要点汇总 以下内容是我在备考和考完后对于部分知识要点的一个汇总和总结 xff0c
  • git在vscode中的使用

    git在vscode中的使用 vscode 作为前端使用较多的软件 xff0c 平时的git操作不可避免 xff0c 但是利用vscode自带的功能和插件 xff0c 可以让我们的工作效率提高不少 项目准备 直接clone span cla
  • 获利空间看刘嘉玲理论来看;乐扣乐扣尽量靠近k

    i tiboo cn 1768805 i tiboo cn 1768806 i tiboo cn 1768807 i tiboo cn 1768810 i tiboo cn 1768813
  • 我见过最清晰的--理解梯度,散度,旋度

    作者 xff1a FRANK WANG 链接 xff1a https www zhihu com question 24074028 answer 26657334 来源 xff1a 知乎 梯度 运算的对像是纯量 运算出来的结果会是向量在一
  • 视觉应用工程师-环境安装教学视频-Mac系统其他操作

    立即学习 https edu csdn net course play 29993 432706 utm source 61 blogtoedu Mac系统安装miniconda搭建深度学习环境 安装 Conda是一个开源的包 环境管理器
  • Windows 环境下安装Redis 5.0.x 服务图文教程

    Windows 环境下安装Redis 5 0 x 服务图文教程 Redis官网并没有提供windows的安装包 xff0c github有第三方制作的windows安装包 下载地址 xff1a https github com tporad
  • Python 爬虫+可视化,手把手教你使用 Python 爬取 JD 网站并且可视化展示

    当你看到别人使用 Python 网络爬虫做出一些高大上的项目你是否也有那么一点点的心动 xff1f 羡慕别人用几行简单的代码就能获取到自己想要的数据 xff1f 羡慕别人用几行代码就能做出优美的可视化图案 xff1f 我将使用最新 Pyth
  • 推荐系统实践:基于数据集MovieLens构造简单推荐系统

    摘要 本文基于 MovieLens 数据集构造了用户 电影项目评价矩阵 xff0c 并基于评价矩阵计算两用户间的相似度 xff0c 取出相似度最高的 N 个用户作为候选用户序列 接着筛选出这 N 个候选用户的高分电影项目且当前用户尚未观看
  • Flask 入门教程:Jinja2模板用法

    Jinja2模板引擎简介 模板 在前面的示例中 xff0c 视图函数的主要作用是生成请求的响应 xff0c 这是最简单的请求 实际上 xff0c 视图函数有两个作用 xff1a 处理业务逻辑和返回响应内容 在大型应用中 xff0c 把业务逻
  • VINS-mono中坐标系定义以及通过VINS-mono求解无人机位姿

    因为在科研中需要使用VINS mono算法来为无人机提供位姿估计信息 因此需要搞清楚VINS mono相应坐标系以及无人机坐标系之间的关系 目录 1 坐标系关系 1 1 VINS mono坐标系定义 1 2 无人机坐标系 2 通过VINS
  • Github Copilot 开始收费了, 帮你列出些替代的插件

    今天打开 VSCode xff0c 弹出了Github Copilot 开始收费的通知 可以免费用到 8 月 22 日 xff0c 每月 70 元还是有些小贵 这里给大家推荐一些替代品 xff1a Kite https www kite c
  • 如何在 Ubuntu上使用 Nginx 设置密码验证

    介绍 设置 Web 服务器时 xff0c 您通常希望限制访问网站的某些部分 Web 应用程序通常提供自己的身份验证和授权方法 xff0c 但如果这些方法不充分或不可用 xff0c 则可以使用 Web 服务器本身来限制访问 在本指南中 xff
  • 使用Argo CD和GitOps持续部署到Kubernetes

    引言 使用Kubernetes部署你的应用程序可以提供显著的基础设施优势 xff0c 例如灵活的伸缩 分布式组件的管理以及对应用程序不同版本的控制 然而 xff0c 随着控制的增加 xff0c 复杂性也随之增加 持续集成和持续部署 CI C
  • GitHub Codespaces 的配置

    CPU xff1a 4x Xeon 64 2 60 GHz 轻度开发够用 xff0c 要是编译什么稍微复杂一点的项目 估计会CPU跑满 内存 xff1a 8G xff0c 勉强够用 自用的Mac 16G都感觉不太够 硬盘 xff1a 32G
  • 使用Zoundry在CSDN发布Blog

    安装一个Zoundry吧 xff0c 用这个来离线写Blog xff0c 再也不怕突然断线和丢失文章了 Zoundry是用Python实现的一个离线撰写Blog工具 支持Community Servedr blogger com Wordp
  • Python中Array的常用操作(二)数组基本操作

    1 数组操作 x代表数组中的元素 xff0c i代表位置 a append x 把元素x添加到数组的尾部 b insert i x 把元素x 插入到位置i c remove x 删除第一个元素x d pop i 删除第i个元素 xff0c

随机推荐

  • Python中Array的常用操作(三)数组高级操作

    1 抽取数组中不重复的数据 gt gt gt a 61 x 2 for x in range 1 5 2 gt gt gt uniq 61 list set a 8 2 4 6 gt gt gt uniq 61 sorted set a 2
  • 2011年,移动互联网加速蔓延 – 来自2011移动开发者大会

    2011移动开发者大会 xff0c 这是第二届移动开发者大会了 xff0c 这一年来移动互联网各个领域蔓延开来 xff0c 蔓延这个词是开复老师演讲的主题 从事塞班开发的请举手 xff0c 举手者寥寥 记得在去年移动开发者大会上 xff0c
  • main函数之前做了什么?

    main函数之前 真正的函数执行入口或开始 一种解释 实际上 xff0c 在可执行文件被加载之后 xff0c 控制权立即交给由编译器插入的Start函数 xff0c 它将对后面这些全局变量进行准备 xff1a osver 操作系统的构件编号
  • detecron2中的注册机制

    文章目录 一 为什么使用注册类二 注册类的实现 传送门 Detectron2 01 注册机制 Registry 实现 一 为什么使用注册类 以下转自知乎 https zhuanlan zhihu com p 93835858 对于detec
  • 单目视觉SLAM在无人机上的应用

    目录 写在前面 本文说明 论文链接和实验视频 源代码链接 一 实验环境 硬件 软件 算法 二 实验环境搭建过程 1 Intel NUC安装Ubuntu 16 04 2 安装ROS D435i驱动以及ORB SLAM2算法 3 ORB SLA
  • TypeError: Expected cv::UMat for argument ‘img‘

    研究Detectron2中的在线数据增强的源码 并显示数据增强后的图像时 xff0c 遇到 TypeError Expected cv UMat for argument 39 img 的问题 显然 xff0c 问题要求是输入一个uint8
  • Linux 桌面终于迎来了 Docker Desktop

    Docker 桌面是容器化应用程序的最简单方法 无需考虑在你选择的系统上设置环境即可开始使用 只需要安装 Docker 桌面 xff0c 就可以开始了 Docker 桌面应用程序附带容器工具 xff0c 如 Kubernetes Docke
  • Dockerfile制作镜像和常用Shell脚本语法记录

    一 常规命令和使用记录 1 定义变量 判断匹配 赋值等 定义变量 addr 61 a namespace 61 b 判断匹配自定义的 包括参数化构建设置的变量 环境变量 xff0c 并赋值 case 34 Env 34 in dev nam
  • [Holo_wo]-vscode常用配置项说明

    vscode 配置文件核心 settings json xff1a 整个vscode的配置 xff0c 是本地vscode的配置 xff0c 如果有ssh远程 xff0c 那么会在远程主机的 vscode server目录下有setting
  • 基于jQuery的ajax跨域请求,PHP作为服务器端代码

    ajax实现跨域请求有两种方式 xff1a 方法一 xff1a jsonp的方式 jsonp方式的关键点在客户请求以jsonp作为数据类型 xff0c 服务器端接收jsonp的回调函数 xff0c 并通过回调函数进行数据的传输 具体代码如下
  • 无人机位置信息计算无人机的瞬时速度的matlab仿真

    目录 1 算法描述 2 仿真效果预览 3 MATLAB核心程序 4 完整MATLAB 1 算法描述 无人机最早在20世纪20年代出现 xff0c 1914年第一次世界大战正进行得如火如荼 xff0c 英国的卡德尔和皮切尔两位将军 xff0c
  • 基于simulink的无人机姿态飞行控制仿真

    目录 1 算法描述 2 仿真效果预览 3 MATLAB核心程序 4 完整MATLAB 1 算法描述 无人机是无人驾驶飞机的简称 xff08 Unmanned Aerial Vehicle xff09 xff0c 是利用无线电遥控设备和自备的
  • 基于ADRC自抗扰控制器的simulink仿真,ESO和TD等模块使用S函数开发

    目录 1 算法仿真效果 2 MATLAB核心程序 3 算法涉及理论知识概要 4 完整MATLAB 1 算法仿真效果 matlab2022a仿真结果如下 xff1a 2 MATLAB核心程序 function sys x0 str ts 61
  • m基于模糊控制与遗传优化的自适应ADRC双闭环控制策略matlab仿真

    目录 1 算法仿真效果 2 MATLAB核心程序 3 算法涉及理论知识概要 4 完整MATLAB 1 算法仿真效果 matlab2013b仿真结果如下 xff1a 遗传优化的优化迭代过程仿真图 xff1a 这个是我们采用的优化算法的有过过程
  • VINS-mono在Ubuntu20.04上从零开始安装运行和环境配置(尝试)

    最近尝试在Ubuntu 20 04上安装运行港科大的VINS mono算法 详细记录一下安装过程以及遇到的问题 先记录一下结果 ROS opencv Eigen Ceres以及VINS mono都编译并安装成功了 但是用euroc数据集跑V
  • 数据结构-C++实现

    之前的2周一直在学数据结构 xff0c 头都大了 我是之前对数据结构一点认识都没有 xff0c 我是直接看书怼的 xff0c 我看的是 大话数据结构 xff0c 前面的讲解还不错 xff0c 到了树 图后 xff0c 就有点看不懂了 xff
  • 几款好看的css表格

    表格一 xff1a 代码 xff1a html代码段 xff1a 是用vs写的 表头 lt th gt 那是从数据库读取的数据段 lt td gt 那是我为测试效果加的代码 xff0c 大家可以自行更改 lt h1 gt 待处理订单 lt
  • 非线性优化 (曲线拟合) 问题:高斯牛顿、g2o 方法总结

    其实还有一个Ceres库可以进行优化 xff0c 但是之前的博客已经具体分析了 xff0c 所以这里就对其余两个进行了介绍 xff0c 相关的内容是SLAM14讲里面的知识 一 理论部分 我们先用一个简单的例子来说明如何求解最小二乘问题 x
  • VINS-Fusion : EUROC、TUM、KITTI测试成功 + 程序进程详细梳理

    完成以下任务的前提是系统安装了必备的库 xff0c 比如cere Eigen3 3等 提前下载好了数据集EUROC xff0c KITTI等 一 相关论文 T Qin J Pan S Cao and S Shen A General Opt
  • ROS 简单理解

    https download csdn net download qq 30022867 11120759 utm medium 61 distribute pc relevant download none task download b