24 :
VelodyneParser(config), previous_firing_stamp_(0), gps_base_usec_(0) {
33 const std::shared_ptr<VelodyneScan>& scan_msg,
34 std::shared_ptr<PointCloud> out_msg) {
36 out_msg->mutable_header()->set_frame_id(scan_msg->header().frame_id());
37 out_msg->set_height(1);
38 out_msg->mutable_header()->set_sequence_num(
39 scan_msg->header().sequence_num());
40 gps_base_usec_ = scan_msg->basetime();
42 size_t packets_size = scan_msg->firing_pkts_size();
44 for (
size_t i = 0; i < packets_size; ++i) {
45 UnpackVLP32C(scan_msg->firing_pkts(
static_cast<int>(i)), out_msg);
48 for (
size_t i = 0; i < packets_size; ++i) {
49 Unpack(scan_msg->firing_pkts(
static_cast<int>(i)), out_msg);
54 int size = out_msg->point_size();
60 uint64_t timestamp = out_msg->point(size - 1).timestamp();
61 out_msg->set_measurement_time(
static_cast<double>(timestamp) / 1e9);
62 out_msg->mutable_header()->set_lidar_timestamp(timestamp);
66 out_msg->set_width(out_msg->point_size());
71uint64_t Velodyne32Parser::GetTimestamp(
double base_time,
float time_offset,
73 double t = base_time - time_offset;
75 t = base_time + time_offset;
78 if (t < previous_firing_stamp_) {
81 if (std::abs(previous_firing_stamp_ - t) > 3599000000) {
82 gps_base_usec_ +=
static_cast<uint64_t
>(3600 * 1e6);
84 <<
". current:" << t <<
", last time:" << previous_firing_stamp_;
86 (previous_firing_stamp_ - t > 34.560f) ||
87 (previous_firing_stamp_ - t < 34.559f)) {
88 AWARN <<
"Current stamp:" << std::fixed << t
89 <<
" less than previous stamp:" << previous_firing_stamp_
90 <<
". GPS time stamp maybe incorrect!";
92 }
else if (previous_firing_stamp_ != 0 &&
93 t - previous_firing_stamp_ > 100000) {
94 AERROR <<
"Current stamp:" << std::fixed << t
95 <<
" ahead previous stamp:" << previous_firing_stamp_
96 <<
" over 100ms. GPS time stamp incorrect!";
99 previous_firing_stamp_ = t;
101 uint64_t gps_stamp = gps_base_usec_ * 1000 +
static_cast<uint64_t
>(t * 1000);
106void Velodyne32Parser::UnpackVLP32C(
const VelodynePacket& pkt,
107 std::shared_ptr<PointCloud> pc) {
108 const RawPacket* raw = (
const RawPacket*)pkt.data().c_str();
114 double basetime =
static_cast<double>(raw->gps_timestamp);
115 float azimuth = 0.0f;
116 float azimuth_diff = 0.0f;
117 float last_azimuth_diff = 0.0f;
118 float azimuth_corrected_f = 0.0f;
119 int azimuth_corrected = 0;
122 azimuth =
static_cast<float>(raw->blocks[i].rotation);
124 azimuth_diff =
static_cast<float>(
125 (36000 + raw->blocks[i + 1].rotation - raw->blocks[i].rotation) %
127 last_azimuth_diff = azimuth_diff;
129 azimuth_diff = last_azimuth_diff;
131 for (
int laser_id = 0, k = 0; laser_id < SCANS_PER_BLOCK;
132 ++laser_id, k += RAW_SCAN_SIZE) {
135 union RawDistance raw_distance;
136 raw_distance.bytes[0] = raw->blocks[i].data[k];
137 raw_distance.bytes[1] = raw->blocks[i].data[k + 1];
142 static_cast<uint16_t
>(i));
144 azimuth_corrected_f =
145 azimuth + (azimuth_diff * (
static_cast<float>(laser_id) / 2.0f) *
146 CHANNEL_TDURATION / SEQ_TDURATION);
148 static_cast<int>(round(fmod(azimuth_corrected_f, 36000.0)));
150 float real_distance =
151 raw_distance.raw_distance * VLP32_DISTANCE_RESOLUTION;
152 float distance = real_distance + corrections.dist_correction;
156 if (raw_distance.raw_distance == 0 ||
160 point_new->set_x(nan);
161 point_new->set_y(nan);
162 point_new->set_z(nan);
163 point_new->set_timestamp(timestamp);
164 point_new->set_intensity(0);
170 point->set_timestamp(timestamp);
173 static_cast<uint16_t
>(azimuth_corrected), point);
174 point->set_intensity(raw->blocks[i].data[k + 2]);
179void Velodyne32Parser::Unpack(
const VelodynePacket& pkt,
180 std::shared_ptr<PointCloud> pc) {
182 const RawPacket* raw = (
const RawPacket*)pkt.data().c_str();
183 double basetime = raw->gps_timestamp;
186 for (
int laser_id = 0, k = 0; laser_id < SCANS_PER_BLOCK;
187 ++laser_id, k += RAW_SCAN_SIZE) {
190 union RawDistance raw_distance;
191 raw_distance.bytes[0] = raw->blocks[i].data[k];
192 raw_distance.bytes[1] = raw->blocks[i].data[k + 1];
195 uint64_t
timestamp =
static_cast<uint64_t
>(GetTimestamp(
196 basetime, (*
inner_time_)[i][laser_id],
static_cast<uint16_t
>(i)));
198 int rotation =
static_cast<int>(raw->blocks[i].rotation);
199 float real_distance = raw_distance.raw_distance * DISTANCE_RESOLUTION;
200 float distance = real_distance + corrections.dist_correction;
202 if (raw_distance.raw_distance == 0 ||
207 point_new->set_x(nan);
208 point_new->set_y(nan);
209 point_new->set_z(nan);
210 point_new->set_timestamp(timestamp);
211 point_new->set_intensity(0);
217 point->set_timestamp(timestamp);
219 ComputeCoords(real_distance, corrections,
static_cast<uint16_t
>(rotation),
221 point->set_intensity(raw->blocks[i].data[k + 2]);
232 cloud->set_width(width);
233 int height = cloud->point_size() / cloud->width();
234 cloud->set_height(height);
236 std::shared_ptr<PointCloud> cloud_origin = std::make_shared<PointCloud>();
237 cloud_origin->CopyFrom(*cloud);
239 for (
int i = 0; i < width; ++i) {
242 for (
int j = 0; j < height; ++j) {
244 int target_index = j * width + i;
245 int origin_index = j * width + col;
246 cloud->mutable_point(target_index)
247 ->CopyFrom(cloud_origin->point(origin_index));
std::map< int, LaserCorrection > laser_corrections_
void Order(std::shared_ptr< PointCloud > cloud)
Velodyne32Parser(const Config &config)
void GeneratePointcloud(const std::shared_ptr< VelodyneScan > &scan_msg, std::shared_ptr< PointCloud > out_msg)
Set up for data processing.
Velodyne data conversion class
const float(* inner_time_)[12][32]
bool is_scan_valid(int rotation, float distance)
bool need_two_pt_correction_
void ComputeCoords(const float &raw_distance, const LaserCorrection &corrections, const uint16_t rotation, PointXYZIT *point)
Compute coords with the data in block
const float INNER_TIME_HDL32E[12][32]
const int ORDER_HDL32E[32]
const float INNER_TIME_VLP32C[12][32]
constexpr int BLOCKS_PER_PACKET
Velodyne HDL-64E 3D LIDAR data accessors