ROS 示例

参考链接1

话题中的Publisher与Subscriber

例1: 发送和接收 hello, world

1、创建工作空间
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
catkin_init_workspace

创建完成后,可以在工作空间的根目录下使用catkin_make命令编译整个工作空间:

cd ~/catkin_ws/
catkin_make

在这里插入图片描述

编译过程中,在工作空间的根目录里会自动产生build和devel两个文件夹及其中的文件。编译完成后,在devel文件夹中已经产生几个setup.*sh形式的环境变量设置脚本。使用source命令运行这些脚本文件,则工作空间中的环境变量可以生效。

source devel/setup.bash

为了确保环境变量已经生效,可以使用如下命令进行检查:

echo $ROS_PACKAGE_PATH

如果打印的路径中已经包含当前工作空间的路径,则说明环境变量设置成功

2、创建功能包 learning_communication

进入代码空间,使用catkin_create_pkg命令创建功能包

# 命令格式
catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
cd ~/catkin_ws/src
catkin_create_pkg learning_communication std_msgs rospy roscpp

回到工作空间的根目录下进行编译(命令行cd),并且设置环境变量

cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bash

在这里插入图片描述

3、创建Publisher

Publisher的主要作用是针对 指定话题 发布 特定数据类型 的消息

创建步骤
·初始化ROS节点。
·向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型。
·按照一定频率循环发布消息。

使用代码实现一个节点,节点中创建一个Publisher并发布字符串“Hello World”
learning_communication\src\talker.cpp

在目录/home/xixi/catkin_ws/src/learning_communication/src 打开命令行
在这里插入图片描述
创建一个空白的.cpp文件

touch talker.cpp

输入[复制 ]该代码

#include <sstream>
#include "ros/ros.h"  // 包含大部分 ROS 中通用的头文件
#include "std_msgs/String.h" // 节点发布的消息 "Hello World" 为 String 类型
int main(int argc, char **argv)
{
    // ROS节点初始化  // 第三个参数定义了Publisher节点的名称,而且该名称在运行的ROS中必须是独一无二的,不允许同时存在相同名称的两个节点。
    ros::init(argc, argv, "talker"); // 前两个参数是命令行或launch文件输入的参数,可以用来完成命名重映射等功能
    // 创建节点句柄  方便对节点资源的使用和管理
    ros::NodeHandle n;
    // 创建一个Publisher,发布名为chatter的topic,消息类型为std_msgs::String
    ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);
    // 设置循环的频率  Hz
    ros::Rate loop_rate(10);
    int count = 0;
    while (ros::ok())
    {
        // 初始化std_msgs::String类型的消息
        std_msgs::String msg;
        std::stringstream ss;
        ss << "hello, world " << count;
        msg.data = ss.str();
        // 发布消息
        ROS_INFO("%s", msg.data.c_str()); // 类似于C/C++中的printf/cout函数,用来打印日志信息。
        chatter_pub.publish(msg); // 发布封装完毕的消息msg
        // 循环等待回调函数
        ros::spinOnce();
        // 按照循环频率延时
        loop_rate.sleep();  // 之前设置了10Hz的休眠时间,节点休眠100ms后又会开始下一个周期的循环工作。
        ++count;
    }
    return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、创建Subscriber

创建一个Subscriber以订阅Publisher节点发布的“Hello World”字符串
learning_communication\src\listener.cpp

在目录/home/xixi/catkin_ws/src/learning_communication/src 打开命令行
在这里插入图片描述
创建一个空白的.cpp文件

touch listener.cpp

输入[复制 ]该代码

#include "ros/ros.h"
#include "std_msgs/String.h"
// 接收到订阅的消息后,会进入消息回调函数
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
    // 将接收到的消息打印出来
    ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
    // 初始化ROS节点
    ros::init(argc, argv, "listener");
    // 创建节点句柄
    ros::NodeHandle n;  // 下一句就用了 n
    // 创建一个Subscriber,订阅名为chatter的话题,注册回调函数chatterCallback
    ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
    // 循环等待回调函数
    ros::spin();
    return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5、编译功能包

