【Autoware】Open Planner代码分析

news2024/11/23 18:40:13

目录

    • 包结构
    • op_global_planner
      • op_global_planner_core.cpp中代码的主要逻辑
    • op_local_planner
      • op_trajectory_generator
      • op_behavior_selector
      • op_common_params
      • op_motion_predictor
      • op_trajectory_evaluator

本篇主要对Open Planner的代码进行分析,主要包括op_global_planner和op_local_planner两个package。
在阅读本文时,应先参照前面两篇关于Autoware即Open Planner的文章。如下列所示:
【Autoware】Autoware人机交互工具Runtime_Manager分析及使用教程

【论文阅读】Open Source Integrated Planner for Autonomous Navigation in Highly Dynamic Environments

【Autoware】OpenPlanner使用教程–从RuntimeManager面板

通过上述文章,能够使用runtime manager并在上面运行open planner的程序,且对相关的原理有一定的理解。建议结合论文一起看。
然后再阅读本文,如果只想看源码结构,也可以不看前面的。

包结构

Open Planner包含四个包,op_global_planner、op_local_planner、op_simulation_package、op_utilities。

  • op_global_planner包含一个node,名称也是op_global_planner。
  • op_local_planner包含的node多一些,有五个,分别是op_behavior_selector,op_common_params,op_motion_predictor,op_trajectory_evaluator,op_trajectory_generator,每个node对应一个launch文件,在同一个包的对应文件夹下。
  • op_simulation_package包含三个node,分别是op_car_simulator、op_perception_simulator、op_signs_simulator。
  • op_utilities包含三个node,op_bag_player、op_data_logger、op_pose2tf。
    基本上每一个node都有一个对应的和node同名的主文件和一个core cpp文件。

实际上这里就对应了Runtime Manager面板中复选框可以选择的内容,除了op_data_logger包之外。意味着每在runtime_manager中选择一个package的复选框,即为启动该package,效用等同于运行

$ roslaunch <package_name> <launch_file> # 这是roslaunch的语法

比如Computing Tab页中,可以在对应的computing.yaml配置文件中可以看到如下描述

- name : OpenPlanner - Local planning
      desc : Local Planner for OpenPlanner
      subs :
      - name : op_common_params
        desc : load common local planning parameters
        cmd  : roslaunch op_local_planner op_common_params.launch
        param: op_common_params
        gui  :
          dialog_width  : 600
          dialog_height : 550

op_common_params对应的cmd就是roslaunch op_local_planner op_common_params.launch

在这里插入图片描述

op_global_planner

输入输出在ROS中主要以topic的方式进行,op_global_planner订阅和发布的topic分别是:
构造函数中订阅:

sub_start_pose = nh.subscribe("/initialpose", 1, &GlobalPlanner::callbackGetStartPose, this);
sub_goal_pose = nh.subscribe("move_base_simple/goal", 1, &GlobalPlanner::callbackGetGoalPose, this);
sub_current_pose = nh.subscribe("/current_pose", 10, &GlobalPlanner::callbackGetCurrentPose, this);
// 下面三个是if-else关系,三选一
sub_robot_odom = nh.subscribe("/odom", 10,  &TrajectoryGen::callbackGetRobotOdom, this);
sub_current_velocity = nh.subscribe("/current_velocity", 10, &TrajectoryGen::callbackGetVehicleStatus, this);
sub_can_info = nh.subscribe("/can_info", 10, &TrajectoryGen::callbackGetCANInfo, this);
//Mapping Section
sub_lanes = nh.subscribe("/vector_map_info/lane", 1, &BehaviorGen::callbackGetVMLanes,  this);
sub_points = nh.subscribe("/vector_map_info/point", 1, &BehaviorGen::callbackGetVMPoints,  this);
sub_dt_lanes = nh.subscribe("/vector_map_info/dtlane", 1, &BehaviorGen::callbackGetVMdtLanes,  this);
sub_intersect = nh.subscribe("/vector_map_info/cross_road", 1, &BehaviorGen::callbackGetVMIntersections,  this);
sup_area = nh.subscribe("/vector_map_info/area", 1, &BehaviorGen::callbackGetVMAreas,  this);
sub_lines = nh.subscribe("/vector_map_info/line", 1, &BehaviorGen::callbackGetVMLines,  this);
sub_stop_line = nh.subscribe("/vector_map_info/stop_line", 1, &BehaviorGen::callbackGetVMStopLines,  this);
sub_signals = nh.subscribe("/vector_map_info/signal", 1, &BehaviorGen::callbackGetVMSignal,  this);
sub_vectors = nh.subscribe("/vector_map_info/vector", 1, &BehaviorGen::callbackGetVMVectors,  this);
sub_curbs = nh.subscribe("/vector_map_info/curb", 1, &BehaviorGen::callbackGetVMCurbs,  this);
sub_edges = nh.subscribe("/vector_map_info/road_edge", 1, &BehaviorGen::callbackGetVMRoadEdges,  this);
sub_way_areas = nh.subscribe("/vector_map_info/way_area", 1, &BehaviorGen::callbackGetVMWayAreas,  this);
sub_cross_walk = nh.subscribe("/vector_map_info/cross_walk", 1, &BehaviorGen::callbackGetVMCrossWalks,  this);
sub_nodes = nh.subscribe("/vector_map_info/node", 1, &BehaviorGen::callbackGetVMNodes,  this);

发布的topic包括:

pub_Paths = nh.advertise<autoware_msgs::LaneArray>("lane_waypoints_array", 1, true);
pub_PathsRviz = nh.advertise<visualization_msgs::MarkerArray>("global_waypoints_rviz", 1, true);
pub_MapRviz  = nh.advertise<visualization_msgs::MarkerArray>("vector_map_center_lines_rviz", 1, true);
pub_GoalsListRviz = nh.advertise<visualization_msgs::MarkerArray>("op_destinations_rviz", 1, true);

左侧是c++中定义的变量名,存储数据,右侧为topic的名称,可以在rviz中添加显示。
其中nh为nodehandle句柄。advertise函数是ros中定义的用来BasePublisher类下面的发布function。

op_global_planner_core.cpp中代码的主要逻辑

主要的业务逻辑在MainLoop()函数中,

  1. 支持三种地图格式,分别为MAP_KML_FILE,MAP_FOLDER,MAP_AUTOWARE
    这几个参数是从launch配置文件中读取的,其代表的含义分别为kml格式的google地图文件,地图文件夹中的文件,autoware自定义格式的文件。

  2. 生成全局路径的函数为GenerateGlobalPlan,调用方法为

bool bNewPlan = GenerateGlobalPlan(m_CurrentPose, goalPoint, m_GeneratedTotalPaths);

生成的路径存储在m_GeneratedTotalPaths参数中,然后调用VisualizeAndSend()将数据可视化,发布到对应的topic中以使其在rviz中显示

pub_GoalsListRviz.publish(goals_array);

其中goals_array变量的类型为visualization_msgs::MarkerArray goals_array;
m_GeneratedTotalPaths的变量类型如下,定义在op_global_planner_core.h文件中,属于protected类型的变量

std::vector<std::vector<PlannerHNS::WayPoint> > m_GeneratedTotalPaths;

op_local_planner

分别有5个node,每个node之间的流程如下图所示:

op_trajectory_generator

主要的业务逻辑依然是在MainLoop函数里面

  1. 订阅的topic包括
sub_initialpose = nh.subscribe("/initialpose", 1, &TrajectoryGen::callbackGetInitPose, this);
sub_current_pose = nh.subscribe("/current_pose", 10, &TrajectoryGen::callbackGetCurrentPose, this);
sub_GlobalPlannerPaths = nh.subscribe("/lane_waypoints_array", 1, &TrajectoryGen::callbackGetGlobalPlannerPath, this);//global_planner输出的topic
//依然的三选一,默认值是current_velocity
"/odom";"/current_velocity";"/can_info"
  1. 生成rollOuts的方法
