ROS通信方式(保姆级教程)

lgqlht / 2024-10-19 / 原文

目录
  • ROS通信方式
      • 主题
        • 前言
        • 发布器编程实例:小海龟速度控制
          • 步骤如下
        • 注意:以下是拿小海龟的矩形来写,圆形也一样
        • 实现效果
        • 订阅器编程实例:小乌龟速度接收
      • 服务
        • 概述
        • 前言
        • 自定义src消息文件
          • 步骤如下
        • 服务端编程
          • 步骤如下
        • 实现效果
        • 客户端编程
          • 步骤如下
        • 实现效果

ROS通信方式

主题

前言

工作空间: catkin_ws1

ROS功能包: xhgpfk

c++文件: xhgfk.cpp和sudujieshou.cpp

定义一个可执行文件: luguoqin

发布器编程实例:小海龟速度控制

对ROS的小海龟来说,速度的控制主题为/turtle1/cmd_vel,只需要对这个主题发送ge-ometry_msgs::Twist这个信息包就可以对小海龟的速度进行调控了。

ge-ometry_msgs::Twist:里面有两个部分速度值,第一个为linear,它表示在机器人的x、y、z、三个方向上,单位是m/s,第二个为angular,它表示在机器人的x、y、z、三个方向上,单位是弧度/s。

步骤如下

Ctrl+Alt+T打开终端

i.创建ROS工作空间

	mkdir -p ~/catkin_ws1/src

ROSA2

ii.切换到catkin_ws1 工作空间内的 src 目录

	cd ~/catkin_ws1/src

ROSA3

iii.初始化一个新的 catkin 工作空间(前提一定要在“工作空间”下的“src 目录”)

	catkin_init_workspace

ROSA4

iv.切换到catkin_ws1 工作空间

	cd ~/catkin_ws1/

ROSA5

v.编译(前提一定要在“工作空间”下)

	catkin_make

ROSA6

可以看到出现build、devel、src,3个文件夹

ROSA10

vi.使 ROS 工作空间的环境变量在每次打开新的终端时自动设置(里面的catkin_ws1要换成自己的“工作空间”)

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

ROSA7

vii.重新执行 ~/.bashrc 文件中的所有命令

ROSA8

viii.切换到catkin_ws1 工作空间内的 src 目录

	cd ~/catkin_ws1/src

ROSA9

ix.创建新的 ROS 包(xhgpfk为包名,可以自己更改)

catkin_create_pkg用于创建新的 ROS 包的命令行工具

	catkin_create_pkg xhgpfk roscpp geometry_msgs

ROSA11

x.打开VSC(Visual Studio Code)点击File(文件)点击Open Folder(打开文件夹)选择“编译空间”的文件

ROSA12

xi.点击“编译空间”的文件的src看到ROS功能包的src鼠标右键单击创建一个c++文件(是在第二个src创建),例如:xhgfk.cpp

ROSA14

ROSA24

ROSA15

xii.i.小海龟的圆形代码如下:

#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
int main(int argc, char** argv)
{
    // 初始化ROS节点
    ros::init(argc, argv, "velocity_publisher");
// 创建节点句柄
	ros::NodeHandle n;

// 创建一个发布者,发布/turtle1/cmd_vel话题,消息队列大小为20
	ros::Publisher vel_pub = 			n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 20);

// 设置循环频率为10Hz
ros::Rate loop_rate(10);

while(ros::ok())
{
    // 创建Twist消息
    geometry_msgs::Twist vel_cmd;
    vel_cmd.linear.x = 2;
    vel_cmd.linear.y = 0;
    vel_cmd.linear.z = 0;
    vel_cmd.angular.x = 0;
    vel_cmd.angular.y = 0;
    vel_cmd.angular.z = 1.8;

    // 发布消息
    vel_pub.publish(vel_cmd);

    // 处理回调函数
    ros::spinOnce();

    // 按照设定的循环频率休眠
    loop_rate.sleep();
}

return 0;
}

xii.ii.小海龟的矩形代码如下:

#include <ros/ros.h>
#include <geometry_msgs/Twist.h>

int main(int argc, char** argv)
  {
    ros::init(argc, argv, "turtle_vel_ctrl_node");
    ros::NodeHandle n;

    ros::Publisher vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 20);
    ros::Rate loop_rate(2);

    int count = 0;

    while(ros::ok())
    {
      geometry_msgs::Twist vel_cmd;
      vel_cmd.linear.x = 1.0;
      vel_cmd.linear.y = 0.0;
      vel_cmd.linear.z = 0.0;
      vel_cmd.angular.x = 0.0;
      vel_cmd.angular.y = 0.0;
      vel_cmd.angular.z = 0.0;

      if(count == 5)
        {
          vel_cmd.angular.z = 3.1415926; // Change angular velocity when count reaches 5
          count = 0; // Reset count
        }
      else
        {
          count++; // Increment count
        }

      vel_pub.publish(vel_cmd);
      ros::spinOnce();
      loop_rate.sleep();
    }

      return 0;
  }

注意:以下是拿小海龟的矩形来写,圆形也一样

xiii.在下面找到CMakeLists.txt,在最后面(第207行开始)添加代码进行编译(你的c++是什么名字就改为什么名字xhgfk.cpp),(luguoqin这个可以改一个随便的)

add_executable(luguoqin src/xhgfk.cpp)
add_dependencies(luguoqin ${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS})
target_link_libraries(luguoqin ${catkin_LIBRARIES})

xiv.切换到 catkin_ws1 工作空间

	cd ~/catkin_ws1/

ROSA5

xv.在创建或修改了 ROS 包后,需要使用 catkin_make 来编译这些更改

	catkin_make

ROSA16

ROSA17

xvi.Ctrl+Alt+T打开终端

xvii.用于启动 ROS 的节点

	roscore

ROSA22

xiii.用于运行 ROS 节点

	rosrun turtlesim turtlesim_node

ROSA20

xix.运行小海龟跑矩形的指令

	rosrun xhgpfk luguoqin

ROSA21

实现效果

ROSA23

订阅器编程实例:小乌龟速度接收

在ROS(机器人操作系统)中,订阅器(Subscriber)是一种节点,它订阅特定的话题(Topic),以接收并处理发布器(Publisher)发布的消息。

i.打开vscode

ii.点击“编译空间”的文件的src看到ROS功能包的src鼠标右键单击创建一个c++文件(是在第二个src创建),例如:xhgfk.cpp

ROSA25

iii.在创建的c++文件添加代码

	#include <ros/ros.h>
#include <geometry_msgs/Twist.h>

// 回调函数,用于处理接收到的消息
void callback(const geometry_msgs::Twist& cmd_vel) {
    ROS_INFO("Received a /turtle1/cmd_vel message!");
    ROS_INFO("Linear Velocity: [%f, %f, %f]",
             cmd_vel.linear.x, cmd_vel.linear.y, cmd_vel.linear.z);
    ROS_INFO("Angular Velocity: [%f, %f, %f]",
             cmd_vel.angular.x, cmd_vel.angular.y, cmd_vel.angular.z);
}

int main(int argc, char** argv) {
    // 初始化ROS节点
    ros::init(argc, argv, "turtle_vel_rece_node");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个订阅者,订阅/turtle1/cmd_vel话题,缓冲区大小为1000
    ros::Subscriber sub = n.subscribe("/turtle1/cmd_vel", 1000, callback);

    // 进入循环,等待回调函数被调用
    ros::spin();

    // 正常情况下,ros::spin()不会返回,除非ROS被关闭
    // 所以这里实际上不会执行到return语句
    return 0;
}

