【ROS2机器人入门到实战】使用API进行导航

这篇具有很好参考价值的文章主要介绍了【ROS2机器人入门到实战】使用API进行导航。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

  1. 当前平台文章汇总地址:ROS2机器人从入门到实战
  2. 获取完整教程及配套资料代码,请关注公众号<鱼香ROS>获取
  3. 教程配套机器人开发平台:两驱版| 四驱版
  4. 为方便交流,搭建了机器人技术问答社区:地址 fishros.org.cn

Navigation 2 对外提供了动作服务用于导航调用。动作通信是 ROS 2 四大通讯机制之一,前面我们并没有介绍,我们以导航调用为例来简单了解下它。

动作通信和其名字一样,主要用于控制场景,它的优点在于其反馈机制,当客户端发送目标给服务端后,除了等待服务端处理完成,还可以收到服务端的处理进度。启动导航后在终端中使用动作相关命令可以查看当前系统所有动作列表,命令及结果如下:

ros2 action list
--
/assisted_teleop
/backup
/compute_path_through_poses
/compute_path_to_pose
/drive_on_heading
/follow_path
/follow_waypoints
/navigate_through_poses
/navigate_to_pose
/smooth_path
/spin
/wait

其中 /navigate_to_pose 就是用于处理导航到点请求的动作。继续使用命令查看该动作的具体信息。

ros2 action info /navigate_to_pose -t
---
Action: /navigate_to_pose
Action clients: 4
    /bt_navigator [nav2_msgs/action/NavigateToPose]
    /waypoint_follower [nav2_msgs/action/NavigateToPose]
    /rviz2 [nav2_msgs/action/NavigateToPose]
    /rviz2 [nav2_msgs/action/NavigateToPose]

Action servers: 1
    /bt_navigator [nav2_msgs/action/NavigateToPose]

可以看到该动作的客户端、服务端以及消息接口情况,使用指令查看 nav2_msgs/action/NavigateToPose 接口定义,命令及结果如下:

ros2 interface show nav2_msgs/action/NavigateToPose
---
#goal definition
geometry_msgs/PoseStamped pose
	std_msgs/Header header
		builtin_interfaces/Time stamp
			int32 sec
			uint32 nanosec
		string frame_id
	Pose pose
		Point position
			float64 x
			float64 y
			float64 z
		Quaternion orientation
			float64 x 0
			float64 y 0
			float64 z 0
			float64 w 1
string behavior_tree
---
#result definition
std_msgs/Empty result
---
#feedback definition
geometry_msgs/PoseStamped current_pose
	std_msgs/Header header
		builtin_interfaces/Time stamp
			int32 sec
			uint32 nanosec
		string frame_id
	Pose pose
		Point position
			float64 x
			float64 y
			float64 z
		Quaternion orientation
			float64 x 0
			float64 y 0
			float64 z 0
			float64 w 1
builtin_interfaces/Duration navigation_time
	int32 sec
	uint32 nanosec
builtin_interfaces/Duration estimated_time_remaining
	int32 sec
	uint32 nanosec
int16 number_of_recoveries
float32 distance_remaining

从该接口定义可以看出,动作消息的接口分为目标、结果和反馈三个部分,相比服务通信接口的目标和结果多出了反馈这一部分。如果在机器人导航时仔细观察 RViz 左下角 Navigation 2 部分,你会发现它会实时的显示当前导航所花费的时间,距离目标点之间的距离,花费的时间以及脱困次数,这些数据就是来自动作服务的反馈部分。

使用命令行工具可以发送动作请求并接收反馈和结果,以请求机器人移动到地图的指定目标点为例,命令及反馈如下。

ros2 action send_goal /navigate_to_pose nav2_msgs/action/NavigateToPose "{pose: {header: {frame_id: map}, pose: {position: {x: 2, y: 2}}}}" --feedback 
---
Waiting for an action server to become available...
Sending goal:
 pose:
  header:
    stamp:
      sec: 0
      nanosec: 0
    frame_id: map
  pose:
    position:
      x: 2.0
      y: 2.0
      z: 0.0
    orientation:
      x: 0.0
      y: 0.0
      z: 0.0
      w: 1.0
behavior_tree: ''
Goal accepted with ID: c5c52646de774f55b4ee71ca5ed3267a
...
Feedback:
    current_pose:
  header:
    stamp:
      sec: 4679
      nanosec: 504000000
    frame_id: map
  pose:
    position:
      x: 2.079677095742107
      y: 1.947119186243544
      z: 0.09189999999999998
    orientation:
      x: 0.0
      y: 0.0
      z: 0.054114175706008266
      w: 0.998534754521674
navigation_time:
  sec: 18
  nanosec: 164000000
estimated_time_remaining:
  sec: 0
  nanosec: 0
number_of_recoveries: 2
distance_remaining: 0.10830961167812347
Result:
    result: {}
Goal finished with status: SUCCEEDED

上面的命令用于请求机器人移动到地图坐标系中的 xy 都为 2.0 的点,反馈结果中,Sending goal 部分表示目标,Feedback 部分是反馈,Result 部分为最终结果。

要灵活使用自然还需要学习如何用代码调用,在 Python 中 nav2_simple_commander 库已经将动作客户端代码封装到 BasicNavigator 节点中,使用该节点的对应函数就可以实现导航操作。在 src/fishbot_application/fishbot_application 下新建文件 nav_to_pose.py,然后编写如下代码:


from geometry_msgs.msg import PoseStamped
from nav2_simple_commander.robot_navigator import BasicNavigator, TaskResult
import rclpy
from rclpy.duration import Duration


def main():
    rclpy.init()
    navigator = BasicNavigator()
    # 等待导航启动完成
    navigator.waitUntilNav2Active()
    # 设置目标点坐标
    goal_pose = PoseStamped()
    goal_pose.header.frame_id = 'map'
    goal_pose.header.stamp = navigator.get_clock().now().to_msg()
    goal_pose.pose.position.x = 1.0
    goal_pose.pose.position.y = 1.0
    goal_pose.pose.orientation.w = 1.0
    # 发送目标接收反馈结果
    navigator.goToPose(goal_pose)
    while not navigator.isTaskComplete():
        feedback = navigator.getFeedback()
        navigator.get_logger().info(
            f'预计: {Duration.from_msg(feedback.estimated_time_remaining).nanoseconds / 1e9} s 后到达')
        # 超时自动取消
        if Duration.from_msg(feedback.navigation_time) > Duration(seconds=600.0):
            navigator.cancelTask()
    # 最终结果判断
    result = navigator.getResult()
    if result == TaskResult.SUCCEEDED:
        navigator.get_logger().info('导航结果:成功')
    elif result == TaskResult.CANCELED:
        navigator.get_logger().warn('导航结果:被取消')
    elif result == TaskResult.FAILED:
        navigator.get_logger().error('导航结果:失败')
    else:
        navigator.get_logger().error('导航结果:返回状态无效')

上面的代码中有关键函数有四个,第一个是 navigator.goToPose 用于发布目标,第二个是 navigator.getFeedback() 用于获取状态反馈,第三个是 navigator.cancelTask() 用于中途取消,第四个是 navigator.getResult() 用于获取最终结果。跳转到 goToPose 的源码可以发现最终发送请求是通过 self.nav_to_pose_client.send_goal_async 函数完成的,而 nav_to_pose_client 就是在 BasicNavigator 函数中定义的动作客户端,定义代码如下:

self.nav_to_pose_client = ActionClient(self, NavigateToPose, 'navigate_to_pose')

保存好代码,注册该节点并重新构建功能包,再次运行仿真和导航,初始化位姿后启动该节点,观察 RViz 中机器人运动情况,启动命令及终端打印如下。

ros2 run fishbot_application nav_to_pose
---
[INFO] [1685599886.677153365] [basic_navigator]: Nav2 is ready for use!
[INFO] [1685599886.707280550] [basic_navigator]: Navigating to goal: 1.0 1.0...
[INFO] [1685599886.852565845] [basic_navigator]: 预计剩余: 0.0 s
[INFO] [1685599891.432155882] [basic_navigator]: 预计剩余: 170.591972225 s
[INFO] [1685599891.532646643] [basic_navigator]: 预计剩余: 98.418445514 s
[INFO] [1685599891.635079916] [basic_navigator]: 预计剩余: 77.541805557 s
[INFO] [1685599914.104374413] [basic_navigator]: 预计剩余: 1.833780316 s
...
[INFO] [1685599918.156745102] [basic_navigator]: 导航结果:成功

