MRPT  1.9.9
CObservationVelodyneScan.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2019, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #pragma once
10 
11 #include <mrpt/obs/CObservation.h>
14 #include <mrpt/poses/CPose3D.h>
16 #include <vector>
17 
18 namespace mrpt
19 {
20 namespace poses
21 {
22 class CPose3DInterpolator;
23 }
24 namespace obs
25 {
26 /** A `CObservation`-derived class for RAW DATA (and optionally, point cloud) of
27  * scans from 3D Velodyne LIDAR scanners.
28  * A scan comprises one or more "velodyne packets" (refer to Velodyne user
29  * manual). Normally, a full 360 degrees sweep is included in one observation
30  * object. Note that if a pointcloud is generated inside this class, each point
31  * is annotated with per-point information about its exact azimuth and laser_id
32  * (ring number), an information that is loss when inserting the observation in
33  * a regular mrpt::maps::CPointsMap.
34  *
35  * <h2>Main data fields:</h2><hr>
36  * - CObservationVelodyneScan::scan_packets with raw data packets.
37  * - CObservationVelodyneScan::point_cloud normally empty after grabbing for
38  * efficiency, can be generated calling \a
39  * CObservationVelodyneScan::generatePointCloud()
40  *
41  * Dual return mode is supported (see mrpt::hwdrivers::CVelodyneScanner).
42  *
43  * Axes convention for point cloud (x,y,z) coordinates:
44  *
45  * <div align=center> <img src="velodyne_axes.jpg"> </div>
46  *
47  * If it can be assumed that the sensor moves SLOWLY through the environment
48  * (i.e. its pose can be approximated to be the same since the beginning to the
49  * end of one complete scan)
50  * then this observation can be converted / loaded into the following other
51  * classes:
52  * - Maps of points (these require first generating the pointcloud in this
53  * observation object with
54  * mrpt::obs::CObservationVelodyneScan::generatePointCloud() ):
55  * - mrpt::maps::CPointsMap::loadFromVelodyneScan() (available in all
56  * derived classes)
57  * - and the generic method:mrpt::maps::CPointsMap::insertObservation()
58  * - mrpt::opengl::CPointCloud and mrpt::opengl::CPointCloudColoured is
59  * supported by first converting
60  * this scan to a mrpt::maps::CPointsMap-derived class, then loading it into
61  * the opengl object.
62  *
63  * Otherwise, the following API exists for accurate reconstruction of the
64  * sensor path in SE(3) over time:
65  * - CObservationVelodyneScan::generatePointCloudAlongSE3Trajectory()
66  *
67  * Note that this object has \b two timestamp fields:
68  * - The standard CObservation::timestamp field in the base class, which
69  * should contain the accurate satellite-based UTC timestamp, and
70  * - the field CObservationVelodyneScan::originalReceivedTimestamp, with the
71  * local computer-based timestamp based on the reception of the message in the
72  * computer.
73  * Both timestamps correspond to the firing of the <b>first</b> laser in the
74  * <b>first</b> CObservationVelodyneScan::scan_packets packet.
75  *
76  * \note New in MRPT 1.4.0
77  * \sa CObservation, mrpt::maps::CPointsMap, mrpt::hwdrivers::CVelodyneScanner
78  * \ingroup mrpt_obs_grp
79  */
81 {
83 
84  public:
85  /** @name Raw scan fixed parameters
86  @{ */
87  static const int SIZE_BLOCK = 100;
88  static const int RAW_SCAN_SIZE = 3;
89  static const int SCANS_PER_BLOCK = 32;
91 
92  static const float ROTATION_RESOLUTION; // = 0.01f; /**< degrees */
94  36000; /**< hundredths of degrees */
95 
96  static const float DISTANCE_MAX; /**< meters */
97  static const float DISTANCE_RESOLUTION; /**< meters */
98  static const float DISTANCE_MAX_UNITS;
99 
100  /** Blocks 0-31 */
101  static const uint16_t UPPER_BANK = 0xeeff;
102  /** Blocks 32-63 */
103  static const uint16_t LOWER_BANK = 0xddff;
104 
105  static const int PACKET_SIZE = 1206;
106  static const int POS_PACKET_SIZE = 512;
107  static const int BLOCKS_PER_PACKET = 12;
108  static const int PACKET_STATUS_SIZE = 4;
110 
111  static const uint8_t RETMODE_STRONGEST = 0x37;
112  static const uint8_t RETMODE_LAST = 0x38;
113  static const uint8_t RETMODE_DUAL = 0x39;
114  /** @} */
115 
116  /** @name Scan data
117  @{ */
118 
119 #pragma pack(push, 1)
121  {
124  };
125  /** Raw Velodyne data block.
126  * Each block contains data from either the upper or lower laser
127  * bank. The device returns three times as many upper bank blocks. */
128  struct raw_block_t
129  {
130  uint16_t header; ///< Block id: UPPER_BANK or LOWER_BANK
131  uint16_t rotation; ///< 0-35999, divide by 100 to get degrees
133  };
134 
135  /** One unit of data from the scanner (the payload of one UDP DATA packet)
136  */
138  {
140  /** us from top of hour */
142  /** 0x37: strongest, 0x38: last, 0x39: dual return */
144  /** 0x21: HDL-32E, 0x22: VLP-16 */
146  };
147 
148  /** Payload of one POSITION packet */
150  {
151  char unused1[198];
154  /** the full $GPRMC message, as received by Velodyne, terminated with
155  * "\r\n\0" */
156  char NMEA_GPRMC[72 + 234];
157  };
158 #pragma pack(pop)
159 
160  /** The maximum range allowed by the device, in meters (e.g. 100m). Stored
161  * here by the driver while capturing based on the sensor model. */
162  double minRange{1.0}, maxRange{130.0};
163  /** The 6D pose of the sensor on the robot/vehicle frame of reference */
165  /** The main content of this object: raw data packet from the LIDAR. \sa
166  * point_cloud */
167  std::vector<TVelodyneRawPacket> scan_packets;
168  /** The calibration data for the LIDAR device. See
169  * mrpt::hwdrivers::CVelodyneScanner and mrpt::obs::VelodyneCalibration for
170  * details. */
172  /** The local computer-based timestamp based on the reception of the message
173  * in the computer. \sa has_satellite_timestamp, CObservation::timestamp in
174  * the base class, which should contain the accurate satellite-based UTC
175  * timestamp. */
177  /** If true, CObservation::timestamp has been generated from accurate
178  * satellite clock. Otherwise, no GPS data is available and timestamps are
179  * based on the local computer clock. */
181 
183  const override; // See base class docs
184 
185  /** See \a point_cloud and \a scan_packets */
186  struct TPointCloud
187  {
188  std::vector<float> x, y, z;
189  /** Color [0,255] */
190  std::vector<uint8_t> intensity;
191  /** Timestamp for each point (if `generatePerPointTimestamp`=true in
192  * `TGeneratePointCloudParameters`), or empty vector if not populated
193  * (default). */
194  std::vector<mrpt::system::TTimeStamp> timestamp;
195  /** Original azimuth of each point (if `generatePerPointAzimuth`=true,
196  * empty otherwise ) */
197  std::vector<float> azimuth;
198  /** Laser ID ("ring number") for each point (0-15 for a VLP-16, etc.) */
199  std::vector<int16_t> laser_id;
200  /** The list of point indices (in x,y,z,...) generated for each laserID
201  * (ring number). Generated only if `generatePointsForLaserID`=true in
202  * `TGeneratePointCloudParameters`*/
203  std::vector<std::vector<uint64_t>> pointsForLaserID;
204 
205  inline std::size_t size() const { return x.size(); }
206  void reserve(std::size_t n);
207  /** Sets all vectors to zero length */
208  void clear();
209  /** Like clear(), but also enforcing freeing memory */
210  void clear_deep();
211  };
212 
213  /** Optionally, raw data can be converted into a 3D point cloud (local
214  * coordinates wrt the sensor, not the vehicle)
215  * with intensity (graylevel) information. See axes convention in
216  * mrpt::obs::CObservationVelodyneScan \sa generatePointCloud()
217  */
219  /** @} */
220 
221  /** @name Related to conversion to 3D point cloud
222  * @{ */
224  {
226  /** Minimum azimuth, in degrees (Default=0). Points will be generated
227  * only the the area of interest [minAzimuth, maxAzimuth] */
228  double minAzimuth_deg{.0};
229  /** Minimum azimuth, in degrees (Default=360). Points will be generated
230  * only the the area of interest [minAzimuth, maxAzimuth] */
231  double maxAzimuth_deg{360.};
232  /** Minimum (default=1.0f) and maximum (default: Infinity)
233  * distances/ranges for a point to be considered. Points must pass this
234  * (application specific) condition and also the minRange/maxRange
235  * values in CObservationVelodyneScan (sensor-specific). */
236  float minDistance{1.0f}, maxDistance{std::numeric_limits<float>::max()};
237  /** The limits of the 3D box (default=infinity) in sensor (not vehicle)
238  * local coordinates for the ROI filter \sa filterByROI */
239  float ROI_x_min{-std::numeric_limits<float>::max()},
240  ROI_x_max{std::numeric_limits<float>::max()},
241  ROI_y_min{-std::numeric_limits<float>::max()},
242  ROI_y_max{std::numeric_limits<float>::max()},
243  ROI_z_min{-std::numeric_limits<float>::max()},
244  ROI_z_max{std::numeric_limits<float>::max()};
245  /** The limits of the 3D box (default=0) in sensor (not vehicle) local
246  * coordinates for the nROI filter \sa filterBynROI */
249  /** (Default:2.0 meters) Minimum distance between a point and its two
250  * neighbors to be considered an invalid point. */
252 
253  /** Enable ROI filter (Default:false): add points inside a given 3D box
254  */
255  bool filterByROI{false};
256  /** Enable nROI filter (Default:false): do NOT add points inside a given
257  * 3D box */
258  bool filterBynROI{false};
259  /** (Default:false) Simple filter to remove spurious returns (e.g. Sun
260  * reflected on large water extensions) */
262  /** (Default:true) In VLP16 dual mode, keep both or just one of the
263  * returns. */
264  bool dualKeepStrongest{true}, dualKeepLast{true};
265  /** (Default:false) If `true`, populate the vector timestamp */
267  /** (Default:false) If `true`, populate the vector azimuth */
269  /** (Default:false) If `true`, populate pointsForLaserID */
271  };
272 
273  /** Derive from this class to generate pointclouds into custom containers.
274  * \sa generatePointCloud() */
276  {
277  virtual void reserve(std::size_t n) {}
278  virtual void resizeLaserCount([[maybe_unused]] std::size_t n) {}
279 
280  /** Process the insertion of a new (x,y,z) point to the cloud, in
281  * sensor-centric coordinates, with the exact timestamp of that LIDAR
282  * ray */
283  virtual void add_point(
284  float pt_x, float pt_y, float pt_z, uint8_t pt_intensity,
285  const mrpt::system::TTimeStamp& tim, const float azimuth,
286  uint16_t laser_id) = 0;
287  };
288 
289  /** Generates the point cloud into the point cloud data fields in \a
290  * CObservationVelodyneScan::point_cloud
291  * where it is stored in local coordinates wrt the sensor (neither the
292  * vehicle nor the world).
293  * So, this method does not take into account the possible motion of the
294  * sensor through the world as it collects LIDAR scans.
295  * For high dynamics, see the more costly API
296  * generatePointCloudAlongSE3Trajectory()
297  * \note Points with ranges out of [minRange,maxRange] are discarded; as
298  * well, other filters are available in \a params.
299  * \sa generatePointCloudAlongSE3Trajectory(),
300  * TGeneratePointCloudParameters
301  */
302  void generatePointCloud(
303  const TGeneratePointCloudParameters& params =
304  TGeneratePointCloudParameters());
305 
306  /** \overload For custom data storage as destination of the pointcloud. */
307  void generatePointCloud(
308  PointCloudStorageWrapper& dest,
309  const TGeneratePointCloudParameters& params =
310  TGeneratePointCloudParameters());
311 
312  /** Results for generatePointCloudAlongSE3Trajectory() */
314  {
315  /** Number of points in the observation */
316  size_t num_points{0};
317  /** Number of points for which a valid interpolated SE(3) pose could be
318  * determined */
320  };
321 
322  /** An alternative to generatePointCloud() for cases where the motion of the
323  * sensor as it grabs one scan (360 deg horiz FOV) cannot be ignored.
324  * \param[in] vehicle_path Timestamped sequence of known poses for the
325  * VEHICLE. Recall that the sensor has a relative pose wrt the vehicle
326  * according to CObservationVelodyneScan::getSensorPose() &
327  * CObservationVelodyneScan::setSensorPose()
328  * \param[out] out_points The generated points, in the same coordinates
329  * frame than \a vehicle_path. Points are APPENDED to the list, so prevous
330  * contents are kept.
331  * \param[out] results_stats Stats
332  * \param[in] params Filtering and other parameters
333  * \sa generatePointCloud(), TGeneratePointCloudParameters
334  */
336  const mrpt::poses::CPose3DInterpolator& vehicle_path,
337  std::vector<mrpt::math::TPointXYZIu8>& out_points,
338  TGeneratePointCloudSE3Results& results_stats,
339  const TGeneratePointCloudParameters& params =
340  TGeneratePointCloudParameters());
341 
342  /** @} */
343 
344  void getSensorPose(mrpt::poses::CPose3D& out_sensorPose) const override
345  {
346  out_sensorPose = sensorPose;
347  } // See base class docs
348  void setSensorPose(const mrpt::poses::CPose3D& newSensorPose) override
349  {
350  sensorPose = newSensorPose;
351  } // See base class docs
353  std::ostream& o) const override; // See base class docs
354 
355 }; // End of class def.
356 
357 } // namespace obs
358 
359 namespace typemeta
360 { // Specialization must occur in the same namespace
361 MRPT_DECLARE_TTYPENAME_PTR_NAMESPACE(CObservationVelodyneScan, ::mrpt::obs)
362 }
363 
364 } // namespace mrpt
float ROI_x_min
The limits of the 3D box (default=infinity) in sensor (not vehicle) local coordinates for the ROI fil...
Velodyne calibration data, for usage in mrpt::obs::CObservationVelodyneScan.
A CObservation-derived class for RAW DATA (and optionally, point cloud) of scans from 3D Velodyne LID...
void getDescriptionAsText(std::ostream &o) const override
Build a detailed, multi-line textual description of the observation contents and dump it to the outpu...
unsigned __int16 uint16_t
Definition: rptypes.h:47
bool filterOutIsolatedPoints
(Default:false) Simple filter to remove spurious returns (e.g.
std::vector< mrpt::system::TTimeStamp > timestamp
Timestamp for each point (if generatePerPointTimestamp=true in TGeneratePointCloudParameters), or empty vector if not populated (default).
std::vector< float > azimuth
Original azimuth of each point (if generatePerPointAzimuth=true, empty otherwise ) ...
static const uint16_t LOWER_BANK
Blocks 32-63.
mrpt::system::TTimeStamp originalReceivedTimestamp
The local computer-based timestamp based on the reception of the message in the computer.
static const float DISTANCE_RESOLUTION
meters
GLenum GLsizei n
Definition: glext.h:5136
bool generatePerPointAzimuth
(Default:false) If true, populate the vector azimuth
mrpt::obs::VelodyneCalibration calibration
The calibration data for the LIDAR device.
bool has_satellite_timestamp
If true, CObservation::timestamp has been generated from accurate satellite clock.
bool filterByROI
Enable ROI filter (Default:false): add points inside a given 3D box.
void generatePointCloud(const TGeneratePointCloudParameters &params=TGeneratePointCloudParameters())
Generates the point cloud into the point cloud data fields in CObservationVelodyneScan::point_cloud w...
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot/vehicle frame of reference.
char NMEA_GPRMC[72+234]
the full $GPRMC message, as received by Velodyne, terminated with "\r\n\0"
static const uint16_t ROTATION_MAX_UNITS
hundredths of degrees
unsigned char uint8_t
Definition: rptypes.h:44
double maxAzimuth_deg
Minimum azimuth, in degrees (Default=360).
mrpt::Clock::time_point TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1...
Definition: datetime.h:40
TPointCloud point_cloud
Optionally, raw data can be converted into a 3D point cloud (local coordinates wrt the sensor...
void generatePointCloudAlongSE3Trajectory(const mrpt::poses::CPose3DInterpolator &vehicle_path, std::vector< mrpt::math::TPointXYZIu8 > &out_points, TGeneratePointCloudSE3Results &results_stats, const TGeneratePointCloudParameters &params=TGeneratePointCloudParameters())
An alternative to generatePointCloud() for cases where the motion of the sensor as it grabs one scan ...
double minRange
The maximum range allowed by the device, in meters (e.g.
static const float ROTATION_RESOLUTION
degrees
std::vector< int16_t > laser_id
Laser ID ("ring number") for each point (0-15 for a VLP-16, etc.)
mrpt::system::TTimeStamp getOriginalReceivedTimeStamp() const override
By default, returns CObservation::timestamp but in sensors capable of satellite (or otherwise) accura...
float isolatedPointsFilterDistance
(Default:2.0 meters) Minimum distance between a point and its two neighbors to be considered an inval...
virtual void add_point(float pt_x, float pt_y, float pt_z, uint8_t pt_intensity, const mrpt::system::TTimeStamp &tim, const float azimuth, uint16_t laser_id)=0
Process the insertion of a new (x,y,z) point to the cloud, in sensor-centric coordinates, with the exact timestamp of that LIDAR ray.
float minDistance
Minimum (default=1.0f) and maximum (default: Infinity) distances/ranges for a point to be considered...
This namespace contains representation of robot actions and observations.
size_t num_correctly_inserted_points
Number of points for which a valid interpolated SE(3) pose could be determined.
uint16_t header
Block id: UPPER_BANK or LOWER_BANK.
bool generatePerPointTimestamp
(Default:false) If true, populate the vector timestamp
#define MRPT_DECLARE_TTYPENAME_PTR_NAMESPACE(_TYPE, __NS)
Definition: TTypeName.h:142
void clear_deep()
Like clear(), but also enforcing freeing memory.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define DEFINE_SERIALIZABLE(class_name)
This declaration must be inserted in all CSerializable classes definition, within the class declarati...
bool generatePointsForLaserID
(Default:false) If true, populate pointsForLaserID
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:84
One unit of data from the scanner (the payload of one UDP DATA packet)
Declares a class that represents any robot&#39;s observation.
Definition: CObservation.h:43
static const uint16_t UPPER_BANK
Blocks 0-31.
void getSensorPose(mrpt::poses::CPose3D &out_sensorPose) const override
A general method to retrieve the sensor pose on the robot.
virtual void resizeLaserCount([[maybe_unused]] std::size_t n)
uint8_t laser_return_mode
0x37: strongest, 0x38: last, 0x39: dual return
std::vector< std::vector< uint64_t > > pointsForLaserID
The list of point indices (in x,y,z,...) generated for each laserID (ring number).
void setSensorPose(const mrpt::poses::CPose3D &newSensorPose) override
A general method to change the sensor pose on the robot.
This class stores a time-stamped trajectory in SE(3) (CPose3D poses).
Derive from this class to generate pointclouds into custom containers.
uint16_t rotation
0-35999, divide by 100 to get degrees
std::vector< TVelodyneRawPacket > scan_packets
The main content of this object: raw data packet from the LIDAR.
GLenum GLint x
Definition: glext.h:3542
bool dualKeepStrongest
(Default:true) In VLP16 dual mode, keep both or just one of the returns.
float nROI_x_min
The limits of the 3D box (default=0) in sensor (not vehicle) local coordinates for the nROI filter...
unsigned __int32 uint32_t
Definition: rptypes.h:50
GLenum const GLfloat * params
Definition: glext.h:3538
#define INVALID_TIMESTAMP
Represents an invalid timestamp, where applicable.
Definition: datetime.h:43
bool filterBynROI
Enable nROI filter (Default:false): do NOT add points inside a given 3D box.



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 8fe78517f Sun Jul 14 19:43:28 2019 +0200 at lun oct 28 02:10:00 CET 2019