EGO_Planner代码学习(二):轨迹服务器ego_planner/traj_server代码流程

EGO_Planner代码学习(二):轨迹服务器ego_planner/traj_server代码流程


上一节我们学习了EGO_Planner的启动流程,下面我们来看一看 roslaunch ego_planner single_run_in_exp.launch启动了 ego_planner/traj_server结点后,该结点都做了什么工作呢

ego_planner/traj_server代码流程

我们查看一下src/planner/plann_manage文件夹下的CMakeLists文件,发现ego_planner/traj_server是通过编译该文件夹下src/traj_server.cpp文件生成的,下面我们就看看这个traj_server.cpp的代码流程。

1->	创建结点  traj_server
2->	订阅规划轨迹 :planner/bspline
	回调函数:bsplineCallback()
	2.1->	收到轨迹,创建两个变量pos_pts konts分别接收geometry_msgs/Point[]类型的pos_pts 和时间变量konts
	2.2->	用收到的pos_pts,konts创建新的均匀B样条曲线pos_traj
	2.3->	计算后面要用的变量:
		start_time_	//等于收到轨迹的成员变量:起始时间
		traj_id_	//等于收到轨迹的成员变量:id
		traj_		//插入pos_traj及其一阶导、二阶导
		traj_duration_	///总时间
	2.4->	receive_traj_=true
3->	创建发布者:pos_cmd_pub ,往 /position_cmd 话题上发布 PositionCommand 类型的数据
4->	创建定时器,间隔10ms进入回调函数一次	
	回调函数 cmdCallback()4.1->	是否收到了轨迹receive_traj_=true,没有的话跳出函数
	4.2->	计算现在的时间和起始时间的间隔 t_cur = time_now-start_time_
	4.3->	判断 t_cur  在不在总时间区间内
		4.3.1->	t_cur < traj_duration_	
			计算当前t_cur的pos vel acc yaw(后面导航命令用),再算一个pos_f(不知道干嘛用的)
		4.3.2->	t_cur > traj_duration_
			计算终点pos ,vel acc 设0,yaw不变; 
		4.3.3->	t_cur < 0
			报错
	4.4->	把pos vel acc yaw等信息装入cmd里,pos_cmd_pub 发布一次cmd到/position_cmd
5->	在cmd指令里设置控制器增益系数
6->	1.0sleep,ros::spin()

	traj_server.cpp 子函数calculate_yaw()
	->参数:double t_cur,vector3d &pos ,ros::Time time_now ,ros::Time time_last
	->功能:计算yaw角方向,变化率,并对输出进行限幅,把yaw输出限制在[-PI,PI]
	->输出:pair of <yaw,yaw_dot>	

通过上述分析,我们发现ego_planner/traj_server结点其实就是为了将规划器发布的轨迹planner/bspline转化为控制器指令cmd并上传到position_cmd话题上。
下一节,我们分析ego_planner_node结点在启动后经历了那些流程。

Ego-Planner是一个基于ROS的路径规划器,它可以在给定的地图和起点、终点信息下,生成一条可行的路径。以下是Ego-Planner代码框架: 1. 首先需要定义一个EgoPlanner类,其中包含了一些必要的成员变量和函数。 ```c++ class EgoPlanner { private: ros::NodeHandle nh_; ros::Subscriber sub_map_; ros::Subscriber sub_pose_; ros::Subscriber sub_goal_; ros::Publisher pub_path_; nav_msgs::OccupancyGrid map_; geometry_msgs::PoseStamped start_; geometry_msgs::PoseStamped goal_; public: EgoPlanner(); // 构造函数 ~EgoPlanner(); // 析构函数 void mapCallback(const nav_msgs::OccupancyGrid::ConstPtr& msg); // 地图回调函数 void poseCallback(const geometry_msgs::PoseStamped::ConstPtr& msg); // 当前位置回调函数 void goalCallback(const geometry_msgs::PoseStamped::ConstPtr& msg); // 目标位置回调函数 void plan(); // 路径规划函数 }; ``` 2. 在构造函数中,需要完成ROS节点的初始化、订阅和发布话题的设置。 ```c++ EgoPlanner::EgoPlanner() { nh_ = ros::NodeHandle("~"); sub_map_ = nh_.subscribe("map", 1, &EgoPlanner::mapCallback, this); sub_pose_ = nh_.subscribe("pose", 1, &EgoPlanner::poseCallback, this); sub_goal_ = nh_.subscribe("goal", 1, &EgoPlanner::goalCallback, this); pub_path_ = nh_.advertise<nav_msgs::Path>("path", 1); } ``` 3. 在地图、当前位置和目标位置的回调函数中,需要将接收到的信息保存到对应的成员变量中。 ```c++ void EgoPlanner::mapCallback(const nav_msgs::OccupancyGrid::ConstPtr& msg) { map_ = *msg; } void EgoPlanner::poseCallback(const geometry_msgs::PoseStamped::ConstPtr& msg) { start_ = *msg; } void EgoPlanner::goalCallback(const geometry_msgs::PoseStamped::ConstPtr& msg) { goal_ = *msg; } ``` 4. 在路径规划函数中,需要调用路径规划算法,生成一条可行的路径,并将路径发布出去。 ```c++ void EgoPlanner::plan() { // 调用路径规划算法,生成一条可行的路径 std::vector<geometry_msgs::PoseStamped> path = pathPlanning(map_, start_, goal_); // 将路径发布出去 nav_msgs::Path path_msg; path_msg.header.frame_id = "map"; path_msg.header.stamp = ros::Time::now(); path_msg.poses = path; pub_path_.publish(path_msg); } ``` 5. 在主函数中,创建EgoPlanner对象,并进入ROS循环。 ```c++ int main(int argc, char** argv) { ros::init(argc, argv, "ego_planner"); EgoPlanner planner; ros::Rate rate(10); while (ros::ok()) { planner.plan(); ros::spinOnce(); rate.sleep(); } return 0; } ``` 以上就是Ego-Planner代码框架,其中路径规划算法需要根据具体情况进行选择和实现。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值