class mrpt::obs::CObservationRotatingScan

A CObservation -derived class for raw range data from a 2D or 3D rotating scanner.

This class is the preferred alternative to CObservationVelodyneScan and CObservation2DRangeScan in MRPT 2.x, since it exposes range data as an organized matrix, more convenient for feature detection directly on “range images”. This class can also import data from KITTI dataset-like binary files containing unorganized (non “undistorted”, i.e. without compensation for lidar motion) point clouds, which get organized into a 2D range image for easier filtering and postprocessing.

Check out the main data fields in the list of members below.

Note that this object has two timestamp fields:

  • The standard CObservation::timestamp field in the base class, which should contain the accurate satellite-based UTC timestamp if available, and

  • the field originalReceivedTimestamp, with the local computer-based timestamp based on the reception of the message in the computer.

Both timestamps correspond to the firing of the first laser in the first CObservationRotatingScan::scan_packets packet.

_images/velodyne_axes.jpg

API for accurate reconstruction of point clouds from raw range images:

  • generatePointCloud()

  • generatePointCloudAlongSE3Trajectory()

New in MRPT 2.0.0

See also:

CObservation, mrpt::hwdrivers::CVelodyneScanner

#include <mrpt/obs/CObservationRotatingScan.h>

class CObservationRotatingScan: public mrpt::obs::CObservation
{
public:
    //
fields

    uint16_t rowCount {0};
    uint16_t columnCount {0};
    mrpt::math::CMatrix_u16 rangeImage {0, 0};
    mrpt::math::CMatrix_u8 intensityImage {0, 0};
    std::map<std::string, mrpt::math::CMatrix_u16> rangeOtherLayers;
    double rangeResolution;
    double startAzimuth {-M_PI};
    double azimuthSpan {2* M_PI};
    double sweepDuration {.0};
    std::string lidarModel {"UNKNOWN_SCANNER"};
    double minRange {1.0};
    double maxRange {130.0};
    mrpt::poses::CPose3D sensorPose;
    mrpt::system::TTimeStamp originalReceivedTimestamp {INVALID_TIMESTAMP};
    bool has_satellite_timestamp {false};

    //
methods

    void fromVelodyne(const mrpt::obs::CObservationVelodyneScan& o);
    void fromScan2D(const mrpt::obs::CObservation2DRangeScan& o);
    void fromPointCloud(const mrpt::obs::CObservationPointCloud& o);
    bool fromGeneric(const mrpt::obs::CObservation& o);
    virtual mrpt::system::TTimeStamp getOriginalReceivedTimeStamp() const;
    virtual void getSensorPose(mrpt::poses::CPose3D& out_sensorPose) const;
    virtual void setSensorPose(const mrpt::poses::CPose3D& newSensorPose);
    virtual void getDescriptionAsText(std::ostream& o) const;
};

Inherited Members

public:
    //
fields

    mrpt::system::TTimeStamp timestamp {mrpt::system::now()};
    std::string sensorLabel;

    //
methods

    mrpt::system::TTimeStamp getTimeStamp() const;
    virtual mrpt::system::TTimeStamp getOriginalReceivedTimeStamp() const;
    virtual bool exportTxtSupported() const;
    virtual std::string exportTxtHeader() const;
    virtual std::string exportTxtDataRow() const;
    virtual void load() const;
    virtual void unload() const;

    template <class METRICMAP>
    bool insertObservationInto(
        METRICMAP& theMap,
        const std::optional<const mrpt::poses::CPose3D>& robotPose = std::nullopt
        ) const;

    virtual void getSensorPose(mrpt::poses::CPose3D& out_sensorPose) const = 0;
    void getSensorPose(mrpt::math::TPose3D& out_sensorPose) const;
    mrpt::math::TPose3D sensorPose() const;
    virtual void setSensorPose(const mrpt::poses::CPose3D& newSensorPose) = 0;
    void setSensorPose(const mrpt::math::TPose3D& newSensorPose);
    virtual void getDescriptionAsText(std::ostream& o) const;
    virtual std::string asString() const;

Fields

uint16_t rowCount {0}

Number of “Lidar rings” (e.g.

16 for a Velodyne VLP16, etc.). This should be constant for a given LiDAR scanner. All matrices in imageLayer_* have this number of rows.

uint16_t columnCount {0}

Number of lidar “firings” for this scan.

It is assumed that firings occur at a fixed rate. Consecutive scans (“scan”=instance of this class) may have different number of firings, and different start and end azimuth. All matrices defined below have this number of columns.

mrpt::math::CMatrix_u16 rangeImage {0, 0}

The NxM matrix of distances (ranges) for each direction (columns) and for each laser “ring” (rows).

Matrix element are integers for efficiency of post-processing filters, etc. Zero means no return (i.e. invalid range). This member must be always provided, containing the ranges for the STRONGEST ray returns. To obtain ranges in meters, multiply this matrix by rangeResolution.

mrpt::math::CMatrix_u8 intensityImage {0, 0}

Optionally, an intensity channel.

Matrix with a 0x0 size if not provided.

std::map<std::string, mrpt::math::CMatrix_u16> rangeOtherLayers

Optional additional layers, e.g.

LAST return, etc. for lidars with multiple returns per firing. A descriptive name of what the alternative range means as std::map Key, e.g. FIRST, SECOND.

double rangeResolution

Real-world scale (in meters) of integer units in range images (e.g.

0.002 means 1 range unit is 2 millimeters)

double startAzimuth {-M_PI}

Azimuth of the first and last columns in ranges, with respect to the sensor forward direction.

Note that startAzimuth may be possitive or negative, and azimuthSpan can be too to reflect the direction of rotation of the scanner: >0 is CCW, <0 is CW.

double sweepDuration {.0}

Time(in seconds) that passed since startAzimuth to* endAzimuth.

std::string lidarModel {"UNKNOWN_SCANNER"}

The driver should fill in this observation.

double minRange {1.0}

The maximum range allowed by the device, in meters (e.g.

100m). Stored here by the driver while capturing based on the sensor model.

mrpt::poses::CPose3D sensorPose

The SE(3) pose of the sensor on the robot/vehicle frame of reference.

mrpt::system::TTimeStamp originalReceivedTimestamp {INVALID_TIMESTAMP}

The local computer-based timestamp based on the reception of the message in the computer.

See also:

has_satellite_timestamp, CObservation::timestamp in the base class, which should contain the accurate satellite-based UTC timestamp.

bool has_satellite_timestamp {false}

If true, CObservation::timestamp has been generated from accurate satellite clock.

Otherwise, no GPS data is available and timestamps are based on the local computer clock.

Methods

bool fromGeneric(const mrpt::obs::CObservation& o)

Will convert from another observation if it’s any of the supported source types (see fromVelodyne(), fromScan2D(), fromPointCloud()) and return true, or will return false otherwise if there is no known way to convert from the passed object.

virtual mrpt::system::TTimeStamp getOriginalReceivedTimeStamp() const

By default, returns CObservation::timestamp but in sensors capable of satellite (or otherwise) accurate UTC timing of readings, this contains the computer-based timestamp of reception, which may be slightly different than timestamp.

See also:

getTimeStamp()

virtual void getSensorPose(mrpt::poses::CPose3D& out_sensorPose) const

A general method to retrieve the sensor pose on the robot.

Note that most sensors will return a full (6D) CPose3D, but see the derived classes for more details or special cases.

See also:

setSensorPose

virtual void setSensorPose(const mrpt::poses::CPose3D& newSensorPose)

A general method to change the sensor pose on the robot.

Note that most sensors will use the full (6D) CPose3D, but see the derived classes for more details or special cases.

See also:

getSensorPose

virtual void getDescriptionAsText(std::ostream& o) const

Build a detailed, multi-line textual description of the observation contents and dump it to the output stream.

If overried by derived classes, call base CObservation::getDescriptionAsText() first to show common information.

This is the text that appears in RawLogViewer when selecting an object in the dataset