使用 Python 可以通过调用 nav2_simple_commander 库方便的实现导航,但如果项目需要换成 C++ 也并不复杂,使用动作客户端也可以方便的调用,如何实现我并不打算再操作一遍,但我将提供给你一份详细的 C++ 调用导航服务的实现代码。文章来源地址https://www.toymoban.com/news/detail-769272.html

#include <memory>
#include "nav2_msgs/action/navigate_to_pose.hpp"  // 导入导航动作消息的头文件
#include "rclcpp/rclcpp.hpp"  // 导入ROS 2的C++客户端库
#include "rclcpp_action/rclcpp_action.hpp"  // 导入ROS 2的C++ Action客户端库

using NavigationAction = nav2_msgs::action::NavigateToPose;  // 定义导航动作类型为NavigateToPose

class NavToPoseClient : public rclcpp::Node {
 public:
  using NavigationActionClient = rclcpp_action::Client<NavigationAction>;  // 定义导航动作客户端类型
  using NavigationActionGoalHandle =
      rclcpp_action::ClientGoalHandle<NavigationAction>;  // 定义导航动作目标句柄类型

  NavToPoseClient() : Node("nav_to_pose_client") {
    // 创建导航动作客户端
    action_client_ = rclcpp_action::create_client<NavigationAction>(
        this, "navigate_to_pose");
  }

  void sendGoal() {
    // 等待导航动作服务器上线,等待时间为5秒
    while (!action_client_->wait_for_action_server(std::chrono::seconds(5))) {
      RCLCPP_INFO(get_logger(), "等待Action服务上线。");
    }
    // 设置导航目标点
    auto goal_msg = NavigationAction::Goal();
    goal_msg.pose.header.frame_id = "map";  // 设置目标点的坐标系为地图坐标系
    goal_msg.pose.pose.position.x = 2.0f;  // 设置目标点的x坐标为2.0
    goal_msg.pose.pose.position.y = 2.0f;  // 设置目标点的y坐标为2.0

    auto send_goal_options =
        rclcpp_action::Client<NavigationAction>::SendGoalOptions();
    // 设置请求目标结果回调函数
    send_goal_options.goal_response_callback =
        [this](NavigationActionGoalHandle::SharedPtr goal_handle) {
          if (goal_handle) {
            RCLCPP_INFO(get_logger(), "目标点已被服务器接收");
          }
        };
    // 设置移动过程反馈回调函数
    send_goal_options.feedback_callback =
        [this](
            NavigationActionGoalHandle::SharedPtr goal_handle,
            const std::shared_ptr<const NavigationAction::Feedback> feedback) {
          (void)goal_handle;  // 假装调用,避免 warning: unused
          RCLCPP_INFO(this->get_logger(), "反馈剩余距离:%f",
                      feedback->distance_remaining);
        };
    // 设置执行结果回调函数
    send_goal_options.result_callback =
        [this](const NavigationActionGoalHandle::WrappedResult& result) {
          if (result.code == rclcpp_action::ResultCode::SUCCEEDED) {
            RCLCPP_INFO(this->get_logger(), "处理成功!");
          }
        };
    // 发送导航目标点
    action_client_->async_send_goal(goal_msg, send_goal_options);
  }

  NavigationActionClient::SharedPtr action_client_;
};

int main(int argc, char** argv) {
  rclcpp::init(argc, argv);
  auto node = std::make_shared<NavToPoseClient>();
  node->sendGoal();
  rclcpp::spin(node);
  rclcpp::shutdown();
  return 0;
}

