Apollo 10.0
自动驾驶开放平台
lslidarCXV4_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
25 LslidarParser(config), previous_packet_stamp_(0), gps_base_usec_(0) {
26 vertical_angle_ = config.vertical_angle();
27 distance_unit_ = config.distance_unit();
28 is_new_c32w_ = true;
29 is_get_scan_altitude_ = false;
30 AERROR << "vertical_angle_ " << vertical_angle_;
31 if (config_.model() == LSLIDAR_C16_V4) {
32 lidar_number_ = 16;
33 AERROR << "lidar: c16";
34 for (int i = 0; i < 16; ++i) {
35 sin_scan_altitude[i] = sin(c16_vertical_angle[i] * DEG_TO_RAD);
36 cos_scan_altitude[i] = cos(c16_vertical_angle[i] * DEG_TO_RAD);
37 }
38 } else if (config_.model() == LSLIDAR_C8_V4) {
39 lidar_number_ = 8;
40 AERROR << "lidar: c8";
41 for (int i = 0; i < 8; ++i) {
42 sin_scan_altitude[i] = sin(c8_vertical_angle[i] * DEG_TO_RAD);
43 cos_scan_altitude[i] = cos(c8_vertical_angle[i] * DEG_TO_RAD);
44 }
45 } else if (config_.model() == LSLIDAR_C1_V4) {
46 lidar_number_ = 1;
47 AERROR << "lidar: c1";
48 for (int i = 0; i < 8; ++i) {
49 sin_scan_altitude[i] = sin(c1_vertical_angle[i] * DEG_TO_RAD);
50 cos_scan_altitude[i] = cos(c1_vertical_angle[i] * DEG_TO_RAD);
51 }
52 } else if (config_.model() == LSLIDAR_C32_V4) {
53 lidar_number_ = 32;
54 if (32 == config.vertical_angle()) {
55 AERROR << "Vertical angle: 32 degrees";
56 for (int i = 0; i < 32; ++i) {
57 sin_scan_altitude[i]
58 = sin(c32_32_vertical_angle[i] * DEG_TO_RAD);
59 cos_scan_altitude[i]
60 = cos(c32_32_vertical_angle[i] * DEG_TO_RAD);
61 }
62 } else if (70 == config.vertical_angle()) {
63 AERROR << "Vertical angle: 70 degrees";
64 for (int k = 0; k < 32; ++k) {
65 sin_scan_altitude[k]
66 = sin(c32_70_vertical_angle2[k] * DEG_TO_RAD);
67 cos_scan_altitude[k]
68 = cos(c32_70_vertical_angle2[k] * DEG_TO_RAD);
69 }
70 } else if (90 == config.vertical_angle()) {
71 AERROR << "Vertical angle: 90 degrees";
72 for (int k = 0; k < 32; ++k) {
73 sin_scan_altitude[k]
74 = sin(c32_90_vertical_angle[k] * DEG_TO_RAD);
75 cos_scan_altitude[k]
76 = cos(c32_90_vertical_angle[k] * DEG_TO_RAD);
77 }
78 }
79 }
80
81 // create the sin and cos table for different azimuth values
82 for (int j = 0; j < 36000; ++j) {
83 double angle = static_cast<double>(j) / 100.0 * DEG_TO_RAD;
84 sin_azimuth_table[j] = sin(angle);
85 cos_azimuth_table[j] = cos(angle);
86 }
87 config_vert_angle = false;
88 lslidar_type = 2;
89}
90
92 // couputer azimuth angle for each firing, 12
93 for (size_t b_idx = 0; b_idx < BLOCKS_PER_PACKET; ++b_idx) {
94 firings.firing_azimuth[b_idx] = packet->blocks[b_idx].rotation
95 % 36000; //* 0.01 * DEG_TO_RAD;
96 }
97 for (size_t block_idx = 0; block_idx < BLOCKS_PER_PACKET; ++block_idx) {
98 const RawBlock &raw_block = packet->blocks[block_idx];
99
100 int32_t azimuth_diff_b = 0;
101 if (config_.return_mode() == 1) {
102 if (block_idx < BLOCKS_PER_PACKET - 1) {
103 azimuth_diff_b = firings.firing_azimuth[block_idx + 1]
104 - firings.firing_azimuth[block_idx];
105 azimuth_diff_b = azimuth_diff_b < 0 ? azimuth_diff_b + 36000
106 : azimuth_diff_b;
107
108 } else {
109 azimuth_diff_b = firings.firing_azimuth[block_idx]
110 - firings.firing_azimuth[block_idx - 1];
111
112 azimuth_diff_b = azimuth_diff_b < 0 ? azimuth_diff_b + 36000
113 : azimuth_diff_b;
114 }
115 } else {
116 // return mode 2
117 if (block_idx < BLOCKS_PER_PACKET - 2) {
118 azimuth_diff_b = firings.firing_azimuth[block_idx + 2]
119 - firings.firing_azimuth[block_idx];
120 azimuth_diff_b = azimuth_diff_b < 0 ? azimuth_diff_b + 36000
121 : azimuth_diff_b;
122
123 } else {
124 azimuth_diff_b = firings.firing_azimuth[block_idx]
125 - firings.firing_azimuth[block_idx - 2];
126
127 azimuth_diff_b = azimuth_diff_b < 0 ? azimuth_diff_b + 36000
128 : azimuth_diff_b;
129 }
130 }
131
132 // 32 scan
133 for (size_t scan_fir_idx = 0; scan_fir_idx < SCANS_PER_FIRING_C32;
134 ++scan_fir_idx) {
135 size_t byte_idx = RAW_SCAN_SIZE * scan_fir_idx;
136 // azimuth
137 firings.azimuth[block_idx * 32 + scan_fir_idx]
138 = firings.firing_azimuth[block_idx]
139 + scan_fir_idx * azimuth_diff_b / FIRING_TOFFSET_C32;
140 firings.azimuth[block_idx * 32 + scan_fir_idx]
141 = firings.azimuth[block_idx * 32 + scan_fir_idx] % 36000;
142 // distance
143 TwoBytes raw_distance{};
144 raw_distance.bytes[0] = raw_block.data[byte_idx];
145 raw_distance.bytes[1] = raw_block.data[byte_idx + 1];
146 firings.distance[block_idx * 32 + scan_fir_idx]
147 = static_cast<double>(raw_distance.distance)
148 * DISTANCE_RESOLUTION * distance_unit_;
149
150 // intensity
151 firings.intensity[block_idx * 32 + scan_fir_idx]
152 = static_cast<double>(raw_block.data[byte_idx + 2]);
153 }
154 }
155 return;
156}
157
159 for (size_t blk_idx = 0; blk_idx < BLOCKS_PER_PACKET; ++blk_idx) {
160 if (packet->blocks[blk_idx].header != UPPER_BANK) {
161 return false;
162 }
163 }
164 return true;
165}
166
168 const std::shared_ptr<LslidarScan> &scan_msg,
169 const std::shared_ptr<PointCloud> &out_msg) {
170 // allocate a point cloud with same time and frame ID as raw data
171 out_msg->mutable_header()->set_timestamp_sec(
172 scan_msg->basetime() / 1000000000.0);
173 out_msg->mutable_header()->set_module_name(
174 scan_msg->header().module_name());
175 out_msg->mutable_header()->set_frame_id(scan_msg->header().frame_id());
176 out_msg->set_height(1);
177 out_msg->set_measurement_time(scan_msg->basetime() / 1000000000.0);
178 out_msg->mutable_header()->set_sequence_num(
179 scan_msg->header().sequence_num());
180 gps_base_usec_ = scan_msg->basetime();
181
182 const unsigned char *difop_ptr
183 = (const unsigned char *)scan_msg->difop_pkts(0).data().c_str();
184 if (difop_ptr[0] == 0xa5 && difop_ptr[1] == 0xff && difop_ptr[2] == 0x00
185 && difop_ptr[3] == 0x5a) {
186 AINFO << "设备包,暂时用不上..."; // todo 暂时不用设备包
187 }
188
189 size_t packets_size = scan_msg->firing_pkts_size();
190 block_num = 0;
191 packet_number_ = packets_size;
192
193 AINFO << "packets_size :" << packets_size;
194
195 for (size_t i = 0; i < packets_size; ++i) {
196 Unpack(scan_msg->firing_pkts(static_cast<int>(i)), out_msg, i);
197 last_time_stamp_ = out_msg->measurement_time();
198 ADEBUG << "stamp: " << std::fixed << last_time_stamp_;
199 }
200
201 if (out_msg->point().empty()) {
202 // we discard this pointcloud if empty
203 AERROR << "All points is NAN!Please check lslidar:" << config_.model();
204 }
205
206 // set default width
207 out_msg->set_width(out_msg->point_size());
208}
209
214void LslidarCXV4Parser::Unpack(
215 const LslidarPacket &pkt,
216 std::shared_ptr<PointCloud> pc,
217 int packet_number) {
218 double point_time;
220 = (const RawPacket_C32 *)(pkt.data().c_str());
221 uint8_t *data = reinterpret_cast<uint8_t *>(
222 const_cast<char *>(pkt.data().c_str()));
223
224 // check if the packet is valid
226 return;
227
228 // decode the packet
230
231 if (!is_get_scan_altitude_
232 && static_cast<uint16_t>(data[1211]) == 0x46) { // old C32w
233 AERROR << "byte[1211] == 0x46: old C32W";
234 is_new_c32w_ = false;
235 for (int k = 0; k < 32; ++k) {
236 sin_scan_altitude[k] = sin(c32_70_vertical_angle[k] * DEG_TO_RAD);
237 cos_scan_altitude[k] = cos(c32_70_vertical_angle[k] * DEG_TO_RAD);
238 }
239 is_get_scan_altitude_ = true;
240 }
241
242 for (size_t fir_idx = 0; fir_idx < SCANS_PER_PACKET; ++fir_idx) {
243 if (!is_new_c32w_ && vertical_angle_ == 70) {
244 if (fir_idx % 32 == 29 || fir_idx % 32 == 6 || fir_idx % 32 == 14
245 || fir_idx % 32 == 22 || fir_idx % 32 == 30 || fir_idx % 32 == 7
246 || fir_idx % 32 == 15 || fir_idx % 32 == 23) {
247 firings.azimuth[fir_idx] += 389;
248 }
249 if (firings.azimuth[fir_idx] > 36000)
250 firings.azimuth[fir_idx] -= 36000;
251 }
252 // convert the point to xyz coordinate
253 size_t table_idx = firings.azimuth[fir_idx];
254 double cos_azimuth = cos_azimuth_table[table_idx];
255 double sin_azimuth = sin_azimuth_table[table_idx];
256 double x_coord, y_coord, z_coord;
257 bool coordinate_opt = true;
258 double R1 = 0.0;
259 if (vertical_angle_ == 90) { // ch32r
260 R1 = CX4_R1_90;
261 } else if (is_new_c32w_) { // new C32w
262 R1 = CX4_C32W;
263 } else { // others
264 R1 = CX4_R1_;
265 }
266 double conversionAngle = (vertical_angle_ == 90)
267 ? CX4_conversionAngle_90
268 : CX4_conversionAngle_;
269 if (coordinate_opt) {
270 x_coord = firings.distance[fir_idx]
271 * cos_scan_altitude[fir_idx % lidar_number_]
272 * cos_azimuth
273 + R1
274 * cos((conversionAngle
275 - firings.azimuth[fir_idx] * 0.01)
276 * DEG_TO_RAD);
277 y_coord = -firings.distance[fir_idx]
278 * cos_scan_altitude[fir_idx % lidar_number_]
279 * sin_azimuth
280 + R1
281 * sin((conversionAngle
282 - firings.azimuth[fir_idx] * 0.01)
283 * DEG_TO_RAD);
284 z_coord = firings.distance[fir_idx]
285 * sin_scan_altitude[fir_idx % lidar_number_];
286
287 } else {
288 // Y-axis correspondence 0 degree
289 x_coord = firings.distance[fir_idx]
290 * cos_scan_altitude[fir_idx % lidar_number_]
291 * sin_azimuth
292 + R1
293 * sin((firings.azimuth[fir_idx] * 0.01
294 - conversionAngle)
295 * DEG_TO_RAD);
296 y_coord = firings.distance[fir_idx]
297 * cos_scan_altitude[fir_idx % lidar_number_]
298 * cos_azimuth
299 + R1
300 * cos((firings.azimuth[fir_idx] * 0.01
301 - conversionAngle)
302 * DEG_TO_RAD);
303 z_coord = firings.distance[fir_idx]
304 * sin_scan_altitude[fir_idx % lidar_number_];
305 }
306
307 // computer the time of the point
308 if (last_packet_time > 1e-6) {
309 point_time = current_packet_time
311 * (SCANS_PER_PACKET - fir_idx - 1)
312 / SCANS_PER_PACKET;
313 } else {
314 point_time = current_packet_time;
315 }
316
317 if (firings.distance[fir_idx] > config_.max_range()
318 || firings.distance[fir_idx] < config_.min_range()) {
319 PointXYZIT *point = pc->add_point();
320 point->set_x(nan);
321 point->set_y(nan);
322 point->set_z(nan);
323 point->set_timestamp(point_time);
324 point->set_intensity(0);
325 } else {
326 if ((firings.azimuth[fir_idx] < config_.scan_start_angle())
327 || (firings.azimuth[fir_idx] > config_.scan_end_angle()))
328 continue;
329 if (packet_number == 0) {
330 if (firings.azimuth[fir_idx] > 30000) {
331 continue;
332 }
333 }
334
335 if (packet_number == packet_number_ - 1) {
336 if (firings.azimuth[fir_idx] < 10000) {
337 continue;
338 }
339 }
340
341 PointXYZIT *point = pc->add_point();
342 point->set_timestamp(point_time);
343
344 point->set_intensity(firings.intensity[fir_idx]);
345 if ((y_coord >= config_.bottom_left_x()
346 && y_coord <= config_.top_right_x())
347 && (-x_coord >= config_.bottom_left_y()
348 && -x_coord <= config_.top_right_y())) {
349 point->set_x(nan);
350 point->set_y(nan);
351 point->set_z(nan);
352 point->set_timestamp(point_time);
353 point->set_intensity(0);
354 } else {
355 point->set_x(y_coord);
356 point->set_y(-x_coord);
357 point->set_z(z_coord);
358 }
359 }
360 }
362}
363
364void LslidarCXV4Parser::Order(std::shared_ptr<PointCloud> cloud) {
365 int width = 32;
366 cloud->set_width(width);
367 int height = cloud->point_size() / cloud->width();
368 cloud->set_height(height);
369
370 std::shared_ptr<PointCloud> cloud_origin = std::make_shared<PointCloud>();
371 cloud_origin->CopyFrom(*cloud);
372
373 for (int i = 0; i < width; ++i) {
374 int col = ORDER_32[i];
375
376 for (int j = 0; j < height; ++j) {
377 // make sure offset is initialized, should be init at setup() just
378 // once
379 int target_index = j * width + i;
380 int origin_index = j * width + col;
381 cloud->mutable_point(target_index)
382 ->CopyFrom(cloud_origin->point(origin_index));
383 }
384 }
385}
386
387} // namespace parser
388} // namespace lslidar
389} // namespace drivers
390} // namespace apollo
void Order(std::shared_ptr< apollo::drivers::PointCloud > cloud)
void GeneratePointcloud(const std::shared_ptr< apollo::drivers::lslidar::LslidarScan > &scan_msg, const std::shared_ptr< apollo::drivers::PointCloud > &out_msg)
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
These classes Unpack raw Lslidar LIDAR packets into several useful formats.
#define DEG_TO_RAD
float cos(Angle16 a)
Definition angle.cc:42
float sin(Angle16 a)
Definition angle.cc:25
class register implement
Definition arena_queue.h:37
uint16_t firing_azimuth[BLOCKS_PER_PACKET]
uint8_t data[BLOCK_DATA_SIZE]
combine rotation1 and rotation2 together to get 0-35999, divide by 100 to get degrees