본 포스트는 ROS1에 대한 전반적인 내용 및 ROS2 Python에 대한 지식이 있다는 가정 하에 작성되었으며, The Construct Youtube 영상을 참고하였습니다.
또한, 시뮬레이션 환경은 turtlebot3 waffle_pi를 사용합니다 : https://github.com/ROBOTIS-GIT/turtlebot3_simulations
ROS2에서 파라미터들은 각각 노드마다 따로 갖고있습니다(roscore가 없으므로). 따라서 노드가 죽으면 관련 파라미터들은 전부 사라집니다. 파라미터는 노드가 시작될 때, 혹은 동작중일때 불러올 수 있습니다.
1. create a demo code
1. 패키지 생성
$ ros2 pkg create --build-type ament_cmake parameter_tests_cpp --dependencies rclcpp geometry_msgs
2. cpp 파일 생성
parameter_tests_node.cpp
#include <cmath>
#include <rclcpp/rclcpp.hpp>
#include <chrono>
#include <functional>
#include <geometry_msgs/msg/twist.hpp>
using namespace std::chrono_literals;
class VelParam: public rclcpp::Node
{
public:
VelParam()
: Node("param_vel_node")
{
auto param_desc = rcl_interfaces::msg::ParameterDescriptor{};
param_desc.description = "Sets the velocity (in m/s) of the robot.";
this->declare_parameter<std::double_t>("velocity", 0.0, param_desc);
timer_ = this->create_wall_timer(
1000ms, std::bind(&VelParam::timer_callback, this));
publisher_ = this->create_publisher<geometry_msgs::msg::Twist>("cmd_vel", 10);
}
void timer_callback()
{
this->get_parameter("velocity", vel_parameter_);
RCLCPP_INFO(this->get_logger(), "Velocity parameter is: %f", vel_parameter_);
auto message = geometry_msgs::msg::Twist();
message.linear.x = vel_parameter_;
publisher_->publish(message);
}
private:
std::double_t vel_parameter_;
rclcpp::TimerBase::SharedPtr timer_;
rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr publisher_;
};
int main(int argc, char** argv)
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<VelParam>());
rclcpp::shutdown();
return 0;
}
3. CMakeLists.txt파일 수정
아래 부분을 추가합니다
add_executable(param_vel_node src/parameter_tests_node.cpp)
ament_target_dependencies(param_vel_node rclcpp geometry_msgs)
install(TARGETS
param_vel_node
DESTINATION lib/${PROJECT_NAME}
)
4. 패키지 빌드 후, 실행
$ ros2 run parameter_tests param_vel_node
2. command line에서 파라미터 상호작용 해보기
이전 코드 실행 후, 아래 결과 확인
$ ros2 param list
다음 명령으로 특정 node의 파라미터만 확인할 수도 있습니다.
$ ros2 param list /param_vel_node
다음 명령으로 파라미터에 대한 설명을 확인할 수 있습니다.
$ ros2 param describe /param_vel_node velocity
다음 명령으로 현재 파라미터 값을 확인할 수 있습니다.
$ ros2 param get /param_vel_node velocity
다음 명령으로 파라미터 값을 설정하면, 로봇이 움직이는 것을 확인할 수 있습니다.
$ ros2 param set /param_vel_node velocity 0.1
YAML 파일 사용하기
다음 커맨드를 사용해서 현재 사용중인 파라미터를 저장할 수 있습니다.
$ ros2 param dump /param_vel_node > param_vel_node.yaml
파일 확인 결과:
다음 명령으로 파라미터를 불러올 수 있습니다.
$ ros2 param load /param_vel_node param_vel_node.yaml
ros2 run 명령으로 node를 실행할 때, 파라미터를 같이 불러올 수 있습니다.
$ ros2 run parameter_tests param_vel --ros-args --params-file /home/user/param_vel_node.yaml
다음 명령으로는 시작하면서 파라미터 값을 설정해줄 수 있습니다.
$ ros2 run parameter_tests param_vel --ros-args -p velocity:=0.1
2. launch 파일에서 파라미터 설정하기
test_parameters.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='parameter_tests',
executable='param_vel',
name='param_vel_node',
output='screen',
emulate_tty=True,
parameters=[
{'velocity': 0.2}
]
)
])
CMakeLists.txt에 다음 내용을 추가합니다.
install(
DIRECTORY launch
DESTINATION share/${PROJECT_NAME}
)
빌드 후, 실행해보면 로봇이 움직이는 것을 확인할 수 있습니다
3. Parameter Callbacks
앞에서 보셨다시피, ROS2에서는 아무때나 파라미터를 바꿀 수 있습니다. 이렇게 파라미터가 바뀔 때, node에서 callback을 호출할 수 있습니다.
1. cpp파일을 만듭니다
parameter_tests_callback.cpp
#include <cmath>
#include <rclcpp/rclcpp.hpp>
#include <chrono>
#include <string>
#include <functional>
#include <geometry_msgs/msg/twist.hpp>
#include <rcl_interfaces/msg/set_parameters_result.hpp>
using namespace std::chrono_literals;
class VelParam: public rclcpp::Node
{
public:
rcl_interfaces::msg::SetParametersResult parametersCallback(
const std::vector<rclcpp::Parameter> ¶meters)
{
rcl_interfaces::msg::SetParametersResult result;
result.successful = false;
result.reason = "";
for (const auto ¶meter : parameters)
{
if (parameter.get_name() == "velocity" &&
parameter.as_double() > 0.2)
{
RCLCPP_INFO(this->get_logger(), "Parameter 'velocity' not changed!");
result.reason = "Parameter 'velocity' cannot be higher than 0.2";
}
else
{
RCLCPP_INFO(this->get_logger(), "Parameter 'velocity' changed!");
result.successful = true;
result.reason = "Parameter 'velocity' is lower than 0.2";
}
}
return result;
}
VelParam()
: Node("param_vel_node")
{
this->declare_parameter<std::double_t>("velocity", 0.0);
timer_ = this->create_wall_timer(1000ms, std::bind(&VelParam::timer_callback, this));
publisher_ = this->create_publisher<geometry_msgs::msg::Twist>("cmd_vel", 10);
callback_handle_ = this->add_on_set_parameters_callback(
std::bind(&VelParam::parametersCallback, this, std::placeholders::_1));
}
void timer_callback()
{
this->get_parameter("velocity", vel_parameter_);
RCLCPP_INFO(this->get_logger(), "Velocity parameter is: %f", vel_parameter_);
auto message = geometry_msgs::msg::Twist();
message.linear.x = vel_parameter_;
publisher_->publish(message);
}
private:
std::double_t vel_parameter_;
rclcpp::TimerBase::SharedPtr timer_;
rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr publisher_;
OnSetParametersCallbackHandle::SharedPtr callback_handle_;
};
int main(int argc, char** argv)
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<VelParam>());
rclcpp::shutdown();
return 0;
}
2. CMakeLists.txt에 아래 내용을 추가합니다
add_executable(param_vel_node2 src/parameter_tests_callback.cpp)
ament_target_dependencies(param_vel_node2 rclcpp geometry_msgs rcl_interfaces)
install(TARGETS
param_vel_node
param_vel_node2
DESTINATION lib/${PROJECT_NAME}
)
빌드 후, 실행하고 파라미터를 바꿔봅니다
$ ros2 param set /param_vel_node velocity 0.2
'Study > [ROS2] ROS2 Basic' 카테고리의 다른 글
ROS2 with CPP - Introduction to Behavior Trees (1) | 2023.08.07 |
---|---|
ROS2 with C++ - Quality of Service (0) | 2023.08.04 |
ROS2 with C++ - Lifecycle Nodes (0) | 2023.08.02 |
ROS2 with C++ - Node composition (0) | 2023.07.30 |
ROS2 with C++ - Action (0) | 2023.07.30 |