到了这里,关于【ROS2机器人入门到实战】使用API进行导航的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【ROS2机器人入门到实战】ROS2服务入门

    当前平台文章汇总地址:ROS2机器人从入门到实战 获取完整教程及配套资料代码,请关注公众号鱼香ROS获取 教程配套机器人开发平台:两驱版| 四驱版 为方便交流,搭建了机器人技术问答社区:地址 fishros.org.cn 大家好,帅鱼又蹬蹬蹬的游回来了。本节小鱼将要带大家一起了解

    2024年02月07日
    浏览(61)
  • 【ROS2机器人入门到实战】使用SLAM_TOOLBOX完成建图

    当前平台文章汇总地址:ROS2机器人从入门到实战 获取完整教程及配套资料代码,请关注公众号鱼香ROS获取 教程配套机器人开发平台:两驱版| 四驱版 为方便交流,搭建了机器人技术问答社区:地址 fishros.org.cn SLAM 是通过传感器获取环境信息然后进行定位和建图。在 ROS 2 中,

    2024年02月06日
    浏览(93)
  • 【ROS2机器人入门到实战】ROS2节点介绍

    当前平台文章汇总地址:ROS2机器人从入门到实战 获取完整教程及配套资料代码,请关注公众号鱼香ROS获取 教程配套机器人开发平台:两驱版| 四驱版 为方便交流,搭建了机器人技术问答社区:地址 fishros.org.cn ROS2中每一个节点也是只负责一个单独的模块化的功能(比如一个

    2024年02月06日
    浏览(56)
  • 【ROS2机器人入门到实战】ROS2接口介绍

    当前平台文章汇总地址:ROS2机器人从入门到实战 获取完整教程及配套资料代码,请关注公众号鱼香ROS获取 教程配套机器人开发平台:两驱版| 四驱版 为方便交流,搭建了机器人技术问答社区:地址 fishros.org.cn 本节小鱼将会带你学习认识一个新的概念,叫做interface,即接口。

    2024年02月05日
    浏览(52)
  • 【ROS2机器人入门到实战】

    当前平台文章汇总地址:ROS2机器人从入门到实战 获取完整教程及配套资料代码,请关注公众号鱼香ROS获取 教程配套机器人开发平台:两驱版| 四驱版 为方便交流,搭建了机器人技术问答社区:地址 fishros.org.cn 第 1 章 ROS2介绍与安装 基础篇-Linux基础 1.Linux与Ubuntu系统介绍 2.在

    2024年02月16日
    浏览(55)
  • 【ROS2机器人入门到实战】4.ROS2初体验

    当前平台文章汇总地址:ROS2机器人从入门到实战 获取完整教程及配套资料代码,请关注公众号鱼香ROS获取 教程配套机器人开发平台:两驱版| 四驱版 为方便交流,搭建了机器人技术问答社区:地址 fishros.org.cn 通过几个简单的小例子来体验ROS2软件库和工具集。 游戏内容:很

    2024年02月04日
    浏览(73)
  • 【ROS2机器人入门到实战】3.动手安装ROS2

    当前平台文章汇总地址:ROS2机器人从入门到实战 获取完整教程及配套资料代码,请关注公众号鱼香ROS获取 教程配套机器人开发平台:两驱版| 四驱版 为方便交流,搭建了机器人技术问答社区:地址 fishros.org.cn 到了这一节,终于可以开始安装ROS2了。安装ROS2本来是一件比较麻

    2024年02月13日
    浏览(59)
  • 【ROS2机器人入门到实战】2.ROS与ROS2对比

    当前平台文章汇总地址:ROS2机器人从入门到实战 获取完整教程及配套资料代码,请关注公众号鱼香ROS获取 教程配套机器人开发平台:两驱版| 四驱版 为方便交流,搭建了机器人技术问答社区:地址 fishros.org.cn 经过上一节的学习,相信你已经对ROS和ROS2的发展有了一定的了解

    2024年02月04日
    浏览(47)
  • 【ROS2机器人入门到实战】2.ROS2功能包与工作空间

    当前平台文章汇总地址:ROS2机器人从入门到实战 获取完整教程及配套资料代码,请关注公众号鱼香ROS获取 教程配套机器人开发平台:两驱版| 四驱版 为方便交流,搭建了机器人技术问答社区:地址 fishros.org.cn 大家好,我是小鱼~上一节小鱼给大家介绍了一下节点,运行一个

    2024年01月23日
    浏览(55)
  • 【ROS2机器人入门到实战】地图保存与编辑

    当前平台文章汇总地址:ROS2机器人从入门到实战 获取完整教程及配套资料代码,请关注公众号鱼香ROS获取 教程配套机器人开发平台:两驱版| 四驱版 为方便交流,搭建了机器人技术问答社区:地址 fishros.org.cn 可以看到有下面的用法 我们的地图话题为map,文件名字我们用f

    2024年02月03日
    浏览(68)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包