Apollo 10.0
自动驾驶开放平台
lslidar16_parser.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19namespace apollo {
20namespace drivers {
21namespace lslidar {
22namespace parser {
23
24float R1_ = 0.04376;
25float R2_ = 0.010875;
26
28 LslidarParser(config), previous_packet_stamp_(0), gps_base_usec_(0) {
30 config_vert_angle = false;
32
33 if (2 == config_.degree_mode()) {
34 for (int i = 0; i < LSC16_SCANS_PER_FIRING; i++) {
36 = std::cos(scan_altitude_original_2[i]);
38 = std::sin(scan_altitude_original_2[i]);
39 scan_altitude[i] = scan_altitude_original_2[i];
40 }
41 } else if (1 == config_.degree_mode()) {
42 for (int i = 0; i < LSC16_SCANS_PER_FIRING; i++) {
44 = std::cos(scan_altitude_original_1[i]);
46 = std::sin(scan_altitude_original_1[i]);
47 scan_altitude[i] = scan_altitude_original_1[i];
48 }
49 }
50
51 for (uint16_t rot_index = 0; rot_index < ROTATION_MAX_UNITS; ++rot_index) {
52 float rotation = ROTATION_RESOLUTION
53 * static_cast<float>(rot_index * M_PI) / 180.0f;
54 cos_azimuth_table[rot_index] = cosf(rotation);
55 sin_azimuth_table[rot_index] = sinf(rotation);
56 }
57}
58
60 const std::shared_ptr<LslidarScan> &scan_msg,
61 const std::shared_ptr<PointCloud> &out_msg) {
62 // allocate a point cloud with same time and frame ID as raw data
63 out_msg->mutable_header()->set_timestamp_sec(
64 scan_msg->basetime() / 1000000000.0);
65 out_msg->mutable_header()->set_module_name(
66 scan_msg->header().module_name());
67 out_msg->mutable_header()->set_frame_id(scan_msg->header().frame_id());
68 out_msg->set_height(1);
69 out_msg->set_measurement_time(scan_msg->basetime() / 1000000000.0);
70 out_msg->mutable_header()->set_sequence_num(
71 scan_msg->header().sequence_num());
72 gps_base_usec_ = scan_msg->basetime();
73
74 const unsigned char *difop_ptr
75 = (const unsigned char *)scan_msg->difop_pkts(0).data().c_str();
76 uint8_t version_data = static_cast<uint8_t>(difop_ptr[1202]);
77
78 if (config_.config_vert()) {
79 if (2 == version_data) {
80 for (int i = 0; i < 16; i++) {
81 uint16_t vert_angle = static_cast<uint16_t>(
82 difop_ptr[234 + 2 * i] * 256
83 + difop_ptr[234 + 2 * i + 1]);
84
85 if (vert_angle > 32767) {
86 vert_angle = vert_angle - 65535;
87 }
88
90 = (static_cast<float>(vert_angle) / 100.f) * DEG_TO_RAD;
91 if (2 == config_.degree_mode()) {
92 if (scan_altitude[i] != 0) {
93 if (fabs(scan_altitude_original_2[i] - scan_altitude[i])
95 > 1.5) {
96 scan_altitude[i] = scan_altitude_original_2[i];
97 }
98 } else {
99 scan_altitude[i] = scan_altitude_original_2[i];
100 }
101 } else if (1 == config_.degree_mode()) {
102 if (scan_altitude[i] != 0) {
103 if (fabs(scan_altitude_original_1[i] - scan_altitude[i])
104 * RAD_TO_DEG
105 > 1.5) {
106 scan_altitude[i] = scan_altitude_original_1[i];
107 }
108 } else {
109 scan_altitude[i] = scan_altitude_original_1[i];
110 }
111 }
112 config_vert_angle = true;
113 }
114 } else {
115 for (int i = 0; i < 16; i++) {
116 uint16_t vert_angle = static_cast<uint16_t>(
117 difop_ptr[245 + 2 * i] * 256
118 + difop_ptr[245 + 2 * i + 1]);
119
120 if (vert_angle > 32767) {
121 vert_angle = vert_angle - 65535;
122 }
123
125 = (static_cast<float>(vert_angle) / 100.f) * DEG_TO_RAD;
126
127 if (2 == config_.degree_mode()) {
128 if (scan_altitude[i] != 0) {
129 if (fabs(scan_altitude_original_2[i] - scan_altitude[i])
130 * RAD_TO_DEG
131 > 1.5) {
132 scan_altitude[i] = scan_altitude_original_2[i];
133 }
134 } else {
135 scan_altitude[i] = scan_altitude_original_2[i];
136 }
137 } else if (1 == config_.degree_mode()) {
138 if (scan_altitude[i] != 0) {
139 if (fabs(scan_altitude_original_1[i] - scan_altitude[i])
140 * RAD_TO_DEG
141 > 1.5) {
142 scan_altitude[i] = scan_altitude_original_1[i];
143 }
144 } else {
145 scan_altitude[i] = scan_altitude_original_1[i];
146 }
147 }
148 config_vert_angle = true;
149 }
150 }
151 }
152
153 size_t packets_size = scan_msg->firing_pkts_size();
154 packet_number_ = packets_size;
155 block_num = 0;
156
157 for (size_t i = 0; i < packets_size; ++i) {
158 Unpack(scan_msg->firing_pkts(static_cast<int>(i)), out_msg, i);
159 last_time_stamp_ = out_msg->measurement_time();
160 ADEBUG << "***************stamp: " << std::fixed << last_time_stamp_;
161 }
162
163 if (out_msg->point().empty()) {
164 // we discard this pointcloud if empty
165 AERROR << "All points is NAN!Please check lslidar:" << config_.model();
166 }
167 // set default width
168 out_msg->set_width(out_msg->point_size());
169}
170
175void Lslidar16Parser::Unpack(
176 const LslidarPacket &pkt,
177 std::shared_ptr<PointCloud> pc,
178 int packet_number) {
179 float x, y, z;
180 float azimuth = 0.0f;
181 uint32_t intensity = 0;
182 float azimuth_diff = 0.0f;
183 float azimuth_corrected_f = 0.0f;
184 int azimuth_corrected = 0;
185 uint64_t point_time;
186 uint64_t packet_end_time;
187
188 if (config_vert_angle) {
189 for (int i = 0; i < LSC16_SCANS_PER_FIRING; i++) {
192 }
193 config_vert_angle = false;
194 }
195 const raw_packet_t *raw = (const raw_packet_t *)pkt.data().c_str();
196
198 packet_end_time = pkt.stamp();
199 } else {
200 packet_end_time = pkt.stamp();
201 }
202 current_packet_time = packet_end_time;
203 int point_count = -1;
204 for (int block = 0; block < BLOCKS_PER_PACKET; block++, block_num++) {
205 if (UPPER_BANK != raw->blocks[block].header)
206 break;
207
208 azimuth = static_cast<float>(
209 256 * raw->blocks[block].rotation_2
210 + raw->blocks[block].rotation_1);
211
212 if (2 == config_.return_mode()) {
213 if (block < (BLOCKS_PER_PACKET - 2)) {
214 int azi1, azi2;
215 azi1 = 256 * raw->blocks[block + 2].rotation_2
216 + raw->blocks[block + 2].rotation_1;
217 azi2 = 256 * raw->blocks[block].rotation_2
218 + raw->blocks[block].rotation_1;
219 azimuth_diff
220 = static_cast<float>((36000 + azi1 - azi2) % 36000);
221 } else {
222 int azi1, azi2;
223 azi1 = 256 * raw->blocks[block].rotation_2
224 + raw->blocks[block].rotation_1;
225 azi2 = 256 * raw->blocks[block - 2].rotation_2
226 + raw->blocks[block - 2].rotation_1;
227 azimuth_diff
228 = static_cast<float>((36000 + azi1 - azi2) % 36000);
229 }
230 } else {
231 if (block < (BLOCKS_PER_PACKET - 1)) {
232 int azi1, azi2;
233 azi1 = 256 * raw->blocks[block + 1].rotation_2
234 + raw->blocks[block + 1].rotation_1;
235 azi2 = 256 * raw->blocks[block].rotation_2
236 + raw->blocks[block].rotation_1;
237 azimuth_diff
238 = static_cast<float>((36000 + azi1 - azi2) % 36000);
239 } else {
240 int azi1, azi2;
241 azi1 = 256 * raw->blocks[block].rotation_2
242 + raw->blocks[block].rotation_1;
243 azi2 = 256 * raw->blocks[block - 1].rotation_2
244 + raw->blocks[block - 1].rotation_1;
245 azimuth_diff
246 = static_cast<float>((36000 + azi1 - azi2) % 36000);
247 }
248 }
249
250 float cos_azimuth;
251 float sin_azimuth;
252
253 for (int firing = 0, k = 0; firing < LSC16_FIRINGS_PER_BLOCK;
254 ++firing) {
255 for (int dsr = 0; dsr < LSC16_SCANS_PER_FIRING;
256 ++dsr, k += RAW_SCAN_SIZE) {
257 point_count++;
258 LaserCorrection &corrections
260
263 azimuth_corrected_f = azimuth
264 + azimuth_diff / (LSC16_SCANS_PER_FIRING * 2)
265 * (LSC16_SCANS_PER_FIRING * firing + dsr);
266
267 azimuth_corrected = static_cast<int>(
268 round(fmod(azimuth_corrected_f, 36000.0)));
269
270 cos_azimuth = cos_azimuth_table[azimuth_corrected];
271 sin_azimuth = sin_azimuth_table[azimuth_corrected];
272
273 // distance
274 union two_bytes tmp;
275 tmp.bytes[0] = raw->blocks[block].data[k];
276 tmp.bytes[1] = raw->blocks[block].data[k + 1];
277 int distance = tmp.uint;
278
279 // read intensity
280 intensity = raw->blocks[block].data[k + 2];
281
282 float distance2 = (distance * DISTANCE_RESOLUTION)
284
285 if (config_.calibration())
286 distance2 = distance2 + corrections.dist_correction;
287
288 // The offset calibration
289 float arg_horiz = static_cast<float>(
290 azimuth_corrected_f * ROTATION_RESOLUTION);
291 arg_horiz = arg_horiz > 360 ? (arg_horiz - 360) : arg_horiz;
292 float arg_horiz_orginal = (14.67 - arg_horiz) * M_PI / 180;
293
294 if (2 == config_.return_mode()) {
295 // modify
296 if (previous_packet_time > 1e-6) {
297 point_time = current_packet_time
298 - (SCANS_PER_PACKET - point_count - 1)
301 / (SCANS_PER_PACKET);
302 } else { // fist packet
303 point_time = current_packet_time;
304 }
305
306 } else {
307 // modify
308 if (previous_packet_time > 1e-6) {
309 point_time = current_packet_time
310 - (SCANS_PER_PACKET - point_count - 1)
313 / (SCANS_PER_PACKET);
314 } else { // fist packet
315 point_time = current_packet_time;
316 }
317 }
318
319 if ((azimuth_corrected < config_.scan_start_angle())
320 || (azimuth_corrected > config_.scan_end_angle()))
321 continue;
322 if (packet_number == 0) {
323 if (azimuth_corrected > 30000) {
324 continue;
325 }
326 }
327
328 if (packet_number == packet_number_ - 1) {
329 if (azimuth_corrected < 10000) {
330 continue;
331 }
332 }
333
334 if (distance2 > config_.max_range()
335 || distance2 < config_.min_range()) {
336 PointXYZIT *point = pc->add_point();
337 point->set_x(nan);
338 point->set_y(nan);
339 point->set_z(nan);
340 point->set_timestamp(point_time);
341 point->set_intensity(0);
342 } else {
343 PointXYZIT *point = pc->add_point();
344 point->set_timestamp(point_time);
345
346 point->set_intensity(intensity);
347
348 if (config_.calibration()) {
350 distance2,
351 &corrections,
352 static_cast<uint16_t>(azimuth_corrected),
353 point);
354
355 } else {
356 x = distance2 * cos_scan_altitude_caliration[dsr]
357 * cos_azimuth
358 + R1_ * cos(arg_horiz_orginal);
359 y = -distance2 * cos_scan_altitude_caliration[dsr]
360 * sin_azimuth
361 + R1_ * sin(arg_horiz_orginal);
362 z = distance2 * sin_scan_altitude_caliration[dsr]
363 + 0.426 / 100.f;
364
365 if ((y >= config_.bottom_left_x()
366 && y <= config_.top_right_x())
367 && (-x >= config_.bottom_left_y()
368 && -x <= config_.top_right_y())) {
369 point->set_x(nan);
370 point->set_y(nan);
371 point->set_z(nan);
372 point->set_timestamp(point_time);
373 point->set_intensity(0);
374 } else {
375 point->set_x(y);
376 point->set_y(-x);
377 point->set_z(z);
378 }
379 }
380 }
381 }
382 }
383 }
385}
386
387void Lslidar16Parser::Order(std::shared_ptr<PointCloud> cloud) {
388 int width = 16;
389 cloud->set_width(width);
390 int height = cloud->point_size() / cloud->width();
391 cloud->set_height(height);
392
393 std::shared_ptr<PointCloud> cloud_origin = std::make_shared<PointCloud>();
394 cloud_origin->CopyFrom(*cloud);
395
396 for (int i = 0; i < width; ++i) {
397 int col = ORDER_16[i];
398
399 for (int j = 0; j < height; ++j) {
400 // make sure offset is initialized, should be init at setup() just
401 // once
402 int target_index = j * width + i;
403 int origin_index = j * width + col;
404 cloud->mutable_point(target_index)
405 ->CopyFrom(cloud_origin->point(origin_index));
406 }
407 }
408}
409
410} // namespace parser
411} // namespace lslidar
412} // namespace drivers
413} // namespace apollo
std::map< int, LaserCorrection > laser_corrections_
Definition calibration.h:72
void GeneratePointcloud(const std::shared_ptr< apollo::drivers::lslidar::LslidarScan > &scan_msg, const std::shared_ptr< apollo::drivers::PointCloud > &out_msg)
void Order(std::shared_ptr< apollo::drivers::PointCloud > cloud)
double cos_scan_altitude_caliration[LSC32_SCANS_PER_FIRING]
void ComputeCoords(const float &raw_distance, LaserCorrection *corrections, const uint16_t rotation, PointXYZIT *point)
double sin_scan_altitude_caliration[LSC32_SCANS_PER_FIRING]
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
These classes Unpack raw Lslidar LIDAR packets into several useful formats.
#define DEG_TO_RAD
#define RAD_TO_DEG
float cos(Angle16 a)
Definition angle.cc:42
float sin(Angle16 a)
Definition angle.cc:25
struct apollo::drivers::lslidar::parser::raw_packet raw_packet_t
class register implement
Definition arena_queue.h:37