33     return originalReceivedTimestamp;
    39     out << timestamp << sensorLabel << rowCount << columnCount
    40         << rangeResolution << startAzimuth << azimuthSpan << sweepDuration
    41         << lidarModel << minRange << maxRange << sensorPose
    42         << originalReceivedTimestamp << has_satellite_timestamp;
    44     out.WriteAs<uint16_t>(rangeImage.cols());
    45     out.WriteAs<uint16_t>(rangeImage.rows());
    46     if (!rangeImage.empty())
    47         out.WriteBufferFixEndianness(&rangeImage(0, 0), rangeImage.size());
    49     out.WriteAs<uint16_t>(intensityImage.cols());
    50     out.WriteAs<uint16_t>(intensityImage.rows());
    51     if (!intensityImage.empty())
    52         out.WriteBufferFixEndianness(
    53             &intensityImage(0, 0), intensityImage.size());
    55     out.WriteAs<uint16_t>(rangeOtherLayers.size());
    56     for (
const auto& ly : rangeOtherLayers)
    61         out.WriteBufferFixEndianness(&ly.second(0, 0), ly.second.size());
    71             in >> timestamp >> sensorLabel >> rowCount >> columnCount >>
    72                 rangeResolution >> startAzimuth >> azimuthSpan >>
    73                 sweepDuration >> lidarModel >> minRange >> maxRange >>
    74                 sensorPose >> originalReceivedTimestamp >>
    75                 has_satellite_timestamp;
    77             const auto nCols = in.
ReadAs<uint16_t>(),
    78                        nRows = in.
ReadAs<uint16_t>();
    79             rangeImage.resize(nRows, nCols);
    80             if (!rangeImage.empty())
    82                     &rangeImage(0, 0), rangeImage.size());
    85                 const auto nIntCols = in.
ReadAs<uint16_t>(),
    86                            nIntRows = in.
ReadAs<uint16_t>();
    87                 intensityImage.resize(nIntRows, nIntCols);
    88                 if (!intensityImage.empty())
    90                         &intensityImage(0, 0), intensityImage.size());
    93             const auto nOtherLayers = in.
ReadAs<uint16_t>();
    94             rangeOtherLayers.clear();
    95             for (
size_t i = 0; i < nOtherLayers; i++)
    99                 auto& im = rangeOtherLayers[name];
   100                 im.resize(nRows, nCols);
   112     CObservation::getDescriptionAsText(o);
   113     o << 
"Homogeneous matrix for the sensor 3D pose, relative to "   117       << sensorPose << endl;
   119     o << 
"lidarModel: " << lidarModel << 
"\n";
   120     o << 
"Range rows=" << rowCount << 
" cols=" << columnCount << 
"\n";
   121     o << 
"Range resolution=" << rangeResolution << 
" [meter]\n";
   124     o << 
"Sweep duration: " << sweepDuration << 
" [s]\n";
   126         "Sensor min/max range: %.02f / %.02f m\n", minRange, maxRange);
   127     o << 
"has_satellite_timestamp: " << (has_satellite_timestamp ? 
"YES" : 
"NO")
   129     o << 
