ROS2自定义消息并在同一功能包与其他功能包中使用(带案例代码)

1创建自定义消息

1.1. 创建工作空间

mkdir -p ros2_ws/src

1.2.创建功能包

cd ros2_ws/src
ros2 pkg create msg_pkg --build-type ament_cmake --dependencies rclcpp std_msgs

1.3.创建消息

在功能包msg_pkg中创建msg文件夹,并在msg目录中创建消息文件.类型.msg. 如Student.msg和Class.msg(切记消息类型首字母大写)

cd msg_pkg
mkdir msg

Student.msg中内容如下:

string name
int16 age

Class.msg中内容如下:

int16 id
Student[] students #当引用同一包中的消息时不需要加包名.如果在其他中中引用需要加上包名msg_pkg/Student[] students

1.4.修改CMakeLists.txt

添加如下代码段

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
#========================================
# 自定义消息
find_package(geometry_msgs REQUIRED)
find_package(rosidl_default_generators REQUIRED)
set(msg_files
"msg/Student.msg"
"msg/Class.msg"
)
rosidl_generate_interfaces(${
    
    PROJECT_NAME}
  ${
    
    msg_files}
  DEPENDENCIES std_msgs geometry_msgs
 )
 ament_export_dependencies(rosidl_default_runtime)

#========================================

1. 5.修改package.xml

添加如下代码段

  <!--添加自定义消息-->
  <buildtool_depend>rosidl_default_generators</buildtool_depend>
  <exec_depend>rosidl_default_runtime</exec_depend>
  <member_of_group>rosidl_interface_packages</member_of_group>
  <!--添加自定义消息-->

1.6.编译并查看

1.6.1.编译

返回到工作空间目录下.这里是ros2_ws目录下,执行如下命令进行编译

colcon build --packages-up-to objectsDetection

1.6.2.查看

. install/local_setup.bash
ros2 interface package msg_pkg

出现如下消息类型,则成功
在这里插入图片描述

2.同一个包下使用自定义消息(简单的发布者和订阅者)

注意点:在同一个包中使用自定义消息在CMakeLists.txt中必须添加如下代码段,不然找不的自定义消息的头文件

rosidl_target_interfaces(classPlush
  ${
    
    PROJECT_NAME} "rosidl_typesupport_cpp")

2.1 发布者(在msg_pkg功能包的src中添加push.cpp)

#include <sys/time.h>
#include <algorithm>
#include <chrono>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <msg_pkg/msg/class.hpp>
#include <msg_pkg/msg/student.hpp>
#include <rclcpp/rclcpp.hpp>
#include <vector>
static volatile int keepRunning = 1;
void signal_handler(int signum) {
    
    
  printf("signal_handler: caught signal %d\n", signum);
  if (signum == SIGINT) {
    
    
    keepRunning = 0;
    // SLAM.Shutdown();
  }
}
int main(int argc, char const *argv[]) {
    
    
  if (signal(SIGINT, signal_handler) == SIG_ERR) {
    
    
    printf("Failed to caught signal\n");
  } else {
    
    
    std::cout << "signal_handler ok" << std::endl;
  }
  /* 初始化rclcpp  */
  rclcpp::init(argc, argv);
  /*产生一个节点*/
  auto node = std::make_shared<rclcpp::Node>("classPlus");
  RCLCPP_INFO(node->get_logger(), "RosNode_1节点已经启动.");
  rclcpp::Publisher<msg_pkg::msg::Class>::SharedPtr clss_pub =
      node->create_publisher<msg_pkg::msg::Class>("classMesag", 1);
  int i = 0;
  msg_pkg::msg::Class cl;
  while (keepRunning) {
    
    
    msg_pkg::msg::Student stu;
    stu.age = i * 10 + 1;
    stu.name = "stu" + std::to_string(i);
    cl.students.push_back(stu);
    if (i % 5 == 0) {
    
    
      cl.id = i;
      clss_pub->publish(cl);
      std::cout << "publish end" << std::endl;
    }
    i++;
  }
  rclcpp::shutdown();
  return 0;
}

2.1.1 修改CMakeLists.txt

添加如下代码段

#=========================================
#发布者
add_executable(classPlush src/push.cpp)
target_link_libraries(classPlush rclcpp::rclcpp )

rosidl_target_interfaces(classPlush
  ${
    
    PROJECT_NAME} "rosidl_typesupport_cpp")
 #注册可执行文件
install(TARGETS classPlush
DESTINATION lib/${
    
    PROJECT_NAME}
)
#=========================================

2.1.2 编译并查看可执行文件

2.1.2.1 编译(同上)

colcon build --packages-up-to objectsDetection

2.1.2.2 查看可执行文件

 ros2 pkg executables msg_pkg

若没有对应可执行文件classPlush出现或者运行报出如下错误,那是因为在CMakeLists.txt中没有加入install(TARGETS classPlush DESTINATION lib/${PROJECT_NAME} )进行注册.

No executable found

2.1.3 执行

2.1.3.1 执行

ros2 run msg_pkg classPlush
ros2 run msg_pkg classSub

在这里插入图片描述

2.2 订阅者(编译修改同上)

#include <memory>
#include <msg_pkg/msg/class.hpp>
#include <msg_pkg/msg/student.hpp>