iv.在下面找到CMakeLists.txt,在最后面(第211行开始)添加代码进行编译(你的c++是什么名字就改为什么名字lihaitong.cpp),(lihaitong这个可以改一个随便的)

add_executable(lihaitong src/lihaitong.cpp)
add_dependencies(lihaitong ${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS})
target_link_libraries(lihaitong ${catkin_LIBRARIES})

v.切换到 catkin_ws1 工作空间

	cd ~/catkin_ws1/

ROSA5

vi.在创建或修改了 ROS 包后,需要使用 catkin_make 来编译这些更改

	catkin_make

ROSA16

ROSA17

vii.Ctrl+Alt+T打开终端

viii.用于启动 ROS 的节点

	roscore

ROSA22

ix.用于运行 ROS 节点

	rosrun turtlesim turtlesim_node

ROSA20

x.运行小海龟跑矩形的指令

	rosrun xhgpfk luguoqin

ROSA21

xi.运行小海龟速度接收的指令

	rosrun xhgpfk lihaitong

ROSA26

xii.显示当前ROS里的节点网络情况

	rqt_graph

ROSA27

服务

概述

与Topie(主题)不同,Service(服务)通信是双向的,它不仅可以发送反馈。一个服务(Service)被分成服务端(Server)和客户端(Client),分别对应节点A和节点B,两个都要到主节点管理器进行注册。在主节点管理器的管理下,节点B(客户端)向节点A(服务端)发送请求,节点A(服务端)响应该请求,实现节点之间的双向通信。在请求机器人执行特定操作时,或者根据特定条件需要产生响应事性时,通常使用Service(服务)。

前言

工作空间: catkin_ws1(和上面是同一个工作空间)

ROS功能包: xhgpfk

c++文件: fuwu.cppkewu.cpp

srv文件: ServiceClientExMsg.srv

定义一个可执行文件: fuwukewu

自定义src消息文件

步骤如下

i.在上面的catkin_ws1工作空间里创建新的ROS功能包,(service_client_pkg为包名,可以自己更改)catkin_create_pkg用于创建新的 ROS 包的命令行工具.

	cd ~/catkin_ws1/src/
	catkin_create_pkg service_client_pkg roscpp std_msgs

ii.进入service_client_pkg文件夹创建srv来放.srv文件

	cd service_client_pkg
	mkdir srv

iii.打开vscode再打开catkin_ws1文件,找到service_client_pkg子文件的srv文件,点击srv鼠标右键创建ServiceClientExMsg.srv,在里面写入代码

string name
---
bool in_class
bool boy
int32 age
string personality

iv.编写完成后在service_client_pkg文件下的package.xml,在59行开始添加下面语句

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

v.添加完成后在service_client_pkg文件下的CMakeLists.txt,内容修改。

#大概第10~18行
find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  message_generation
  std_msgs
  std_srvs
)
#大概第61~65行
add_service_files(
  FILES
  ServiceClientExMsg.srv
  # Service2.srv
)
#大概第75~78行
generate_messages(
  DEPENDENCIES
  std_msgs
)
#大概第109~115行
catkin_package(
 INCLUDE_DIRS include
 LIBRARIES service_client_pkg
 CATKIN_DEPENDS roscpp std_msgs
 DEPENDS system_lib
 CATKIN_DEPENDS message_runtime
)

vi.在工作空间进行代码编译

	cd ~/catkin_ws1
	catkin_make

服务端编程

步骤如下

i.打开vscode再打开catkin_ws1文件,找到service_client_pkg子文件的src文件,点击src鼠标右键创建fuwu.cpp,在里面写入代码

#include <ros/ros.h>

#include <service_client_pkg/ServiceClientExMsg.h> // 注意文件扩展名应该是 .h 而不是 .hx

using namespace std;


bool infoInquiry(service_client_pkg::ServiceClientExMsgRequest& request, 
                 service_client_pkg::ServiceClientExMsgResponse& response) {
    ROS_INFO("Callback activated");
    string inputName = request.name;
    response.in_class = false;

    if (inputName.compare("Tom") == 0) {
        ROS_INFO("Student information about Tom");
        response.in_class = true;
        response.boy = true;
        response.age = 20;
        response.personality = "outgoing";
    } else if (inputName.compare("Mary") == 0) {
        ROS_INFO("Student information about Mary");
        response.in_class = true;
        response.boy = false;
        response.age = 21;
        response.personality = "introverted";
    }
    return true;
}

int main(int argc, char **argv) {
    ros::init(argc, argv, "service_example_node");
    ros::NodeHandle n;
    ros::ServiceServer service = n.advertiseService("info_inquiry_by_name", infoInquiry);
    ROS_INFO("Ready to inquiry names.");
    ros::spin();
    return 0;
}

ii.写完后在service_client_pkg文件下的CMakeLists.txt,在最后面添加编译规则

add_executable(fuwu src/fuwu.cpp)
add_dependencies(fuwu ${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS})
target_link_libraries(fuwu ${catkin_LIBRARIES})

iii.切换到 catkin_ws1 工作空间

	cd ~/catkin_ws1/

iv.在创建或修改了 ROS 包后,需要使用 catkin_make 来编译这些更改

	catkin_make

v.Ctrl+Alt+T打开终端

x.用于启动 ROS 的节点

	roscore

vi.用于运行 fuwu 节点

	rosrun service_client_pkg fuwu

vii.测试节点是否正常反馈信息

	rosservice call /info_inquiry_by_name "Tom"

实现效果

ROSC1

客户端编程

步骤如下

i.打开vscode再打开catkin_ws1文件,找到service_client_pkg子文件的src文件,点击src鼠标右键创建kehu.cpp,在里面写入代码

#include <ros/ros.h>
#include <service_client_pkg/ServiceClientExMsg.h>
#include <iostream>
#include <string>

using namespace std;

int main(int argc, char **argv)
{
    ros::init(argc, argv, "client_example_node");
    ros::NodeHandle n;

    ros::ServiceClient client = n.serviceClient<service_client_pkg::ServiceClientExMsg>("info_inquiry_by_name");
    service_client_pkg::ServiceClientExMsg srv;

    string input_name;

    while(ros::ok())
    {
        cout << endl;
        cout << "Enter a name (q to quit): ";
        cin >> input_name;

        if (input_name.compare("q") == 0)
        {
            return 0;
        }

        srv.request.name = input_name;

        if (client.call(srv))
        {
            if (srv.response.in_class)
            {
                if (srv.response.boy)
                {
                    cout << srv.request.name << " is a boy;" << endl;
                }
                else
                {
                    cout << srv.request.name << " is a girl;" << endl;
                }
                cout << srv.request.name << " is " << srv.response.age << " years old;" << endl;
                cout << srv.request.name << " has a " << srv.response.personality << " personality." << endl;
            }
            else
            {
                cout << srv.request.name << " is not in class" << endl;
            }
        }
        else
        {
            ROS_ERROR("Failed to call service info_inquiry_byname");
            return 1;
        }
    }

    return 0;
}

ii.写完后在service_client_pkg文件下的CMakeLists.txt,在最后面添加编译规则

add_executable(kehu src/kehu.cpp)
add_dependencies(kehu ${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS})
target_link_libraries(kehu ${catkin_LIBRARIES})

iii.切换到 catkin_ws1 工作空间

	cd ~/catkin_ws1/

iv.在创建或修改了 ROS 包后,需要使用 catkin_make 来编译这些更改

	catkin_make

v.Ctrl+Alt+T打开终端

x.用于启动 ROS 的节点

	roscore

vi.用于运行 fuwu 节点

	rosrun service_client_pkg fuwu

vii.用于运行 kehu 节点

	rosrun service_client_pkg kehu

viii.输入Tom

实现效果

ROSC6

ROSC7