std::vector<PlannerHNS::WayPoint> sampledPoints_debug;
      m_Planner.GenerateRunoffTrajectory(m_GlobalPathSections, m_CurrentPos,
                m_PlanningParams.enableLaneChange,
                m_VehicleStatus.speed,
                m_PlanningParams.microPlanDistance,
                m_PlanningParams.maxSpeed,
                m_PlanningParams.minSpeed,
                m_PlanningParams.carTipMargin,
                m_PlanningParams.rollInMargin,
                m_PlanningParams.rollInSpeedFactor,
                m_PlanningParams.pathDensity,
                m_PlanningParams.rollOutDensity,
                m_PlanningParams.rollOutNumber,
                m_PlanningParams.smoothingDataWeight,
                m_PlanningParams.smoothingSmoothWeight,
                m_PlanningParams.smoothingToleranceError,
                m_PlanningParams.speedProfileFactor,
                m_PlanningParams.enableHeadingSmoothing,
                -1 , -1,
                m_RollOuts, sampledPoints_debug);

调用的是PlannerH.cpp里面的GenerateRunoffTrajectory()函数。
其中返回的m_RollOuts是rollOutsPaths,里面包含了多条local_rollOutPaths

rollOutsPaths.push_back(local_rollOutPaths);

生成之后,通过TrajectoriesToMarkers函数将rollouts转换成marker以在rviz中显示,进而publish

visualization_msgs::MarkerArray all_rollOuts;
PlannerHNS::ROSHelpers::TrajectoriesToMarkers(m_RollOuts, all_rollOuts);
pub_LocalTrajectoriesRviz.publish(all_rollOuts);
  1. 发布的topic
pub_LocalTrajectories = nh.advertise<autoware_msgs::LaneArray>("local_trajectories", 1);//作为op_trajectory_evaluator的订阅
pub_LocalTrajectoriesRviz = nh.advertise<visualization_msgs::MarkerArray>("local_trajectories_gen_rviz", 1);

op_behavior_selector

同样的主要业务逻辑在MainLoop里面

  1. 订阅的topic
sub_current_pose = nh.subscribe("/current_pose", 10,  &BehaviorGen::callbackGetCurrentPose, this);//必选项
//传统三选一,默认值是current_velocity
"/odom";"/current_velocity";"/can_info"
//
sub_GlobalPlannerPaths = nh.subscribe("/lane_waypoints_array", 1, &BehaviorGen::callbackGetGlobalPlannerPath, this);//global_planner输出的topic
sub_LocalPlannerPaths = nh.subscribe("/local_weighted_trajectories", 1, &BehaviorGen::callbackGetLocalPlannerPath, this);
sub_TrafficLightStatus = nh.subscribe("/light_color", 1, &BehaviorGen::callbackGetTrafficLightStatus, this);
sub_TrafficLightSignals  = nh.subscribe("/roi_signal", 1, &BehaviorGen::callbackGetTrafficLightSignals, this);
sub_Trajectory_Cost = nh.subscribe("/local_trajectory_cost", 1, &BehaviorGen::callbackGetLocalTrajectoryCost, this);

sub_twist_raw = nh.subscribe("/twist_raw", 1, &BehaviorGen::callbackGetTwistRaw, this);
sub_twist_cmd = nh.subscribe("/twist_cmd", 1, &BehaviorGen::callbackGetTwistCMD, this);

//Mapping Section
//...这部分同上
  1. 发布的topic
pub_LocalPath = nh.advertise<autoware_msgs::Lane>("final_waypoints", 1,true);
pub_LocalBasePath = nh.advertise<autoware_msgs::Lane>("base_waypoints", 1,true);
pub_ClosestIndex = nh.advertise<std_msgs::Int32>("closest_waypoint", 1,true);
pub_BehaviorState = nh.advertise<geometry_msgs::TwistStamped>("current_behavior", 1);//作为op_trajectory_evaluator的订阅
pub_SimuBoxPose    = nh.advertise<geometry_msgs::PoseArray>("sim_box_pose_ego", 1);
pub_BehaviorStateRviz = nh.advertise<visualization_msgs::MarkerArray>("behavior_state", 1);
pub_SelectedPathRviz = nh.advertise<visualization_msgs::MarkerArray>("local_selected_trajectory_rviz", 1);

op_common_params

op_motion_predictor

  1. 订阅的topic
sub_StepSignal = nh.subscribe("/pred_step_signal",1,&MotionPrediction::callbackGetStepForwardSignals,this);
sub_tracked_objects  = nh.subscribe("/tracked_objects",1,&MotionPrediction::callbackGetTrackedObjects,this);
sub_current_pose   = nh.subscribe("/current_pose", 10,&MotionPrediction::callbackGetCurrentPose,this);
//依然的三选一,默认值是current_velocity
"/odom";"/current_velocity";"/can_info"
//Mapping Section
//...这部分同上
  1. 业务逻辑
  2. 发布的topic
pub_predicted_objects_trajectories = nh.advertise<autoware_msgs::DetectedObjectArray>("/predicted_objects", 1);//作为op_trajectory_evaluator的订阅
pub_PredictedTrajectoriesRviz = nh.advertise<visualization_msgs::MarkerArray>("/predicted_trajectories_rviz", 1);
pub_CurbsRviz          = nh.advertise<visualization_msgs::MarkerArray>("/map_curbs_rviz", 1);
pub_ParticlesRviz = nh.advertise<visualization_msgs::MarkerArray>("prediction_particles", 1);

op_trajectory_evaluator

  1. 订阅的topic
//老生常谈项
sub_current_pose = nh.subscribe("/current_pose", 10, &TrajectoryEval::callbackGetCurrentPose, this);
//经典三选一,默认值是current_velocity
"/odom";"/current_velocity";"/can_info";
//其他的
sub_GlobalPlannerPaths = nh.subscribe("/lane_waypoints_array", 1, &TrajectoryEval::callbackGetGlobalPlannerPath, this);//global_planner的输出
sub_LocalPlannerPaths = nh.subscribe("/local_trajectories", 1, &TrajectoryEval::callbackGetLocalPlannerPath, this);//op_trajectory_generator的输出
sub_predicted_objects = nh.subscribe("/predicted_objects", 1, &TrajectoryEval::callbackGetPredictedObjects, this);//op_motion_predictor的输出
sub_current_behavior = nh.subscribe("/current_behavior", 1, &TrajectoryEval::callbackGetBehaviorState, this);//op_behavior_selector的输出
  1. 业务逻辑
  2. 发布的topic
pub_CollisionPointsRviz = nh.advertise<visualization_msgs::MarkerArray>("dynamic_collision_points_rviz", 1);
pub_LocalWeightedTrajectoriesRviz = nh.advertise<visualization_msgs::MarkerArray>("local_trajectories_eval_rviz", 1);
pub_LocalWeightedTrajectories = nh.advertise<autoware_msgs::LaneArray>("local_weighted_trajectories", 1);
pub_TrajectoryCost = nh.advertise<autoware_msgs::Lane>("local_trajectory_cost", 1);
pub_SafetyBorderRviz = nh.advertise<visualization_msgs::Marker>("safety_border", 1);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/514541.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FSS对象存储挂载到windows云服务器操作方法

FSS对象存储可以挂载到云主机中用于存储视频、备份等不需要 经常读写的大文件。不适合存放数据库等对IO需求较高、经常读写的场景。 1、远程登陆服务器&#xff0c;打开控制面板&#xff0c;然后点击“打开或关闭windows功能”。 windows2008系统&#xff1a; 选择“功能”-- …

