Apollo 11.0
自动驾驶开放平台
apollo::perception::lidar::GraphSegmentation类 参考

#include <graph_segmentation.h>

类 apollo::perception::lidar::GraphSegmentation 继承关系图:
apollo::perception::lidar::GraphSegmentation 的协作图:

Public 成员函数

 GraphSegmentation ()=default
 
 ~GraphSegmentation ()=default
 
bool Init (const LidarDetectorInitOptions &options=LidarDetectorInitOptions()) override
 Init graph segmentation
 
bool Detect (const LidarDetectorOptions &options, LidarFrame *frame) override
 Segment pointcloud into objects
 
std::string Name () const override
 Get class name
 
bool Segment (LidarFrame *frame)
 Graph segment
 
float NodeDistance (BgNode n1, int x1, int y1, BgNode n2, int x2, int y2)
 Compute node distance
 
void GetObjectsFromClusters (LidarFrame *frame)
 Get the Objects From Clusters
 
bool Split (LidarFrame *frame)
 background filter
 
bool NeedSplit (std::shared_ptr< base::Object > object)
 judge if the object need to split
 
bool SetBgObjectDefaulVal (LidarFrame *frame)
 Set the Bacground Object Defaul Value
 
- Public 成员函数 继承自 apollo::perception::lidar::BaseLidarDetector
 BaseLidarDetector ()=default
 Construct a new Base Lidar Detector object
 
virtual ~BaseLidarDetector ()=default
 Destroy the Base Lidar Detector object
 

详细描述

在文件 graph_segmentation.h 第 42 行定义.

构造及析构函数说明

◆ GraphSegmentation()

apollo::perception::lidar::GraphSegmentation::GraphSegmentation ( )
default

◆ ~GraphSegmentation()

apollo::perception::lidar::GraphSegmentation::~GraphSegmentation ( )
default

成员函数说明

◆ Detect()

bool apollo::perception::lidar::GraphSegmentation::Detect ( const LidarDetectorOptions &  options,
LidarFrame *  frame 
)
overridevirtual

Segment pointcloud into objects

参数
options
frameLidar frame
返回
true
false

实现了 apollo::perception::lidar::BaseLidarDetector.

在文件 graph_segmentation.cc 第 59 行定义.

59 {
60 // clear background objects buffer
61 bg_objects_.clear();
62
63 // reset background map
64 if (!bg_map_.Reset(frame->cloud->size())) {
65 AERROR << "bg_map_ Reset error.";
66 return false;
67 }
68 // update map
69 if (!bg_map_.UpdateMap(frame)) {
70 AERROR << "bg_map_ Update error.";
71 return false;
72 }
73 // cluster
74 if (!Segment(frame)) {
75 AERROR << "Graph Segment error.";
76 return false;
77 }
78 // split
79 if (!Split(frame)) {
80 AERROR << "Split object error.";
81 return false;
82 }
83 // set default value and id for bg_objects_
84 if (!SetBgObjectDefaulVal(frame)) {
85 AERROR << "SetBgObjectDefaulVal error.";
86 return false;
87 }
88
89 // get all background objects
90 frame->segmented_objects.insert(frame->segmented_objects.end(), bg_objects_.begin(), bg_objects_.end());
91 AINFO << "Graph segment, background objects number: " << bg_objects_.size();
92 return true;
93}
bool UpdateMap(LidarFrame *frame)
Update map, update mask and node
bool Reset(size_t point_number)
Reset all data
bool SetBgObjectDefaulVal(LidarFrame *frame)
Set the Bacground Object Defaul Value
bool Segment(LidarFrame *frame)
Graph segment
bool Split(LidarFrame *frame)
background filter
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42

◆ GetObjectsFromClusters()

void apollo::perception::lidar::GraphSegmentation::GetObjectsFromClusters ( LidarFrame *  frame)

Get the Objects From Clusters

参数
framelidar frame

在文件 graph_segmentation.cc 第 225 行定义.

225 {
226 // point cloud
227 auto original_cloud_ = frame->cloud;
228 auto original_world_cloud_ = frame->world_cloud;
229 // clear background objects
230 bg_objects_.clear();
231 // background object
232 for (size_t i = 0; i < clusters_.size(); ++i) {
233 auto cluster = clusters_[i];
234 if (cluster->point_ids.size() < min_pt_number_) {
235 continue;
236 }
237 base::Object object;
238 object.confidence = cluster->confidence;
239 for (auto idx : cluster->point_ids) {
240 object.lidar_supplement.point_ids.push_back(static_cast<int>(idx));
241 }
242 object.lidar_supplement.num_points_in_roi = cluster->point_ids.size();
243 object.lidar_supplement.cloud.CopyPointCloud(*original_cloud_, cluster->point_ids);
244 object.lidar_supplement.cloud_world.CopyPointCloud(*original_world_cloud_, cluster->point_ids);
245 // copy to background objects
246 std::shared_ptr<base::Object> obj(new base::Object);
247 *obj = object;
248 bg_objects_.push_back(std::move(obj));
249 }
250 // background object builder
251 BgObjectBuilder(&bg_objects_, frame->lidar2novatel_extrinsics);
252}
bool BgObjectBuilder(std::vector< base::ObjectPtr > *objects, Eigen::Affine3d &lidar2novatel_pose)
background objects builder

