mirror of
https://github.com/introlab/rtabmap.git
synced 2026-10-05 17:47:49 +08:00
114 lines
5.4 KiB
C++
114 lines
5.4 KiB
C++
/*
|
|
Copyright (c) 2010-2026, 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 LIDARCAMERACALIBRATION_CALIBRATIONPROBLEM_H_
|
|
#define LIDARCAMERACALIBRATION_CALIBRATIONPROBLEM_H_
|
|
|
|
#include <rtabmap/core/Transform.h>
|
|
|
|
#include <opencv2/core/core.hpp>
|
|
#include <Eigen/Geometry>
|
|
|
|
#include <functional>
|
|
#include <vector>
|
|
|
|
// What makes a lidar point an edge point, in order of precedence.
|
|
enum EdgeType
|
|
{
|
|
kEdgeDepth = 0, // in front of a depth discontinuity
|
|
kEdgeCrease = 1, // where the surface's orientation changes (e.g., wall and floor)
|
|
kEdgeIntensity = 2 // where the surface's reflectance changes
|
|
};
|
|
|
|
// One node of the database: its image, its lidar scan, and the lidar's edges.
|
|
struct Frame
|
|
{
|
|
int id;
|
|
cv::Mat gray; // as stored, matching the camera model
|
|
cv::Mat edges; // CV_8U: the image's edges (Canny), non-zero on an edge
|
|
cv::Mat edgeDistance; // CV_32F: distance (pixels) to the image's nearest edge
|
|
cv::Mat edgeScore; // CV_32F: 1 on the image's edges, decaying with the distance to them
|
|
cv::Mat K; // CV_64F 3x3
|
|
rtabmap::Transform scanToCam; // camera pose in the scan frame, before correction
|
|
cv::Mat cloud; // Nx4 CV_32F, scan frame: x y z intensity (0 without intensity)
|
|
cv::Mat normals; // Mx6 CV_32F, scan frame: voxelized points and their normals (for creases)
|
|
bool hasIntensity;
|
|
// The robot's speeds (m/s, deg/s; negative if unknown): instantaneous, odometry's when the
|
|
// node was added, and mean along odometry over the meanWindow (s) since the previous
|
|
// node, which is when an assembled scan was taken.
|
|
float linearSpeed = -1.0f, angularSpeed = -1.0f;
|
|
float meanLinearSpeed = -1.0f, meanAngularSpeed = -1.0f, meanWindow = 0.0f;
|
|
int meanPoses = 0; // odometry steps the mean speed is from: more than 1 with intermediate nodes
|
|
std::vector<cv::Point3f> edgePoints; // depth and intensity edge points, scan frame
|
|
std::vector<float> edgeWeights;
|
|
std::vector<unsigned char> edgeTypes; // EdgeType of each edge point
|
|
};
|
|
|
|
// The correction of parameters p = tx ty tz (m), rx ry rz (deg), in the camera frame.
|
|
rtabmap::Transform correctionFrom(const double p[6]);
|
|
// The same, in double precision: rtabmap's Transform is float, too coarse for the small
|
|
// steps of numerical derivatives.
|
|
Eigen::Isometry3d correctionFromDouble(const double p[6]);
|
|
|
|
// The lidar edge points of some nodes, and how well a candidate correction C lines them
|
|
// up with their images' edges. This is all a solver sees of the calibration.
|
|
class CalibrationProblem
|
|
{
|
|
public:
|
|
// The frames' edge points are read at each call, so they can be selected again after
|
|
// the problem is made. minDepth: lidar points closer than this to the camera (m) are
|
|
// ignored.
|
|
CalibrationProblem(const std::vector<Frame> & frames, const std::vector<int> & nodes, float minDepth);
|
|
|
|
const std::vector<Frame> & frames() const {return frames_;}
|
|
const std::vector<int> & nodes() const {return nodes_;}
|
|
float minDepth() const {return minDepth_;}
|
|
|
|
// Calls visit(frame, point index, u, v) for each edge point that C projects in its
|
|
// image, at full resolution.
|
|
void project(const rtabmap::Transform & C,
|
|
const std::function<void(const Frame &, size_t, float, float)> & visit) const;
|
|
|
|
// What the direct solvers maximize: the weighted mean of the image edges' score under
|
|
// the projected lidar edge points, in [0, 1]. A point out of its image counts as 0.
|
|
double score(const rtabmap::Transform & C) const;
|
|
int evaluations() const {return evaluations_;}
|
|
|
|
// What the least-squares solvers minimize, per point: the distance (pixels) from
|
|
// where p projects edge point i of f to f's nearest image edge, capped; the cap where
|
|
// it does not project in the image. In double precision, for numerical derivatives.
|
|
double edgeDistance(const Frame & f, size_t i, const double p[6], double cap) const;
|
|
|
|
private:
|
|
const std::vector<Frame> & frames_;
|
|
std::vector<int> nodes_;
|
|
float minDepth_;
|
|
mutable int evaluations_;
|
|
};
|
|
|
|
#endif /* LIDARCAMERACALIBRATION_CALIBRATIONPROBLEM_H_ */
|