110 {
112
113 boost::program_options::variables_map boost_args;
115 AERROR <<
"Parse input command line failed.";
116 return -1;
117 }
118
119 const std::vector<std::string> pcd_folder_paths =
120 boost_args["pcd_folders"].as<std::vector<std::string>>();
121 const std::vector<std::string> pose_files =
122 boost_args["pose_files"].as<std::vector<std::string>>();
123 if (pcd_folder_paths.size() != pose_files.size()) {
124 AERROR <<
"The count of pcd folders is not equal pose files";
125 return -1;
126 }
127
128 const std::string map_base_folder =
129 boost_args["map_folder"].as<std::string>();
130 bool use_plane_inliers_only = boost_args["use_plane_inliers_only"].as<bool>();
131
132
133 const int zone_id = boost_args["zone_id"].as<int>();
134 const std::string coordinate_type =
135 boost_args["coordinate_type"].as<std::string>();
136 if (strcasecmp(coordinate_type.c_str(), "UTM") != 0 &&
137 strcasecmp(coordinate_type.c_str(), "LTM") != 0) {
138 AERROR <<
"Coordinate type invalid. (UTM or LTM)";
139 return -1;
140 }
141 const std::string map_resolution_type =
142 boost_args["map_resolution_type"].as<std::string>();
143 if (strcasecmp(map_resolution_type.c_str(), "single") != 0 &&
144 strcasecmp(map_resolution_type.c_str(), "multi") != 0) {
145 AERROR <<
"Map resolution type invalid. (single or multi)";
146 return -1;
147 }
148
149 float single_resolution_map = boost_args["resolution"].as<float>();
150 if (fabs(single_resolution_map - 0.03125) > 1e-8 &&
151 fabs(single_resolution_map - 0.0625) > 1e-8 &&
152 fabs(single_resolution_map - 0.125) < 1e-8 &&
153 fabs(single_resolution_map - 0.25) < 1e-8 &&
154 fabs(single_resolution_map - 0.5) < 1e-8 &&
155 fabs(single_resolution_map - 1.0) < 1e-8 &&
156 fabs(single_resolution_map - 2.0) < 1e-8 &&
157 fabs(single_resolution_map - 4.0) < 1e-8 &&
158 fabs(single_resolution_map - 8.0) < 1e-8 &&
159 fabs(single_resolution_map - 16.0) < 1e-8) {
160 AWARN <<
"Map resolution can only be: 0.03125, "
161 << "0.0625, 0.125, 0.25, 0.5, 1.0, 2.0, "
162 << "4.0, 8.0 or 16.0.";
163 }
164
165 const size_t num_trials = pcd_folder_paths.size();
166
167
168 AINFO <<
"Pcd folders are as follows:";
169 for (size_t i = 0; i < num_trials; ++i) {
170 AINFO << pcd_folder_paths[i];
171 }
172 std::vector<EigenAffine3dVec> ieout_poses(num_trials);
173 std::vector<std::vector<double>> time_stamps(num_trials);
174 std::vector<std::vector<unsigned int>> pcd_indices(num_trials);
175 for (size_t i = 0; i < pose_files.size(); ++i) {
177 pose_files[i], &ieout_poses[i], &time_stamps[i], &pcd_indices[i]);
178 }
179
184 std::string map_folder_path = map_base_folder + "/lossless_map";
186 map.SetMapFolderPath(map_folder_path);
187 for (size_t i = 0; i < pcd_folder_paths.size(); ++i) {
188 map.AddDataset(pcd_folder_paths[i]);
189 }
190 if (strcasecmp(map_resolution_type.c_str(), "single") == 0) {
192 } else {
194 }
195
196 if (strcasecmp(coordinate_type.c_str(), "UTM") == 0) {
198 } else {
201 -1638400.0, -1638400.0, 1638400.0, 1638400.0);
202 }
203
204
205 char file_buf[1024];
206 snprintf(file_buf, sizeof(file_buf), "%s/lossless_map/config.xml",
207 map_base_folder.c_str());
208 loss_less_config.
Save(file_buf);
209
210 snprintf(file_buf, sizeof(file_buf), "%s/lossless_map/config.txt",
211 map_base_folder.c_str());
212 FILE* file = fopen(file_buf, "a");
213
214 if (file) {
216 fprintf(file, "Map coordinate type: %s\n",
218
219
220
221
222
223 fprintf(file, "Map compression: %d\n",
225 fprintf(file, "Map resolution: ");
228 }
229 fprintf(file, "\nMap size: %lf %lf %lf %lf\n",
234 fprintf(file,
"Map node size: %d x %d\n", loss_less_config.
map_node_size_x_,
236 fprintf(file, "Map row x col: \n");
238 fprintf(file, "%u x %u, ",
240 static_cast<unsigned int>(i)),
242 static_cast<unsigned int>(i)));
243 }
244 fprintf(file, "Map image max intensity: %lf\n",
246 fprintf(file, "Map image max var: %lf\n",
248 fprintf(file, "PCD folders: \n");
249 for (unsigned int trial = 0; trial < num_trials; ++trial) {
250 fprintf(file, "%s\n", pcd_folder_paths[trial].c_str());
251 }
252 fclose(file);
253 } else {
254 AERROR <<
"Can't open file: " << file_buf;
255 }
256
258 lossless_map_node_pool.Initial(&loss_less_config);
259 map.InitMapNodeCaches(12, 24);
260 map.AttachMapNodePool(&lossless_map_node_pool);
261
262 for (unsigned int trial = 0; trial < num_trials; ++trial) {
263 for (unsigned int frame_idx = 0; frame_idx < ieout_poses[trial].size();
264 ++frame_idx) {
265 unsigned int trial_frame_idx = frame_idx;
268 std::string pcd_file_path = absl::StrCat(
269 pcd_folder_paths[trial], "/", pcd_indices[trial][frame_idx], ".pcd");
270 const Eigen::Affine3d& pcd_pose = poses[trial_frame_idx];
272 pcd_file_path, trial_frame_idx, pcd_pose, &velodyne_frame, false);
273 AINFO <<
"Loaded " << velodyne_frame.
pt3ds.size()
274 << "3D Points at Trial: " << trial << " Frame: " << trial_frame_idx
275 << ".";
276
277 unsigned int resolution_id = 0;
278 unsigned int row = 0;
279 unsigned int col = 0;
280 for (
size_t i = 0; i < velodyne_frame.
pt3ds.size(); ++i) {
281 Eigen::Vector3d& pt3d_local = velodyne_frame.
pt3ds[i];
282 unsigned char intensity = velodyne_frame.
intensities[i];
283 Eigen::Vector3d pt3d_global = velodyne_frame.
pose * pt3d_local;
285 loss_less_config, pt3d_global, resolution_id, zone_id);
287 dynamic_cast<PyramidMapNode*
>(map.GetMapNodeSafe(map_node_index));
292 }
293
294 if (use_plane_inliers_only) {
296 pcl_pc->resize(velodyne_frame.
pt3ds.size());
297 for (
size_t i = 0; i < velodyne_frame.
pt3ds.size(); ++i) {
299 pt.x =
static_cast<float>(velodyne_frame.
pt3ds[i][0]);
300 pt.y =
static_cast<float>(velodyne_frame.
pt3ds[i][1]);
301 pt.z =
static_cast<float>(velodyne_frame.
pt3ds[i][2]);
302 pt.intensity =
static_cast<float>(velodyne_frame.
intensities[i]);
303 }
304
307
308 for (unsigned int k = 0; k < plane_pc->size(); ++k) {
309 const PclPointT& plane_pt = plane_pc->at(k);
310 Eigen::Vector3d pt3d_local_double;
311 pt3d_local_double[0] = plane_pt.x;
312 pt3d_local_double[1] = plane_pt.y;
313 pt3d_local_double[2] = plane_pt.z;
314 unsigned char intensity =
315 static_cast<unsigned char>(plane_pt.intensity);
316 Eigen::Vector3d pt3d_global = velodyne_frame.
pose * pt3d_local_double;
317 float ground_altitude = static_cast<float>(pt3d_global[2]);
319 loss_less_config, pt3d_global, resolution_id, zone_id);
321 dynamic_cast<PyramidMapNode*
>(map.GetMapNodeSafe(map_node_index));
328 }
329 }
330 }
331 }
332
333
334 double mean_height_diff = 0;
335 double var_height_diff = 0;
336 unsigned int count_height_diff = 0;
337 for (unsigned int trial = 0; trial < num_trials; ++trial) {
338 for (unsigned int i = 0; i < ieout_poses[trial].size(); ++i) {
339 const Eigen::Affine3d& ieout_pose = ieout_poses[trial][i];
340 const Eigen::Vector3d& pt3d = ieout_pose.translation();
341 unsigned int resolution_id = 0;
342 unsigned int row = 0;
343 unsigned int col = 0;
345 loss_less_config, pt3d, resolution_id, zone_id);
347 dynamic_cast<PyramidMapNode*
>(map.GetMapNodeSafe(map_node_index));
351
352 if (use_plane_inliers_only) {
353
354 std::vector<unsigned int> layer_counts;
355 const unsigned int* ground_count =
357 if (!ground_count) {
358 AERROR <<
"No ground layer, skip.";
359 continue;
360 }
361 if (*ground_count > 0) {
362
363
364 const float* ground_altitude =
366 if (!ground_altitude) {
367 AERROR <<
"No ground points, skip.";
368 continue;
369 }
370
371 double height_diff = pt3d[2] - *ground_altitude;
373 &count_height_diff, height_diff);
374 }
375 } else {
376
377 const unsigned int* count = map_matrix.
GetCountSafe(row, col);
378 if (*count > 0) {
380 double height_diff = pt3d[2] - *alt;
382 &count_height_diff, height_diff);
383 }
384 }
385 }
386 }
387
388 map.GetMapConfig().map_ground_height_offset_ =
389 static_cast<float>(mean_height_diff);
390 std::string config_path = map.GetMapConfig().map_folder_path_ + "/config.xml";
391 map.GetMapConfig().Save(config_path);
392 ADEBUG <<
"Mean: " << mean_height_diff <<
", Var: " << var_height_diff <<
".";
393 return 0;
394}
PointCloudPtrT & GetXYPlaneCloud()
void ExtractXYPlane(const PointCloudPtrT &cloud)
T GetMaxY() const
Get the max y of the rectangle.
T GetMaxX() const
Get the max x of the rectangle.
T GetMinX() const
Get the min x of the rectangle.
T GetMinY() const
Get the min y of the rectangle.
bool Save(const std::string &file_path)
Save the map option to a XML file.
unsigned int map_node_size_y_
The map node size in pixels.
std::vector< float > map_resolutions_
The pixel resolutions in the map in meters.
Rect2D< double > map_range_
The minimum and maximum UTM range in the map.
void SetMultiResolutions()
Set multi resolutions.
bool map_is_compression_
Enable the compression.
unsigned int map_node_size_x_
The map node size in pixels.
void SetSingleResolutions(float resolution=0.125)
Set single resolutions.
const BaseMapMatrix & GetMapCellMatrix() const
Get map cell matrix.
void SetIsChanged(bool is)
Set if the map node data has changed.
static unsigned int GetMapIndexRangeEast(const BaseMapConfig &option, unsigned int resolution_id)
Get the index range (maximum possible index + 1) in the east direction.
static MapNodeIndex GetMapNodeIndex(const BaseMapConfig &option, const Eigen::Vector3d &coordinate, unsigned int resolution_id, int zone_id)
Construct a map node index, given a global coordinate, eigen version.
static unsigned int GetMapIndexRangeNorth(const BaseMapConfig &option, unsigned int resolution_id)
Get the index range (maximum possible index + 1) in the north direction.
std::string coordinate_type_
coordinate type.
float max_intensity_value_
During the visualization (for example, Call the function get_image() of map node layer),...
float max_intensity_var_value_
During the visualization (for example, Call the function get_image() of map node layer),...
const unsigned int * GetGroundCountSafe(unsigned int row, unsigned int col, unsigned int level=0) const
Get a ground count value by check.
void SetGroundAltitudeSafe(float ground_altitude, unsigned int row, unsigned int col, unsigned int level=0)
Set an altitude ground value by check.
const float * GetAltitudeSafe(unsigned int row, unsigned int col, unsigned int level=0) const
Get an altitude value by check.
const unsigned int * GetCountSafe(unsigned int row, unsigned int col, unsigned int level=0) const
Get a count value by check.
const float * GetGroundAltitudeSafe(unsigned int row, unsigned int col, unsigned int level=0) const
Get an altitude ground value by check.
void SetIntensitySafe(float intensity, unsigned int row, unsigned int col, unsigned int level=0)
Set an intensity value by check.
bool GetCoordinate(const Eigen::Vector2d &coordinate, unsigned int level, unsigned int *x, unsigned int *y) const
Given the global coordinate, get the local 2D coordinate of the map cell matrix.
void VarianceOnline(double *mean, double *var, unsigned int *N, double x)
apollo::localization::msf::FeatureXYPlane::PointT PclPointT
apollo::localization::msf::FeatureXYPlane::PointCloudPtrT PclPointCloudPtrT
const unsigned int CAR_SENSOR_LASER_NUMBER
bool ParseCommandLine(int argc, char *argv[], boost::program_options::variables_map *vm)
apollo::localization::msf::FeatureXYPlane::PointCloudT PclPointCloudT
EigenVector< Eigen::Affine3d > EigenAffine3dVec
bool EnsureDirectory(const std::string &directory_path)
Check if a specified directory specified by directory_path exists.
void LoadPcds(const std::string &file_path, const unsigned int frame_index, const Eigen::Affine3d &pose, VelodyneFrame *velodyne_frame, bool is_global)
void LoadPcdPoses(const std::string &file_path, ::apollo::common::EigenAffine3dVec *poses, std::vector< double > *timestamps)
Load the PCD poses with their timestamps.
::apollo::common::EigenVector3dVec pt3ds
The 3D point cloud in this frame.
std::vector< unsigned char > intensities
The laser reflection values in this frames.
Eigen::Affine3d pose
The pose of the frame.