Apollo解读代码系列之perceptionlidar模块tracker逻辑分析 lidar模块之tracker Apollo感知代码之激光雷达模块的追踪使用的是SORT算法架构。主要包括以下几个模块:关联模块association、通用模块common、测量值模块measurement、多激光雷达融合模块multi_lidar_fusion、地图分割semantic_map。lidar-tracker代码主要结构图 其中MlfTrackData为追踪数据处理结构,继承TrackData,TrackedObject为输入的测量值结构,初始化都是base::ConcurrentObjectPool的序列容器存储。你可以理解TrackedObject就是输入的目标,MlfTrackData为追踪列
里面的一个目标物体,然后通过base::ConcurrentObjectPool来存储多个TrackedObject与MlfTrackData物体。补:我们知道追踪列表维护一个数据结构就是上面的TrackData,测量值维护的数据结构是TrackObject。这里的MlfTrackData继承自TrackData主要是由于激光雷达有不同的品牌类型,所以会存在传感器类型的一个数据确认过程。具体细节请看代码部分吧,这里仅仅做个提示。 上面为感知激光的追踪代码,MlfEngine继承接口类BaseMultiTargetTracker,其内部包含两个变量MlfTracker与MlfTrackObjectMatcher。MlfTracker属于状态变量更新模块,MlfTrackObjectMatcher属于数据匹配模块,主要采取多种距离加权方式来设定关联权重,其中关联矩阵获取最终的匹配结果根据激光雷达障碍物是否为背景采取不同的方式。voidMlfTrackObjectMatcher::ComputeAssociateMatrix(conststd::vector
&tracks,conststd::vector&new_objects,common::SecureMat*association_mat){for(size_ti=0;iComputeDistance(new_objects[j],tracks[i]);}}} 下面我们看下激光测量object与追踪track的之间距离计算方式:关于具体每个权重计算函数可以在distance_collection.h查看。floatMlfTrackObjectDistance::ComputeDistance(constTrackedObjectConstPtr&object,constMlfTrackDataConstPtr&track)const{//是否为背景目标boolis_background=object->is_background;//获取最新的追踪目标constTrackedObjectConstPtrlatest_object=track->GetLatestObject().second;std::stringkey=latest_object->sensor_info.name+object->sensor_info.name;conststd::vector*weights=nullptr;if(is_background)//判断是否为背景{autoiter=background_weight_table_.find(key);if(iter==background_weight_table_.end()){weights=&kBackgroundDefaultWeight;//背景权重超参}else{weights=&iter->second;}}else{autoiter=foreground_weight_table_.find(key);if(iter==foreground_weight_table_.end()){weights=&kForegroundDefaultWeight;//前景超参}else{weights=&iter->second;}}if(weights==nullptr||weights->size()<7){AERROR<<"Invalidweights";return1e+10f;}floatdistance=0.f;floatdelta=1e-10f;doublecurrent_time=object->object_ptr->latest_tracked_time;//根据最新的时间预测track->PredictState(current_time);//时间差doubletime_diff=track->age_?current_time-track->latest_visible_time_:0;if(weights->at(0)>delta){distance+=weights->at(0)*LocationDistance(latest_object,track->predict_.state,object,time_diff);//位置距离}if(weights->at(1)>delta){distance+=weights->at(1)*DirectionDistance(latest_object,track->predict_.state,object,time_diff);//朝向距离}if(weights->at(2)>delta){distance+=weights->at(2)*BboxSizeDistance(latest_object,track->predict_.state,object,time_diff);//boxsize距离计算}if(weights->at(3)>delta){distance+=weights->at(3)*PointNumDistance(latest_object,track->predict_.state,object,time_diff);//点云点集距离计算}if(weights->at(4)>delta){distance+=weights->at(4)*HistogramDistance(latest_object,track->predict_.state,object,time_diff);//直方图距离计算}if(weights->at(5)>delta){distance+=weights->at(5)*CentroidShiftDistance(latest_object,track->predict_.state,object,time_diff);//重心}if(weights->at(6)>delta){distance+=weights->at(6)*BboxIouDistance(latest_object,track->predict_.state,object,time_diff,background_object_match_threshold_);//boxiou计算权重}//forforeground,calculatesemanticmapbaseddistance//if(!is_background){//distance+=weights->at(7)*SemanticMapDistance(*track,object);//}returndistance;} 计算出object与trackobject之间的权重获取关联矩阵后,判断是否为背景目标,如果是使用GnnBipartiteGraphMatcher。否则使用MultiHmBipartiteGraphMatcher来求解出关联结果。lidar-tracker代码模块之状态更新 在上述关联结果之后,需要使用测量值object对追踪列表进行状态更新。从上述结构来看总共有两种滤波方式,MlfShapeFilter与MlfMotionFilter。关于object的更新部分主要包括基础的中心点、框大小等。其中MlfMotionFilter更新状态速度使用部分卡尔曼状态监测方式。关于MlfBaseFilter为两者的对外接口类,Apollo通过一个std::vector来存储多种滤波方式,以此来进行不同变量使用不同的滤波方式。请看MlfTracker的初始化代码可以发现:boolMlfTracker::Init(constMlfTrackerInitOptionsoptions){autoconfig_manager=lib::ConfigManager::Instance();constlib::ModelConfig*model_config=nullptr;ACHECK(config_manager->GetModelConfig(Name(),&model_config));conststd::stringwork_root=config_manager->work_root();std::stringconfig_file;std::stringroot_path;ACHECK(model_config->get_value("root_path",&root_path));config_file=GetAbsolutePath(work_root,root_path);config_file=GetAbsolutePath(config_file,"mlf_tracker.conf");MlfTrackerConfigconfig;ACHECK(cyber::common::GetProtoFromFile(config_file,&config));//通过循环访问配置文件里面的filtername来获取多种的filterfor(inti=0;iInit(filter_init_options));filters_.push_back(filter);//这里通过filters_来存储多种的滤波方式AINFO<<"MlfTrackeraddfilter:"<Name();}returntrue;}lidar-tracker代码模块之measurement 在measurement测量值模块中,Apollo采用以下几种特征计算:下述方式主要是在运动估计平滑时候使用得到相关的测量值。voidMlfMotionMeasurement::ComputeMotionMeasurment(constMlfTrackDataConstPtr&track_data,TrackedObjectPtrnew_object){//prefertochooseobjectsfromthesamesensorstd::stringsensor_name=new_object->sensor_info.name;TrackedObjectConstPtrlatest_object=track_data->GetLatestSensorObject(sensor_name).second;if(latest_object==nullptr){latest_object=track_data->GetLatestObject().second;}if(latest_object.get()==nullptr){AERROR<<"latest_objectisnotavailable";return;}//shouldweestimatethemeasurementifthetimediffistoosmall?doublelatest_time=latest_object->object_ptr->latest_tracked_time;doublecurrent_time=new_object->object_ptr->latest_tracked_time;doubletime_diff=current_time-latest_time;if(fabs(time_diff)流程与数据结构大概就是这么多,具体到里面的算法单元细节后续在逐步介绍。本篇主要是讲解其中的数据结构与调用流程,以及相对关键的部分模块细节。 -全文完-