◆ Init()

bool apollo::perception::lidar::GraphSegmentation::Init ( const LidarDetectorInitOptions &  options = LidarDetectorInitOptions())
overridevirtual

Init graph segmentation

参数
options
返回
true
false

实现了 apollo::perception::lidar::BaseLidarDetector.

在文件 graph_segmentation.cc 第 25 行定义.

25 {
26 std::string config_file = GetConfigFile(options.config_path, options.config_file);
27 ACHECK(apollo::cyber::common::GetProtoFromFile(config_file, &bg_config_));
28 // get config
29 // grid_width_ = bg_config_.grid_width();
30 // grid_height_ = bg_config_.grid_height();
31 resolution_ = bg_config_.resolution();
32 threshold_ = bg_config_.threshold();
33 min_pt_number_ = bg_config_.min_pt_number();
34 search_radius_ = bg_config_.search_radius();
35 height_threshold_ = bg_config_.height_threshold();
36 semantic_cost_ = bg_config_.semantic_cost();
37
38 // initialize graph segmentor
39 graph_segmentor_.Init(threshold_);
40 // ACHECK(bg_map_.Init(grid_width_, grid_height_, resolution_, height_threshold_));
41
42 ACHECK(bg_map_.Init(
43 bg_config_.xmin(),
44 bg_config_.xmax(),
45 bg_config_.ymin(),
46 bg_config_.ymax(),
47 resolution_,
48 height_threshold_));
49 grid_width_ = static_cast<int>((bg_config_.ymax() - bg_config_.ymin()) * 1.0f / resolution_);
50 grid_height_ = static_cast<int>((bg_config_.xmax() - bg_config_.xmin()) * 1.0f / resolution_);
51
52 // clear background objects
53 bg_objects_.clear();
54
55 AINFO << "graph segmentation config: " << bg_config_.DebugString();
56 return true;
57}
void Init(const float initial_threshold)
bool Init(int width, int height, float resolution, float height_threshold)
Init background map
#define ACHECK(cond)
Definition log.h:80
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
Definition file.cc:132
std::string GetConfigFile(const std::string &config_path, const std::string &config_file)
Definition util.cc:80

◆ Name()

std::string apollo::perception::lidar::GraphSegmentation::Name ( ) const
inlineoverridevirtual

Get class name

返回
std::string

实现了 apollo::perception::lidar::BaseLidarDetector.

在文件 graph_segmentation.h 第 68 行定义.

68 {
69 return "GraphSegmentation";
70 }

◆ NeedSplit()

bool apollo::perception::lidar::GraphSegmentation::NeedSplit ( std::shared_ptr< base::Object >  object)

judge if the object need to split

参数
object
返回
true
false

在文件 graph_segmentation.cc 第 284 行定义.

284 {
285 // get length and width
286 float length, width;
287 if (object->size(0) > object->size(1)) {
288 length = object->size(0);
289 width = object->size(1);
290 } else {
291 length = object->size(1);
292 width = object->size(0);
293 }
294 if ((width > kEpsilon) && (length / (width + kEpsilon) > bg_config_.split_aspect_ratio())) {
295 return true;
296 }
297 return false;
298}
uint32_t width
Width of point cloud

◆ NodeDistance()

float apollo::perception::lidar::GraphSegmentation::NodeDistance ( BgNode  n1,
int  x1,
int  y1,
BgNode  n2,
int  x2,
int  y2 
)

Compute node distance

参数
n1node one
x1x coordinate of node one
y1y coordinate of node one
n2node two
x2x coordinate of node two
y2y coordinate of node two
返回
float

在文件 graph_segmentation.cc 第 181 行定义.

