ROS2】MOMO的鱼香ROS2(六)ROS2入门篇——ROS2通信之参数与动作

ROS2通信之参数与动作

  • 引言
  • 1 参数通信
    • 1.1 参数常用指令
  • 2 参数之RCLPY实现
    • 2.1 创建功能包和节点
    • 2.2 编辑脚本文件parameters_basic.py
    • 2.3 编译测试
  • 3 动作(Action)通信
    • 3.1 动作常用指令
  • 3.2 自定义通信接口
  • 4 动作之RCLPY实现

引言

笔者跟着鱼香ROS的ROS2学习之旅
学习参考:
【ROS2机器人入门到实战】
笔者的学习目录

  1. MOMO的鱼香ROS2(一)ROS2入门篇——从Ubuntu操作系统开启
  2. MOMO的鱼香ROS2(二)ROS2入门篇——ROS2初体验
  3. MOMO的鱼香ROS2(三)ROS2入门篇——ROS2第一个节点
  4. MOMO的鱼香ROS2(四)ROS2入门篇——ROS2节点通信之话题与服务
  5. MOMO的鱼香ROS2(五)ROS2入门篇——ROS2接口与自定义

1 参数通信

参数是节点的一个配置值,你可以认为参数是一个节点的设置

ROS2支持的参数值的类型

bool 和bool[],布尔类型用来表示开关,比如我们可以控制雷达控制节点,开始扫描和停止扫描。
int64 和int64[],整形表示一个数字,含义可以自己来定义,这里我们可以用来表示李四节点写小说的周期值
float64 和float64[],浮点型,可以表示小数类型的参数值
string 和string[],字符串,可以用来表示雷达控制节点中真实雷达的ip地址
byte[],字节数组,这个可以用来表示图片,点云数据等信息

1.1 参数常用指令

打开终端,运行小乌龟节点

# 终端1
ros2 run turtlesim turtlesim_node
# 终端2
ros2 run turtlesim turtle_teleop_key

查看参数信息

# 列举所有的参数
ros2 param list
# 参数的详细信息
ros2 param describe <node_name> <param_name>
# 举例
ros2 param describe /turtlesim background_b
# 查看参数值
ros2 param get /turtlesim background_b

设置参数

ros2 param set <node_name> <parameter_name> <value>
# 举例
ros2 param set /turtlesim background_r 44

保存参数

ros2 param dump <node_name>
# 举例
ros2 param dump /turtlesim

文件被保存成了yaml格式,用cat指令看一看

cat ./turtlesim.yaml

恢复参数值

ros2 param load  /turtlesim ./turtlesim.yaml

启动节点时加载参数快照

ros2 run <package_name> <executable_name> --ros-args --params-file <file_name>
# 举例
ros2 run turtlesim turtlesim_node --ros-args --params-file ./turtlesim.yaml

2 参数之RCLPY实现

2.1 创建功能包和节点

cd alian_ws/
ros2 pkg create alian_parameters_rclpy --build-type ament_python --dependencies rclpy --destination-directory src --node-name parameters_basic --maintainer-name "alian" 

2.2 编辑脚本文件parameters_basic.py

#!/usr/bin/env python3
import rclpy
from rclpy.node import Nodeclass ParametersBasicNode(Node):"""创建一个ParametersBasicNode节点,并在初始化时输出一个话"""def __init__(self, name):super().__init__(name)self.get_logger().info(f"节点已启动:{name}!")# 声明参数self.declare_parameter('alian_level', 0)# 获取参数log_level = self.get_parameter("alian_level").value# 设置参数self.get_logger().set_level(log_level)# 定时修改self.timer = self.create_timer(0.5, self.timer_callback)def timer_callback(self):"""定时器回调函数"""# 获取参数log_level = self.get_parameter("alian_level").value# 设置参数self.get_logger().set_level(log_level)print(f"========================{log_level}=============================")self.get_logger().debug("我是DEBUG级别的日志,我被打印出来了!")self.get_logger().info("我是INFO级别的日志,我被打印出来了!")self.get_logger().warn("我是WARN级别的日志,我被打印出来了!")self.get_logger().error("我是ERROR级别的日志,我被打印出来了!")self.get_logger().fatal("我是FATAL级别的日志,我被打印出来了!")      def main(args=None):rclpy.init(args=args) # 初始化rclpynode = ParametersBasicNode("parameters_basic")  # 新建一个节点rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)rclpy.shutdown() # 关闭rclpy

2.3 编译测试

colcon build --packages-select alian_parameters_rclpy
source install/setup.bash
ros2 run alian_parameters_rclpy parameters_basic

在这里插入图片描述
1. 指定参数值测试
终端1:

ros2 run alian_parameters_rclpy parameters_basic --ros-args -p alian_level:=10

在这里插入图片描述
2. 动态设置参数测试
在终端1运行的前提下,打开终端2:

ros2 param list
ros2 param set /parameters_basic alian_level 40

在这里插入图片描述

3 动作(Action)通信

参数是由服务构建出来了,而Action是由话题和服务共同构建出来的(一个Action = 三个服务+两个话题)
三个服务分别是: 1.目标传递服务 2.结果传递服务 3.取消执行服务
两个话题:1.反馈话题(服务发布,客户端订阅)2.状态话题(服务端发布,客户端订阅)

3.1 动作常用指令

列举目前存在的动作

ros2 action list -t

获取接口的信息

ros2 interface show turtlesim/action/RotateAbsolute 

查看动作信息

ros2 action info /turtle1/rotate_absolute 
ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.5}" --feedback

3.2 自定义通信接口

1. 创建接口功能包和接口文件

cd alian_ws/
ros2 pkg create robot_control_interfaces --build-type ament_cmake --destination-directory src --maintainer-name "alian"
mkdir -p src/robot_control_interfaces/action
touch src/robot_control_interfaces/action/MoveRobot.action

2. 修改packages.xml

  <depend>rosidl_default_generators</depend><member_of_group>rosidl_interface_packages</member_of_group>

在这里插入图片描述
3. 修改CMakeLists.txt

find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED)rosidl_generate_interfaces(${PROJECT_NAME}"action/MoveRobot.action"
)

在这里插入图片描述
4. 编写MoveRobot.action接口

# Goal: 要移动的距离
float32 distance
---
# Result: 最终的位置
float32 pose
---
# Feedback: 中间反馈的位置和状态
float32 pose
uint32 status
uint32 STATUS_MOVEING = 3
uint32 STATUS_STOP = 4

在这里插入图片描述
5. 编译生成接口

colcon build --packages-select robot_control_interfaces

4 动作之RCLPY实现

1. 创建功能包和节点

cd alian_ws/
ros2 pkg create alian_action_rclpy --build-type ament_python --dependencies rclpy robot_control_interfaces --destination-directory src --node-name action_robot --maintainer-name "alian" 
# 手动再创建action_control_02节点文件
touch src/alian_action_rclpy/alian_action_rclpy/action_control.py
#手动创建机器人类robot.py
touch src/alian_action_rclpy/alian_action_rclpy/robot.py

2. 节点文件1:robot.py 机器人类

from robot_control_interfaces.action import MoveRobot
import math
class Robot():"""机器人类,模拟一个机器人"""def __init__(self) -> None:self.current_pose_ = 0.0self.target_pose_ = 0.0self.move_distance_ = 0.0self.status_ = MoveRobot.Feedbackdef get_status(self):"""获取状态"""return self.status_def get_current_pose(self):"""获取当前位置"""return self.current_pose_def close_goal(self):"""接近目标"""return math.fabs(self.target_pose_ - self.current_pose_) < 0.01def stop_move(self):"""停止移动"""self.status_ = MoveRobot.Feedback.STATUS_STOPdef move_step(self):"""移动一小步"""direct = self.move_distance_ / math.fabs(self.move_distance_)step = direct * math.fabs(self.target_pose_ - self.current_pose_) * 0.1self.current_pose_ += step  # 移动一步print(f"移动了:{step}当前位置:{self.current_pose_}")return self.current_pose_def set_goal(self, distance):"""设置目标"""self.move_distance_ = distanceself.target_pose_ += distance  # 更新目标位置if self.close_goal():self.stop_move()return Falseself.status_ = MoveRobot.Feedback.STATUS_MOVEING  # 更新状态为移动return True

