mirror of
https://github.com/introlab/rtabmap.git
synced 2026-10-07 02:27:47 +08:00
Merge branch 'master' of github.com:introlab/rtabmap into gtest
This commit is contained in:
@@ -60,6 +60,7 @@ public:
|
||||
int stopMapId = -1,
|
||||
bool priorsIgnored = false,
|
||||
bool imuIgnored = false,
|
||||
bool intermediateNodesAreNormalNodes = false,
|
||||
const std::vector<Transform> & cameraLocalTransformOverrides = std::vector<Transform>());
|
||||
DBReader(const std::list<std::string> & databasePaths,
|
||||
float frameRate = 0.0f, // -1 = use Database stamps, 0 = inf
|
||||
@@ -76,6 +77,7 @@ public:
|
||||
int stopMapId = -1,
|
||||
bool priorsIgnored = false,
|
||||
bool imuIgnored = false,
|
||||
bool intermediateNodesAreNormalNodes = false,
|
||||
const std::vector<Transform> & cameraLocalTransformOverrides = std::vector<Transform>());
|
||||
virtual ~DBReader();
|
||||
|
||||
@@ -106,6 +108,7 @@ private:
|
||||
int _stopId;
|
||||
std::vector<unsigned int> _cameraIndices;
|
||||
bool _intermediateNodesIgnored;
|
||||
bool _intermediateNodesAreNormalNodes;
|
||||
bool _landmarksIgnored;
|
||||
bool _featuresIgnored;
|
||||
bool _priorsIgnored;
|
||||
|
||||
@@ -118,15 +118,18 @@ Transform RTABMAP_CORE_EXPORT calcRMSE(
|
||||
float & rotational_max,
|
||||
bool align2D = false);
|
||||
|
||||
void RTABMAP_CORE_EXPORT computeMaxGraphErrors(
|
||||
struct MaxGraphErrors
|
||||
{
|
||||
float linear=-1.0f; // absolute error (m) of the link with maximum linear error
|
||||
float angular=-1.0f; // absolute error (rad) of the link with maximum angular error
|
||||
float linearRatio=-1.0f; // Ratio = absolute error (m) / linear std (m), of the link with maximum linear error
|
||||
float angularRatio=-1.0f; // Ratio = absolute error (rad) / angular std (rad), of the link with maximum angular error
|
||||
Link linearLink; // link with maximum linear error
|
||||
Link angularLink; // link with maximum angular error
|
||||
};
|
||||
MaxGraphErrors RTABMAP_CORE_EXPORT computeMaxGraphErrors(
|
||||
const std::map<int, Transform> & poses,
|
||||
const std::multimap<int, Link> & links,
|
||||
float & maxLinearErrorRatio,
|
||||
float & maxAngularErrorRatio,
|
||||
float & maxLinearError,
|
||||
float & maxAngularError,
|
||||
const Link ** maxLinearErrorLink = 0,
|
||||
const Link ** maxAngularErrorLink = 0,
|
||||
bool for3DoF = false);
|
||||
|
||||
std::vector<double> RTABMAP_CORE_EXPORT getMaxOdomInf(const std::multimap<int, Link> & links);
|
||||
|
||||
@@ -64,7 +64,8 @@ public:
|
||||
kXYZNormal=8, /**< 3D points with X, Y, Z and normal vectors. */
|
||||
kXYZINormal=9, /**< 3D points with X, Y, Z, intensity and normal vectors. */
|
||||
kXYZRGBNormal=10, /**< 3D points with X, Y, Z, RGB color and normal vectors. */
|
||||
kXYZIT=11 /**< 3D points with X, Y, Z, intensity and time. */
|
||||
kXYZIT=11, /**< 3D points with X, Y, Z, intensity and time. */
|
||||
kXYZIRT=12 /**< 3D points with X, Y, Z, intensity, ring and time. */
|
||||
};
|
||||
|
||||
/// @name Static Utility Functions
|
||||
@@ -76,6 +77,7 @@ public:
|
||||
static bool isScanHasRGB(const Format & format);
|
||||
static bool isScanHasIntensity(const Format & format);
|
||||
static bool isScanHasTime(const Format & format);
|
||||
static bool isScanHasRing(const Format & format);
|
||||
static float packRGB(unsigned char r, unsigned char g, unsigned char b);
|
||||
static void unpackRGB(float rgb, unsigned char & r, unsigned char & g, unsigned char & b);
|
||||
|
||||
@@ -176,6 +178,7 @@ public:
|
||||
bool hasRGB() const {return isScanHasRGB(format_);}
|
||||
bool hasIntensity() const {return isScanHasIntensity(format_);}
|
||||
bool hasTime() const {return isScanHasTime(format_);}
|
||||
bool hasRing() const {return isScanHasRing(format_);}
|
||||
bool isCompressed() const {return !data_.empty() && data_.type()==CV_8UC1;}
|
||||
bool isOrganized() const {return data_.rows > 1;}
|
||||
LaserScan clone() const;
|
||||
@@ -187,7 +190,8 @@ public:
|
||||
int getIntensityOffset() const {return hasIntensity()?(is2d()?2:3):-1;}
|
||||
int getRGBOffset() const {return hasRGB()?(is2d()?2:3):-1;}
|
||||
int getNormalsOffset() const {return hasNormals()?(2 + (is2d()?0:1) + ((hasRGB() || hasIntensity())?1:0)):-1;}
|
||||
int getTimeOffset() const {return hasTime()?4:-1;}
|
||||
int getRingOffset() const {return format_==kXYZIRT?4:-1;}
|
||||
int getTimeOffset() const {return format_==kXYZIT?4:(format_==kXYZIRT?5:-1);}
|
||||
|
||||
/**
|
||||
* @brief Access a specific field value of a point.
|
||||
|
||||
@@ -140,6 +140,7 @@ public:
|
||||
float radius,
|
||||
const std::map<int, Transform> & optimizedPoses,
|
||||
int maxGraphDepth) const;
|
||||
void convertToIntermediate(int locationId);
|
||||
void deleteLocation(int locationId, std::list<int> * deletedWords = 0);
|
||||
void saveLocationData(int locationId);
|
||||
void removeLink(int idA, int idB);
|
||||
@@ -162,7 +163,7 @@ public:
|
||||
float getSimilarityThreshold() const {return _similarityThreshold;}
|
||||
std::map<int, int> getWeights() const;
|
||||
int getLastSignatureId() const;
|
||||
const Signature * getLastWorkingSignature() const;
|
||||
const Signature * getLastWorkingSignature(bool ignoreIntermediateNodes) const;
|
||||
std::map<int, Link> getNodesObservingLandmark(int landmarkId, bool lookInDatabase) const;
|
||||
int getSignatureIdByLabel(const std::string & label, bool lookInDatabase = true) const;
|
||||
bool labelSignature(int id, const std::string & label);
|
||||
|
||||
@@ -57,7 +57,8 @@ public:
|
||||
kTypeOpenVINS = 10,
|
||||
kTypeFLOAM = 11,
|
||||
kTypeOpen3D = 12,
|
||||
kTypeCuVSLAM = 13
|
||||
kTypeCuVSLAM = 13,
|
||||
kTypeLIOSAM = 14
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
@@ -218,7 +218,7 @@ class RTABMAP_CORE_EXPORT Parameters
|
||||
RTABMAP_PARAM(Mem, ReduceGraph, bool, false, uFormat("Reduce graph. Merge nodes when loop closures are added (ignoring those with user data). Note that this approach assumes that 100%% of the loop closures accepted are good, so it is highly recommended to enable \"%s\" at the same time.", kRGBDOptimizeMaxError().c_str()));
|
||||
RTABMAP_PARAM(Mem, RecentWmRatio, float, 0.2, "Ratio of locations after the last loop closure in WM that cannot be transferred.");
|
||||
RTABMAP_PARAM(Mem, TransferSortingByWeightId, bool, false, "On transfer, signatures are sorted by weight->ID only (i.e. the oldest of the lowest weighted signatures are transferred first). If false, the signatures are sorted by weight->Age->ID (i.e. the oldest inserted in WM of the lowest weighted signatures are transferred first). Note that retrieval updates the age, not the ID.");
|
||||
RTABMAP_PARAM(Mem, RehearsalIdUpdatedToNewOne, bool, false, "On merge, update to new id. When false, no copy.");
|
||||
RTABMAP_PARAM(Mem, RehearsalIdUpdatedToNewOne, bool, false, uFormat("On merge, update to new id. When false, no copy. Keep this disable if %s=true.", kRtabmapCreateIntermediateNodes().c_str()));
|
||||
RTABMAP_PARAM(Mem, RehearsalWeightIgnoredWhileMoving, bool, false, "When the robot is moving, weights are not updated on rehearsal.");
|
||||
RTABMAP_PARAM(Mem, GenerateIds, bool, true, "True=Generate location IDs, False=use input image IDs.");
|
||||
RTABMAP_PARAM(Mem, BadSignaturesIgnored, bool, false, "Bad signatures are ignored.");
|
||||
@@ -249,7 +249,7 @@ class RTABMAP_CORE_EXPORT Parameters
|
||||
RTABMAP_PARAM(Kp, MinDepth, float, 0, "Filter extracted keypoints by depth.");
|
||||
RTABMAP_PARAM(Kp, MaxFeatures, int, 500, "Maximum features extracted from the images (0 means not bounded, <0 means no extraction).");
|
||||
RTABMAP_PARAM(Kp, SSC, bool, false, "If true, SSC (Suppression via Square Covering) is applied to limit keypoints.");
|
||||
RTABMAP_PARAM(Kp, BadSignRatio, float, 0.5, "Bad signature ratio (less than Ratio x AverageWordsPerImage = bad).");
|
||||
RTABMAP_PARAM(Kp, BadSignRatio, float, 0.5, uFormat("Bad signature ratio. If %s=0, the ratio is computed from the average number of words per signature (less than Ratio x AverageWordsPerImage = bad).", kKpMaxFeatures().c_str()));
|
||||
RTABMAP_PARAM(Kp, NndrRatio, float, 0.8, "NNDR ratio (A matching pair is detected, if its distance is closer than X times the distance of the second nearest neighbor.)");
|
||||
#if CV_MAJOR_VERSION > 2 && !defined(HAVE_OPENCV_XFEATURES2D)
|
||||
// OpenCV>2 without xFeatures2D module doesn't have BRIEF
|
||||
@@ -379,6 +379,7 @@ class RTABMAP_CORE_EXPORT Parameters
|
||||
RTABMAP_PARAM(RGBD, NewMapOdomChangeDistance, float, 0, "A new map is created if a change of odometry translation greater than X m is detected (0 m = disabled).");
|
||||
RTABMAP_PARAM(RGBD, OptimizeFromGraphEnd, bool, false, "Optimize graph from the newest node. If false, the graph is optimized from the oldest node of the current graph (this adds an overhead computation to detect to oldest node of the current graph, but it can be useful to preserve the map referential from the oldest node). Warning when set to false: when some nodes are transferred, the first referential of the local map may change, resulting in momentary changes in robot/map position (which are annoying in teleoperation).");
|
||||
RTABMAP_PARAM(RGBD, OptimizeMaxError, float, 3.0, uFormat("Reject loop closures if optimization error ratio is greater than this value (0=disabled). Ratio is computed as absolute error over standard deviation of each link. This will help to detect when a wrong loop closure is added to the graph. If used with \"%s\", the disabled loop closure links will be removed.", kOptimizerRobust().c_str()));
|
||||
RTABMAP_PARAM(RGBD, OptimizeMaxErrorRepairRadius, float, 0.0, uFormat("If two consecutive loop closures are rejected by %s on the same old loop closure link, we will remove that old link, and other old links under that radius if necessary, until optimization is accepted. When optimization is accepted, the old loop closure links are removed from the graph. This feature is useful to reject bad loop closures that were accepted previously. Set to 0 to disable this feature.", kRGBDOptimizeMaxError().c_str()));
|
||||
RTABMAP_PARAM(RGBD, MaxLoopClosureDistance, float, 0.0, "Reject loop closures/localizations if the distance from the map is over this distance (0=disabled).");
|
||||
RTABMAP_PARAM(RGBD, ForceOdom3DoF, bool, true, uFormat("Force odometry pose to be 3DoF if %s=true.", kRegForce3DoF().c_str()));
|
||||
RTABMAP_PARAM(RGBD, StartAtOrigin, bool, false, uFormat("If true, rtabmap will assume the robot is starting from origin of the map. If false, rtabmap will assume the robot is restarting from the last saved localization pose from previous session (the place where it shut down previously). Used only in localization mode (%s=false).", kMemIncrementalMemory().c_str()));
|
||||
@@ -465,7 +466,7 @@ class RTABMAP_CORE_EXPORT Parameters
|
||||
RTABMAP_PARAM(GTSAM, IncRelinearizeSkip, int, 1, "Only relinearize any variables every X calls to ISAM2::update(). See GTSAM::ISAM2 doc for more info.");
|
||||
|
||||
// Odometry
|
||||
RTABMAP_PARAM(Odom, Strategy, int, 0, "0=Frame-to-Map (F2M) 1=Frame-to-Frame (F2F) 2=Fovis 3=viso2 4=DVO-SLAM 5=ORB_SLAM 6=OKVIS 7=LOAM 8=MSCKF_VIO 9=VINS-Fusion 10=OpenVINS 11=FLOAM 12=Open3D 13=cuVSLAM");
|
||||
RTABMAP_PARAM(Odom, Strategy, int, 0, "0=Frame-to-Map (F2M) 1=Frame-to-Frame (F2F) 2=Fovis 3=viso2 4=DVO-SLAM 5=ORB_SLAM 6=OKVIS 7=LOAM 8=MSCKF_VIO 9=VINS-Fusion 10=OpenVINS 11=FLOAM 12=Open3D 13=cuVSLAM 14=LIO-SAM");
|
||||
RTABMAP_PARAM(Odom, ResetCountdown, int, 0, "Automatically reset odometry after X consecutive images where odometry cannot be computed (a value of 0 disables auto-reset). When a reset occurs, odometry resumes from the last successfully computed pose with large covariance to trigger a new map. If external odometry is used, it will also be reset based on the motion estimated relative to the last computed pose but no large covariance will be received, so that a new map won't be triggered.");
|
||||
RTABMAP_PARAM(Odom, Holonomic, bool, true, "If the robot is holonomic (strafing commands can be issued). If not, y value will be estimated from x and yaw values (y=x*tan(yaw)).");
|
||||
RTABMAP_PARAM(Odom, FillInfoData, bool, true, "Fill info with data (inliers/outliers features).");
|
||||
@@ -687,6 +688,21 @@ class RTABMAP_CORE_EXPORT Parameters
|
||||
// Odometry cuVSLAM
|
||||
RTABMAP_PARAM(OdomCuVSLAM, MulticamMode, int, 0, "cuVSLAM multicam_mode setting: 0=moderate, 1=performance, 2=precision.");
|
||||
|
||||
// Odometry LIO-SAM
|
||||
RTABMAP_PARAM_STR(OdomLIOSAM, ConfigPath, "", "Path to LIO-SAM params.yaml config file. When set, sensor/IMU/feature parameters are loaded from the file and the individual parameters below are ignored.");
|
||||
RTABMAP_PARAM(OdomLIOSAM, Sensor, int, 0, "LiDAR sensor: 0=Velodyne, 1=Ouster, 2=Livox");
|
||||
RTABMAP_PARAM(OdomLIOSAM, NScan, int, 16, "Number of LiDAR channels (16, 32, 64, 128).");
|
||||
RTABMAP_PARAM(OdomLIOSAM, HorizonScan, int, 1800, "Horizontal resolution (Velodyne:1800, Ouster:512/1024/2048).");
|
||||
RTABMAP_PARAM(OdomLIOSAM, ImuAccNoise, float, 0.01, "IMU accelerometer white noise.");
|
||||
RTABMAP_PARAM(OdomLIOSAM, ImuGyrNoise, float, 0.001, "IMU gyroscope white noise.");
|
||||
RTABMAP_PARAM(OdomLIOSAM, ImuAccBiasN, float, 0.0002,"IMU accelerometer bias noise.");
|
||||
RTABMAP_PARAM(OdomLIOSAM, ImuGyrBiasN, float, 0.00003,"IMU gyroscope bias noise.");
|
||||
RTABMAP_PARAM(OdomLIOSAM, ImuGravity, float, 9.80511,"Gravity magnitude.");
|
||||
RTABMAP_PARAM(OdomLIOSAM, EdgeThreshold,float, 1.0, "Edge feature curvature threshold.");
|
||||
RTABMAP_PARAM(OdomLIOSAM, SurfThreshold,float, 0.1, "Surface feature curvature threshold.");
|
||||
RTABMAP_PARAM(OdomLIOSAM, LinVar, float, 0.01, "Linear output variance.");
|
||||
RTABMAP_PARAM(OdomLIOSAM, AngVar, float, 0.01, "Angular output variance.");
|
||||
|
||||
// Common registration parameters
|
||||
RTABMAP_PARAM(Reg, RepeatOnce, bool, true, "Do a second registration with the output of the first registration as guess. Only done if no guess was provided for the first registration (like on loop closure). It can be useful if the registration approach used can use a guess to get better matches.");
|
||||
RTABMAP_PARAM(Reg, Strategy, int, 0, "0=Vis, 1=Icp, 2=VisIcp");
|
||||
|
||||
@@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "rtabmap/core/Statistics.h"
|
||||
#include "rtabmap/core/Link.h"
|
||||
#include "rtabmap/core/ProgressState.h"
|
||||
#include "rtabmap/core/Graph.h"
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <list>
|
||||
@@ -264,6 +265,13 @@ private:
|
||||
std::multimap<int, Link> * constraints = 0,
|
||||
double * error = 0,
|
||||
int * iterationsDone = 0) const;
|
||||
std::list<std::pair<int, int> > repairGraph(
|
||||
graph::MaxGraphErrors & maxGraphErrors,
|
||||
std::map<int, Transform> & poses,
|
||||
std::multimap<int, Link> & constraints,
|
||||
double & optimizationError,
|
||||
int & optimizationIterations,
|
||||
cv::Mat & optimizationCovariance);
|
||||
void updateGoalIndex();
|
||||
bool computePath(int targetNode, std::map<int, Transform> nodes, const std::multimap<int, rtabmap::Link> & constraints);
|
||||
|
||||
@@ -320,6 +328,7 @@ private:
|
||||
std::string _databasePath;
|
||||
bool _optimizeFromGraphEnd;
|
||||
float _optimizationMaxError;
|
||||
float _optimizationMaxErrorRepairRadius;
|
||||
bool _startNewMapOnLoopClosure;
|
||||
bool _startNewMapOnGoodSignature;
|
||||
float _goalReachedRadius; // meters
|
||||
@@ -379,6 +388,7 @@ private:
|
||||
std::map<int, Transform> _odomCachePoses; // used in localization mode to reject loop closures
|
||||
std::multimap<int, Link> _odomCacheConstraints; // used in localization mode to reject loop closures
|
||||
std::map<int, Transform> _markerPriors;
|
||||
std::pair<int, int> _lastRejectedLoopClosureIds;
|
||||
|
||||
std::set<int> _nodesToRepublish;
|
||||
|
||||
|
||||
@@ -106,7 +106,6 @@ private:
|
||||
unsigned int _dataBufferMaxSize;
|
||||
float _rate;
|
||||
bool _createIntermediateNodes;
|
||||
UTimer * _frameRateTimer;
|
||||
double _previousStamp;
|
||||
|
||||
Rtabmap * _rtabmap;
|
||||
|
||||
@@ -495,6 +495,12 @@ public:
|
||||
_userDataCompressed.empty() &&
|
||||
_keypoints.size() == 0 &&
|
||||
_descriptors.empty() &&
|
||||
_groundCellsRaw.empty() &&
|
||||
_groundCellsCompressed.empty() &&
|
||||
_obstacleCellsRaw.empty() &&
|
||||
_obstacleCellsCompressed.empty() &&
|
||||
_emptyCellsRaw.empty() &&
|
||||
_emptyCellsCompressed.empty() &&
|
||||
imu_.empty());
|
||||
}
|
||||
|
||||
@@ -750,12 +756,6 @@ public:
|
||||
const cv::Mat & empty,
|
||||
float cellSize,
|
||||
const cv::Point3f & viewPoint);
|
||||
|
||||
/**
|
||||
* @brief Clears raw occupancy grid data (keeps compressed)
|
||||
*/
|
||||
void clearOccupancyGridRaw() {_groundCellsRaw = cv::Mat(); _obstacleCellsRaw = cv::Mat();}
|
||||
|
||||
/**
|
||||
* @brief Returns raw ground cells
|
||||
* @return Const reference to raw ground cells matrix
|
||||
@@ -959,12 +959,12 @@ public:
|
||||
* Clear compressed rgb/depth (left/right) images, compressed laser scan and compressed user data.
|
||||
* Raw data are kept is set.
|
||||
*/
|
||||
void clearCompressedData(bool images = true, bool scan = true, bool userData = true);
|
||||
void clearCompressedData(bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true);
|
||||
/**
|
||||
* Clear raw rgb/depth (left/right) images, raw laser scan and raw user data.
|
||||
* Compressed data are kept is set.
|
||||
*/
|
||||
void clearRawData(bool images = true, bool scan = true, bool userData = true);
|
||||
void clearRawData(bool images = true, bool scan = true, bool userData = true, bool occupancyGrid = true);
|
||||
|
||||
/**
|
||||
* @brief Checks if a 3D point is visible from any camera
|
||||
|
||||
@@ -126,6 +126,13 @@ class RTABMAP_CORE_EXPORT Statistics
|
||||
RTABMAP_STATS(Loop, Optimization_max_ang_error_ratio, );
|
||||
RTABMAP_STATS(Loop, Optimization_error, );
|
||||
RTABMAP_STATS(Loop, Optimization_iterations, );
|
||||
RTABMAP_STATS(Loop, Optimization_max_error_from_id, );
|
||||
RTABMAP_STATS(Loop, Optimization_max_error_to_id, );
|
||||
RTABMAP_STATS(Loop, Optimization_max_ang_error_from_id, );
|
||||
RTABMAP_STATS(Loop, Optimization_max_ang_error_to_id, );
|
||||
RTABMAP_STATS(Loop, Optimization_max_error_removed_from_id, );
|
||||
RTABMAP_STATS(Loop, Optimization_max_error_removed_to_id, );
|
||||
RTABMAP_STATS(Loop, Optimization_max_error_removed_count, );
|
||||
RTABMAP_STATS(Loop, Linear_variance,);
|
||||
RTABMAP_STATS(Loop, Angular_variance,);
|
||||
RTABMAP_STATS(Loop, Landmark_detected,);
|
||||
|
||||
@@ -41,11 +41,11 @@ LaserScan laserScanFromPointCloud(const PointCloud2T & cloud, bool filterNaNs, b
|
||||
return LaserScan();
|
||||
}
|
||||
//determine the output type
|
||||
int fieldStates[8] = {0}; // x,y,z,normal_x,normal_y,normal_z,rgb,intensity
|
||||
int fieldStates[10] = {0}; // x,y,z,normal_x,normal_y,normal_z,rgb,intensity,time,ring
|
||||
#if PCL_VERSION_COMPARE(>=, 1, 10, 0)
|
||||
std::uint32_t fieldOffsets[8] = {0};
|
||||
std::uint32_t fieldOffsets[10] = {0};
|
||||
#else
|
||||
pcl::uint32_t fieldOffsets[8] = {0};
|
||||
pcl::uint32_t fieldOffsets[10] = {0};
|
||||
#endif
|
||||
for(unsigned int i=0; i<cloud.fields.size(); ++i)
|
||||
{
|
||||
@@ -102,6 +102,42 @@ LaserScan laserScanFromPointCloud(const PointCloud2T & cloud, bool filterNaNs, b
|
||||
fieldStates[7] = 1;
|
||||
fieldOffsets[7] = cloud.fields[i].offset;
|
||||
}
|
||||
else if(cloud.fields[i].name.compare("time") == 0)
|
||||
{
|
||||
if(cloud.fields[i].datatype != pcl::PCLPointField::FLOAT32)
|
||||
{
|
||||
static bool warningShown = false;
|
||||
if(!warningShown)
|
||||
{
|
||||
UWARN("The input scan cloud has an \"time\" field "
|
||||
"but the datatype (%d) is not supported. Time will be ignored. "
|
||||
"This message is only shown once.", cloud.fields[i].datatype);
|
||||
warningShown = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
fieldStates[8] = 1;
|
||||
fieldOffsets[8] = cloud.fields[i].offset;
|
||||
}
|
||||
else if(cloud.fields[i].name.compare("ring") == 0)
|
||||
{
|
||||
if(cloud.fields[i].datatype != pcl::PCLPointField::UINT16)
|
||||
{
|
||||
static bool warningShown = false;
|
||||
if(!warningShown)
|
||||
{
|
||||
UWARN("The input scan cloud has an \"ring\" field "
|
||||
"but the datatype (%d) is not supported. Ring will be ignored. "
|
||||
"This message is only shown once.", cloud.fields[i].datatype);
|
||||
warningShown = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
fieldStates[9] = 1;
|
||||
fieldOffsets[9] = cloud.fields[i].offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
UDEBUG("Ignoring \"%s\" field", cloud.fields[i].name.c_str());
|
||||
@@ -117,6 +153,8 @@ LaserScan laserScanFromPointCloud(const PointCloud2T & cloud, bool filterNaNs, b
|
||||
bool hasNormals = fieldStates[3] || fieldStates[4] || fieldStates[5];
|
||||
bool hasIntensity = fieldStates[7];
|
||||
bool hasRGB = !hasIntensity&&fieldStates[6];
|
||||
bool hasTime = hasIntensity&&fieldStates[8];
|
||||
bool hasRing = hasIntensity&&fieldStates[9];
|
||||
bool is3D = fieldStates[0] && fieldStates[1] && fieldStates[2];
|
||||
|
||||
LaserScan::Format format;
|
||||
@@ -140,7 +178,18 @@ LaserScan laserScanFromPointCloud(const PointCloud2T & cloud, bool filterNaNs, b
|
||||
}
|
||||
else if(!hasNormals && hasIntensity)
|
||||
{
|
||||
format = LaserScan::kXYZI;
|
||||
if(hasTime && hasRing)
|
||||
{
|
||||
format = LaserScan::kXYZIRT;
|
||||
}
|
||||
else if(hasTime)
|
||||
{
|
||||
format = LaserScan::kXYZIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
format = LaserScan::kXYZI;
|
||||
}
|
||||
}
|
||||
else if(!hasNormals && hasRGB)
|
||||
{
|
||||
@@ -183,6 +232,7 @@ LaserScan laserScanFromPointCloud(const PointCloud2T & cloud, bool filterNaNs, b
|
||||
transformRot = transform.rotation();
|
||||
}
|
||||
int oi=0;
|
||||
UASSERT(cloud.height == 1 || cloud.row_step != 0);
|
||||
for (uint32_t row = 0; row < (uint32_t)cloud.height; ++row)
|
||||
{
|
||||
const uint8_t* row_data = &cloud.data[row * cloud.row_step];
|
||||
@@ -242,26 +292,45 @@ LaserScan laserScanFromPointCloud(const PointCloud2T & cloud, bool filterNaNs, b
|
||||
{
|
||||
ptr[0] = *(float*)(msg_data + fieldOffsets[0]);
|
||||
ptr[1] = *(float*)(msg_data + fieldOffsets[1]);
|
||||
ptr[2] = *(float*)(msg_data + fieldOffsets[3]);
|
||||
ptr[3] = *(float*)(msg_data + fieldOffsets[4]);
|
||||
ptr[4] = *(float*)(msg_data + fieldOffsets[5]);
|
||||
if(format == LaserScan::kXYZIT)
|
||||
{
|
||||
ptr[2] = *(float*)(msg_data + fieldOffsets[2]);
|
||||
ptr[3] = *(float*)(msg_data + fieldOffsets[7]);
|
||||
ptr[4] = *(float*)(msg_data + fieldOffsets[8]);
|
||||
}
|
||||
else // kXYNormal
|
||||
{
|
||||
ptr[2] = *(float*)(msg_data + fieldOffsets[3]);
|
||||
ptr[3] = *(float*)(msg_data + fieldOffsets[4]);
|
||||
ptr[4] = *(float*)(msg_data + fieldOffsets[5]);
|
||||
}
|
||||
valid = uIsFinite(ptr[0]) && uIsFinite(ptr[1]) && uIsFinite(ptr[2]) && uIsFinite(ptr[3]) && uIsFinite(ptr[4]);
|
||||
}
|
||||
else if(laserScan.channels() == 6)
|
||||
{
|
||||
ptr[0] = *(float*)(msg_data + fieldOffsets[0]);
|
||||
ptr[1] = *(float*)(msg_data + fieldOffsets[1]);
|
||||
if(format == LaserScan::kXYINormal)
|
||||
{
|
||||
ptr[2] = *(float*)(msg_data + fieldOffsets[7]);
|
||||
}
|
||||
else // XYZNormal
|
||||
if(format == LaserScan::kXYZIRT)
|
||||
{
|
||||
ptr[2] = *(float*)(msg_data + fieldOffsets[2]);
|
||||
ptr[3] = *(float*)(msg_data + fieldOffsets[7]);
|
||||
ptr[4] = float(*(unsigned short*)(msg_data + fieldOffsets[9])); // Convert 16U to float
|
||||
ptr[5] = *(float*)(msg_data + fieldOffsets[8]);
|
||||
}
|
||||
else // with normal
|
||||
{
|
||||
if(format == LaserScan::kXYINormal)
|
||||
{
|
||||
ptr[2] = *(float*)(msg_data + fieldOffsets[7]);
|
||||
}
|
||||
else // XYZNormal
|
||||
{
|
||||
ptr[2] = *(float*)(msg_data + fieldOffsets[2]);
|
||||
}
|
||||
ptr[3] = *(float*)(msg_data + fieldOffsets[3]);
|
||||
ptr[4] = *(float*)(msg_data + fieldOffsets[4]);
|
||||
ptr[5] = *(float*)(msg_data + fieldOffsets[5]);
|
||||
}
|
||||
ptr[3] = *(float*)(msg_data + fieldOffsets[3]);
|
||||
ptr[4] = *(float*)(msg_data + fieldOffsets[4]);
|
||||
ptr[5] = *(float*)(msg_data + fieldOffsets[5]);
|
||||
valid = uIsFinite(ptr[0]) && uIsFinite(ptr[1]) && uIsFinite(ptr[2]) && uIsFinite(ptr[3]) && uIsFinite(ptr[4]) && uIsFinite(ptr[5]);
|
||||
}
|
||||
else if(laserScan.channels() == 7)
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright (c) 2010-2016, Mathieu Labbe - IntRoLab - Universite de Sherbrooke
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the Universite de Sherbrooke nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ODOMETRYLIOSAM_H_
|
||||
#define ODOMETRYLIOSAM_H_
|
||||
|
||||
#include <rtabmap/core/Odometry.h>
|
||||
|
||||
#ifdef RTABMAP_LIOSAM
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Geometry>
|
||||
#include <vector>
|
||||
namespace lio_sam { class LioSamCore; }
|
||||
#endif
|
||||
|
||||
namespace rtabmap {
|
||||
|
||||
class RTABMAP_CORE_EXPORT OdometryLIOSAM : public Odometry
|
||||
{
|
||||
public:
|
||||
OdometryLIOSAM(const rtabmap::ParametersMap & parameters = rtabmap::ParametersMap());
|
||||
virtual ~OdometryLIOSAM();
|
||||
|
||||
virtual void reset(const Transform & initialPose = Transform::getIdentity());
|
||||
virtual Odometry::Type getType() {return Odometry::kTypeLIOSAM;}
|
||||
virtual bool canProcessAsyncIMU() const {return true;}
|
||||
|
||||
private:
|
||||
virtual Transform computeTransform(SensorData & data, const Transform & guess = Transform(), OdometryInfo * info = 0);
|
||||
|
||||
#ifdef RTABMAP_LIOSAM
|
||||
bool init(const Transform & imuLocalTransform, const Transform & lidarLocalTransform);
|
||||
#endif
|
||||
|
||||
private:
|
||||
#ifdef RTABMAP_LIOSAM
|
||||
lio_sam::LioSamCore * lioSam_;
|
||||
Transform lastPose_;
|
||||
bool lost_;
|
||||
float linVar_;
|
||||
float angVar_;
|
||||
ParametersMap parameters_;
|
||||
Transform imuLocalTransform_; // base_link -> imu_link (cached for deferred init)
|
||||
|
||||
// Buffered IMU samples received before initialization
|
||||
struct ImuSample {
|
||||
double stamp;
|
||||
Eigen::Vector3d acc;
|
||||
Eigen::Vector3d gyro;
|
||||
Eigen::Quaterniond orientation;
|
||||
};
|
||||
std::vector<ImuSample> imuBuffer_;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* ODOMETRYLIOSAM_H_ */
|
||||
@@ -39,6 +39,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <rtabmap/core/Parameters.h>
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <rtabmap/core/ProgressState.h>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
@@ -48,6 +49,20 @@ namespace rtabmap
|
||||
/**
|
||||
* @brief This namespace contains 3D point cloud processing utilities.
|
||||
*/
|
||||
|
||||
// Point type carrying xyz + intensity + ring (laser line index) + time
|
||||
// (per-point acquisition offset, seconds from the scan start). Matches the
|
||||
// layout expected by LIO-SAM's Velodyne feature extractor so it can be fed
|
||||
// directly via util3d::laserScanFromPointCloud().
|
||||
struct EIGEN_ALIGN16 PointXYZIRT
|
||||
{
|
||||
PCL_ADD_POINT4D;
|
||||
float intensity;
|
||||
std::uint16_t ring;
|
||||
float time;
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
};
|
||||
|
||||
namespace util3d
|
||||
{
|
||||
|
||||
@@ -704,7 +719,7 @@ LaserScan RTABMAP_CORE_EXPORT laserScanFromPointCloud(const pcl::PointCloud<pcl:
|
||||
LaserScan RTABMAP_CORE_EXPORT laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZRGB> & cloud, const pcl::IndicesPtr & indices, const Transform & transform = Transform(), bool filterNaNs = true);
|
||||
/**
|
||||
* @ingroup LaserScanFromPointCloud
|
||||
* @brief `pcl::PointXYZRGB` → (x, y, z, intensity) → LaserScan::kXYZI
|
||||
* @brief `pcl::PointXYZI` → (x, y, z, intensity) → LaserScan::kXYZI
|
||||
*/
|
||||
LaserScan RTABMAP_CORE_EXPORT laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZI> & cloud, const Transform & transform = Transform(), bool filterNaNs = true);
|
||||
/**
|
||||
@@ -713,6 +728,16 @@ LaserScan RTABMAP_CORE_EXPORT laserScanFromPointCloud(const pcl::PointCloud<pcl:
|
||||
*/
|
||||
LaserScan RTABMAP_CORE_EXPORT laserScanFromPointCloud(const pcl::PointCloud<pcl::PointXYZI> & cloud, const pcl::IndicesPtr & indices, const Transform & transform = Transform(), bool filterNaNs = true);
|
||||
/**
|
||||
* @ingroup LaserScanFromPointCloud
|
||||
* @brief `rtabmap::PointXYZIRT` → (x, y, z, intensity, ring time) → LaserScan::kXYZIRT
|
||||
*/
|
||||
LaserScan RTABMAP_CORE_EXPORT laserScanFromPointCloud(const pcl::PointCloud<rtabmap::PointXYZIRT> & cloud, const Transform & transform = Transform(), bool filterNaNs = true);
|
||||
/**
|
||||
* @ingroup LaserScanFromPointCloud
|
||||
* @brief `rtabmap::PointXYZIRT` → (x, y, z, intensity, ring time) → LaserScan::kXYZIRT
|
||||
*/
|
||||
LaserScan RTABMAP_CORE_EXPORT laserScanFromPointCloud(const pcl::PointCloud<rtabmap::PointXYZIRT> & cloud, const pcl::IndicesPtr & indices, const Transform & transform = Transform(), bool filterNaNs = true);
|
||||
/**
|
||||
* @ingroup LaserScanFromPointCloud
|
||||
* @brief `pcl::PointXYZRGBNormal` → (x, y, z, rgb, nx, ny, nz) → LaserScan::kXYZRGBNormal
|
||||
*/
|
||||
@@ -1321,6 +1346,15 @@ LaserScan RTABMAP_CORE_EXPORT deskew(
|
||||
} // namespace util3d
|
||||
} // namespace rtabmap
|
||||
|
||||
POINT_CLOUD_REGISTER_POINT_STRUCT(rtabmap::PointXYZIRT,
|
||||
(float, x, x)
|
||||
(float, y, y)
|
||||
(float, z, z)
|
||||
(float, intensity, intensity)
|
||||
(std::uint16_t, ring, ring)
|
||||
(float, time, time)
|
||||
)
|
||||
|
||||
#include "rtabmap/core/impl/util3d.hpp"
|
||||
|
||||
#endif /* UTIL3D_H_ */
|
||||
|
||||
Reference in New Issue
Block a user