ObtacleCostFunction
定义了一个ObstacleCostFunction类,继承自Trajectory类,Trajectory类有8个类参
总共有8个类参
double xv_,yv_,thetav_ 这三分别是用于生成轨迹的x,y,角速度
double cost_ 轨迹得分
double time_delta_ 轨迹点之间的时间间隔
std::vector<double> x_pts_,y_pts_,theta_pts_,轨迹上的x,y角度点集
它的类参是
costmap_2d::Costmap2D* costmap_;
std::vector<geometry_msgs::Point> footprint_spec_; //geometry_msgs::Point如果单就point,就x,y,z三个值
base_local_planner::WorldModel* world_model_;
double max_trans_vel_;
bool sum_scores_;
double max_scaling_factor_, scaling_speed_;
这个类的主要作用是如果机器人足迹在轨迹的任意点上遇到障碍物的话,就用costmap 2d去分配负的代价值。
下面是几个函数
1.ObstacleCostFunction(costmap_2d::Costmap2D* costmap);
这个构造函数直接把costmap赋值给类参 costmap_,都是指针,另外把false赋值给sum_score_,所以默认是返回轨迹最后一个点的足迹变换
后的代价值。
如果costmap_不为空的话,直接把costmap变一变赋值给类参world_model_
world_model_ = new base_local_planner::CostmapModel(*costmap_);
2.~ObstacleCostFunction();
这个是用来删除world_model_的,当world_model_不为空的时候,直接删除它。也是指针
3. bool prepare();
直接返回true.
4.void setParams(double max_trans_vel, double max_scaling_factor, double scaling_speed);
直接把里面的三个值依次赋值给类参max_trans_vel_,max_scaling_factor_,scaling_speed_
5.void setFootprint(std::vector<geometry_msgs::Point> footprint_spec);
直接把里面值赋值给类参footprint_spec_.
6. static double footprintCost(
const double& x,
const double& y,
const double& th,
double scale,
std::vector<geometry_msgs::Point> footprint_spec,
costmap_2d::Costmap2D* costmap,
base_local_planner::WorldModel* world_model);
这个函数用来得footprintCost的,先调用WorldModel类里面的footprintCost函数,用x,y,th把footprint_spec变成世界坐标下坐标,还得到原点在世界坐标系坐标,内切半径,外切半径。根据这些,调用CostmapModel类里的footprintCost函数,转换到costmap坐标系下,用光栅化算法得到栅格点,由栅格点的代价值得到足迹点线段的代价值,再得到整个足迹点集的代价值就可以了。
7.static double getScalingFactor(Trajectory &traj, double scaling_speed, double max_trans_vel, double max_scaling_factor);
这个函数是用来得到scale的,它是根据traj的x,y速度值得到它们的平方和的根,然后和scaling_speed比较,如果小于的话,根据
max_trans_vel得到ratio,用ratio修改max_scaling_factor得到scale
8. void setSumScores(bool score_sums){ sum_scores_=score_sums; }
这个直接用变量值设置sum_scores_的值。
9. double scoreTrajectory(Trajectory &traj);
这个会先根据类参算得scale,然后判断类参footprint_spec_,如果足迹为空,返回-9.
否则算足迹点集在经过轨迹点变换之后的footprintCost设为f_cost,如果f_cost小于0,得分就是f_cost,如果不小于0,就根据
sum_score_是否为true,选择返回f_cost的和还是最后一个f_cost.
具体实现:
#include <base_local_planner/obstacle_cost_function.h>
#include <cmath>
#include <Eigen/Core>
#include <ros/console.h>
namespace base_local_planner {
ObstacleCostFunction::ObstacleCostFunction(costmap_2d::Costmap2D* costmap)
: costmap_(costmap), sum_scores_(false) {
if (costmap != NULL) {
world_model_ = new base_local_planner::CostmapModel(*costmap_);//CostmapModel也只有一个类参costmap_,
}
}
//这个析构函数用来删除world_model_的
ObstacleCostFunction::~ObstacleCostFunction() {
if (world_model_ != NULL) {
delete world_model_;
}
}
//设置参数里依次把变量值赋值给障碍代价函数类里的max_trans_vel_,max_scaling_factor_,scaling_speed_
void ObstacleCostFunction::setParams(double max_trans_vel, double max_scaling_factor, double scaling_speed) {
// TODO: move this to prepare if possible 如果可能的话,删除这些去prepare?
max_trans_vel_ = max_trans_vel;
max_scaling_factor_ = max_scaling_factor;
scaling_speed_ = scaling_speed;
}
//设置足迹是把变量值赋值给障碍代价函数类的footprint_spec_
void ObstacleCostFunction::setFootprint(std::vector<geometry_msgs::Point> footprint_spec) {
footprint_spec_ = footprint_spec;
}
//这个类的prepare函数直接返回true
bool ObstacleCostFunction::prepare() {
return true;
}
/*scoreTrajectory函数是用来给轨迹打分的,很多轨迹点组成一个轨迹,它是利用每个轨迹点把足迹点转换到世界坐标下坐标,再到costmap坐标系,然后得到足迹点
* 构成的各个栅格点的代价值,取这些代价值的最大值,这个得分是根据这个代价值来的。
* 过程(1)用getScalingFactor(traj,scaling_speed_,max_trans_vel_,max_scaling_factor_)得到scale,这个是根据traj的x,y速度得到vmag,然后vmag跟scaling_speed_比,
* 如果小于的话,就修改max_scaling_factor为新的scale.但这个scale没有用啊。
* (2)判断footprin_spec_的大小,如果size为0,就发出警告,scoreTrajectory函数返回-9.
* (3) 如果footprint_spec_有点,那么造一个for循环,从0到轨迹点数,由traj.getPoint(i, px, py, pth);得到px,py,pth
* 由 double f_cost = footprintCost(px, py, pth,scale, footprint_spec_,costmap_, world_model_)得到代价值。这个函数首先调用WorldModel里的footprintCost函数
* ,然后调用类CostmapModel类的footprintCost函数,最后得到代价值。
* 如果f_cost小于0,函数返回f_cost;为-6.0,-7.0
* 如果ObstacleCostFunction类里的sum_score_为true,那么返回各个f_cost(它们大于等于0的话)的和,如果定义为false,返回最后一个cost
*/
double ObstacleCostFunction::scoreTrajectory(Trajectory &traj) {
double cost = 0;
double scale = getScalingFactor(traj, scaling_speed_, max_trans_vel_, max_scaling_factor_);
double px, py, pth;
if (footprint_spec_.size() == 0) {
// Bug, should never happen
ROS_ERROR("Footprint spec is empty, maybe missing call to setFootprint?");
return -9;
}
for (unsigned int i = 0; i < traj.getPointsSize(); ++i) {
traj.getPoint(i, px, py, pth);
double f_cost = footprintCost(px, py, pth,
scale, footprint_spec_,
costmap_, world_model_);
if(f_cost < 0){
return f_cost;
}
if(sum_scores_)
cost += f_cost;
else
cost = f_cost;
}
return cost;
}
/*getScalingFactor这个函数是用来得到scale的,scale是轨迹代价函数的类参。它是利用轨迹traj,scaling_speed,max_trans_vel,max_scaling_factor
* _factor得到的。
* (1)由轨迹traj的x,y速度得到vmag.vmag = hypot(traj.xv_, traj.yv_)
* 如果vmag大于scaleing_speed,那么令ratio为(vmag - scaling_speed) / (max_trans_vel - scaling_speed)
* scale就为max_scaling_factor * ratio + 1.0
*/
double ObstacleCostFunction::getScalingFactor(Trajectory &traj, double scaling_speed, double max_trans_vel, double max_scaling_factor) {
double vmag = hypot(traj.xv_, traj.yv_);
//if we're over a certain speed threshold, we'll scale the robot's
//footprint to make it either slow down or stay further from walls
double scale = 1.0;
if (vmag > scaling_speed) {
//scale up to the max scaling factor linearly... this could be changed later
double ratio = (vmag - scaling_speed) / (max_trans_vel - scaling_speed);
scale = max_scaling_factor * ratio + 1.0;
}
return scale;
}
/*footprintCost函数这里的变量是x,y,th,scale,footprint_spec,costmap,world_model,这里scale没有用到。
* (1)利用world_model的footprintCost函数得到足迹点的cost值,world_model->footprintCost(x, y, th, footprint_spec);它这里面首先调用WorldModel类的footprintCost
* 函数得到机器人在世界坐标系下原点坐标,足迹在世界坐标系下坐标,内切半径,外切半径,然后调用类CostmapModel类的footprintCost函数,把footprint_spec
* 转换成地图下坐标,如果有一次转换不成功,就返回false,如果都转换成功,就返回光栅化后的所有足迹点的最大代价值。
* 这里把得到的代价值记为footprint_cost,如果footprint_cost小于0,那么障碍代价函数类footprintCost函数返回-6.0
* (2)把x,y转成cell_x,cell_y如果转换不成功,返回-7.0,之前在类WorldModel里,如果转换不成功,是返回-1.0,这里是区分开了,更详细
* (3)如果footprint_cost不小于0,而且原点转换成功,那么返回值取footprint_cost,0.0,和原点代价值最大值
* 也就是说返回值3种情况-6.0,-7.0,footprint_cost,0.0,和原点代价值最大值
*/
double ObstacleCostFunction::footprintCost (
const double& x,
const double& y,
const double& th,
double scale,
std::vector<geometry_msgs::Point> footprint_spec,
costmap_2d::Costmap2D* costmap,
base_local_planner::WorldModel* world_model) {
//check if the footprint is legal
// TODO: Cache inscribed radius
double footprint_cost = world_model->footprintCost(x, y, th, footprint_spec);
if (footprint_cost < 0) {
return -6.0;
}/
unsigned int cell_x, cell_y;
//we won't allow trajectories that go off the map... shouldn't happen that often anyways
if ( ! costmap->worldToMap(x, y, cell_x, cell_y)) {
return -7.0;
}
double occ_cost = std::max(std::max(0.0, footprint_cost), double(costmap->getCost(cell_x, cell_y)));//occ_cost取footprint_cost,0.0,cell_x,cell_y处的代价值的最大值
return occ_cost;
}
} /* namespace base_local_planner */
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
- ABP源码分析二十二:Navigation
MenuDefinition:封装了导航栏上的主菜单的属性. MenuItemDefinition:封装了主菜单的子菜单的属性.子菜单可以引用其他子菜单构成一个菜单树 UserMenu/UserMen ...
- HashMap与TreeMap源码分析
1. 引言 在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...
- ABP源码分析二十四:Notification
NotificationDefinition: 用于封装Notification Definnition 的信息.注意和Notification 的区别,如果把Notification看成是具体的消息 ...
- ABP源码分析三十三:ABP.Web
ABP.Web模块并不复杂,主要完成ABP系统的初始化和一些基础功能的实现. AbpWebApplication : 继承自ASP.Net的HttpApplication类,主要完成下面三件事一,在A ...
- ABP源码分析三十四:ABP.Web.Mvc
ABP.Web.Mvc模块主要完成两个任务: 第一,通过自定义的AbpController抽象基类封装ABP核心模块中的功能,以便利的方式提供给我们创建controller使用. 第二,一些常见的基础 ...
- Orchard源码分析(1):Orchard架构
本文主要参考官方文档"How Orchard works"以及Orchardch上的翻译. 源码分析应该做到庖丁解牛,而不是以管窥豹或瞎子摸象.所以先对Orchard架构有 ...
- Bootstrap导航栏navbar源码分析
1.本文目地:分析bootstrap导航栏及其响应式的实现方式,提升自身css水平 先贴一个bootstrap的导航栏模板 http://v3.bootcss.com/examples/navbar- ...
- 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入
使用react全家桶制作博客后台管理系统 前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...
随机推荐
- js模拟自动化测试 -- 多用户登录
1.核心登录提交方法 /** * 动态表单提交方法 * @param url{string}: 提交地址 * @param params{object}: 要提交的表单数据 **/ function ...
- 通过编写串口助手工具学习MFC过程——(七)添加Tab Control控件
通过编写串口助手工具学习MFC过程 因为以前也做过几次MFC的编程,每次都是项目完成时,MFC基本操作清楚了,但是过好长时间不再接触MFC的项目,再次做MFC的项目时,又要从头开始熟悉.这次通过做一个 ...
- nginx运行出现 file not found 错误处理原因
在阿里云装nginx+php+mysql nginx运行出现 file not found 错误处理原因 1,第一情况 location ~ \.php$ { # root html; fastcgi ...
- P3198 [HNOI2008]遥远的行星
传送门 发现 $A$ 不大,又允许较大的误差,考虑乱搞 考虑求出每个位置的答案,因为有 $1e5$ 个位置,所以每个位置差不多可以计算 $100$ 次贡献 所以把每个可以贡献的位置尽量均匀分成 $10 ...
- 小程序之如和使用view内部组件来进行页面的排版功能
这篇文章主要介绍了关于小程序之如和使用view内部组件来进行页面的排版功能,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 涉及知识点: 1.垂直排列,水平排列 2.居中对齐 示例: 1 ...
- Android模拟器运行慢的解决方案
在android开发的过程,发现android模拟器的速度不是一般的慢,那主要是因为android模拟器默认采用的是arm处理器造成的,这里主要提供两种方法: ① 利用intel虚拟硬件加速的方式,实 ...
- 如何在github上部署自己的前端项目
很多时候我们想需要一个地址就可以访问自己的前端作品, 但是注册一个服务器和域名是需要花钱,很多小伙伴都不愿意, 其实这种前端静态页面github就可以帮我们预览其效果,而且只要在有网的情况下都可以访问 ...
- ElasticSearch - 解决ES的深分页问题 (游标 scroll)
https://www.jianshu.com/p/f4d322415d29 1.简介 ES为了避免深分页,不允许使用分页(from&size)查询10000条以后的数据,因此如果要查询第10 ...
- Taro -- Swiper的图片由小变大3d轮播效果
Swiper的图片由小变大3d轮播效果 this.state = ({ nowIdx:, swiperH:'', imgList:[ {img:'../../assets/12.jpg'}, {img ...
- Python chardet字符编码的判断
使用 chardet 可以很方便的实现字符串/文件的编码检测.尤其是中文网页,有的页面使用GBK/GB2312,有的使用UTF8,如果你需要去爬一些页面,知道网页编码很重要的,虽然HTML页面有cha ...