3. 节点文件2:action_robot.py 机器人节点

#!/usr/bin/env python3
import time
# 导入rclpy相关库
import rclpy
from rclpy.node import Node
from rclpy.action import ActionServer
from rclpy.action.server import ServerGoalHandle
# 导入接口
from robot_control_interfaces.action import MoveRobot
# 导入机器人类
from alian_action_rclpy.robot import Robot
#from rclpy.executors import MultiThreadedExecutor
#from rclpy.callback_groups import MutuallyExclusiveCallbackGroupclass ActionRobot(Node):"""机器人端Action服务"""def __init__(self,name):super().__init__(name)self.get_logger().info(f"节点已启动:{name}!")self.robot_ = Robot()self.action_server_ = ActionServer(self, MoveRobot, 'move_robot', self.execute_callback# ,callback_group=MutuallyExclusiveCallbackGroup())def execute_callback(self, goal_handle: ServerGoalHandle):"""执行回调函数,若采用默认handle_goal函数则会自动调用"""self.get_logger().info('执行移动机器人')feedback_msg = MoveRobot.Feedback()self.robot_.set_goal(goal_handle.request.distance)# rate = self.create_rate(2)while rclpy.ok() and not self.robot_.close_goal():# moveself.robot_.move_step()# feedbackfeedback_msg.pose = self.robot_.get_current_pose()feedback_msg.status = self.robot_.get_status()goal_handle.publish_feedback(feedback_msg)# cancel checkif goal_handle.is_cancel_requested:result = MoveRobot.Result()result.pose = self.robot_.get_current_pose()return result# rate.sleep() # Rate会造成死锁,单线程执行器时不能使用time.sleep(0.5)goal_handle.succeed()result = MoveRobot.Result()result.pose = self.robot_.get_current_pose()return resultdef main(args=None):"""主函数"""rclpy.init(args=args)action_robot = ActionRobot("action_robot")# 采用多线程执行器解决rate死锁问题# executor = MultiThreadedExecutor()# executor.add_node(action_robot_02)# executor.spin()rclpy.spin(action_robot)rclpy.shutdown()

4. 节点文件3:action_control.py 控制节点

import rclpy
from rclpy.action import ActionClient
from rclpy.node import Node
# 导入Action接口
from robot_control_interfaces.action import MoveRobotclass ActionControl(Node):"""Action客户端"""def __init__(self, name):super().__init__(name)self.get_logger().info(f"节点已启动:{name}!")self.action_client_ = ActionClient(self, MoveRobot, 'move_robot')self.send_goal_timer_ = self.create_timer(1, self.send_goal)def send_goal(self):"""发送目标"""self.send_goal_timer_.cancel()goal_msg = MoveRobot.Goal()goal_msg.distance = 5.0self.action_client_.wait_for_server()self._send_goal_future = self.action_client_.send_goal_async(goal_msg,feedback_callback=self.feedback_callback)self._send_goal_future.add_done_callback(self.goal_response_callback)def goal_response_callback(self, future):"""收到目标处理结果"""goal_handle = future.result()if not goal_handle.accepted:self.get_logger().info('Goal rejected :(')returnself.get_logger().info('Goal accepted :)')self._get_result_future = goal_handle.get_result_async()self._get_result_future.add_done_callback(self.get_result_callback)def get_result_callback(self, future):"""获取结果反馈"""result = future.result().resultself.get_logger().info(f'Result: {result.pose}')def feedback_callback(self, feedback_msg):"""获取回调反馈"""feedback = feedback_msg.feedbackself.get_logger().info(f'Received feedback: {feedback.pose}')def main(args=None):"""主函数"""rclpy.init(args=args)action_robot = ActionControl("action_control")rclpy.spin(action_robot)rclpy.shutdown()

5. 修改setup.py

'console_scripts': ['robot = alian_action_rclpy.robot:main''action_robot = alian_action_rclpy.action_robot:main','action_control = alian_action_rclpy.action_control:main'

在这里插入图片描述

6. 编译测试

cd alian_ws/
colcon build --packages-up-to alian_action_rclpy
# 运行机器人节点
source install/setup.bash 
ros2 run alian_action_rclpy  action_robot
# 新终端
source install/setup.bash 
ros2 run alian_action_rclpy  action_control

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全屏页面滚动个人简历模板源码

标题模板介绍 HTML5全屏页面滚动个人简历模板&#xff0c;响应式设计&#xff0c;自适应屏幕分辨率&#xff0c;兼容PC端 和手机移动端&#xff0c;单页面&#xff0c;多栏目&#xff0c;有工作经验、联系我、技能、关于我等栏目。 下载地址 CSDN下载

新版网易滑块

突然发现脸皮厚根本没用&#xff0c;大冬天的&#xff0c;风吹过来还是会冷。 大哥们多整件衣裳&#xff0c;好冷&#xff01;&#xff01;&#xff01;&#xff01; 网易更新了&#xff0c;这俩 dt跟f值。 dt为 这里返回的&#xff0c;忽略掉他。 data参数中的d值&#xff…

驾驭未来:从传统运维到智能化运维的转型之路

随着科技的飞速发展&#xff0c;企业的业务需求也在不断变化。为了满足这些需求&#xff0c;企业的IT架构逐渐向云原生、容器化和微服务化演进。作为支撑企业业务发展的运维人员&#xff0c;我们需要紧跟时代步伐&#xff0c;不断提升自己的技能和认知水平。 在2023年全球运维大…

python统计分析——操作案例(模拟抽样)

参考资料&#xff1a;用python动手学统计学 import numpy as np import pandas as pd from matplotlib import pyplot as plt import seaborn as snsdata_setpd.read_csv(r"C:\python统计学\3-4-1-fish_length_100000.csv")[length] #此处将文件路径改为自己的路…

计算机网络 —— 数据链路层

数据链路层 3.1 数据链路层概述 数据链路层把网络层交下来的数据构成帧发送到链路上&#xff0c;以及把收到的帧数据取出并上交给网络层。链路层属于计算机网络的底层。数据链路层使用的信道主要由以下两种类型&#xff1a; 点对点通信。广播通信。 数据链路和帧 链路&…

网络共享服务

存储类型&#xff1a;直连式&#xff08;DAS&#xff09;:距离最近&#xff0c;存储设备且直接连接到服务器上 存储区域网络&#xff08;SAN&#xff09;&#xff1a;适用于大型应用或数据库系统&#xff0c;可以使用文件的空间&#xff0c; 以及管理空间…

如何在Windows 10/11的防火墙中禁止和允许某个应用程序,这里提供详细步骤

想阻止应用程序访问互联网吗&#xff1f;以下是如何通过简单的步骤阻止和允许Windows防火墙中的程序。​ 一般来说&#xff0c;大多数用户永远不需要担心应用程序访问互联网。然而&#xff0c;在某些情况下&#xff0c;你需要限制应用程序访问互联网。 例如&#xff0c;有问题…

Linux系统使用超详细(十)~vi/vim命令①

vi/vim命令有很多&#xff0c;其实只有少数的用法对于我们日常工作中起到了很大帮助&#xff0c;但是既然我选择梳理Linux的学习笔记&#xff0c;那么一定全力把自己的理解和学习笔记的内容认真整理汇总&#xff0c;内容或许有错误&#xff0c;还请发现的C友们发现了及时指出。…

线性代数——行列式按行(列)展开

目录 一、余子式&#xff1a;将行列式某元素所在行和列的元素全去掉 剩余部分所构成的行列式&#xff0c;称为该元素的余子式 二、代数余子式 三、行列式等于它的任一行&#xff08;列&#xff09;的各元素与对应代数余子式乘积之和 四、行列式某行元素&#xff08;列&…

C++核心编程之类和对象---C++面向对象的三大特性--多态

目录 一、多态 1. 多态的概念 2.多态的分类&#xff1a; 1. 静态多态&#xff1a; 2. 动态多态&#xff1a; 3.静态多态和动态多态的区别&#xff1a; 4.动态多态需要满足的条件&#xff1a; 4.1重写的概念&#xff1a; 4.2动态多态的调用&#xff1a; 二、多态 三、多…

Elasticsearch:Search tutorial - 使用 Python 进行搜索 (四)

在本节中&#xff0c;你将了解另一种机器学习搜索方法&#xff0c;该方法利用 Elastic Learned Sparse EncodeR 模型或 ELSER&#xff0c;这是一种由 Elastic 训练来执行语义搜索的自然语言处理模型。这是继之前的文章 “Elasticsearch&#xff1a;Search tutorial - 使用 Pyth…

JDK介绍

JDK(Java Development Kit)是Sun Microsystems针对Java开发员的产品。自从Java推出以来&#xff0c;JDK已经成为使用最广泛的Java SDK&#xff08;Software development kit&#xff09;&#xff0c;JDK是一个写Java的applet和应用程序的程序开发环境。它由一个处于操作系统层之…

HTML--CSS--边框、列表、表格样式

边框样式 属性&#xff1a; border-width 边框宽度 border-style 边框外观 border-color 边框颜色 需要同时设定三个属性 border-width 边框宽度 取值为像素值 border-style 边框样式 none 无样式 dashed 虚线 solid 实线 border-color 边框颜色 如示例&#xff1a; 为div设…

C语言中关于指针的理解及用法

关于指针意思的参考&#xff1a;https://baike.baidu.com/item/%e6%8c%87%e9%92%88/2878304 指针 指针变量 地址 野指针 野指针就是指针指向的位置是不可知的&#xff08;随机的&#xff0c;不正确的&#xff0c;没有明确限制的&#xff09; 以下是导致野指针的原因 1.指针…

JAVA毕业设计122—基于Java+Springboot+Vue的摄影跟拍预订管理系统(源代码+数据库+万字论文+PPT)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootVue的摄影跟拍预订管理系统(源代码数据库万字论文PPT)122 一、系统介绍 本项目前后端分离&#xff0c;本系统分为管理员、用户、摄影师三种角色 1、用户&#…

k8s的存储卷(数据卷)

1、存储卷&#xff1a;容器内的目录和宿主机的目录进行挂载 2、容器在系统上的生命周期是短暂的&#xff0c;delete&#xff0c;k8s用控制器创建的pod&#xff0c;delete相当于重启&#xff0c;容器的状态也会恢复到初始状态&#xff0c;一旦回到初始状态&#xff0c;所有的后…

时间序列数据的季节性检测

时间序列分析是统计学和数据科学的一个基本研究领域&#xff0c;它为理解和预测序列数据中的模式提供了一个强大的框架。特别是时间序列数据&#xff0c;它捕获连续时间间隔内的信息&#xff0c;使分析师能够揭示趋势&#xff0c;季节性模式和其他时间依赖性。在时间序列分析的…

css深度选择器 /deep/

一、/deep/的含义和使用 /deep/ 是一种 CSS 深度选择器&#xff0c;也被称为深度组合器或者阴影穿透组合器&#xff0c;主要用在 Web 组件样式封装中。 在 Vue.js 或者 Angular 中&#xff0c;使用了样式封装技术使得组件的样式不会影响到全局&#xff0c;也就是说组件内部的…

远程访问及控制

文章目录 远程访问及控制一、SSH远程管理1、SSH&#xff08;Secure Shell&#xff09;协议定义2、SSH的优点3、OpenSSHell 二、配置OpenSSH服务端1、sshd_config配置文件的常用选项2、sshd服务支持的两种验证方式2.1 密码验证2.2 秘钥对验证 三、SSH客户端程序的使用1、基本用法…

数据结构(三)堆和哈希表

目录 哈希表和堆什么是哈希表 &#xff1f;什么是堆 &#xff1f;什么是图 &#xff1f;案例一&#xff1a;使用python实现最小堆案例二 &#xff1a; 如何用Python通过哈希表的方式完成商品库存管理闯关题 &#xff08;包含案例三&#xff1a;python实现哈希表&#xff09; 本…