在node_main.cc中,当::ros::spin()结束了之后(在运行node的时候,按下Ctrl+C即结束spin开始运行spin之后的语句),开始结束所有处于活动状态的轨迹,
1 2 3 4 5 6 7 8 void Run () { ... ::ros::spin (); node.FinishAllTrajectories (); ... }
下面是FinishAllTrajectories的详细代码。
1 2 3 4 5 6 7 8 9 10 11 void Node::FinishAllTrajectories () { absl::MutexLock lock (&mutex_) ; for (const auto & entry : map_builder_bridge_.GetTrajectoryStates ()) { if (entry.second == TrajectoryState::ACTIVE) { const int trajectory_id = entry.first; CHECK_EQ (FinishTrajectoryUnderLock (trajectory_id).code, cartographer_ros_msgs::StatusCode::OK); } } }
此函数,调用map_builder_bridge来获取轨迹的状态,key为轨迹ID,value为轨迹状态,轨迹状态一共有四种
1 enum class TrajectoryState { ACTIVE, FINISHED, FROZEN, DELETED };
如果有轨迹的状态为ACTIVE,那么我们就通过FinishTrajectoryUnderLock, 将其进行结束操作
FinishTrajectoryUnderLock 此函数用于结束一条指定id的轨迹,返回一个状态,用于判定是否结束成功
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 cartographer_ros_msgs::StatusResponse Node::FinishTrajectoryUnderLock ( const int trajectory_id) { cartographer_ros_msgs::StatusResponse status_response; if (trajectories_scheduled_for_finish_.count (trajectory_id)) { status_response.message = absl::StrCat ("Trajectory " , trajectory_id, " already pending to finish." ); status_response.code = cartographer_ros_msgs::StatusCode::OK; LOG (INFO) << status_response.message; return status_response; } status_response = TrajectoryStateToStatus ( trajectory_id, {TrajectoryState::ACTIVE} ); if (status_response.code != cartographer_ros_msgs::StatusCode::OK) { LOG (ERROR) << "Can't finish trajectory: " << status_response.message; return status_response; } if (subscribers_.count (trajectory_id)) { for (auto & entry : subscribers_[trajectory_id]) { entry.subscriber.shutdown (); subscribed_topics_.erase (entry.topic); LOG (INFO) << "Shutdown the subscriber of [" << entry.topic << "]" ; } CHECK_EQ (subscribers_.erase (trajectory_id), 1 ); } map_builder_bridge_.FinishTrajectory (trajectory_id); trajectories_scheduled_for_finish_.emplace (trajectory_id); status_response.message = absl::StrCat ("Finished trajectory " , trajectory_id, "." ); status_response.code = cartographer_ros_msgs::StatusCode::OK; return status_response; }
检查一:是否在trajectoriesscheduled_for_finish 里面 如果判定轨迹已经在将要结束的轨迹中,trajectoriesscheduled_for_finish ,则直接给status_response一个OK状态
1 2 3 4 5 6 7 8 if (trajectories_scheduled_for_finish_.count (trajectory_id)) { status_response.message = absl::StrCat ("Trajectory " , trajectory_id, " already pending to finish." ); status_response.code = cartographer_ros_msgs::StatusCode::OK; LOG (INFO) << status_response.message; return status_response; }
检查二:检查轨迹是否存在和状态 检查这个轨迹是否存在, 如果存在则检查这个轨迹是否是ACTIVE状态
1 2 3 4 5 6 7 8 9 status_response = TrajectoryStateToStatus ( trajectory_id, {TrajectoryState::ACTIVE} ); if (status_response.code != cartographer_ros_msgs::StatusCode::OK) { LOG (ERROR) << "Can't finish trajectory: " << status_response.message; return status_response; }
检查三:若存在,检查subscriber是否关闭 如果通过了步骤二,说明轨迹存在并且状态是ACTIVE。那么开始检查对应的轨迹ID是否有订阅者,使用count可以查看map里面的对应key的value个数,使用shutdown来关闭对应的订阅者。并且移除记录subscribedtopics 里面记录的已经有的topic名字。最后把subscribers_ 里面的轨迹ID给清除掉
1 2 3 4 5 6 7 8 9 10 if (subscribers_.count (trajectory_id)) { for (auto & entry : subscribers_[trajectory_id]) { entry.subscriber.shutdown (); subscribed_topics_.erase (entry.topic); LOG (INFO) << "Shutdown the subscriber of [" << entry.topic << "]" ; } CHECK_EQ (subscribers_.erase (trajectory_id), 1 ); }
结束轨迹 调用cartographer中的mapbuilder的FinishTrajectory()进行轨迹的结束,然后放入trajectories_scheduled_for_finish ,设置status_response的message和code即可
1 2 3 4 5 6 map_builder_bridge_.FinishTrajectory (trajectory_id); trajectories_scheduled_for_finish_.emplace (trajectory_id); status_response.message = absl::StrCat ("Finished trajectory " , trajectory_id, "." ); status_response.code = cartographer_ros_msgs::StatusCode::OK;