181 {
182 float x_diff = static_cast<float>(x1 - x2) * resolution_;
183 float y_diff = static_cast<float>(y1 - y2) * resolution_;
184 float mean_height_diff = n1.mean_height - n2.mean_height;
185 float max_height_diff = n1.max_height - n2.max_height;
186 float mean_intensity = (n1.mean_intensity - n2.mean_intensity) / 255.0;
187 // semantic label
188 int max_label_1 = static_cast<int>(std::distance(
189 n1.pc_semantic_types.begin(), std::max_element(n1.pc_semantic_types.begin(), n1.pc_semantic_types.end())));
190 int max_label_2 = static_cast<int>(std::distance(
191 n2.pc_semantic_types.begin(), std::max_element(n2.pc_semantic_types.begin(), n2.pc_semantic_types.end())));
192 // motion label
193 int max_motion_label_1 = static_cast<int>(std::distance(
194 n1.pc_motion_types.begin(), std::max_element(n1.pc_motion_types.begin(), n1.pc_motion_types.end())));
195 int max_motion_label_2 = static_cast<int>(std::distance(
196 n2.pc_motion_types.begin(), std::max_element(n2.pc_motion_types.begin(), n2.pc_motion_types.end())));
197 // total cost
198 float total_cost = std::sqrt(
199 x_diff * x_diff + y_diff * y_diff + mean_height_diff * mean_height_diff + max_height_diff * max_height_diff
200 + mean_intensity * mean_intensity);
201
202 // semantic coefficient
203 if ((max_label_1 != static_cast<int>(PointSemanticLabel::UNKNOWN))
204 && (max_label_2 != static_cast<int>(PointSemanticLabel::UNKNOWN))) {
205 if (max_label_1 == max_label_2) {
206 total_cost *= bg_config_.same_semantic_coefficient();
207 } else {
208 total_cost *= bg_config_.diff_semantic_coefficient();
209 }
210 }
211
212 // motion coefficient
213 if ((max_motion_label_1 != static_cast<int>(PointMotionLabel::UNKNOWN))
214 && (max_motion_label_2 != static_cast<int>(PointMotionLabel::UNKNOWN))) {
215 if (max_motion_label_1 == max_motion_label_2) {
216 total_cost *= bg_config_.same_motion_coefficient();
217 } else {
218 total_cost *= bg_config_.diff_semantic_coefficient();
219 }
220 }
221
222 return total_cost;
223}

◆ Segment()

bool apollo::perception::lidar::GraphSegmentation::Segment ( LidarFrame *  frame)

Graph segment

参数
framelidar frame
返回
true
false

在文件 graph_segmentation.cc 第 95 行定义.

95 {
96 std::vector<algorithm::Edge> edge_set;
97 edge_set.clear();
98 algorithm::Edge edge;
99 for (int x = 0; x < grid_height_; ++x) {
100 for (int y = 0; y < grid_width_; ++y) {
101 int grid_idx = x * grid_width_ + y;
102 if (!bg_map_.bg_nodes_.at(grid_idx).is_valid) {
103 continue;
104 }
105
106 edge.a = bg_map_.bg_nodes_.at(grid_idx).id;
107 BgNode n1 = bg_map_.bg_nodes_.at(grid_idx);
108
109 // rows
110 for (int ny = y; ny < grid_width_ && ny <= y + search_radius_; ++ny) {
111 int grid_ny = x * grid_width_ + ny;
112 if (bg_map_.bg_nodes_.at(grid_ny).is_valid) {
113 edge.b = bg_map_.bg_nodes_.at(grid_ny).id;
114 BgNode n2 = bg_map_.bg_nodes_.at(grid_ny);
115 edge.w = NodeDistance(n1, x, y, n2, x, ny);
116 edge_set.push_back(edge);
117 }
118 }
119 // next line, next column
120 for (int nx = x + 1; nx < grid_height_ && nx <= x + search_radius_; ++nx) {
121 for (int ny = y; ny < grid_width_ && ny < y + search_radius_; ++ny) {
122 int grid_nxny = nx * grid_width_ + ny;
123 if (bg_map_.bg_nodes_.at(grid_nxny).is_valid) {
124 edge.b = bg_map_.bg_nodes_.at(grid_nxny).id;
125 BgNode n2 = bg_map_.bg_nodes_.at(grid_nxny);
126 edge.w = NodeDistance(n1, x, y, n2, nx, ny);
127 edge_set.push_back(edge);
128 }
129 }
130 }
131 }
132 }
133
134 if (edge_set.size() == 0) {
135 AINFO << "Graph segmentation, edges are empty.";
136 return true;
137 }
138
139 // graph segment
140 graph_segmentor_.SegmentGraph(bg_map_.id(), edge_set.size(), edge_set.data());
141 algorithm::Universe* universe = graph_segmentor_.mutable_universe();
142 std::vector<size_t> mapping(bg_map_.id(), 0);
143 std::map<size_t, size_t> label_map;
144 size_t label = 0;
145 for (int i = 0; i < bg_map_.id(); ++i) {
146 mapping[i] = universe->Find(i);
147 auto iter = label_map.find(mapping[i]);
148 if (iter == label_map.end()) {
149 // key:value --> father:label
150 label_map.emplace(mapping[i], label);
151 mapping[i] = label;
152 label++;
153 } else {
154 mapping[i] = iter->second;
155 }
156 }
157
158 // get point clusters
159 auto original_cloud = frame->cloud;
160 // SppClusterList clusters;
161 clusters_.Reset();
162 clusters_.resize(label_map.size());
163 for (size_t i = 0; i < bg_map_.point_mask_.size(); ++i) {
164 if (!bg_map_.point_mask_.at(i)) {
165 continue;
166 }
167 size_t index = bg_map_.point_idx_.at(i);
168 size_t cluster_label = mapping.at(bg_map_.bg_nodes_.at(index).id);
169 clusters_.AddPointSample(cluster_label, original_cloud->at(i), original_cloud->points_height(i), i);
170 }
172
173 for (int i = 0; i <= clusters_.size() - 1; i++) {
174 clusters_[i]->clear();
175 }
176 clusters_.Reset();
177
178 return true;
179}
void SegmentGraph(const int num_vertices, const int num_edges, Edge *edges, bool need_sort=true)
float NodeDistance(BgNode n1, int x1, int y1, BgNode n2, int x2, int y2)
Compute node distance
void GetObjectsFromClusters(LidarFrame *frame)
Get the Objects From Clusters
void AddPointSample(size_t cluster_id, const base::PointF &point, float height, uint32_t point_id)

