iT邦幫忙

2023 iThome 鐵人賽

DAY 18
0
自我挑戰組

一個營建系學生的韌體之路-自走車篇系列 第 18

【AMR_Day18】ROS2 基本功- 用c++寫個綜合練習(下)

  • 分享至 

  • xImage
  •  

從0開始建自己的cpp專案

延續昨天的workspace、package、publisher/subscriber node,今天針對publisher node來增加一個Parameter吧~~

publisher code

先把昨天完整版的publisher程式放在下方,可以看到這個publisher的任務是每秒發布兩次的message.data = "Hello, world! " + std::to_string(count_++),那我希望現在能把"Hello, world! "的world任意修改成我想要的文字,而且不需要每改一次就重新編譯。

#include <chrono>
#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.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("minimal_publisher"), count_(0)
  {
    publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
    timer_ = this->create_wall_timer(
      500ms, std::bind(&MinimalPublisher::timer_callback, this));
  }

private:
  void timer_callback()
  {
    auto message = std_msgs::msg::String();
    message.data = "Hello, world! " + std::to_string(count_++);
    RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
    publisher_->publish(message);
  }
  rclcpp::TimerBase::SharedPtr timer_;
  rclcpp::Publisher<std_msgs::msg::String>::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;
}

Parameter

那就開始來使用Parameter吧~~

宣告Parameter

在ROS2中宣告Parameter 字串變數的方法是用declare_parameter(),裡面放變數的名稱與預設值

this->declare_parameter("my_parameter", "world");

那它應該放在節點的預設建構函式中

class MinimalPublisher : public rclcpp::Node
{
public:
  MinimalPublisher()
  : Node("minimal_publisher"), count_(0)
  {
    //宣告底家!!!!
    this->declare_parameter("my_parameter", "world");
  
    publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
    timer_ = this->create_wall_timer(
      500ms, std::bind(&MinimalPublisher::timer_callback, this));
  }

取得與使用Parameter

接下來可以看到MinimalPublisher()有個函式timer_callback()會去負責不斷執行直到程式中止,那"Hello, world! "的發布也是由這裡在編輯,也就是說Parameter要在這個函式中被使用,在那之前要先get_parameter()取得現在parameter的值。

std::string my_param = this->get_parameter("my_parameter").as_string();

//如果是整數或浮點數的話就可以用
get_parameter("my_parameter").as_int();
get_parameter("my_parameter").as_double();

接下來就可以如同一般使用c++變數一樣使用my_param變數了

//可以把舊的
message.data = "Hello, world! " + std::to_string(count_++);
//替換成
message.data = "Hello, "+ my_param +"! "+ std::to_string(count_++);

完整的timer_callback()長這樣

  void timer_callback()
  {
    //取得my_parameter
    std::string my_param = this->get_parameter("my_parameter").as_string();

    auto message = std_msgs::msg::String();
    
    //使用my_parameter
    message.data = "Hello, " + my_param +" ! "+ std::to_string(count_++);
    RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
    publisher_->publish(message);
  }

執行

程式碼的部份就完成了,接下來就可以

colcon build && . install/setup.bash 
os2 run cpp_pubsub talker #預設是world

!
那有幾個方式可以修改成指定的Parameter

# 1.直接用新的run
ros2 run cpp_pubsub talker --ros-args -p my_parameter:=EJ
# count被影響,歸0了


# 2.執行中的node 設置新變數
ros2 param set /minimal_publisher my_parameter earth
# count不會被影響

https://ithelp.ithome.com.tw/upload/images/20231003/20140433amHdaRQI4e.png

[INFO] [1696338186.994345376] [minimal_publisher]: Publishing: 'Hello, EJ ! 9'
[INFO] [1696338187.494316111] [minimal_publisher]: Publishing: 'Hello, EJ ! 10'
[INFO] [1696338187.994306081] [minimal_publisher]: Publishing: 'Hello, earth ! 11'
[INFO] [1696338188.494302361] [minimal_publisher]: Publishing: 'Hello, earth ! 12'
[INFO] [1696338188.994287811] [minimal_publisher]: Publishing: 'Hello, earth ! 13'

Launch

那用我習慣的寫法來把所有東西都寫成Launch文件,Launch細節可以看DAY14和DAY15,不贅述了~

from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    ld = LaunchDescription()
    publisher=Node(
            package="cpp_pubsub",
            executable="talker",
            name="custom_minimal_publisher",
            output="screen",
            emulate_tty=True,
            parameters=[
                {"my_parameter": "earth"}
            ]
        )
    subscriber=Node(
            package="cpp_pubsub",
            executable="listener",
            output="screen"
        )

    ld.add_action(publisher)
    ld.add_action(subscriber)
    return ld

https://ithelp.ithome.com.tw/upload/images/20231003/20140433ksFypRBjQk.png
這樣就能同時在terminal裡發布和接收啦~~~

練習完成

寫package真的要多練習呢...


上一篇
【AMR_Day17】ROS2 基本功- 用c++寫個綜合練習(上)
下一篇
【AMR_Day19】ROS2的常見工具們—RQt
系列文
一個營建系學生的韌體之路-自走車篇30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言