"originalReceivedTimestamp: "   139     using degree_cents = uint16_t;
   140     using gps_microsecs = uint32_t;
   159     gps_microsecs last_pkt_tim = std::numeric_limits<gps_microsecs>::max();
   160     degree_cents last_pkt_az = 0;  
   163     std::map<degree_cents, gps_microsecs> azimuth2timestamp;
   164     std::multiset<double> rotspeed;  
   169     rowCount = num_lasers;
   175     const double timeBetweenLastTwoBlocks =
   179     rangeImage.setZero(rowCount, columnCount);
   180     intensityImage.setZero(rowCount, columnCount);
   181     rangeOtherLayers.clear();
   187     for (
size_t pktIdx = 0; pktIdx < o.
scan_packets.size(); pktIdx++)
   191         model = pkt.velodyne_model_ID;
   193         const degree_cents pkt_azimuth = pkt.blocks[0].rotation();
   195         if (last_pkt_tim != std::numeric_limits<uint32_t>::max())
   199             const double dT = 1e-6 * (pkt.gps_timestamp() - last_pkt_tim);
   200             const auto dAzimuth = 1e-2 * (pkt_azimuth - last_pkt_az);
   201             const auto estRotVel = dAzimuth / dT;
   202             rotspeed.insert(estRotVel);
   204         last_pkt_tim = pkt.gps_timestamp();
   205         last_pkt_az = pkt_azimuth;
   207         azimuth2timestamp[pkt_azimuth] = pkt.gps_timestamp();
   214             const double maxRotSpeed = *rotspeed.rbegin(),
   215                          minRotSpeed = *rotspeed.begin();
   217             ASSERT_BELOW_((maxRotSpeed - minRotSpeed) / maxRotSpeed, 0.01);
   220             const double rotVel_degps = [&]() {
   221                 auto it = rotspeed.begin();
   222                 std::advance(it, rotspeed.size() / 2);
   232             const double curAng =
   234             const double nextAng =
   239             azimuthSpan += incrAng;
   245             const int dsr_offset =
   247             const bool block_is_dual_strongest_range =
   249                  ((block & 0x01) != 0));
   250             const bool block_is_dual_last_range =
   252                  ((block & 0x01) == 0));
   256                 if (!pkt.blocks[block]
   261                 const auto rawLaserId = 
static_cast<uint8_t
>(dsr + dsr_offset);
   262                 uint8_t laserId = rawLaserId;
   266                 if (num_lasers == 16)
   282                     pkt.blocks[block].laser_returns[k].distance() +
   283                     static_cast<uint16_t
>(
   286                 const auto columnIdx = [&]() {
   309                     block_is_dual_strongest_range)
   312                     rangeImage(laserId, columnIdx) = 
distance;
   315                     intensityImage(laserId, columnIdx) =
   316                         pkt.blocks[block].laser_returns[k].intensity();
   318                 else if (block_is_dual_last_range)
   321                     auto& r = rangeOtherLayers[
"STRONGEST"];
   323                     if (static_cast<size_t>(r.rows()) != num_lasers)
   324                         r.setZero(rowCount, columnCount);
   337     const auto microsecs_1st_pkt = o.
scan_packets.begin()->gps_timestamp();
   338     const auto microsecs_last_pkt = o.
scan_packets.rbegin()->gps_timestamp();
   339     sweepDuration = 1e-6 * (microsecs_last_pkt - microsecs_1st_pkt) +
   340                     timeBetweenLastTwoBlocks;
   346             lidarModel = 
"HDL-32E";
   349             lidarModel = 
"VLP-16";
   352             lidarModel = 
"Unknown";
   367     this->has_satellite_timestamp = 
false;
   377     this->rangeImage.setZero(rowCount, columnCount);
   378     this->intensityImage.setZero(rowCount, columnCount);
   379     this->rangeOtherLayers.clear();
   380     this->rangeResolution = 0.01;
   386         uint16_t& range_out = rangeImage(0, i);
   387         uint8_t& intensity_out = intensityImage(0, i);
   393         const uint16_t r_discr =
   394             static_cast<uint16_t
>((r / 
d2f(rangeResolution)) + 0.5f);
   403     this->lidarModel = std::string(
"2D_SCAN_") + this->sensorLabel;
   420     if (
auto oVel = dynamic_cast<const CObservationVelodyneScan*>(&o); oVel)
   425     if (
auto o2D = dynamic_cast<const CObservation2DRangeScan*>(&o); o2D)
   430     if (
auto oPc = dynamic_cast<const CObservationPointCloud*>(&o); oPc)
   432         fromPointCloud(*oPc);
 
A compile-time fixed-size numeric matrix container. 
 
A CObservation-derived class for RAW DATA (and optionally, point cloud) of scans from 3D Velodyne LID...
 
void fromPointCloud(const mrpt::obs::CObservationPointCloud &o)
 
#define THROW_EXCEPTION(msg)
 
An observation from any sensor that can be summarized as a pointcloud. 
 
std::string std::string format(std::string_view fmt, ARGS &&... args)
 
#define ASSERT_BELOW_(__A, __B)
 
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
To be added to all CSerializable-classes implementation files. 
 
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. 
 
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object. 
 
T angDistance(T from, T to)
Computes the shortest angular increment (or distance) between two planar orientations, such that it is constrained to [-pi,pi] and is correct for any combination of angles (e.g. 
 
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. 
 
static const uint8_t RETMODE_DUAL
 
static const int SCANS_PER_FIRING
 
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot/vehicle frame of reference. 
 
size_t getScanSize() const
Get number of scan rays. 
 
void fromVelodyne(const mrpt::obs::CObservationVelodyneScan &o)
 
float maxRange
The maximum range allowed by the device, in meters (e.g. 
 
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations. 
 
mrpt::Clock::time_point TTimeStamp
A system independent time type, it holds the the number of 100-nanosecond intervals since January 1...
 
float d2f(const double d)
shortcut for static_cast<float>(double) 
 
void getDescriptionAsText(std::ostream &o) const override
Build a detailed, multi-line textual description of the observation contents and dump it to the outpu...
 
double minRange
The maximum range allowed by the device, in meters (e.g. 
 
#define ASSERT_EQUAL_(__A, __B)
Assert comparing two values, reporting their actual values upon failure. 
 
constexpr double DEG2RAD(const double x)
Degrees to radians. 
 
STORED_TYPE ReadAs()
De-serialize a variable and returns it by value. 
 
std::vector< PerLaserCalib > laser_corrections
 
static const int SCANS_PER_PACKET
 
This namespace contains representation of robot actions and observations. 
 
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive. 
 
#define ASSERT_ABOVEEQ_(__A, __B)
 
const int32_t & getScanIntensity(const size_t i) const
The intensity values of the scan. 
 
static const int BLOCKS_PER_PACKET
 
std::string sensorLabel
An arbitrary label that can be used to identify the sensor. 
 
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries. 
 
mrpt::system::TTimeStamp timestamp
The associated UTC time-stamp. 
 
A "CObservation"-derived class that represents a 2D range scan measurement (typically from a laser sc...
 
Virtual base class for "archives": classes abstracting I/O streams. 
 
bool fromGeneric(const mrpt::obs::CObservation &o)
Will convert from another observation if it's any of the supported source types (see fromVelodyne()...
 
mrpt::vision::TStereoCalibResults out
 
Declares a class that represents any robot's observation. 
 
std::string dateTimeToString(const mrpt::system::TTimeStamp t)
Convert a timestamp into this textual form (UTC time): YEAR/MONTH/DAY,HH:MM:SS.MMM. 
 
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive. 
 
const float & getScanRange(const size_t i) const
The range values of the scan, in meters. 
 
constexpr double RAD2DEG(const double x)
Radians to degrees. 
 
#define ASSERT_ABOVE_(__A, __B)
 
float aperture
The "aperture" or field-of-view of the range finder, in radians (typically M_PI = 180 degrees)...
 
void fromScan2D(const mrpt::obs::CObservation2DRangeScan &o)
 
MRPT_TODO("toPointCloud / calibration")
 
bool hasIntensity() const
Return true if scan has intensity. 
 
std::vector< TVelodyneRawPacket > scan_packets
The main content of this object: raw data packet from the LIDAR. 
 
A CObservation-derived class for raw range data from a 2D or 3D rotating scanner. ...
 
size_t ReadBufferFixEndianness(T *ptr, size_t ElementCount)
Reads a sequence of elemental datatypes, taking care of reordering their bytes from the MRPT stream s...
 
static constexpr float DISTANCE_RESOLUTION
meters 
 
mrpt::poses::CPose3D sensorPose
The 6D pose of the sensor on the robot at the moment of starting the scan. 
 
static const int SCANS_PER_BLOCK
 
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space. 
 
bool rightToLeft
The scanning direction: true=counterclockwise; false=clockwise. 
 
bool getScanRangeValidity(const size_t i) const
It's false (=0) on no reflected rays, referenced to elements in scan.