#include "rclcpp/rclcpp.hpp"
using std::placeholders::_1;

class MinimalSubscriber : public rclcpp::Node {
    
    
 public:
  MinimalSubscriber() : Node("classSub") {
    
    
    subscription_ = this->create_subscription<msg_pkg::msg::Class>(
        "classMesag", 10,
        std::bind(&MinimalSubscriber::topic_callback, this, _1));
  }

 private:
  void topic_callback(const msg_pkg::msg::Class::SharedPtr msg) const {
    
    
    std::cout << "clssid: " << msg->id << std::endl;
    for (int i = 0; i < msg->students.size(); i++) {
    
    
      msg_pkg::msg::Student std = msg->students[i];
      std::cout << "age: " << std.age << std::endl;
    }
  }
  rclcpp::Subscription<msg_pkg::msg::Class>::SharedPtr subscription_;
};

int main(int argc, char* argv[]) {
    
    
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MinimalSubscriber>());
  rclcpp::shutdown();
  return 0;
}

3 使用其他包中的消息

3.1 发布者与订阅者

3.1.1 发布者代码

#include <chrono>
#include <functional>
#include <memory>
#include <string>

//引用其他包的消息头文件
#include "msg_pkg/msg/class.hpp"
#include "msg_pkg/msg/student.hpp"
#include "rclcpp/rclcpp.hpp"

using namespace std::chrono_literals;

/* This example creates a subclass of Node and uses std::bind() to register a
 * member function as a callback from the timer. */

class MinimalPublisher : public rclcpp::Node {
    
    
 public:
  MinimalPublisher() : Node("class_publisher"), count_(0) {
    
    
    publisher_ =
        this->create_publisher<msg_pkg::msg::Class>("ClassMessage", 10);
    timer_ = this->create_wall_timer(
        500ms, std::bind(&MinimalPublisher::timer_callback, this));
  }

 private:
  void timer_callback() {
    
    
    int i = count_++;
    msg_pkg::msg::Class cls;
    while (i % 5 != 0) {
    
    
      msg_pkg::msg::Student stu;
      stu.age = i * 10 + 1;
      stu.name = "stu" + std::to_string(i);
      cls.students.push_back(stu);
      i++;
    }
    cls.id = count_;
    RCLCPP_INFO(this->get_logger(), "Publishing: '%d'", cls.id);
    publisher_->publish(cls);
  }
  rclcpp::TimerBase::SharedPtr timer_;
  rclcpp::Publisher<msg_pkg::msg::Class>::SharedPtr publisher_;
  size_t count_;
};

int main(int argc, char* argv[]) {
    
    
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MinimalPublisher>());
  rclcpp::shutdown();
  return 0;
}

3.1.2 订阅者代码

#include <memory>
#include <msg_pkg/msg/class.hpp>
#include <msg_pkg/msg/student.hpp>

#include "rclcpp/rclcpp.hpp"
using std::placeholders::_1;

class MinimalSubscriber : public rclcpp::Node {
    
    
 public:
  MinimalSubscriber() : Node("classSub") {
    
    
    subscription_ = this->create_subscription<msg_pkg::msg::Class>(
        "ClassMessage", 10,
        std::bind(&MinimalSubscriber::topic_callback, this, _1));
  }

 private:
  void topic_callback(const msg_pkg::msg::Class::SharedPtr msg) const {
    
    
    std::cout << "clssid: " << msg->id << std::endl;
    for (int i = 0; i < msg->students.size(); i++) {
    
    
      msg_pkg::msg::Student std = msg->students[i];
      //   std::cout << "age: " << std.age << std::endl;
    }
  }
  rclcpp::Subscription<msg_pkg::msg::Class>::SharedPtr subscription_;
};

int main(int argc, char* argv[]) {
    
    
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MinimalSubscriber>());
  rclcpp::shutdown();
  return 0;
}

3.2 CMakeLists.txt 添加如下代码段



#使用其他包自定义消息
find_package(msg_pkg REQUIRED)
include_directories(
  include
  ${msg_pkg_INCLUDE_DIRS}
)
#=========================================
#发布者
add_executable(classPlush2 src/pus.cpp)
ament_target_dependencies(  #依赖的引用采用target_link_libraries 无法找到不知原因
  classPlush2 
    rclcpp 
    msg_pkg
)
install(TARGETS classPlush2
DESTINATION lib/${PROJECT_NAME}
)
#=========================================

#=========================================
#订阅者
add_executable(classSub2 src/sub.cpp)
ament_target_dependencies(  #依赖的引用采用target_link_libraries 无法找到不知原因
    classSub2 
    rclcpp 
    msg_pkg
)
install(TARGETS classSub2
DESTINATION lib/${PROJECT_NAME}
)

install(TARGETS
    classPlush2
    classSub2
    DESTINATION lib/${PROJECT_NAME}
)  
#=========================================


3.3 修改package.xml 添加如下代码

  <depend>std_msgs</depend>
  <depend>msg_pkg</depend>

3.4 运行

ros2 run  msg_pkg2 classPlush2
ros2 run msg_pkg2 classSub2

在这里插入图片描述

案例代码

猜你喜欢

转载自blog.csdn.net/u011573853/article/details/131925304