当前位置: 首页 > news >正文

48.在ROS中实现local planner(1)- 实现一个可以用的模板

有了之前45.在ROS中实现global planner(1)- 实现一个可以用模板的global planner的经验, 现在再去创建一个local planner的包就容易多了

1. 创建包

  • 创建
cd ~/pibot_ros/ros_ws/src  # 这里可以使用自己的ros workspace
catkin_create_pkg sample_local_planner
  • 添加类
    我们需要实现一个从nav_core::BaseLocalPlanner继承的类, nav_core::BaseLocalPlanner接口类定义在这里base_local_planner.h#L50)可以看到

  • 修改编译
    修改CMakeLists.txt,添加相关编译参数和选项

  • 添加bgp_plugin.xml文件
    指定导出的类名称

<library path="lib/libsample_local_planner"><class name="sample_local_planner/LocalPlanner" type="sample_local_planner::LocalPlanner" base_class_type="nav_core::BaseLocalPlanner"><description>A sample implementation of a grid local planner </description></class>
</library>

目录结构这样

❯ tree sample_local_planner
sample_local_planner
├── bgp_plugin.xml
├── CMakeLists.txt
├── include
│   └── sample_local_planner
│       └── planner_node.h
├── package.xml
└── src└── planner_node.cpp
  • 导出类
    参考navigation里面, 添加宏导出该类
PLUGINLIB_EXPORT_CLASS(sample_local_planner::LocalPlanner, nav_core::BaseLocalPlanner)

2. 接口实现

2.1 接口

base_local_planner.h#L50)可以看到接口类

namespace nav_core {class BaseLocalPlanner{public:virtual bool computeVelocityCommands(geometry_msgs::Twist& cmd_vel) = 0;virtual bool isGoalReached() = 0;virtual bool setPlan(const std::vector<geometry_msgs::PoseStamped>& plan) = 0;virtual void initialize(std::string name, tf2_ros::Buffer* tf, costmap_2d::Costmap2DROS* costmap_ros) = 0;};
};  // namespace nav_core

通过命名大概就知道其定义,

  • initialize
    初始化接口,给我们传相关功能接口的,如tfcostmap
  • setPlan
    规划控制接口,给我们提供一个plan,这个应该是global planner的输出,通过move_base转了一手给到我们,后面可以看下move_base源码
  • computeVelocityCommands
    计算速度,传入的参数是一个引用,应该是输出函数,我们把计算好的速度填进去就可以
  • isGoalReached
    获取是否以及到达目标点

2.2 不同ros版本接口差异

BaseLocalPlannerros kinetic 中的initialize接口稍有差异 见base_local_planner.h#L78


// kinetic
virtual void initialize(std::string name, tf::TransformListener* tf, costmap_2d::Costmap2DROS* costmap_ros) = 0;// melodic&noetic
virtual void initialize(std::string name, tf2_ros::Buffer* tf, costmap_2d::Costmap2DROS* costmap_ros) = 0;

后面我们以melodic&noetic实现

2.3 实现

主要代码如下,stopwatch_为计时器,我们在setPlan调用后,设置变量,computeVelocityCommands接口中设置固定的速度,在时间到达后,输出0,同时isGoalReached接口返回true

void LocalPlanner::initialize(std::string name, tf::TransformListener *tf,costmap_2d::Costmap2DROS *costmap_ros){ROS_INFO("LocalPlanner initialize");}bool LocalPlanner::computeVelocityCommands(geometry_msgs::Twist &cmd_vel){ROS_INFO("LocalPlanner computeVelocityCommands");if (start_flag_) {cmd_vel.linear.x = 0.2;cmd_vel.linear.y = 0;cmd_vel.angular.z = 0.8;} else {cmd_vel.linear.x = 0;cmd_vel.linear.y = 0;cmd_vel.angular.z = 0;}return true;}bool LocalPlanner::setPlan(const std::vector<geometry_msgs::PoseStamped> &orig_global_plan){ROS_INFO("LocalPlanner setPlan");if (!start_flag_) {start_flag_ = true;stopwatch_.reset();}return true;}bool LocalPlanner::isGoalReached(){if (stopwatch_.elapsed(std::chrono::seconds(2))){ROS_INFO("LocalPlanner GoalReached");return true;}return false;}

