ROS Navigation Stack之dwa_local_planner源码分析

2024-04-27 01:58

本文主要是介绍ROS Navigation Stack之dwa_local_planner源码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

DWA和base_local_planner的关系

在base_local_planner包中有两个文件叫trajectory_planner.cpp 以及对应的ros实现,其和DWA是同一层的。
由于nav_core提供了统一的接口,因此我们可以先看看统一的接口有哪些,那我们便知道每一个算法里比较重要的函数有哪些。

nav_core包里的base_local_planner.h文件
//最为关键的地方,计算机器人下一刻的速度
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, tf::TransformListener* tf, costmap_2d::Costmap2DROS* costmap_ros) = 0;

下面我们就先看看base_local_planner的computeVelocityCommands的主要实现框架

bool TrajectoryPlannerROS::computeVelocityCommands(geometry_msgs::Twist& cmd_vel)
{//检查初始化、检查是否已经到达目标点...略transformGlobalPlan(*tf_, global_plan_, global_pose, *costmap_, global_frame_, transformed_plan);//如果已经到达目标点,姿态还没到if (xy_tolerance_latch_ || (getGoalPositionDistance(global_pose, goal_x, goal_y) <= xy_goal_tolerance_)) {tc_->updatePlan(transformed_plan);//所以这个函数里最关键的子函数是findBestPathTrajectory path = tc_->findBestPath(global_pose, robot_vel, drive_cmds);return true;}tc_->updatePlan(transformed_plan);Trajectory path = tc_->findBestPath(global_pose, robot_vel, drive_cmds);//然后又是转换,然后就发布出速度了...
}

接下来我们看一下TrajectoryPlanner的findBestPath的实现框架,Come on~

Trajectory TrajectoryPlanner::findBestPath(tf::Stamped<tf::Pose> global_pose, tf::Stamped<tf::Pose> global_vel,tf::Stamped<tf::Pose>& drive_velocities)
{//...Trajectory best = createTrajectories(pos[0], pos[1], pos[2], vel[0], vel[1], vel[2],acc_lim_x_, acc_lim_y_, acc_lim_theta_);//...
}

顺藤摸瓜,一睹createTrajectories的内部实现,这个函数是轨迹采样算法,可以说是一个非常关键的函数。

Trajectory TrajectoryPlanner::createTrajectories(double x, double y, double theta,double vx, double vy, double vtheta,double acc_x, double acc_y, double acc_theta) 
{//检查最终点是否是有效的,判断变量在updatePlan中被赋值if( final_goal_position_valid_ ){double final_goal_dist = hypot( final_goal_x_ - x, final_goal_y_ - y );max_vel_x = min( max_vel_x, final_goal_dist / sim_time_ );}//是否使用dwa算法, sim_peroid_是1/controller_frequency_,暂时不清楚sim_period_和sim_time_的区别if (dwa_){max_vel_x = max(min(max_vel_x, vx + acc_x * sim_period_), min_vel_x_);min_vel_x = max(min_vel_x_, vx - acc_x * sim_period_);max_vel_theta = min(max_vel_th_, vtheta + acc_theta * sim_period_);min_vel_theta = max(min_vel_th_, vtheta - acc_theta * sim_period_);}else{max_vel_x = max(min(max_vel_x, vx + acc_x * sim_time_), min_vel_x_);min_vel_x = max(min_vel_x_, vx - acc_x * sim_time_);max_vel_theta = min(max_vel_th_, vtheta + acc_theta * sim_time_);min_vel_theta = max(min_vel_th_, vtheta - acc_theta * sim_time_);}//...先忽略其中的逻辑,只要知道按照不同的规则生成路径,调用的子函数是generateTrajectory
}

这个子函数的作用就是生成路径,并且评分

void TrajectoryPlanner::generateTrajectory
{//主要有两大作用://生成路径和速度vx_i = computeNewVelocity(vx_samp, vx_i, acc_x, dt);vy_i = computeNewVelocity(vy_samp, vy_i, acc_y, dt);vtheta_i = computeNewVelocity(vtheta_samp, vtheta_i, acc_theta, dt);//计算位置x_i = computeNewXPosition(x_i, vx_i, vy_i, theta_i, dt);y_i = computeNewYPosition(y_i, vx_i, vy_i, theta_i, dt);theta_i = computeNewThetaPosition(theta_i, vtheta_i, dt);//对路径进行评分if (!heading_scoring_) {//cost = pdist_scale_ * path_dist + goal_dist * gdist_scale_ + occdist_scale_ * occ_cost;} else {cost = occdist_scale_ * occ_cost + pdist_scale_ * path_dist + 0.3 * heading_diff + goal_dist * gdist_scale_;}//这里的顺序与源码不同,我觉得总分来看更有组织性//该轨迹与全局路径的相对距离path_dist = path_map_(cell_x, cell_y).target_dist;//距离目标点距离goal_dist = goal_map_(cell_x, cell_y).target_dist;//离障碍物距离double footprint_cost = footprintCost(x_i, y_i, theta_i);occ_cost = std::max(std::max(occ_cost, footprint_cost), double(costmap_.getCost(cell_x, cell_y)));
}

综上所述,其整一个逻辑顺序就是computeVelocityCommands->findBestTrajectory --> createTrajectories --> generateTrajectory

最终,选择分数最低的轨迹,发布出去。这便是整个局部规划器的实现思路和逻辑。下一篇,谈谈Costmap2D。

这篇关于ROS Navigation Stack之dwa_local_planner源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/939236

相关文章

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

C++——stack、queue的实现及deque的介绍

目录 1.stack与queue的实现 1.1stack的实现  1.2 queue的实现 2.重温vector、list、stack、queue的介绍 2.1 STL标准库中stack和queue的底层结构  3.deque的简单介绍 3.1为什么选择deque作为stack和queue的底层默认容器  3.2 STL中对stack与queue的模拟实现 ①stack模拟实现

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud