Apollo 10.0
自动驾驶开放平台
velodyne16_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 velodyne {
22
24 : VelodyneParser(config), previous_packet_stamp_(0), gps_base_usec_(0) {
27}
28
30 const std::shared_ptr<VelodyneScan>& scan_msg,
31 std::shared_ptr<PointCloud> out_msg) {
32 // allocate a point cloud with same time and frame ID as raw data
33 out_msg->mutable_header()->set_frame_id(scan_msg->header().frame_id());
34 out_msg->set_height(1);
35 out_msg->mutable_header()->set_sequence_num(
36 scan_msg->header().sequence_num());
37 gps_base_usec_ = scan_msg->basetime();
38
39 size_t packets_size = scan_msg->firing_pkts_size();
40 for (size_t i = 0; i < packets_size; ++i) {
41 Unpack(scan_msg->firing_pkts(static_cast<int>(i)), out_msg);
42 last_time_stamp_ = out_msg->measurement_time();
43 ADEBUG << "stamp: " << std::fixed << last_time_stamp_;
44 }
45
46 if (out_msg->point().empty()) {
47 // we discard this pointcloud if empty
48 AERROR << "All points is NAN!Please check velodyne:" << config_.model();
49 }
50
51 // set default width
52 out_msg->set_width(out_msg->point_size());
53}
54
55uint64_t Velodyne16Parser::GetTimestamp(double base_time, float time_offset,
56 uint16_t block_id) {
57 double t = base_time - time_offset;
58 uint64_t timestamp = Velodyne16Parser::GetGpsStamp(t, &previous_packet_stamp_,
59 &gps_base_usec_);
60 return timestamp;
61}
62
68void Velodyne16Parser::Unpack(const VelodynePacket& pkt,
69 std::shared_ptr<PointCloud> pc) {
70 float azimuth_diff = 0.0f;
71 float last_azimuth_diff = 0.0f;
72 float azimuth_corrected_f = 0.0f;
73 int azimuth_corrected = 0;
74
75 // const RawPacket* raw = (const RawPacket*)&pkt.data[0];
76 const RawPacket* raw = (const RawPacket*)pkt.data().c_str();
77 double basetime = raw->gps_timestamp; // usec
78
79 for (int block = 0; block < BLOCKS_PER_PACKET; block++) {
80 float azimuth = static_cast<float>(raw->blocks[block].rotation);
81 if (block < (BLOCKS_PER_PACKET - 1)) {
82 azimuth_diff =
83 static_cast<float>((36000 + raw->blocks[block + 1].rotation -
84 raw->blocks[block].rotation) %
85 36000);
86 last_azimuth_diff = azimuth_diff;
87 } else {
88 azimuth_diff = last_azimuth_diff;
89 }
90
91 for (int firing = 0, k = 0; firing < VLP16_FIRINGS_PER_BLOCK; ++firing) {
92 for (int dsr = 0; dsr < VLP16_SCANS_PER_FIRING;
93 ++dsr, k += RAW_SCAN_SIZE) {
94 LaserCorrection& corrections = calibration_.laser_corrections_[dsr];
95
97 union RawDistance raw_distance;
98 raw_distance.bytes[0] = raw->blocks[block].data[k];
99 raw_distance.bytes[1] = raw->blocks[block].data[k + 1];
100
103 azimuth_corrected_f =
104 azimuth + (azimuth_diff *
105 ((static_cast<float>(dsr) * VLP16_DSR_TOFFSET) +
106 (static_cast<float>(firing) * VLP16_FIRING_TOFFSET)) /
107 VLP16_BLOCK_TDURATION);
108 azimuth_corrected =
109 static_cast<int>(round(fmod(azimuth_corrected_f, 36000.0)));
110
111 // set 4th param to LOWER_BANK, only use lower_gps_base_usec_ and
112 // lower_previous_packet_stamp_
113 uint64_t timestamp = GetTimestamp(
114 basetime,
115 (*inner_time_)[block][firing * VLP16_SCANS_PER_FIRING + dsr],
116 LOWER_BANK);
117
118 if (block == BLOCKS_PER_PACKET - 1 &&
119 firing == VLP16_FIRINGS_PER_BLOCK - 1 &&
120 dsr == VLP16_SCANS_PER_FIRING - 1) {
121 // set header stamp before organize the point cloud
122 pc->set_measurement_time(static_cast<double>(timestamp) / 1e9);
123 }
124
125 float real_distance = raw_distance.raw_distance * DISTANCE_RESOLUTION;
126 float distance = real_distance + corrections.dist_correction;
127
128 if (raw_distance.raw_distance == 0 ||
129 !is_scan_valid(azimuth_corrected, distance)) {
130 // if organized append a nan point to the cloud
131 if (config_.organized()) {
132 PointXYZIT* point = pc->add_point();
133 point->set_x(nan);
134 point->set_y(nan);
135 point->set_z(nan);
136 point->set_timestamp(timestamp);
137 point->set_intensity(0);
138 }
139
140 continue;
141 }
142 PointXYZIT* point = pc->add_point();
143 point->set_timestamp(timestamp);
144 // append this point to the cloud
145 ComputeCoords(real_distance, corrections,
146 static_cast<uint16_t>(azimuth_corrected), point);
147 point->set_intensity(raw->blocks[block].data[k + 2]);
148 // append this point to the cloud
149
150 if (block == 0 && firing == 0) {
151 ADEBUG << "point x:" << point->x() << " y:" << point->y()
152 << " z:" << point->z()
153 << " intensity:" << int(point->intensity());
154 }
155 }
156 }
157 }
158}
159
160void Velodyne16Parser::Order(std::shared_ptr<PointCloud> cloud) {
161 int width = 16;
162 cloud->set_width(width);
163 int height = cloud->point_size() / cloud->width();
164 cloud->set_height(height);
165
166 std::shared_ptr<PointCloud> cloud_origin = std::make_shared<PointCloud>();
167 cloud_origin->CopyFrom(*cloud);
168
169 for (int i = 0; i < width; ++i) {
170 int col = velodyne::ORDER_16[i];
171
172 for (int j = 0; j < height; ++j) {
173 // make sure offset is initialized, should be init at setup() just once
174 int target_index = j * width + i;
175 int origin_index = j * width + col;
176 cloud->mutable_point(target_index)
177 ->CopyFrom(cloud_origin->point(origin_index));
178 }
179 }
180}
181
182} // namespace velodyne
183} // namespace drivers
184} // namespace apollo
std::map< int, LaserCorrection > laser_corrections_
Definition calibration.h:70
void GeneratePointcloud(const std::shared_ptr< VelodyneScan > &scan_msg, std::shared_ptr< PointCloud > out_msg)
Set up for data processing.
void Order(std::shared_ptr< PointCloud > cloud)
bool is_scan_valid(int rotation, float distance)
uint64_t GetGpsStamp(double current_stamp, double *previous_stamp, uint64_t *gps_base_usec)
void ComputeCoords(const float &raw_distance, const LaserCorrection &corrections, const uint16_t rotation, PointXYZIT *point)
Compute coords with the data in block
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
const float INNER_TIME_16[12][32]
const int ORDER_16[16]
Order array for re-ordering point cloud.
constexpr int BLOCKS_PER_PACKET
Definition driver.h:33
class register implement
Definition arena_queue.h:37
Velodyne HDL-64E 3D LIDAR data accessors