通过查看move_base源码,上面几个接口是在同一个线程被调用,所有后续不需要考虑资源竞争,即变量无需加锁

3. 测试

3.1 编译

cd ~/pibot_ros/ros_ws
catkin_make

3.2 测试

修改~/pibot_ros/src/pibot_simulator/move_base_params.yaml

# base_local_planner: "dwa_local_planner/DWAPlannerROS"
base_local_planner: sample_local_planner/LocalPlanner

dwa_local_planner/DWAPlannerROS ----> sample_local_planner/LocalPlanner

  • 启动模拟器
pibot_simulator
  • 查看当前的local_planner
❯ rosparam get /move_base/base_local_planner
sample_local_planner/LocalPlanner  # 输出sample_local_planner/LocalPlanner表示插件已经被正确加载
  • 启动rviz发送点位,选点导航测试
pibot_view

3.3 测试结果

[ INFO] [1676647988.863610652]: make plan start:[0.000000 0.000000], goal:[-2.986773 4.282055]
[ INFO] [1676647989.063781836]: LocalPlanner setPlan
[ INFO] [1676647989.064015702]: LocalPlanner computeVelocityCommands
[ INFO] [1676647989.263707871]: LocalPlanner computeVelocityCommands
[ INFO] [1676647989.463771479]: LocalPlanner computeVelocityCommands
[ INFO] [1676647989.663754028]: LocalPlanner computeVelocityCommands
[ INFO] [1676647989.863583610]: LocalPlanner computeVelocityCommands
[ INFO] [1676647989.864067517]: make plan start:[0.000000 0.000000], goal:[-2.986773 4.282055]
[ INFO] [1676647990.063701815]: LocalPlanner setPlan
[ INFO] [1676647990.063874092]: LocalPlanner computeVelocityCommands
[ INFO] [1676647990.263710418]: LocalPlanner computeVelocityCommands
[ INFO] [1676647990.463773749]: LocalPlanner computeVelocityCommands
[ INFO] [1676647990.663630163]: LocalPlanner computeVelocityCommands
[ INFO] [1676647990.863635728]: LocalPlanner computeVelocityCommands
[ INFO] [1676647990.864087581]: make plan start:[0.000000 0.000000], goal:[-2.986773 4.282055]
[ INFO] [1676647991.063713670]: LocalPlanner setPlan
[ INFO] [1676647991.063894899]: LocalPlanner computeVelocityCommands
[ INFO] [1676647991.263639509]: LocalPlanner GoalReached

通过日志可以看出

  • 在全局规划(make plan start是我们前面文章新增的astar planner输出)后LocalPlanner的接口setPlan被调用
  • computeVelocityCommands函数没0.2s被调用一次, 期间机器人也在做圆周运动
  • 全局规划再次被调用(move_bsae里配置了规划频率1hz,这里可以看到间隔1s全局规划一次),重复前面的
  • 直到超时GoalReached返回true完成

4. 总结

本文简单实现了一个local planner的插件,显然实际没啥用,不过可以作为一个模板,基于该模板实现自己的算法。后面我们将基于该模板实现可用的局部规划控制。

本文代码见sample_local_planner

相关文章:

48.在ROS中实现local planner(1)- 实现一个可以用的模板

有了之前45.在ROS中实现global planner&#xff08;1&#xff09;- 实现一个可以用模板的global planner的经验, 现在再去创建一个local planner的包就容易多了 1. 创建包 创建 cd ~/pibot_ros/ros_ws/src # 这里可以使用自己的ros workspace catkin_create_pkg sample_loc…...

jenkins基础部署

一、jenkins是什么1.Jenkins的前身是Hudson&#xff0c;采用JAVA编写的持续集成开源工具。Hudson由Sun公司在2004年启动&#xff0c;第一个版本于2005年在java.net发布。2007年开始Hudson逐渐取代CruiseControl和其他的开源构建工具的江湖地位。在2008年的JavaOne大会上在开发者…...

Unity3D -知识点(1)

1.场景视图鼠标滚轮&#xff1a;场景放大缩小鼠标右键&#xff1a;场景左右平移场景编辑器中&#xff0c;能看到什么&#xff1f;网格&#xff0c;每一格大小为1unit&#xff0c;建模不同&#xff0c;规定不同&#xff0c;(对应屏幕上100个像素)世界坐标系y轴向上为正x轴向右为…...