节点的代码已经完成,C++是一种编译语言,在运行之前需要将代码编译成可执行文件,如果使用Python等解析语言编写代码,则不需要进行编译,可以省去此步骤。

ROS中的编译器使用的是CMake,编译规则通过功能包中的CMakeLists.txt文件设置,使用catkin命令创建的功能包中会自动生成该文件

打开功能包中的CMakeLists.txt文件,找到以下配置项,去掉注释并稍作修改
在这里插入图片描述
CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

project(learning_communication)

include_directories(include ${catkin_INCLUDE_DIRS})

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

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)

CMakeLists.txt修改完成后,在工作空间的根路径下开始编译:

cd ~/catkin_ws
catkin_make

————
报错:

/home/xixi/catkin_ws/src/learning_communication/src/listener.cpp:1:10: fatal error: ros/ros.h: No such file or directory
    1 | #include "ros/ros.h"
      |          ^~~~~~~~~~~
compilation terminated.

解决办法链接

6、运行Publisher与Subscriber

在运行节点之前,需要在终端中设置环境变量,否则无法找到功能包最终编译生成的可执行文件:

cd ~/catkin_ws
source ./devel/setup.bash

也可以将环境变量的配置脚本添加到终端的配置文件中:

echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc

环境变量设置成功后,可以按照以下步骤启动例程。

1.启动roscore

roscore

2.启动Publisher
Publisher和Subscriber节点的启动顺序在ROS中没有要求,这里先使用rosrun命令启动Publisher:

rosrun learning_communication talker

——
报错:
解决办法链接
因为改了 CMakeLists.txt,返回第5步编译。
————
在这里插入图片描述
3.启动Subscriber
Publisher节点已经成功运行,接下来需要运行Subscriber节点,订阅Publisher发布的消息:

rosrun learning_communication listener

在这里插入图片描述
—————

例2:自定义话题消息

在ROS的元功能包common_msgs中提供了许多不同消息类型的功能包,如std_msgs(标准数据类型)、geometry_msgs(几何学数据类型)、sensor_msgs(传感器数据类型)等。

learning_communication/msg/Person.msg
在这里插入图片描述
新建名为 msg 的文件夹
在该文件夹 中 Open in Terminal
通过下列命令 新建文件 Person.msg

touch Person.msg

Person.msg

string name
uint8  sex
uint8  age

uint8 unknown = 0
uint8 male    = 1
uint8 female  = 2

编译msg文件
(1)在package.xml中添加功能包依赖
首先打开功能包的package.xml文件,确保该文件中设置了以下编译和运行的相关依赖:

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

去掉注释

在这里插入图片描述

补充:
在这里插入图片描述
<build_depend></build_depend>标签定义了功能包中代码编译所依赖的其他功能包,而<run_depend></run_depend>标签定义了功能包中可执行程序运行时所依赖的其他功能包。

(2)在CMakeLists.txt中添加编译选项
打开功能包的CMakeLists.txt文件,在find_package中添加消息生成依赖的功能包message_generation,这样在编译时才能找到所需要的文件:

find_package(catkin REQUIRED COMPONENTS
    geometry_msgs
    roscpp
    rospy
    std_msgs
    message_generation
)

catkin依赖也需要进行以下设置:

catkin_package(
    ……
    CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs message_runtime
    ……)

最后设置需要编译的msg文件:

add_message_files(
    FILES
    Person.msg
)
generate_messages(
    DEPENDENCIES
    std_msgs
)

以上配置工作都完成后,就可以回到工作空间的根路径下,使用catkin_make命令进行编译了。

cd ~/catkin_ws
catkin_make

————
报错:

Error(s):
- The manifest of package "learning_communication" (with format version 2) must not contain the following tags: run_depend
- Please replace <run_depend> tags with <exec_depend> tags.

按照提示修改
发现已有,去掉注释即可
在这里插入图片描述

报错2:

CMake Error at /opt/ros/noetic/share/catkin/cmake/catkin_package.cmake:196 (message):
  catkin_package() the catkin package 'geometry_msgs' has been
  find_package()-ed but is not listed as a build dependency in the
  package.xml

三件套 安排
在这里插入图片描述
报错3:

CMake Error at /opt/ros/noetic/share/genmsg/cmake/genmsg-extras.cmake:197 (message):
  generate_messages() must be called before catkin_package() in project
  'learning_communication'
Call Stack (most recent call first):
  learning_communication/CMakeLists.txt:30 (generate_messages)


-- Configuring incomplete, errors occurred!

调整位置

再次编译

cd ~/catkin_ws
catkin_make

———————————
编译成功后,可以使用如下命令查看自定义的Person消息类型

rosmsg show Person

在这里插入图片描述
CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

project(learning_communication)



find_package(catkin REQUIRED COMPONENTS
    geometry_msgs
    roscpp
    rospy
    std_msgs
    message_generation
)
include_directories(include ${catkin_INCLUDE_DIRS})

## 位置也挺重要
add_message_files(
    FILES
    Person.msg
)
generate_messages(
    DEPENDENCIES
    std_msgs
)

catkin_package(CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs message_runtime) 

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

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)

package.xml

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

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
  <maintainer email="xixi@todo.todo">xixi</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/learning_communication</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>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>
  


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

  </export>
</package>

服务中的Server和Client

例:加法

本例目标
Client发布两个需要相加的int类型变量,Server节点接收请求后完成运算并返回加法运算结果。

服务一般分为服务端(Server)和客户端(Client)两个部分,Client负责发布请求数据,等待Server处理;Server负责处理相应的功能,并且返回应答数据
一般放置在功能包根目录下的srv文件夹中。
若是上述例1中的第1-2步没走,要走一遍。
这里直接从第3步开始

还需要:自定义服务数据

一般放置在功能包根目录下的srv文件夹中。该文件包含请求应答两个数据域,数据域中的内容与话题消息的数据类型相同,只是在请求与应答的描述之间,需要使用“---”进行分割。

针对加法运算例程中的服务需求,创建一个定义服务数据类型的srv文件learning_communication/srv/AddTwoInts.srv

创建文件夹 srv
创建文件 AddTwoInts.srv

touch AddTwoInts.srv

AddTwoInts.srv

int64 a
int64 b
---
int64 sum

在功能包的package.xml和CMakeLists.txt文件中配置依赖与编译规则,在编译过程中将该描述文件转换成编程语言所能识别的代码。
打开package.xml文件,添加以下依赖配置
取消相应的注释即可
在这里插入图片描述
打开CMakeLists.txt文件,添加如下配置

find_package(catkin REQUIRED COMPONENTS
    geometry_msgs
    roscpp
    rospy
    std_msgs
    message_generation
)
add_service_files(
    FILES
    AddTwoInts.srv
)

编译

cd ~/catkin_ws
catkin_make

报错:
在这里插入图片描述

解决办法链接

最终 CMakeLists.txt 在第5步中。

编译成功后,可以使用如下命令查看自定义的AddTwoInts服务类型

rossrv show AddTwoInts

在这里插入图片描述

3、创建Server

创建步骤
·初始化ROS节点。
·创建Server实例。
·循环等待服务请求,进入回调函数。
·在回调函数中完成服务功能的处理并反馈应答数据。

首先创建Server节点,提供加法运算的功能,返回求和之后的结果。
learning_communication/src/server.cpp

在目录/home/xixi/catkin_ws/src/learning_communication/src 打开命令行
在这里插入图片描述
创建一个空白的.cpp文件

touch server.cpp

输入[复制 ]该代码

#include "ros/ros.h"
#include "learning_communication/AddTwoInts.h" // 必须包含服务数据类型的头文件
// service回调函数,输入参数req,输出参数res
bool add(learning_communication::AddTwoInts::Request  &req,
         learning_communication::AddTwoInts::Response &res)
{
    // 将输入参数中的请求数据相加,结果放到应答变量中
    res.sum = req.a + req.b;
    ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
    ROS_INFO("sending back response: [%ld]", (long int)res.sum);
    return true;
}
int main(int argc, char **argv)
{
    // ROS节点初始化
    ros::init(argc, argv, "add_two_ints_server");
    // 创建节点句柄
    ros::NodeHandle n;
    // 创建一个名为add_two_ints的server,注册回调函数add()
    ros::ServiceServer service = n.advertiseService("add_two_ints", add);
    // 循环等待回调函数
    ROS_INFO("Ready to add two ints.");
    ros::spin();
    return 0;
}

在这里插入图片描述

4、创建Client

创建流程
·初始化ROS节点。
·创建一个Client实例。
·发布服务请求数据。
·等待Server处理之后的应答结果。

创建Client节点,通过终端输入的两个加数发布服务请求,等待应答结果
learning_communication/src/client.cpp

创建一个空白的.cpp文件

touch client.cpp

输入[复制 ]该代码

#include <cstdlib>
#include "ros/ros.h"
#include "learning_communication/AddTwoInts.h"
int main(int argc, char **argv)
{
    // ROS节点初始化
    ros::init(argc, argv, "add_two_ints_client");
    // 从终端命令行获取两个加数
    if (argc != 3)
    {
        ROS_INFO("usage: add_two_ints_client X Y");
        return 1;
    }
    // 创建节点句柄
    ros::NodeHandle n;
    // 创建一个client,请求add_two_int service
    // service消息类型是learning_communication::AddTwoInts
    ros::ServiceClient client = n.serviceClient<learning_communication::AddTwoInts> ("add_two_ints");
    // 创建learning_communication::AddTwoInts类型的service消息
    learning_communication::AddTwoInts srv;
    srv.request.a = atoll(argv[1]);
    srv.request.b = atoll(argv[2]);
    // 发布service请求,等待加法运算的应答结果
    if (client.call(srv))
    {
        ROS_INFO("Sum: %ld", (long int)srv.response.sum);
    }
    else
    {
        ROS_ERROR("Failed to call service add_two_ints");
        return 1;
    }
    return 0;
}
5、编译功能包 CMakeLists.txt

接下来编辑CMakeLists.txt文件

cmake_minimum_required(VERSION 2.8)

project(learning_communication)



find_package(catkin REQUIRED COMPONENTS
    geometry_msgs
    roscpp
    rospy
    std_msgs
    message_generation
)
include_directories(include ${catkin_INCLUDE_DIRS})

#[[
## 位置也挺重要 自定义 话题消息
add_message_files(
    FILES
    Person.msg
)
generate_messages(
    DEPENDENCIES
    std_msgs
)
]]

# 自定义 服务 数据
add_service_files( 
    FILES
    AddTwoInts.srv
)
generate_messages(
    DEPENDENCIES
    std_msgs
)

catkin_package(CATKIN_DEPENDS geometry_msgs roscpp rospy std_msgs message_runtime) 

#[[
# 话题
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)

add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
]]

## 服务中的Server和Client
add_executable(server src/server.cpp)
target_link_libraries(server ${catkin_LIBRARIES})
add_dependencies(server ${PROJECT_NAME}_gencpp)

add_executable(client src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client ${PROJECT_NAME}_gencpp)


cd ~/catkin_ws
catkin_make
6、运行Server和Client

1.启动roscore

roscore

2.运行Server节点

rosrun learning_communication server

3.运行Client节点
打开一个新的终端,运行Client节点,同时需要输入加法运算的两个加数值:

rosrun learning_communication client 3 5

在这里插入图片描述

实现TF的广播和监听功能。

参考链接 Plus

例:小乌龟跟随移动

仍是第一步创建工作空间
第二步 创建功能包
这里从第2步开始

2、创建功能包 learning_tf

进入代码空间,使用catkin_create_pkg命令创建功能包

# 命令格式
catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
cd ~/catkin_ws/src
catkin_create_pkg learning_tf roscpp rospy tf turtlesim

回到工作空间的根目录下进行编译(命令行cd),并且设置环境变量

cd ~/catkin_ws
catkin_make
source ~/catkin_ws/devel/setup.bash

在这里插入图片描述

3、创建TF广播器

创建一个发布乌龟坐标系与世界坐标系之间TF变换的节点
learning_tf/src/turtle_tf_broadcaster.cpp

touch turtle_tf_broadcaster.cpp

在这里插入图片描述

#include <ros/ros.h>
#include <tf/transform_broadcaster.h>
#include <turtlesim/Pose.h>
std::string turtle_name;
void poseCallback(const turtlesim::PoseConstPtr& msg)
{
    // TF广播器
    static tf::TransformBroadcaster br;
    // 根据乌龟当前的位姿,设置相对于世界坐标系的坐标变换
    tf::Transform transform;
    transform.setOrigin( tf::Vector3(msg->x, msg->y, 0.0) );
    tf::Quaternion q;
    q.setRPY(0, 0, msg->theta);
    transform.setRotation(q);
    // 发布坐标变换
    br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", turtle_name));
}
int main(int argc, char** argv)
{
    // 初始化节点
    ros::init(argc, argv, "my_tf_broadcaster");
    if (argc != 2)
    {
        ROS_ERROR("need turtle name as argument"); 
        return -1;
    };
    turtle_name = argv[1];
    // 订阅乌龟的pose信息
    ros::NodeHandle node;
    ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
    ros::spin();
    return 0;
};
4、创建TF监听器

TF消息广播之后,其他节点就可以监听该TF消息,从而获取需要的坐标变换了。目前我们已经将乌龟相对于world坐标系的TF变换进行了广播,接下来需要监听TF消息,并从中获取turtle2相对于turtle1坐标系的变换,从而控制turtle2移动。
learning_tf/src/turtle_tf_listener.cpp

touch turtle_tf_listener.cpp
#include <ros/ros.h>
#include <tf/transform_listener.h>
#include <geometry_msgs/Twist.h>
#include <turtlesim/Spawn.h>
int main(int argc, char** argv)
{
    // 初始化节点
    ros::init(argc, argv, "my_tf_listener");
    ros::NodeHandle node;
    // 通过服务调用,产生第二只乌龟turtle2
    ros::service::waitForService("spawn");
    ros::ServiceClient add_turtle =
    node.serviceClient<turtlesim::Spawn>("spawn");
    turtlesim::Spawn srv;
    add_turtle.call(srv);
    // 定义turtle2的速度控制发布器
    ros::Publisher turtle_vel =
    node.advertise<geometry_msgs::Twist>("turtle2/cmd_vel", 10);
    // TF监听器
    tf::TransformListener listener;
    ros::Rate rate(10.0);
    while (node.ok())
    {
        tf::StampedTransform transform;
        try
        {
            // 查找turtle2与turtle1的坐标变换
            listener.waitForTransform("/turtle2", "/turtle1", ros::Time(0), ros:: Duration(3.0));
            listener.lookupTransform("/turtle2", "/turtle1", ros::Time(0), transform);
        }
        catch (tf::TransformException &ex) 
        {
            ROS_ERROR("%s",ex.what());
            ros::Duration(1.0).sleep();
            continue;
        }
        // 根据turtle1和turtle2之间的坐标变换,计算turtle2需要运动的线速度和角速度
        // 并发布速度控制指令,使turtle2向turtle1移动
        geometry_msgs::Twist vel_msg;
        vel_msg.angular.z = 4.0 * atan2(transform.getOrigin().y(),
                                        transform.getOrigin().x());
        vel_msg.linear.x = 0.5 * sqrt(pow(transform.getOrigin().x(), 2) +
                                      pow(transform.getOrigin().y(), 2));
        turtle_vel.publish(vel_msg);
        rate.sleep();
    }
    return 0;
};
52、编辑并编译launch文件

到目前为止,在教程中,一直在为运行的每个新节点打开新终端。当创建越来越多的节点同时运行更复杂的系统时,打开终端并重新输入配置详细信息将变得乏味和低效。 launch文件将需要启动的节点写在一个launch文件中,通过在终端中运行launch文件,就可以同时启动多个节点,解决了以往需要打开多个终端不断输入指令的麻烦。

关于launch 参考链接

learning_tf/launch/start_demo_with_listener.launch
新建文件夹 launch
新建文件 start_demo_with_listener.launch

touch start_demo_with_listener.launch
<launch>
    <!-- 海龟仿真器 -->
    <node pkg="turtlesim" type="turtlesim_node" name="sim"/>
    <!-- 键盘控制 -->
    <node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
    <!-- 两只海龟的TF广播 -->
    <node pkg="learning_tf" type="turtle_tf_broadcaster"
          args="/turtle1" name="turtle1_tf_broadcaster" />
    <node pkg="learning_tf" type="turtle_tf_broadcaster"
          args="/turtle2" name="turtle2_tf_broadcaster" />
    <!-- 监听TF广播,并且控制turtle2移动 -->
    <node pkg="learning_tf" type="turtle_tf_listener"
          name="listener" />
 </launch>
roscore
roslaunch learning_tf start_demo_with_listener.launch

启动键盘控制 小乌龟 移动

rosrun turtlesim turtle_teleop_key

在这里插入图片描述

launch 补充

一次性启动所有节点
在这里插入图片描述

# 结点 定义
<node pkg="package-name" type="executable-name" name="node-name" />

在这里插入图片描述

<param name="output_frame" value="odom"/>
<rosparam file="$(find 2dnav_pr2)/config/costmap_common_params.yaml" command="load" ns="local_costmap" />
<arg name="arg-name" default= "arg-value"/>
<param name="foo" value="$(arg arg-name)" />
<node name="node" pkg="package" type="type " args="$(arg arg-name)" />

重映射
别人功能包的接口与系统不兼容时

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

嵌套复用

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

http://wiki.ros.org/roslaunch/XML
————————

CMake方法要打开N个终端,弃了 ——> 改launch

实在好奇,可参考这里

51、编译功能包 CMakeLists.txt

接下来编辑CMakeLists.txt文件

add_executable(turtle_tf_broadcaster src/turtle_tf_broadcaster.cpp)target_link_libraries(turtle_tf_broadcaster ${catkin_LIBRARIES})add_executable(turtle_tf_listener src/turtle_tf_listener.cpp)target_link_libraries(turtle_tf_listener ${catkin_LIBRARIES})
cd ~/catkin_ws
catkin_make
6、运行TF广播和监听【这里不完整】

1.启动roscore

roscore

启动海龟结点

//新建终端
rosrun turtlesim turtlesim_node

2.运行TF广播

rosrun learning_tf turtle_tf_broadcaster

3.运行TF监听

rosrun learning_tf turtle_tf_listener

rosbag 录制与回放

例: rosbag 录制与回放 小乌龟轨迹

启动键盘控制乌龟例程所需的所有节点

roscore
rosrun turtlesim turtlesim_node
rosrun turtlesim turtle_teleop_key

查看在当前ROS系统中到底存在哪些话题

rostopic list -v

使用rosbag抓取这些话题的消息,并且打包成一个文件放置到指定文件夹中:

可以在习惯的地方创建一个bagfiles文件,Open in Terminal。运行第3句即可

mkdir ~/bagfiles
cd ~/bagfiles
rosbag record -a  # 记录所有消息 all

不要画很复杂的,不然回放也会要比较久。
在终端中控制小乌龟移动一段时间,然后在数据记录运行的终端中按下“Ctrl+C”,即可终止数据记录
在这里插入图片描述
关闭所有终端。
————————————
重启turtlesim_node

roscore
rosrun turtlesim turtlesim_node

查看数据
若是生成的bag后缀多了 .active。还需要进一步处理

# rosbag reindex xxx.bag.active; 
# 等待修复,按照录制包的大小时间可能长也可能短
# rosbag fix xxx.bag.active result.bag;
# 等待生成结果包,也就是result.bag,不要强制结束,可能会比较长,我怀疑是重跑了一遍rosbag play
rosbag reindex 2023-10-11-11-09-06.bag.active
rosbag fix 2023-10-11-11-09-06.bag.active xiaowugui.bag  # 趁机改名

查看 bag 的信息

rosbag info xiaowugui.bag

回放所记录的话题数据

rosbag play xiaowugui.bag

注意有一小段切换时间,因为录制的时候也不是一运行录制命令就马上开始控制小乌龟。如果轨迹很长,稍等。
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值