25 for (
int i = 0; i < 4; i++) {
26 gps_base_usec_[i] = 0;
27 previous_packet_stamp_[i] = 0;
53void Velodyne64Parser::SetBaseTimeFromPackets(
const VelodynePacket& pkt) {
59 static int year = -1, month = -1, day = -1, hour = -1, minute = -1,
61 static int gps_status = 0;
64 switch (status_type) {
66 year = status_value + 2000;
78 minute = status_value;
81 second = status_value;
84 gps_status = status_value;
90 AINFO <<
"Get base time from packets. Obtained (" << year <<
"." << month
91 <<
"." << day <<
" " << hour <<
":" << minute <<
":" << second;
93 if (status_type ==
GPS_STATUS && year > 0 && month > 0 && day > 0 &&
94 hour >= 0 && minute >= 0 && second >= 0) {
95 if (gps_status != 65) {
96 AWARN <<
"Sync failed because Velodyne-GPS Sync is NOT good! "
97 <<
"Status: " <<
static_cast<int>(gps_status)
98 <<
" (65 = both; 86 = gps only; 80 = PPS only; 0 "
99 <<
"= GPS not connected)";
102 time.tm_year = year - 1900;
103 time.tm_mon = month - 1;
112 uint64_t unix_base =
static_cast<uint64_t
>(timegm(&time));
113 for (
int i = 0; i < 4; ++i) {
114 gps_base_usec_[i] = unix_base * 1000000;
119void Velodyne64Parser::CheckGpsStatus(
const VelodynePacket& pkt) {
121 const RawPacket* raw = (
const RawPacket*)pkt.data().c_str();
123 char status_value = raw->status_value;
126 if (status_value != 65) {
127 AWARN <<
"Sync failed because Velodyne-GPS Sync is NOT good! "
128 <<
"Status: " <<
static_cast<int>(status_value)
129 <<
" (65 = both; 86 = gps only; 80 = PPS only; "
130 <<
"0 = GPS not connected)";
135void Velodyne64Parser::InitOffsets() {
138 for (
int i = 0; i <
width; ++i) {
144 static_cast<int>(corrections.rot_correction / ANGULAR_RESOLUTION + 0.5);
145 offsets_[i] = offset;
150 const std::shared_ptr<VelodyneScan>& scan_msg,
151 std::shared_ptr<PointCloud> pointcloud) {
153 if (online_calibration_.
decode(scan_msg) == -1) {
163 pointcloud->mutable_header()->set_frame_id(scan_msg->header().frame_id());
164 pointcloud->set_height(1);
165 pointcloud->mutable_header()->set_sequence_num(
166 scan_msg->header().sequence_num());
169 size_t packets_size = scan_msg->firing_pkts_size();
170 for (
size_t i = 0; i < packets_size; ++i) {
171 if (gps_base_usec_[0] == 0) {
173 SetBaseTimeFromPackets(scan_msg->firing_pkts(
static_cast<int>(i)));
177 CheckGpsStatus(scan_msg->firing_pkts(
static_cast<int>(i)));
178 Unpack(scan_msg->firing_pkts(
static_cast<int>(i)), pointcloud);
187 int size = pointcloud->point_size();
192 uint64_t timestamp = pointcloud->point(size - 1).timestamp();
193 pointcloud->set_measurement_time(
static_cast<double>(timestamp) / 1e9);
194 pointcloud->mutable_header()->set_lidar_timestamp(timestamp);
196 pointcloud->set_width(pointcloud->point_size());
200uint64_t Velodyne64Parser::GetTimestamp(
double base_time,
float time_offset,
202 double t = base_time - time_offset;
203 double timestamp = 0.0;
207 index = block_id & 1;
208 double& previous_packet_stamp = previous_packet_stamp_[index];
209 uint64_t& gps_base_usec = gps_base_usec_[index];
210 timestamp =
static_cast<double>(
211 GetGpsStamp(t, &previous_packet_stamp, &gps_base_usec));
213 index = block_id & 3;
214 double& previous_packet_stamp = previous_packet_stamp_[index];
215 uint64_t& gps_base_usec = gps_base_usec_[index];
216 timestamp =
static_cast<double>(
217 GetGpsStamp(t, &previous_packet_stamp, &gps_base_usec));
219 return static_cast<uint64_t
>(timestamp);
222int Velodyne64Parser::IntensityCompensate(
const LaserCorrection& corrections,
223 const uint16_t raw_distance,
225 float tmp = 1.0f -
static_cast<float>(raw_distance) / 65535.0f;
227 static_cast<int>(corrections.focal_slope *
228 (fabs(corrections.focal_offset - 256 * tmp * tmp)));
230 if (intensity < corrections.min_intensity) {
231 intensity = corrections.min_intensity;
234 if (intensity > corrections.max_intensity) {
235 intensity = corrections.max_intensity;
240void Velodyne64Parser::Unpack(
const VelodynePacket& pkt,
241 std::shared_ptr<PointCloud> pc) {
242 ADEBUG <<
"Received packet, time: " << pkt.stamp();
245 const RawPacket* raw = (
const RawPacket*)pkt.data().c_str();
246 double basetime = raw->gps_timestamp;
249 if (
mode_ != DUAL && !is_s2_ && ((i & 3) >> 1) > 0) {
256 int bank_origin = (raw->blocks[i].laser_block_id == LOWER_BANK) ? 32 : 0;
258 for (
int j = 0, k = 0; j < SCANS_PER_BLOCK;
259 ++j, k += RAW_SCAN_SIZE) {
261 uint8_t laser_number =
262 static_cast<uint8_t
>(j + bank_origin);
263 LaserCorrection& corrections =
266 union RawDistance raw_distance;
267 raw_distance.bytes[0] = raw->blocks[i].data[k];
268 raw_distance.bytes[1] = raw->blocks[i].data[k + 1];
272 static_cast<uint16_t
>(i));
274 if (j == SCANS_PER_BLOCK - 1) {
276 pc->set_measurement_time(
static_cast<double>(timestamp) / 1e9);
279 float real_distance = raw_distance.raw_distance * DISTANCE_RESOLUTION;
280 float distance = real_distance + corrections.dist_correction;
282 if (raw_distance.raw_distance == 0 ||
287 point_new->set_x(nan);
288 point_new->set_y(nan);
289 point_new->set_z(nan);
290 point_new->set_timestamp(timestamp);
291 point_new->set_intensity(0);
297 point->set_timestamp(timestamp);
299 ComputeCoords(real_distance, corrections, raw->blocks[i].rotation, point);
300 point->set_intensity(IntensityCompensate(
301 corrections, raw_distance.raw_distance, raw->blocks[i].data[k + 2]));
309 cloud->set_height(height);
310 int width = cloud->point_size() / cloud->height();
311 cloud->set_width(width);
313 std::shared_ptr<PointCloud> cloud_origin = std::make_shared<PointCloud>();
314 cloud_origin->CopyFrom(*cloud);
316 for (
int i = 0; i < height; ++i) {
319 for (
int j = 0; j < width; ++j) {
321 int row = (j + offsets_[i] + width) % width;
322 int target_index = j * height + i;
323 int origin_index = row * height + col;
324 cloud->mutable_point(target_index)
325 ->CopyFrom(cloud_origin->point(origin_index));
std::map< int, LaserCorrection > laser_corrections_
int decode(const std::shared_ptr< VelodyneScan > &scan_msgs)
Calibration calibration() const
void GeneratePointcloud(const std::shared_ptr< VelodyneScan > &scan_msg, std::shared_ptr< PointCloud > out_msg)
Set up for data processing.
Velodyne64Parser(const Config &config)
void setup() override
Set up for on-line operation.
void Order(std::shared_ptr< PointCloud > cloud)
Velodyne data conversion class
virtual void setup()
Set up for on-line operation.
const float(* inner_time_)[12][32]
bool is_scan_valid(int rotation, float distance)
uint64_t GetGpsStamp(double current_stamp, double *previous_stamp, uint64_t *gps_base_usec)
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
uint32_t width
Width of point cloud
const float INNER_TIME_64[12][32]
const float INNER_TIME_64E_S3[12][32]
constexpr int BLOCKS_PER_PACKET
optional bool calibration_online
unsigned char status_type
unsigned char status_value
Velodyne HDL-64E 3D LIDAR data accessors