54 set<string> lstGPSLabels;
62 if (outInfo) *outInfo = outInfoTemp;
64 map<string, map<Clock::time_point, TPoint3D>>
68 bool ref_valid =
false;
82 const double std_0 = memFil.
read_double(
"CONSISTENCY_TEST",
"std_0", 0);
83 bool doConsistencyCheck = std_0 > 0;
87 const bool doUncertaintyCovs = outInfoTemp.
W_star.
rows() != 0;
88 if (doUncertaintyCovs &&
91 "ERROR: W_star matrix for uncertainty estimation is provided but " 92 "it's not a 6x6 matrix.");
99 using TListGPSs = std::map<
101 TListGPSs list_gps_obs;
103 map<string, size_t> GPS_RTK_reads;
104 map<string, TPoint3D>
105 GPS_local_coords_on_vehicle;
107 for (
size_t i = first; !abort && i <= last; i++)
114 case CRawlog::etObservation:
123 if (obs->has_GGA_datum() &&
125 .fields.fix_quality == 4)
128 list_gps_obs[obs->timestamp][obs->sensorLabel] = obs;
130 lstGPSLabels.insert(obs->sensorLabel);
134 if (obs->has_GGA_datum() &&
136 .fields.fix_quality == 4 ||
140 GPS_RTK_reads[obs->sensorLabel]++;
144 if (GPS_local_coords_on_vehicle.find(
146 GPS_local_coords_on_vehicle.end())
147 GPS_local_coords_on_vehicle[obs->sensorLabel] =
148 TPoint3D(obs->sensorPose.asTPose());
154 gps_paths[obs->sensorLabel][obs->timestamp] =
TPoint3D(
175 map<set<string>,
double> Ad_ij;
176 map<set<string>,
double>
180 map<size_t, string> D_cov_rev_indexes;
186 if (doConsistencyCheck && GPS_local_coords_on_vehicle.size() == 3)
188 unsigned int cnt = 0;
189 for (
auto i = GPS_local_coords_on_vehicle.begin();
190 i != GPS_local_coords_on_vehicle.end(); ++i)
193 D_cov_indexes[i->first] = cnt;
194 D_cov_rev_indexes[cnt] = i->first;
197 for (
auto j = i; j != GPS_local_coords_on_vehicle.end(); ++j)
204 phi_ij[
make_set(i->first, j->first)] =
205 atan2(pj.
y - pi.
y, pj.
x - pi.
x);
209 ASSERT_(D_cov_indexes.size() == 3 && D_cov_rev_indexes.size() == 3);
211 D_cov.
setSize(D_cov_indexes.size(), D_cov_indexes.size());
212 D_mean.
resize(D_cov_indexes.size());
219 square(Ad_ij[
make_set(D_cov_rev_indexes[0], D_cov_rev_indexes[1])]);
222 square(Ad_ij[
make_set(D_cov_rev_indexes[0], D_cov_rev_indexes[2])]);
225 square(Ad_ij[
make_set(D_cov_rev_indexes[1], D_cov_rev_indexes[2])]);
228 Ad_ij[
make_set(D_cov_rev_indexes[0], D_cov_rev_indexes[1])] *
229 Ad_ij[
make_set(D_cov_rev_indexes[0], D_cov_rev_indexes[2])] *
230 cos(phi_ij[
make_set(D_cov_rev_indexes[0], D_cov_rev_indexes[1])] -
231 phi_ij[
make_set(D_cov_rev_indexes[0], D_cov_rev_indexes[2])]);
232 D_cov(0, 1) = D_cov(1, 0);
235 -Ad_ij[
make_set(D_cov_rev_indexes[0], D_cov_rev_indexes[1])] *
236 Ad_ij[
make_set(D_cov_rev_indexes[1], D_cov_rev_indexes[2])] *
237 cos(phi_ij[
make_set(D_cov_rev_indexes[0], D_cov_rev_indexes[1])] -
238 phi_ij[
make_set(D_cov_rev_indexes[1], D_cov_rev_indexes[2])]);
239 D_cov(0, 2) = D_cov(2, 0);
242 Ad_ij[
make_set(D_cov_rev_indexes[0], D_cov_rev_indexes[2])] *
243 Ad_ij[
make_set(D_cov_rev_indexes[1], D_cov_rev_indexes[2])] *
244 cos(phi_ij[
make_set(D_cov_rev_indexes[0], D_cov_rev_indexes[2])] -
245 phi_ij[
make_set(D_cov_rev_indexes[1], D_cov_rev_indexes[2])]);
246 D_cov(1, 2) = D_cov(2, 1);
248 D_cov *= 4 *
square(std_0);
255 square(Ad_ij[
make_set(D_cov_rev_indexes[0], D_cov_rev_indexes[1])]);
257 square(Ad_ij[
make_set(D_cov_rev_indexes[0], D_cov_rev_indexes[2])]);
259 square(Ad_ij[
make_set(D_cov_rev_indexes[1], D_cov_rev_indexes[2])]);
262 doConsistencyCheck =
false;
267 int N_GPSs = list_gps_obs.size();
273 if (list_gps_obs.size() > 4)
275 auto F = list_gps_obs.begin();
278 auto E = list_gps_obs.end();
282 for (
auto it = F; it != E; ++it)
286 std::map<std::string, CObservationGPS::Ptr>& GPS = it->second;
289 for (
const auto& lstGPSLabel : lstGPSLabels)
292 bool fnd = (GPS.find(lstGPSLabel) != GPS.end());
305 if (i_b1->second.find(lstGPSLabel) != i_b1->second.end())
306 GPS_b1 = i_b1->second.find(lstGPSLabel)->second;
308 if (i_a1->second.find(lstGPSLabel) != i_a1->second.end())
309 GPS_a1 = i_a1->second.find(lstGPSLabel)->second;
311 if (!disableGPSInterp && GPS_a1 && GPS_b1)
314 GPS_b1->timestamp, GPS_a1->timestamp) < 0.5)
316 auto new_gps = CObservationGPS::Create(*GPS_a1);
317 new_gps->sensorLabel = lstGPSLabel;
327 .fields.longitude_degrees =
332 .fields.longitude_degrees);
334 .fields.latitude_degrees =
339 .fields.latitude_degrees);
341 .fields.altitude_meters =
346 .fields.altitude_meters);
350 (GPS_a1->timestamp.time_since_epoch()
352 GPS_b1->timestamp.time_since_epoch()
356 it->second[new_gps->sensorLabel] = new_gps;
365 for (
auto i = list_gps_obs.begin(); i != list_gps_obs.end();
369 if (i->second.size() >= 3)
371 const size_t N = i->second.size();
372 std::map<std::string, CObservationGPS::Ptr>& GPS = i->second;
374 std::map<string, size_t>
383 .getAsStruct<TGeodeticCoords>();
389 std::map<std::string, CObservationGPS::Ptr>::iterator g_it;
391 for (k = 0, g_it = GPS.begin(); g_it != GPS.end(); ++g_it, ++k)
401 string(
"OFFSET_") + g_it->second->sensorLabel;
406 XYZidxs[g_it->second->sensorLabel] =
415 d2f(g_it->second->sensorPose.x()),
416 d2f(g_it->second->sensorPose.y()),
417 d2f(g_it->second->sensorPose.z())));
424 if (doConsistencyCheck && GPS.size() == 3)
435 X[XYZidxs[D_cov_rev_indexes[0]]],
436 Y[XYZidxs[D_cov_rev_indexes[0]]],
437 Z[XYZidxs[D_cov_rev_indexes[0]]]);
439 X[XYZidxs[D_cov_rev_indexes[1]]],
440 Y[XYZidxs[D_cov_rev_indexes[1]]],
441 Z[XYZidxs[D_cov_rev_indexes[1]]]);
443 X[XYZidxs[D_cov_rev_indexes[2]]],
444 Y[XYZidxs[D_cov_rev_indexes[2]]],
445 Z[XYZidxs[D_cov_rev_indexes[2]]]);
452 iGPSdist2, D_mean, D_cov_1);
462 double optimal_scale;
467 corrs, optimal_pose, optimal_scale,
true);
482 robot_path.
insert(i->first, veh_pose);
485 if (doUncertaintyCovs)
489 final_veh_uncert.
cov = outInfoTemp.
W_star;
495 final_veh_uncert.
cov;
501 if (PATH_SMOOTH_FILTER > 0 && robot_path.
size() > 1)
507 const double MAX_DIST_TO_FILTER = 4.0;
509 for (
auto i = robot_path.
begin(); i != robot_path.
end(); ++i)
520 k < PATH_SMOOTH_FILTER && q != robot_path.
begin(); k++)
524 q->first, i->first)) < MAX_DIST_TO_FILTER)
532 k < PATH_SMOOTH_FILTER && q != (--robot_path.
end()); k++)
536 q->first, i->first)) < MAX_DIST_TO_FILTER)
547 filtered_robot_path.
insert(i->first, p);
550 robot_path = filtered_robot_path;
562 for (
auto& GPS_RTK_read : GPS_RTK_reads)
564 if (GPS_RTK_read.second > bestNum)
566 bestNum = GPS_RTK_read.second;
567 bestLabel = GPS_RTK_read.first;
574 const string sect = string(
"OFFSET_") + bestLabel;
598 if (outInfo) *outInfo = outInfoTemp;
mrpt::math::CQuaternionDouble & quat()
Read/Write access to the quaternion representing the 3D rotation.
std::chrono::duration< rep, period > duration
This class implements a config file-like interface over a memory-stored string list.
double averageWrap2Pi(const CVectorDouble &angles)
Computes the average of a sequence of angles in radians taking into account the correct wrapping in t...
uint8_t fix_quality
NMEA standard values: 0 = invalid, 1 = GPS fix (SPS), 2 = DGPS fix, 3 = PPS fix, 4 = Real Time Kinema...
CPose3D mean
The mean value.
double latitude_degrees
The measured latitude, in degrees (North:+ , South:-)
std::chrono::time_point< Clock > time_point
#define THROW_EXCEPTION(msg)
double roll
Roll coordinate (rotation angle over X coordinate).
T y() const
Return y coordinate of the quaternion.
void read_matrix(const std::string §ion, const std::string &name, MATRIX_TYPE &outMatrix, const MATRIX_TYPE &defaultMatrix=MATRIX_TYPE(), bool failIfNotFound=false) const
Reads a configuration parameter as a matrix written in a matlab-like format - for example: "[2 3 4 ; ...
A set of geodetic coordinates: latitude, longitude and height, defined over a given geoid (typically...
void geodeticToENU_WGS84(const TGeodeticCoords &in_coords, mrpt::math::TPoint3D &out_ENU_point, const TGeodeticCoords &in_coords_origin)
Coordinates transformation from longitude/latitude/height to ENU (East-North-Up) X/Y/Z coordinates Th...
void setInterpolationMethod(TInterpolatorMethod method)
Change the method used to interpolate the robot path.
Used to return optional information from mrpt::topography::path_from_rtk_gps.
void push_back(const T &val)
#define ASSERT_(f)
Defines an assertion mechanism.
float d2f(const double d)
shortcut for static_cast<float>(double)
double altitude_meters
The measured altitude, in meters (A).
This base provides a set of functions for maths stuff.
T r() const
Return r (real part) coordinate of the quaternion.
#define CLASS_ID(T)
Access to runtime class ID for a defined class name.
#define MRPT_CHECK_NORMAL_NUMBER(v)
Throws an exception if the number is NaN, IND, or +/-INF, or return the same number otherwise...
CObservation::Ptr getAsObservation(size_t index) const
Returns the i'th element in the sequence, as being an observation, where index=0 is the first object...
std::map< mrpt::Clock::time_point, mrpt::math::CMatrixDouble66 > vehicle_uncertainty
The 6x6 covariance matrix for the uncertainty of each vehicle pose (may be empty if there is no W_sta...
double longitude_degrees
The measured longitude, in degrees (East:+ , West:-)
This class stores a rawlog (robotic datasets) in one of two possible formats:
This namespace contains representation of robot actions and observations.
TPoint3D_< double > TPoint3D
Lightweight 3D point.
double read_double(const std::string §ion, const std::string &name, double defaultValue, bool failIfNotFound=false) const
double x() const
Common members of all points & poses classes.
A class used to store a 3D pose as a translation (x,y,z) and a quaternion (qr,qx,qy,qz).
Derived inverse_LLt() const
Returns the inverse of a symmetric matrix using LLt.
T sqrDistanceTo(const TPoint3D_< T > &p) const
Point-to-point distance, squared.
size_type rows() const
Number of rows in the matrix.
size_type cols() const
Number of columns in the matrix.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
A structure for holding correspondences between two sets of points or points-like entities in 2D or 3...
double pitch
Pitch coordinate (rotation angle over Y axis).
mrpt::math::CMatrixDouble66 cov
The 6x6 covariance matrix.
return_t square(const num_t x)
Inline function for the square of a number.
void setMaxTimeInterpolation(const mrpt::Clock::duration &time)
Set value of the maximum time to consider interpolation.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
T x() const
Return x coordinate of the quaternion.
void clear()
Clears the current sequence of poses.
void path_from_rtk_gps(mrpt::poses::CPose3DInterpolator &robot_path, const mrpt::obs::CRawlog &rawlog, size_t rawlog_first, size_t rawlog_last, bool isGUI=false, bool disableGPSInterp=false, int path_smooth_filter_size=2, TPathFromRTKInfo *outInfo=nullptr)
Reconstruct the path of a vehicle equipped with 3 RTK GPSs.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
std::set< T > make_set(const T &v0, const T &v1)
std::map< mrpt::Clock::time_point, mrpt::math::TPoint3D > best_gps_path
the path of the "best" GPS.
mrpt::math::CMatrixDouble W_star
The reference covariance matrix used to compute vehicle_uncertainty.
void setSize(size_t row, size_t col, bool zeroNewElements=false)
Changes the size of matrix, maintaining the previous contents.
VECTORLIKE1::Scalar mahalanobisDistance(const VECTORLIKE1 &X, const VECTORLIKE2 &MU, const MAT &COV)
Computes the mahalanobis distance of a vector X given the mean MU and the covariance inverse COV_inv ...
TGEODETICCOORDS getAsStruct() const
Return the geodetic coords as a mrpt::topography::TGeodeticCoords structure (requires linking against...
void setFromValues(const double x0, const double y0, const double z0, const double yaw=0, const double pitch=0, const double roll=0)
Set the pose from a 3D position (meters) and yaw/pitch/roll angles (radians) - This method recomputes...
Lightweight 3D pose (three spatial coordinates, plus three angular coordinates).
content_t fields
Message content, accesible by individual fields.
Declares a class that represents a Probability Density function (PDF) of a 3D pose ...
bool se3_l2(const mrpt::tfest::TMatchingPairList &in_correspondences, mrpt::poses::CPose3DQuat &out_transform, double &out_scale, bool forceScaleToUnity=false)
Least-squares (L2 norm) solution to finding the optimal SE(3) transform between two reference frames ...
T distanceTo(const TPoint3D_< T > &p) const
Point-to-point distance.
This class stores a time-stamped trajectory in SE(3) (CPose3D poses).
std::map< mrpt::Clock::time_point, double > mahalabis_quality_measure
A measure of the quality at each point (may be empty if not there is no enough information).
TEntryType getType(size_t index) const
Returns the type of a given element.
void insert(const mrpt::Clock::time_point &t, const pose_t &p)
Inserts a new pose in the sequence.
void changeCoordinatesReference(const CPose3D &newReferenceBase) override
this = p (+) this.
double timeDifference(const mrpt::system::TTimeStamp t_first, const mrpt::system::TTimeStamp t_later)
Returns the time difference from t1 to t2 (positive if t2 is posterior to t1), in seconds...
void resize(std::size_t N, bool zeroNewElements=false)
This namespace provides topography helper functions, coordinate transformations.
This class stores messages from GNSS or GNSS+IMU devices, from consumer-grade inexpensive GPS receive...
T z() const
Return z coordinate of the quaternion.
size_t size() const
Returns the number of actions / observations object in the sequence.
Functions for estimating the optimal transformation between two frames of references given measuremen...
void getCommentTextAsConfigFile(mrpt::config::CConfigFileMemory &memCfg) const
Saves the block of comment text for the rawlog into the passed config file object.