◆ SetBgObjectDefaulVal()

bool apollo::perception::lidar::GraphSegmentation::SetBgObjectDefaulVal ( LidarFrame *  frame)

Set the Bacground Object Defaul Value

参数
frame

在文件 graph_segmentation.cc 第 300 行定义.

300 {
301 int start_index = frame->segmented_objects.size();
302 for (size_t i = 0; i < bg_objects_.size(); i++) {
303 std::shared_ptr<base::Object> object = bg_objects_.at(i);
304 object->id = start_index++;
305 object->lidar_supplement.is_in_roi = true;
306 object->lidar_supplement.is_background = true;
307 object->lidar_supplement.is_clustered = true;
308 // classification
309 object->type = base::ObjectType::UNKNOWN;
310 object->lidar_supplement.raw_probs.push_back(
311 std::vector<float>(static_cast<int>(base::ObjectType::MAX_OBJECT_TYPE), 0.f));
312 object->lidar_supplement.raw_probs.back()[static_cast<int>(object->type)] = 1.0f;
313 object->lidar_supplement.raw_classification_methods.push_back(Name());
314 // copy to type
315 object->type_probs.assign(
316 object->lidar_supplement.raw_probs.back().begin(), object->lidar_supplement.raw_probs.back().end());
317 // lidar supplement detections
318 object->lidar_supplement.detections.resize(7);
319 for (size_t jj = 0; jj < 7; jj++) {
320 object->lidar_supplement.detections[jj] = 0.0;
321 }
322 }
323 return true;
324}
std::string Name() const override
Get class name

◆ Split()

bool apollo::perception::lidar::GraphSegmentation::Split ( LidarFrame *  frame)

background filter

参数
framelidar frame
返回
true
false

在文件 graph_segmentation.cc 第 254 行定义.

254 {
255 std::vector<std::shared_ptr<base::Object>> split_objects;
256 // record object number
257 int before_split_num = bg_objects_.size();
258
259 int valid_number = 0;
260 for (size_t i = 0; i < bg_objects_.size(); i++) {
261 std::shared_ptr<base::Object> obj = bg_objects_.at(i);
262 if (NeedSplit(obj)) {
263 std::vector<base::ObjectPtr> this_split;
264 SplitObject(obj, &this_split, bg_config_.split_distance());
265 BgObjectBuilder(&this_split, frame->lidar2novatel_extrinsics);
266 split_objects.insert(split_objects.end(), this_split.begin(), this_split.end());
267 continue;
268 }
269 bg_objects_.at(valid_number) = obj;
270 valid_number += 1;
271 }
272 int split_number = bg_objects_.size() - valid_number;
273 bg_objects_.resize(valid_number);
274
275 // put all split object to bg_objects_
276 bg_objects_.insert(bg_objects_.end(), split_objects.begin(), split_objects.end());
277 int after_split_num = bg_objects_.size();
278
279 AINFO << "Before split object number: " << before_split_num << ", split number: " << split_number
280 << ", after split number: " << after_split_num;
281 return true;
282}
bool NeedSplit(std::shared_ptr< base::Object > object)
judge if the object need to split
void SplitObject(const base::ObjectPtr &obj, std::vector< base::ObjectPtr > *split_objs, float split_distance)
split object

该类的文档由以下文件生成: