19 #include <std_msgs/Int8.h> 24 LslidarC16Decoder::LslidarC16Decoder(
28 publish_point_cloud(true),
31 sweep_start_time(0.0),
33 packet_start_time(0.0),
34 sweep_data(new lslidar_c16_msgs::LslidarC16Sweep()),
35 multi_scan(new lslidar_c16_msgs::LslidarC16Layer())
49 double tmp_min, tmp_max;
50 ROS_WARN(
"discard Point cloud angle from %2.2f to %2.2f", angle3_disable_min, angle3_disable_max);
53 angle3_disable_min = tmp_min;
54 angle3_disable_max = tmp_max;
55 ROS_WARN(
"switch angle from %2.2f to %2.2f in left hand rule", angle3_disable_min, angle3_disable_max);
64 ROS_WARN(
"Using GPS timestamp or not %d", use_gps_ts);
69 ROS_INFO(
"require to publish scan type message");
71 ROS_WARN(
"scan message not publish");
75 ROS_WARN(
"This is apollo interface mode");
87 "lslidar_point_cloud", 10);
97 ROS_ERROR(
"Cannot load all required parameters...");
107 for (
size_t scan_idx = 0; scan_idx < 16; ++scan_idx) {
108 size_t remapped_scan_idx = scan_idx%2 == 0 ? scan_idx/2 : scan_idx/2+8;
113 for (
size_t i = 0; i < 6300; ++i) {
114 double angle =
static_cast<double>(i) / 1000.0;
136 pcl::PointCloud<pcl::PointXYZI>::Ptr point_cloud(
new pcl::PointCloud<pcl::PointXYZI>);
138 point_cloud->header.frame_id =
frame_id;
139 point_cloud->height = 1;
141 for (
size_t i = 0; i < 16; ++i) {
142 const lslidar_c16_msgs::LslidarC16Scan& scan =
sweep_data->scans[i];
152 point_cloud->header.stamp =
static_cast<uint64_t
>(timestamp * 1e6);
155 if (scan.points.size() == 0)
continue;
157 pcl::PointXYZI point;
158 for (j = 1; j < scan.points.size()-1; ++j) {
163 point.x = scan.points[j].x;
164 point.y = scan.points[j].y;
165 point.z = scan.points[j].z;
166 point.intensity = scan.points[j].intensity;
167 point_cloud->points.push_back(point);
168 ++point_cloud->width;
172 sensor_msgs::PointCloud2 pc_msg;
218 multi_scan = lslidar_c16_msgs::LslidarC16LayerPtr(
219 new lslidar_c16_msgs::LslidarC16Layer());
221 sensor_msgs::LaserScan scan;
225 if(
sweep_data->scans[layer_num_local].points.size() <= 1)
228 for (uint16_t j=0; j<16; j++)
233 scan.angle_min = 0.0;
234 scan.angle_max = 2.0*M_PI;
235 scan.angle_increment = (scan.angle_max - scan.angle_min)/
point_num;
241 scan.ranges.assign(
point_num, std::numeric_limits<float>::infinity());
244 scan.intensities.assign(
point_num, std::numeric_limits<float>::infinity());
246 for(uint16_t i = 0; i <
sweep_data->scans[j].points.size(); i++)
248 double point_azimuth =
sweep_data->scans[j].points[i].azimuth;
267 scan.ranges[i] = std::numeric_limits<float>::infinity();
271 if (j == layer_num_local)
282 sensor_msgs::LaserScan::Ptr scan(
new sensor_msgs::LaserScan);
285 if(
sweep_data->scans[layer_num_local].points.size() <= 1)
289 scan->header.stamp =
sweep_data->header.stamp;
291 scan->angle_min = 0.0;
292 scan->angle_max = 2.0*M_PI;
293 scan->angle_increment = (scan->angle_max - scan->angle_min)/
point_num;
299 scan->ranges.assign(
point_num, std::numeric_limits<float>::infinity());
302 scan->intensities.assign(
point_num, std::numeric_limits<float>::infinity());
304 for(uint16_t i = 0; i <
sweep_data->scans[layer_num_local].points.size(); i++)
306 double point_azimuth =
sweep_data->scans[layer_num_local].points[i].azimuth;
321 scan->ranges[
point_num - 1-point_idx] =
sweep_data->scans[layer_num_local].points[i].distance;
322 scan->intensities[
point_num - 1-point_idx] =
sweep_data->scans[layer_num_local].points[i].intensity;
328 scan->ranges[i] = std::numeric_limits<float>::infinity();
339 int num = clusters.size();
342 tmp.
distance = std::numeric_limits<float>::infinity();
343 tmp.
intensity = std::numeric_limits<float>::infinity();
348 double mean_distance = 0, mean_intensity = 0;
350 for (
int i = 0; i < num; i++)
352 mean_distance += clusters[i].distance;
353 mean_intensity += clusters[i].intensity;
366 size_t blk_idx = fir_idx / 2;
373 size_t lfir_idx = fir_idx - 1;
374 size_t rfir_idx = fir_idx + 1;
377 if (fir_idx == FIRINGS_PER_PACKET - 1) {
378 lfir_idx = fir_idx - 3;
379 rfir_idx = fir_idx - 1;
384 azimuth_diff = azimuth_diff < 0 ? azimuth_diff + 2*M_PI : azimuth_diff;
400 size_t fir_idx = blk_idx*FIRINGS_PER_BLOCK + blk_fir_idx;
402 double azimuth_diff = 0.0;
403 if (fir_idx < FIRINGS_PER_PACKET - 1)
410 for (
size_t scan_fir_idx = 0; scan_fir_idx <
SCANS_PER_FIRING; ++scan_fir_idx){
412 SCANS_PER_FIRING*blk_fir_idx + scan_fir_idx);
420 raw_distance.
bytes[0] = raw_block.
data[byte_idx];
421 raw_distance.
bytes[1] = raw_block.
data[byte_idx+1];
427 raw_block.
data[byte_idx+2]);
443 ROS_WARN(
"layer num outside of the index, select layer 0 instead!");
448 ROS_WARN(
"layer num outside of the index, select layer 15 instead!");
450 ROS_INFO(
"select layer num: %d", msg->data);
456 const lslidar_c16_msgs::LslidarC16PacketConstPtr&
msg) {
470 size_t new_sweep_start = 0;
484 size_t start_fir_idx = 0;
485 size_t end_fir_idx = new_sweep_start;
493 start_fir_idx = new_sweep_start;
500 for (
size_t fir_idx = start_fir_idx; fir_idx < end_fir_idx; ++fir_idx) {
506 size_t table_idx = floor(
firings[fir_idx].azimuth[scan_idx]*1000.0+0.5);
534 int remapped_scan_idx = scan_idx%2 == 0 ? scan_idx/2 : scan_idx/2+8;
535 sweep_data->scans[remapped_scan_idx].points.push_back(
536 lslidar_c16_msgs::LslidarC16Point());
538 lslidar_c16_msgs::LslidarC16Point& new_point =
540 sweep_data->scans[remapped_scan_idx].points.size()-1];
543 new_point.time = time;
544 new_point.x = x_coord;
545 new_point.y = y_coord;
546 new_point.z = z_coord;
582 sweep_data = lslidar_c16_msgs::LslidarC16SweepPtr(
583 new lslidar_c16_msgs::LslidarC16Sweep());
592 start_fir_idx = end_fir_idx;
595 for (
size_t fir_idx = start_fir_idx; fir_idx < end_fir_idx; ++fir_idx) {
601 size_t table_idx = floor(
firings[fir_idx].azimuth[scan_idx]*1000.0+0.5);
625 double time = packet_start_time +
629 int remapped_scan_idx = scan_idx%2 == 0 ? scan_idx/2 : scan_idx/2+8;
630 sweep_data->scans[remapped_scan_idx].points.push_back(
631 lslidar_c16_msgs::LslidarC16Point());
632 lslidar_c16_msgs::LslidarC16Point& new_point =
634 sweep_data->scans[remapped_scan_idx].points.size()-1];
637 new_point.time = time;
638 new_point.x = x_coord;
639 new_point.y = y_coord;
640 new_point.z = z_coord;
647 packet_start_time +=
FIRING_TOFFSET * (end_fir_idx-start_fir_idx);
static const double DISTANCE_RESOLUTION
uint16_t rotation
0-35999, divide by 100 to get degrees
void layerCallback(const std_msgs::Int8Ptr &msg)
point_struct getMeans(std::vector< point_struct > clusters)
void packetCallback(const lslidar_c16_msgs::LslidarC16PacketConstPtr &msg)
void publish(const boost::shared_ptr< M > &message) const
#define ROS_INFO_ONCE(...)
double angle3_disable_min
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
bool isPointInRange(const double &distance)
Firing firings[FIRINGS_PER_PACKET]
static const int FIRINGS_PER_BLOCK
double azimuth[SCANS_PER_FIRING]
double cos_azimuth_table[6300]
double sin_azimuth_table[6300]
TFSIMD_FORCE_INLINE tfScalar distance(const Vector3 &v) const
TFSIMD_FORCE_INLINE const tfScalar & y() const
ros::Publisher point_cloud_pub
RawBlock blocks[BLOCKS_PER_PACKET]
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
static const double cos_scan_altitude[16]
static const int FIRINGS_PER_PACKET
static const double FIRING_TOFFSET
void decodePacket(const RawPacket *packet)
double rawAzimuthToDouble(const uint16_t &raw_azimuth)
lslidar_c16_msgs::LslidarC16LayerPtr multi_scan
static const double scan_altitude[16]
static const int RAW_SCAN_SIZE
lslidar_c16_msgs::LslidarC16SweepPtr sweep_data
static const int SCANS_PER_FIRING
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
double distance[SCANS_PER_FIRING]
TFSIMD_FORCE_INLINE const tfScalar & x() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void publishChannelScan()
TFSIMD_FORCE_INLINE const tfScalar & z() const
static const double sin_scan_altitude[16]
double intensity[SCANS_PER_FIRING]
uint8_t data[BLOCK_DATA_SIZE]
static const double DSR_TOFFSET
double angle3_disable_max
uint16_t header
UPPER_BANK or LOWER_BANK.
static const int BLOCKS_PER_PACKET
ros::Publisher channel_scan_pub
bool checkPacketValidity(const RawPacket *packet)
void toROSMsg(const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
ros::Subscriber layer_sub
static const uint16_t UPPER_BANK
ros::Subscriber packet_sub