ROS 示例

news2025/1/18 11:54:49

参考链接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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1107497.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nfs+rpcbind实现服务器之间的文件共享

NFS简介 NFS服务及Network File System&#xff0c;用于在网络上共享存储&#xff0c;分为2,3,4三个版本&#xff0c;最新为4.1版本。NFS基于RPC协议&#xff0c;RPC为Remote Procedure Call的简写。 应用场景&#xff1a;用于A,B,C三台机器上需要保证被访问到的文件是一样…

用Bing绘制「V我50」漫画;GPT-5业内交流笔记;LLM大佬的跳槽建议;Stable Diffusion生态全盘点第一课 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f525; 美国升级AI芯片出口禁令&#xff0c;13家中国GPU企业被列入实体清单 nytimes.com/2023/10/05/technology/chip-makers-china-lobbying…

QT自定义空间之软键盘

QT自定义空间之软键盘 1.功能列表2.效果2.1 中文键盘&汉字输入2.2 英文输入法2.3 数字键盘2.4 数据键盘效果 3.部分代码3.1 汉字输入3.2 切换数字键盘3.3 键盘显示&隐藏3.4 控件提升3.5样式设置3.6 使用QLineEditAllKeyBoard 控件 1.功能列表 支持中文输入法支持引文输…

jdk7新增时间类Date,SimpleDateFormat,Calendar

Date //需求1 打印时间远点开始一年后的时间extracted();//需求2 定义任意两个date对象 比较那个时间在前 哪个在后Random rnew Random();Date date1new Date(Math.abs(r.nextInt()));Date date2new Date(Math.abs(r.nextInt()));System.out.println(date1);System.out.printl…

在迪拜举行的 GITEX GLOBAL 2023 IT 展览会上,Positive Technologies 荣获两项大奖!

&#x1f3c6; 在迪拜举行的 GITEX GLOBAL 2023 IT 展览会上&#xff0c;Positive Technologies 荣获两项大奖。这两个奖项都是影响力网络安全领域的最佳供应商。 &#x1f3f5; Future Enterprise Awards 2023 是该地区 IT 行业最重要的奖项之一。该奖项每年颁发给对信息技术…

python---三目运算符

在Python中三目运算符也叫三元运算符&#xff0c;其主要作用&#xff1a;就是用于 简化if...else...语句。 基本语法&#xff1a; 原 if 条件判断: # 语句段1 else: # 语句段2 新-----三目运算符/三元运算符 语句段1 if 条件判断 else 语句段2 案例 输入两个数…

网站如何优化加速,让网站降低延迟

优化网站架构 精简页面加载过程&#xff1a;通过消除冗余代码和不必要的图像&#xff0c;并采用CDN资源分发&#xff0c;以减少加载时间。 精心规划内容架构&#xff1a;通过使用恰当的标题和描述&#xff0c;使搜索引擎能够快速理解页面的内涵。 选择性能出众的前端框架&…

【QT】常用控件——按钮组

继承Widget PushButton 设置图片&#xff0c;先导入图片资源&#xff0c;见&#xff1a;【QT】资源文件导入_复制其他项目中的文件到qt项目中_StudyWinter的博客-CSDN博客 在布局中添加图片 调整尺寸 toolButton 显示图片、文本 显示图片&#xff08;图片和文字都有时&#…

git学习——第5节 远程仓库

自行设置&#xff1a;远程仓库 - 廖雪峰的官方网站 (liaoxuefeng.com) 添加远程库 现在的情景是&#xff0c;你已经在本地创建了一个Git仓库后&#xff0c;又想在GitHub创建一个Git仓库&#xff0c;并且让这两个仓库进行远程同步&#xff0c;这样&#xff0c;GitHub上的仓库既…

排查手机应用app微信登录问题不跳转失败原因汇总及其解决方案

经过最近我发的文章,我个人觉得解决了不少小问题,因为最近很小白的问题已经没有人私聊问我了,我总结了一下排查手机应用app微信登录问题不跳转失败的原因汇总及其解决方案在这篇文章中,分析微信登录不跳转的原因,并提供解决方案。希望通过这篇文章,能够帮助大家顺利解决这…

Python Connect SQLServer 2008

Macos&#xff08;经过了两天&#xff0c;无数次的方法验证&#xff0c;寻找各种资料&#xff0c;总结如下&#xff09; brew install freetds0.91 如果出现错误就进行手工安装 brew install freedts0.91 出错。 linqllinqldeMBP-2 / % brew install freetds0.91 Warning: No …

css-水滴登录页

效果图&#xff1a; html <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><link type"text/css" rel"stylesheet" href"login.css" /></head><body><…

从零开始的C语言学习第十九课:C语言内存函数

目录 1. memcpy使用和模拟实现 2. memmove使用和模拟实现 3. memset函数的使用 4. memcmp函数的使用 1. memcpy使用和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); 函数memcpy从source的位置开始向后复制num个字节的数据到destinati…

sylar高性能服务器-配置(P9)代码解析+调试分析

文章目录 一、代码解析1.1配置基类(ConfigVarBase)1.2配置参数类(ConfigVar)1.3配置管理类(Config) 二、代码调试2.1SYLAR_LOG_INFO(SYLAR_LOG_ROOT())2.2ConfigVart调试 本节内容主要讲诉了sylar高性能服务器视频P9的内容&#xff0c;并给出了代码逐步调试的步骤和结果。本节内…

Linux块设备缓存Bcache使用

1 Bcache简介 Bcache是Linux内核块层cache&#xff0c;它使用SSD来作为HDD硬盘的cache&#xff0c;从而起到加速作用。Bcache内核模块仅在Linux 3.10及以上版本支持&#xff0c;因此使用Bcache&#xff0c;需要将内核升级到3.10及以上版本&#xff0c;并在内核配置项中打开Bca…

vue3后台管理系统之layout组件的搭建

1.1静态布局 <template><div class"layout_container"><!-- 左侧导航 --><div class"layout_slider"></div><!-- 顶部导航 --><div class"layout_tabbar"></div><!-- 内容展示区 --><…

【Linux】Ubuntu存储分析

文章目录 前言1 如何对系统进行存储分析2 如果出现存储空间不足的警告应该怎么办&#xff1f;3 存储空间太小导致不能开机怎么办&#xff1f;4 如何对系统进行扩容 前言 因为要编译一个ARM架构的Linux SDK&#xff0c;结果没想到这个SDK解压编译完大小远超我想象&#xff0c;直…

【算法|前缀和系列No.5】leetcode1314. 矩阵区域和

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【Leetcode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

【茫茫架构路】1. Class File字节码文件解析

本文所有内容的JDK版本为 OpenJDK 11 JDK11 Class File官方说明。 Java解析字节码文件源码参考&#xff0c;以下为部分字节码解析源码展示。 public ClassFile(DataInputStream in) {try {//magic: 0xCAFEBABEthis.magic ClassReader.readInt(in);System.out.println("m…

Vue 异步更新 -- $nextTick

Vue 异步更新 – $nextTick **创建 工程&#xff1a; H:\java_work\java_springboot\vue_study ctrl按住不放 右键 悬着 powershell H:\java_work\java_springboot\js_study\Vue2_3入门到实战-配套资料\01-随堂代码素材\day04\准备代码\16-$nextTick vue --version vue crea…