图可视化工具Gephi使用教程

图可视化工具Gephi使用教程 操作界面介绍在Gephi界面完成图的绘制键盘输入导入CSV文件直接在概览界面鼠标点击创建自己创建一个红楼梦关系网络图用一个Web of Science上的数据创建一个有向关系图 静态随机数据使用动态数据的使用Gephi的可视化处理节点移动节点放大&缩小单个…

【JAVA程序设计】(C00133)基于SSM的勤工助学管理系统

基于SSM的勤工助学管理系统 项目简介项目获取开发环境项目技术运行截图 项目简介 本系统为基于SSM的学生勤工助学俭学管理系统&#xff0c;本系统分为三种角色&#xff1a;管理员、学生、用人单位&#xff1b; 管理员功能&#xff1a;个人中心、面试邀请管理、岗位报名管理、…

二十三:创建交易

功能需求&#xff1a; 用户在交易主页面&#xff0c;点击”创建”按钮&#xff0c;跳转到创建交易的页面&#xff1b; 用户在创建交易的页面填写表单&#xff0c;点击”保存”按钮&#xff0c;完成创建交易的功能。 *所有者、阶段、类型、来源 都是动态的 *市场活动源是可搜…

《编程思维与实践》1061.计算n!右端0的个数(II)

《编程思维与实践》1061.计算n!右端0的个数(II) 题目 思路 可以用大整数的乘法来处理,不过有些题目可以用数论的方法得到更方便的做法, 以本题为例: 注意到 10 2 ⋅ 5 102\cdot 5 102⋅5 , 所以只需要将阶乘的每一项分解成2和5的乘积形式即可, 同时由于每出现一个5,必然会出现…

shell补充命令

目录 排序sort命令 语法格式: 常用选项: 去重uniq命令 替换tr命令 替换字符 删除​编辑 压缩​编辑 压缩替换​编辑 删除空行 截取cut命令 拆分split命令 合并paste命令​ eval命令 排序sort命令 以行为单位对文件内容进行排序&#xff0c;也可以根据不同的数据类型…

淘天集团首战618,一场平台生态的“再创业”

电商行业还在“卷”&#xff0c;但不是所有人都还把目光放在低价、噱头上。 5月10日&#xff0c;淘宝天猫618商家大会应时而至&#xff0c;随之而来的&#xff0c;是“淘天集团”的首次公开亮相。淘天集团CEO戴珊表示&#xff0c;“新生变革”、自我变革不是选择题而是必答题。…

4.实现csdn暗黑模式-油猴脚本实战1

4.实现csdn暗黑模式-油猴脚本实战1 Start 前面的文章&#xff0c;对油猴脚本做了基础的介绍。今天来我们来实战一下&#xff0c;编写一个有实际作用的油猴脚本。 如果我希望我的csdn是暗黑模式&#xff0c;怎么办&#xff1f; 看我表演&#xff1f; 注意&#xff01;本文仅用…

shell脚本----正则表达式

文章目录 一、什么是正则表达式二、正则表达式的使用 一、什么是正则表达式 正则表达式是由普通字符与元字符组成&#xff1a; 普通字符 包括大小写字母、数字、标点符号及一些其他符号。 元字符 是指在正则表达式中具有特殊意义的专用字符&#xff0c;可以用来规定其前导字符…

科技助农 智慧养鸡2D组态可视化管理云平台

前言 养殖业是农业的一个重要分支&#xff0c;主要包括家禽养殖、畜牧养殖和水产养殖三个细分产业。养殖业发展至今&#xff0c;已成为与种植业并列的农业两大支柱产业之一。 建设背景 我国作为养殖业大国&#xff0c;各类型的散养农户、大中小型养殖场数量极多&#xff0c;…

事务的隔离级别有哪几种,解决了什么问题?

事务的隔离级别主要是为了保证多事务环境下的并发安全性&#xff0c;共有四大隔离级别&#xff0c;如下&#xff1a; 如果不考虑隔离性&#xff0c;在SQL操作中&#xff0c;多个事务竞争可能会产生三种不同的现象&#xff0c;分别是脏读、幻读、不可重复读。 首先来看脏读&am…

slf4j log4j log4j-over-slf4j self-log4j12

一、Java日志体系概述 图1-1 Java日志体系概况 日志门面接口&#xff08;SLF4J、JCL&#xff09;一系列绑定和桥接具体的日志实现 先来两个例子&#xff1a; Spring项目中通过Commons Logging直接使用log4j 图1-2 通过Commons Logging使用log4j本例中由于spring-core中原生依…

IS200TREGH1BEC直流并励电动机的启动

​ IS200TREGH1BEC​​​​​​直流并励电动机的启动 要启动机器&#xff0c;电机在零速时产生的扭矩必须超过负载所需的扭矩。然后 TM − TL 将为正&#xff0c;d!/dt 也为正&#xff0c;机器加速。 通常&#xff0c;直流电机的电枢电阻在满载电流时会导致 1% 到 5% 的下降。…

制作RPM包createrepo

每次源码安装很费事&#xff0c;所以直接做一个RPM包 安装 rpm-build 软件包 [rootproxy ~]# yum -y install rpm-build 生成 rpmbuild 目录结构 或许只有在家目录下生成一个不存在的目录才会生成 rpmbuild目录和子目录 若想在自己创建的目录下生成只有自己手动去创建&#…

基于.NET实现的家电维修保养信息系统[含文档+PPT+源码等]精品

1 项目简介 Hi&#xff0c;各位同学好呀&#xff0c;这里是卡莫&#xff01; 基于.NET实现的家电维修保养信息系统[含文档PPT源码等]精品 该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等 软件开发环境及开发工具&#xff1a; 开发软件&#xff1a;…

怎么查看特定的端口是否被屏蔽了

文章目录 怎么查看特定的端口是否被屏蔽了前言无法访问原因查看命令所用环境开启windows的telnet功能查看特定端口是否被墙WSL演示windows终端演示总结 怎么查看特定的端口是否被屏蔽了 前言 如果你不知道自己的服务器的某个端口是否被屏蔽了&#xff0c;通过阅读本文&#x…

如何利用EAP系统优化锂电生产线的自动化流程?

锂电行业是新兴的能源产业&#xff0c;其快速发展和规模化生产对设备自动化系统的需求也越来越高。在生产过程中&#xff0c;设备自动化系统EAP&#xff08;Equipment Automation Program&#xff09;可以实现对生产线上的所有机台进行实时管控&#xff0c;从而实现设备运行的自…

“AIGC早报”已内测2个月了,来看看她长什么样子

今天&#xff0c;是咱们社群“AI产品经理大本营”六周年活动的第二天&#xff0c;正式给大家介绍下&#xff0c;已内测2个月的重要会员权益——AIGC日报。 会分三个部分&#xff1a;效果口碑、我们如何做到的、今日的AIGC早报展示‍‍‍‍‍‍‍‍ ps&#xff0c;文末会发福利星…

将群晖NAS加入域控,来点企业级应用

1. 使用逻辑 将NAS加入域&#xff0c;所有套件和文件可通过域用户来访问。设置NAS中的文件夹权限时&#xff0c;NAS识别出域用户和域群组&#xff0c;并可设置二级文件夹的权限。域管理员会成为NAS的管理员。在域控管理台&#xff0c;可以看到NAS加入到了域控中&#xff0c;在…

dom操作

<script>var htmlEldocument.documentElementvar bodyEldocument.bodyvar headEldocument.headvar doctypedocument.doctypeconsole.log(htmlEl,bodyEl,headEl,doctype)</script> ul>li{$}*5 节点之间的关系(极少用) 空行注释没标签包括的文字也算是一个节点 子…