准备工作
开始学习代码之前,先看一下代码结构,有助于在高层次上理解整个功能。
OriginBot的手势控制代码库包含多个组件,每个组件都有其特定的职责:
-
CMakeLists.txt
:定义了如何构建项目。 -
README.md
:提供了项目的概述和使用说明。 -
launch/
:存放启动文件,用于启动和配置节点。 -
src/
:包含主要的源代码文件。 -
include/
:存放头文件,用于定义接口和数据结构。
关键的代码文件有如下几个:
-
gesture_control_node.cpp
:这是手势控制节点的主要实现文件。它订阅手势识别消息,并根据消息内容发布机器人的运动控制指令。 -
param_node.cpp
:参数节点用于管理配置参数,如手势识别的灵敏度和机器人的运动速度。 -
gesture_control_engine.cpp
和gesture_control_engine.h
:这些文件定义了GestureControlEngine
类,它是处理手势识别和生成控制指令的核心组件
函数调用链路
我尝试梳理出OriginBot手势控制功能的函数调用链路。以下是主要的组件和它们的交互方式:
1. main.cpp
-
程序的入口点,初始化ROS 2并启动所有的节点和执行器。 -
调用 rclcpp::init
来初始化ROS 2节点。 -
创建 GestureControlEngine
的实例,并将其节点添加到执行器中。 -
启动执行器,进入spin循环,等待消息和回调。
2. GestureControlEngine
-
一个单例类,负责管理手势控制的整个流程。 -
FeedSmart
方法将接收到的手势消息推送到队列中,并通知处理线程。 -
RunStrategy
方法从队列中取出手势消息,并根据手势类型决定机器人的动作。 -
DoRotate
和DoMove
方法根据手势的方向和步长计算出机器人的运动指令。 -
CancelMove
方法用于取消当前的运动指令。 -
UpdateRobotPose
方法(未在提供的内容中明确提及,但根据命名推测)可能用于更新机器人的运动状态。
3. GestureControlNode
-
一个ROS 2节点,订阅手势识别消息并将其传递给 GestureControlEngine
。 -
SmartTopicCallback
是订阅手势消息的回调函数,它将接收到的消息传递给GestureControlEngine
的FeedSmart
方法。
4. ParametersClass
-
另一个ROS 2节点,用于管理和响应配置参数的变化。 -
Respond
方法定期检查参数的变化,并将新的参数值应用到GestureControlEngine
。
5. gesture_control.launch.py
-
ROS 2启动文件,用于配置和启动 GestureControlNode
和ParametersClass
节点。 -
通过 Node
动作启动GestureControlNode
和ParametersClass
。
调用链路概览
main.cpp | v rclcpp::init | v GestureControlEngine::Instance() | | v v GestureControlEngine::FeedSmart -> GestureControlEngine::RunStrategy | | v v GestureControlNode (订阅手势消息) -> ParametersClass (管理参数) | | v v GestureControlNode::SmartTopicCallback -> ParametersClass::Respond | v GestureControlEngine::DoRotate/DoMove/CancelMove
这个调用链路展示了从手势识别到机器人运动控制的整个流程。每个组件都有明确的职责,通过ROS 2的消息传递和回调机制相互协作。
Launch文件详解
launch文件作为这个功能最终的入口,应当先来梳理清楚这部分的配置。
gesture_control.launch.py
文件内容
这个文件定义了如何启动GestureControlNode
和相关的依赖节点。它使用launch
库来创建节点的实例,并设置参数。
import os
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from ament_index_python import get_package_share_directory
def generate_launch_description():
# 手势控制节点
gesture_control_node = Node(
package='gesture_control',
executable='gesture_control',
output='screen',
parameters=[
{"ai_msg_sub_topic_name": "/hobot_hand_gesture_detection"},
{"twist_pub_topic_name": "/cmd_vel"},
{"activate_wakeup_gesture": 0},
{"track_serial_lost_num_thr": 100},
{"move_step": 0.5},
{"rotate_step": 0.5}
],
arguments=['--ros-args', '--log-level', 'warn']
)
# 包含手势检测节点的启动文件
hand_gesture_det_node = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(
get_package_share_directory('hand_gesture_detection'),
'launch/hand_gesture_detection.launch.py'
))
)
return LaunchDescription([
hand_gesture_det_node,
gesture_control_node
])
参数解释
在generate_launch_description
函数中,我们可以看到Node
动作创建了gesture_control
节点的实例,并传递了一系列参数:
-
package
: 指定节点所属的ROS 2包名。 -
executable
: 指定要执行的可执行文件名。 -
output
: 指定节点输出的控制台。 -
parameters
: 一系列键值对参数,用于配置节点的行为。 -
ai_msg_sub_topic_name
: 订阅的手势识别消息主题。 -
twist_pub_topic_name
: 发布机器人运动控制消息的主题。 -
activate_wakeup_gesture
: 是否启用唤醒手势。 -
track_serial_lost_num_thr
: 目标连续消失帧数阈值。 -
move_step
: 线速度步长。 -
rotate_step
: 角速度步长。 -
arguments
: 传递给ROS 2的额外参数,用于设置日志级别。
结合源代码
在GestureControlNode
的源代码中,我们可以看到这些参数是如何被使用的:
GestureControlNode::GestureControlNode(const std::string& node_name, SmartCbType smart_cb)
: Node(node_name), smart_cb_(smart_cb) {
// ...省略其他代码...
this->declare_parameter<std::string>("twist_pub_topic_name", twist_pub_topic_name_);
this->declare_parameter<std::string>("ai_msg_sub_topic_name", ai_msg_sub_topic_name_);
// ...省略其他代码...
twist_publisher_ = this->create_publisher
在这个构造函数中,declare_parameter
方法用于声明参数,这样它们就可以在节点的生命周期中被访问和修改。twist_publisher_
是用于发布Twist
消息的发布器,它使用twist_pub_topic_name
参数来确定发布到哪个主题。
代码详解
手势控制中最终的两个部分就是手势识别和运动控制,下面分别来讲。
手势控制功能在OriginBot中是通过一系列精心设计的组件和流程来实现的。下面我们将详细介绍与手势识别和运动控制相关的源代码。
手势识别
手势识别是通过hand_gesture_detection
节点来实现的,这个节点订阅来自摄像头或其他图像源的视觉数据,并运行手势识别算法来检测和识别手势。识别到的手势会被封装成PerceptionTargets
消息类型,并发布到指定的主题上。
在gesture_control.launch.py
中,我们看到了如何启动这个节点的引用:
hand_gesture_det_node = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(
get_package_share_directory('hand_gesture_detection'),
'launch/hand_gesture_detection.launch.py'
))
)
这个启动文件会包含手势识别节点的配置和启动指令。具体的手势识别逻辑是在hand_gesture_detection
包中的,这个代码并不直接包含在OriginBot的代码库中,而是调用了相机模组的代码,就不再继续深入解释。
运动控制
运动控制部分是在GestureControlNode
中实现的。这个节点订阅手势识别消息,并根据识别到的手势来控制机器人的运动。下面是GestureControlNode
的一些关键部分:
-
「订阅手势识别消息」:
smart_subscription_ =
this->create_subscription
这里,create_subscription
方法用于创建一个订阅者,它订阅ai_msgs::msg::PerceptionTargets
类型的消息。SmartTopicCallback
是接收到消息时的回调函数。
-
「处理手势识别消息」:
void GestureControlNode::SmartTopicCallback(
const ai_msgs::msg::PerceptionTargets::ConstSharedPtr msg) {
// ...处理手势消息...
}
在SmartTopicCallback
中,节点会解析接收到的手势识别消息,并根据识别到的手势来决定下一步的动作。
-
「控制机器人运动」:
void GestureControlNode::RobotCtl(const Twist &msg) const {
twist_publisher_->publish(msg);
}
RobotCtl
方法负责将计算出的运动控制指令(Twist
类型的消息)发布到/cmd_vel
主题上,从而控制机器人的运动。
手势控制逻辑
手势控制的逻辑主要在GestureControlEngine
中实现。这个类处理手势识别消息,并根据识别到的手势生成相应的运动控制指令。以下是一些关键的方法:
-
FeedSmart
: 将新的手势识别消息添加到队列中。 -
RunStrategy
: 从队列中取出手势消息,并根据手势类型决定机器人的动作。 -
DoRotate
和DoMove
: 根据手势的方向和步长计算出机器人的运动指令。 -
CancelMove
: 取消当前的运动指令。
这里跟人体跟踪部分有一点类似
这些方法会根据GestureControlEngine
中的跟踪信息和配置参数来生成运动控制指令,并通过RobotCtl
方法发布这些指令。
总结
OriginBot的手势控制功能通过结合手势识别和运动控制两个关键部分来实现。手势识别节点负责检测和识别手势,而GestureControlNode
和GestureControlEngine
则负责解析这些手势并生成相应的运动控制指令。这些指令通过ROS 2的消息系统发布给机器人,从而实现手势控制。
评论(0)
您还未登录,请登录后发表或查看评论