【学习笔记】NOIP暴零赛3

博弈(game) 观察到博弈过程中胜负态不会发生改变&#xff0c;那么求出从每个棋子出发能走的最长链&#xff0c;然后背包即可。 复杂度O(nm)O(nm)O(nm)。 #include<bits/stdc.h> #define ll long long #define pb push_back using namespace std; const int mod9982443…...

Java JSR规范列表

Java JSR规范列表目录概述需求&#xff1a;设计思路实现思路分析1.JSR2.JSR方法3.web service4.Webservice:5.数据处理器拓展实现参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,m…...

Java必备小知识点1

Java程序类型: Applications和AppletApplications:是指在计算机操作系统中运行的程序。是完整的程序&#xff0c;能独立运行。被编译后&#xff0c;用普通的Java解释器就可以使其边解释边执行。必定含有一个main方法&#xff0c;程序执行时&#xff0c;首先寻找main方法&#x…...

JavaScript作用域、闭包

文章目录作用域、作用域链作用域作用域链循环中的作用域自由变量、闭包自由变量闭包的定义、表现、应用如何确定在闭包中获取正确的变量总结作用域、作用域链 作用域 编程语言中存储、访问、修改变量当中的值是一项基本能力、存储变量、访问变量必须按照一定的规则&#xff0…...

JavaScript Date(日期) 对象

JavaScript Date 对象是 JavaScript 中用于处理日期和时间的内置对象。它可以用于获取当前时间、设置日期和时间、计算日期和时间之间的差异、以及将日期和时间格式化为各种字符串格式。在本文中&#xff0c;我们将详细介绍 JavaScript Date 对象的作用和在实际工作中的用途。 …...

rust过程宏 proc-macro-workshop解题-4-sorted

名字版本号rust1.69.0OSubuntu 22.04这一大关卡介绍的是属性式过程宏。 第一关:01-parse-enum 还是简单的看我们是否已经实现了一个属性式过程宏的空架子,如果有这个空架子,就直接通过了。 use proc_macro::TokenStream; use proc_macro2; use syn;#[proc_macro_attribut…...

数据结构与算法—队列

队列 队列介绍 有序列表&#xff0c;可以用数组或者链表实现。遵循先进先出原则。 数组实现队列 public class ArrayQueue {public static void main(String[] args) {ArrayQueue queue new ArrayQueue(3);// 接收用户输入char key ;Scanner sc new Scanner(System.in);…...

AcWing3416.时间显示——学习笔记

目录 题目 代码 AC结果 思路 关键步骤 题目 3416. 时间显示 - AcWing题库https://www.acwing.com/problem/content/description/3419/ 代码 import java.util.Scanner;public class Main {public static void main(String[] args){Scanner input new Scanner(System.in…...

贴吧手机端防删图GIF动态图制作解析

贴吧存活 思路技术运气 1&#xff1a;防删图不是存活的绝对因素&#xff0c;除了防删图&#xff0c;还有账号&#xff0c;ip&#xff0c;内容&#xff0c;吧的问题 2&#xff1a;一个图不是每个吧都可以发 3&#xff1a;一个贴不被删不仅仅看图片 4&#xff1a;有时候运气也很…...

iOS接入Google登录

1.在Google Cloud后台配置客户端ID 首先要在 Google Cloud 中创建一个项目。新创建的Project需要先配置同意屏幕。一共有4步骤需要配置。 1.OAuth 同意屏幕 User Type选择"外部"进行创建。填写必必要的信息&#xff0c;应用名称、用户支持电子邮件地址、开发者电子邮…...

【C语言】大小端字节序问题

一、大小端字节序问题 大小端是由CPU决定的&#xff0c;大小端可以理解为字节顺序&#xff0c;所以大小端全称叫大端字节序、小端字节序。其实大端、小端这两个词是从《格列佛游记》里出来的。《格列佛游记》有一段讲的是吃鸡蛋是从大的那头敲开还是小的那头敲开的问题&#xf…...

Linux | 网络通信 | 序列化和反序列化的讲解与实现

文章目录为什么要序列化&#xff1f;协议的实现服务端与客户端代码实现为什么要序列化&#xff1f; 由于默认对齐数的不同&#xff0c;不同的平台对相同数据进行内存对齐后&#xff0c;可能得到不同的数据。如果直接将这些数据进行网络传输&#xff0c;对方很可能无法正确的获…...

C#的委托原理刨析and事件原理刨析和两者的比较

什么是委托委托是一种引用类型&#xff0c;表示对具有特定参数列表和返回类型的方法的引用。 在实例化委托时&#xff0c;你可以将其实例与任何具有兼容参数和返回类型的方法进行绑定。 你可以通过委托实例调用方法。简单的理解&#xff0c;委托是方法的抽象类&#xff0c;它定…...

Redis学习【8】之Redis RDB持久化

文章目录Redis 持久化1 持久化基本原理2 RDB(Redis DataBase) 持久化2.1 持久化的执行2.2 手动 save 命令2.3 手动 bgsave 命令2.4 自动条件触发2.5 查看持久化时间3 RDB 优化配置3.1 save3.2 stop-write-on-bgsave-error3.3 rdbcompression3.4 rdbchecksum3.5 sanitize-dump-p…...

SpringSecurity认证

文章目录登陆校验流程依赖yaml实现建表、工具类、实体类加密器、AuthenticationManager登录逻辑登录过滤器、配置过滤器登出登陆校验流程 认证 登录&#xff1a; ​ ①自定义登录接口 ​ 调用ProviderManager的方法进行认证 如果认证通过生成token&#xff0c;根据userId把用…...

Socket套接字

概念 Socket套接字&#xff0c;是由系统提供用于网络通信的技术&#xff0c;是基于TCP/IP协议的网络通信的基本操作单元。基于Socket套接字的网络程序开发就是网络编程。 分类 Socket套接字主要针对传输层协议划分为如下三类&#xff1a; 流套接字&#xff1a;使用传输层TCP…...

mysql详解之innoDB

索引 Mysql由索引组织&#xff0c;所以索引是mysql多重要概念之一。 聚簇索引 InnoDB和MyISAm一样都是采用B树结构&#xff0c;但不同点在于InnoDB是聚簇索引&#xff08;或聚集索引&#xff09;&#xff0c;将数据行直接放在叶子节点后面。 这里可能存在一个误区&#xff1…...

电信运营商的新尝试:探索非通信领域的发展

近年来&#xff0c;随着电信运营商竞争的日趋激烈和网络建设的成本不断攀升&#xff0c;许多电信运营商已经开始缩减IT投资。然而&#xff0c;在如此情况下&#xff0c;电信运营商仍然需要寻找新的增长机会。那么&#xff0c;在持续缩减IT投资的情况下&#xff0c;电信运营商可…...

第07章_单行函数

第07章_单行函数 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 1. 函数的理解 1.1 什么是函数 函数在计算机语言的使用中贯穿始终&#xff0c;函数的作用是什么呢&#xff1f;它可以把我们经…...

Echarts实现多柱状图重叠重叠效果

有两种重叠效果: 1. 多个柱子重叠为一个 2. 多个柱子重叠为两组 第一种,图例: 这个灰色不是阴影哦, 是柱子. 1. 使用详解 (1) series.Z 折线图组件的所有图形的 z 值。控制图形的前后顺序。 z 值小的图形会被 z 值大的图形覆盖。z 相比 zlevel 优先级更低&#xff0c;而且不会…...

PHP学习笔记(一谦四益)

前言 上一篇文章 PHP学习笔记&#xff08;观隅反三&#xff09;分享了数组的知识&#xff0c;这篇文章接着分享和数组相关的算法。 算法效率 算法效率分为两种&#xff1a;第一种是时间效率&#xff0c;第二种是空间效率。时间效率被称为时间复杂度&#xff0c;而空间效率被称…...

Jvm -堆对象的划分

堆对于一个jvm进程来说是唯一的&#xff0c;一个进程只有一个jvm&#xff0c;但是进程半酣多个线程&#xff0c;多个线程共享一个堆。 也就是说&#xff0c;一个jvm实例只存在一个堆&#xff0c;同时对也是Java内存管理的核心区域。 Java堆区域的大小在jvm启动时就已经被确定…...

2023美赛F题讲解+数据领取

我们给大家准备了F题的数据&#xff0c;免费领取&#xff01;在文末 国内生产总值(GDP)可以说是一个国家经济健康状况最著名和最常用的指标之--。它通常用于确定一个国家的购买力和获得贷款的机会,为各国提出提高GDP的政策和项目提供动力。GDP“衡量一个国家在给定时间段内生产…...

【博客625】keepalived开启garp refresh的重要性

keepalived开启garp refresh的重要性 1、场景 1-1、对keepavlied master机器热迁移后出现vip不通&#xff0c;过后恢复 原因&#xff1a;机器迁移后网关那边的arp表没有刷新&#xff0c;流量还是转发到老的端口&#xff0c;但是机器已经迁移到别的端口了&#xff0c;于是网络…...

nginx防护规则,拦截非法字符,防止SQL注入、防XSS,nginx过滤url访问,屏蔽垃圾蜘蛛,WordPress安全代码篇

nginx防护规则,拦截非法字符,防止SQL注入、防XSS,nginx过滤url访问,屏蔽垃圾蜘蛛,WordPress安全代码篇 精心强化,小白一键复制 资源宝分享:www.httple.net 宝塔为例:/www/server/panel/vhost/nginx/你的网站域名.conf,复制代码点击保存 修改www.xx.net你自己域名incl…...

【计算机网络】网络层

文章目录网络层概述网络层提供的两种服务IPv4地址IPv4地址概述分类编址的IPv4地址划分子网的IPv4地址无分类编址的IPv4地址IPv4地址的应用规划IP数据报的发送和转发过程静态路由配置及其可能产生的路由环路问题路由选择路由选择协议概述路由信息协议RIP的基本工作原理开放最短路…...

产品经理知识体系:1.什么是互联网思维?

互联网思维 思考 笔记 用户思维 是要注重用户体验&#xff0c;产品带给用户的价值是什么&#xff0c;是能帮助用户获取想要的商品、解决生活中的问题、获取想要的信息&#xff0c;还是产品能通过兜售参与感、满足感等来满足用户的心理需求。 贯穿产品的整个生命周期过程。 简…...

网站建设的流程图示/淘宝站外引流推广方法

重构学习笔记1. 封装集合                                                    概念&#xff1a;本文所讲的封装集合就是把集合进行封装&#xff0c;只提供调用端需要的接口。 正文&#xff1a;在很多时候&#xff0c;我们…...

网站建设包括哪些方面/推广之家

适合计算机专业毕业生参考的英文范文。Dear Sir or Madam,Having read your internship position ad from qzzjx.cn, I decide to send you my resume because I know I will learn from you as well as bring values to your company.I am going to graduate at June this yea…...

自己的网站 做采集怎么做/百度推广在线客服

2019独角兽企业重金招聘Python工程师标准>>> 优先队列 出队顺序与入队顺序无关&#xff0c; 和优先级有关 对于总共N个请求&#xff0c;使用普通数组或顺序数组&#xff0c; 最差N^2, 使用堆&#xff1a;NLogN 二叉堆 孩子节点不大于它的父亲节点&#xff08;最大堆…...

个人网站如何在工信部备案/百度推广业务员电话

某站后端代码被“开源”&#xff0c;同时刷遍全网的&#xff0c;还有代码里的那些神注释。 我们这才知道&#xff0c;原来程序员个个都是段子手&#xff1b;这么多年来&#xff0c;我们也走过了他们的无数套路… 首先&#xff0c;产品经理&#xff0c;是永远永远吐槽不完的&a…...

wordpress语言设置/企业优化推广

好久没技术,但手痒,写数学也行吧...试试... 市场上有很多好的教材,这里只为自己记忆,做笔记而用,无他.很多资料可能也是转载的,帮助自己消化,也便于以后自己参考 一.随机试验和随机事件 如果一个试验在相同条件下可以重复进行&#xff0c;而每次试验的可能结果不止一个&#xf…...

阿里云网站公安备案系统/挖掘关键词的工具

文章目录vmplayer介绍1.下载和安装2.下载虚拟机镜像3.创建新的虚拟机创建虚拟机运行附件vmplayer介绍 VMware Player &#xff08;现已更名为VMware Workstation Player&#xff09;是一款桌面虚拟化应用&#xff0c;无需重新启动即可在同一计算机上运行一个或多个操作系统。凭…...