From 40c9e189072bbb7704de31377e0ac8230f3f2a8f Mon Sep 17 00:00:00 2001 From: jvallve <jvallve@224674b8-e365-4e73-a4a8-558dbbfec58c> Date: Fri, 27 Mar 2015 17:47:31 +0000 Subject: [PATCH] states units in sensor base (and constructors of derived), getting and setting covariance blocks and computing mahalanobis distance (in progress...) --- src/capture_base.cpp | 2 +- src/capture_base.h | 43 +- src/capture_gps_fix.h | 11 +- src/capture_laser_2D.cpp | 336 +++++++----- src/capture_laser_2D.h | 2 + src/capture_odom_2D.cpp | 161 +++--- src/ceres_wrapper/ceres_manager.cpp | 73 ++- src/constraint_base.h | 47 +- src/constraint_corner_2D_theta.h | 10 +- src/constraint_gps_2D.h | 4 +- src/constraint_odom_2D_complex_angle.h | 71 ++- src/constraint_odom_2D_theta.h | 79 ++- src/examples/CMakeLists.txt | 8 +- src/examples/test_ceres_2_lasers.cpp | 711 ++++++++++++------------- src/frame_base.h | 4 +- src/landmark_base.h | 140 +++-- src/node_linked.h | 1 - src/sensor_base.cpp | 56 +- src/sensor_base.h | 60 ++- src/sensor_gps_fix.cpp | 4 +- src/sensor_gps_fix.h | 5 +- src/sensor_laser_2D.cpp | 4 +- src/sensor_laser_2D.h | 21 +- src/sensor_odom_2D.cpp | 4 +- src/sensor_odom_2D.h | 5 +- src/state_base.h | 7 + src/state_complex_angle.cpp | 5 + src/state_complex_angle.h | 9 +- src/state_orientation.h | 40 +- src/state_point.h | 8 +- src/state_theta.cpp | 56 +- src/state_theta.h | 79 +-- src/wolf.h | 74 ++- src/wolf_manager.h | 307 ++++++----- src/wolf_problem.cpp | 64 ++- src/wolf_problem.h | 22 +- 36 files changed, 1370 insertions(+), 1163 deletions(-) diff --git a/src/capture_base.cpp b/src/capture_base.cpp index 60cb39225..f2ce6f2a7 100644 --- a/src/capture_base.cpp +++ b/src/capture_base.cpp @@ -24,7 +24,7 @@ CaptureBase::CaptureBase(const TimeStamp& _ts, SensorBase* _sensor_ptr, const Ei data_(_data), data_covariance_(_data_covariance) { - // + //std::cout << "created CaptureBase " << nodeId() << std::endl << "covariance: " << std::endl << data_covariance_ << std::endl; } CaptureBase::~CaptureBase() diff --git a/src/capture_base.h b/src/capture_base.h index a19f47213..64cda3a3b 100644 --- a/src/capture_base.h +++ b/src/capture_base.h @@ -1,4 +1,3 @@ - #ifndef CAPTURE_BASE_H_ #define CAPTURE_BASE_H_ @@ -18,7 +17,7 @@ class FeatureBase; #include "sensor_base.h" //class CaptureBase -class CaptureBase : public NodeLinked<FrameBase,FeatureBase> +class CaptureBase : public NodeLinked<FrameBase, FeatureBase> { protected: TimeStamp time_stamp_; ///< Time stamp @@ -27,44 +26,44 @@ class CaptureBase : public NodeLinked<FrameBase,FeatureBase> Eigen::MatrixXs data_covariance_; ///< Noise of the capture Eigen::Vector3s sensor_pose_global_; ///< Sensor pose in world frame: composition of the frame pose and the sensor pose. TODO: use state units Eigen::Vector3s inverse_sensor_pose_; ///< World pose in the sensor frame: inverse of the global_pose_. TODO: use state units - + public: - CaptureBase(const TimeStamp& _ts, SensorBase* _sensor_ptr);//TODO: to be removed ?? - + CaptureBase(const TimeStamp& _ts, SensorBase* _sensor_ptr); //TODO: to be removed ?? + CaptureBase(const TimeStamp& _ts, SensorBase* _sensor_ptr, const Eigen::VectorXs& _data); CaptureBase(const TimeStamp& _ts, SensorBase* _sensor_ptr, const Eigen::VectorXs& _data, const Eigen::MatrixXs& _data_covariance); virtual ~CaptureBase(); - + /** \brief Set link to Frame - * + * * Set link to Frame * **/ void linkToFrame(FrameBase* _frm_ptr); - + /** \brief Adds a Feature to the down node list - * + * * Adds a Feature to the down node list * - **/ + **/ void addFeature(FeatureBase* _ft_ptr); /** \brief Gets up_node_ptr_ - * + * * Gets up_node_ptr_, which is a pointer to the Frame owning of this Capture * - **/ + **/ FrameBase* getFramePtr() const; - + /** \brief Gets a pointer to feature list - * + * * Gets a pointer to feature list * - **/ + **/ FeatureBaseList* getFeatureListPtr(); - + /** \brief Fills the provided list with all constraints related to this capture * * Fills the provided list with all constraints related to this capture @@ -75,11 +74,11 @@ class CaptureBase : public NodeLinked<FrameBase,FeatureBase> TimeStamp getTimeStamp() const; SensorBase* getSensorPtr() const; - + SensorType getSensorType() const; - + void setTimeStamp(const TimeStamp & _ts); - + void setTimeStampToNow(); Eigen::VectorXs getData(); @@ -87,12 +86,12 @@ class CaptureBase : public NodeLinked<FrameBase,FeatureBase> Eigen::MatrixXs getDataCovariance(); void setData(unsigned int _size, const WolfScalar *_data); - + void setData(const Eigen::VectorXs& _data); void setDataCovariance(const Eigen::MatrixXs& _data_cov); - - virtual void processCapture();// = 0; + + virtual void processCapture(); // = 0; virtual Eigen::VectorXs computePrior() const = 0; diff --git a/src/capture_gps_fix.h b/src/capture_gps_fix.h index cd516619a..42fdd7dca 100644 --- a/src/capture_gps_fix.h +++ b/src/capture_gps_fix.h @@ -1,4 +1,3 @@ - #ifndef CAPTURE_GPS_FIX_H_ #define CAPTURE_GPS_FIX_H_ @@ -13,14 +12,14 @@ class CaptureGPSFix : public CaptureBase { public: - CaptureGPSFix(const TimeStamp& _ts, SensorBase* _sensor_ptr); + CaptureGPSFix(const TimeStamp& _ts, SensorBase* _sensor_ptr); + + CaptureGPSFix(const TimeStamp& _ts, SensorBase* _sensor_ptr, const Eigen::VectorXs& _data); - CaptureGPSFix(const TimeStamp& _ts, SensorBase* _sensor_ptr, const Eigen::VectorXs& _data); + CaptureGPSFix(const TimeStamp& _ts, SensorBase* _sensor_ptr, const Eigen::VectorXs& _data, const Eigen::MatrixXs& _data_covariance); - CaptureGPSFix(const TimeStamp& _ts, SensorBase* _sensor_ptr, const Eigen::VectorXs& _data, const Eigen::MatrixXs& _data_covariance); - virtual ~CaptureGPSFix(); - + virtual void processCapture(); virtual Eigen::VectorXs computePrior() const; diff --git a/src/capture_laser_2D.cpp b/src/capture_laser_2D.cpp index 432bb2234..d6255c7e2 100644 --- a/src/capture_laser_2D.cpp +++ b/src/capture_laser_2D.cpp @@ -1,6 +1,5 @@ #include "capture_laser_2D.h" - // unsigned int CaptureLaser2D::segment_window_size = 8;//window size to extract segments // double CaptureLaser2D::theta_min = 0.4; //minimum theta between consecutive segments to detect corner. PI/8=0.39 // double CaptureLaser2D::theta_max_parallel = 0.1; //maximum theta between consecutive segments to fuse them in a single line. @@ -15,11 +14,10 @@ //{ // laser_ptr_ = (SensorLaser2D*)sensor_ptr_; //} -CaptureLaser2D::CaptureLaser2D(const TimeStamp & _ts, SensorBase* _sensor_ptr, const std::vector<float>& _ranges): - CaptureBase(_ts, _sensor_ptr), - ranges_(_ranges) +CaptureLaser2D::CaptureLaser2D(const TimeStamp & _ts, SensorBase* _sensor_ptr, const std::vector<float>& _ranges) : + CaptureBase(_ts, _sensor_ptr), ranges_(_ranges) { - laser_ptr_ = (SensorLaser2D*)sensor_ptr_; + laser_ptr_ = (SensorLaser2D*) sensor_ptr_; } //CaptureLaser2D::CaptureLaser2D(const TimeStamp & _ts, SensorBase* _sensor_ptr, const Eigen::VectorXs& _ranges, const Eigen::VectorXs& _intensities): @@ -29,12 +27,10 @@ CaptureLaser2D::CaptureLaser2D(const TimeStamp & _ts, SensorBase* _sensor_ptr, c //{ // laser_ptr_ = (SensorLaser2D*)sensor_ptr_; //} -CaptureLaser2D::CaptureLaser2D(const TimeStamp & _ts, SensorBase* _sensor_ptr, const std::vector<float>& _ranges, const std::vector<float>& _intensities): - CaptureBase(_ts, _sensor_ptr), - ranges_(_ranges), - intensities_(_intensities) +CaptureLaser2D::CaptureLaser2D(const TimeStamp & _ts, SensorBase* _sensor_ptr, const std::vector<float>& _ranges, const std::vector<float>& _intensities) : + CaptureBase(_ts, _sensor_ptr), ranges_(_ranges), intensities_(_intensities) { - laser_ptr_ = (SensorLaser2D*)sensor_ptr_; + laser_ptr_ = (SensorLaser2D*) sensor_ptr_; } CaptureLaser2D::~CaptureLaser2D() @@ -46,16 +42,16 @@ void CaptureLaser2D::processCapture() { //variables //std::list<Eigen::Vector4s> corners; - std::list<laserscanutils::Corner> corners; - + std::list < laserscanutils::Corner > corners; + //extract corners from range data - extractCorners(corners); + extractCorners (corners); //std::cout << corners.size() << " corners extracted" << std::endl; - + //generate a feature for each corner createFeatures(corners); //std::cout << getFeatureListPtr()->size() << " Features created" << std::endl; - + //Establish constraints for each feature establishConstraints(); //std::cout << "Constraints created" << std::endl; @@ -63,9 +59,9 @@ void CaptureLaser2D::processCapture() unsigned int CaptureLaser2D::extractCorners(std::list<laserscanutils::Corner> & _corner_list) const { - std::list<laserscanutils::Line> line_list; - laserscanutils::extractLines(laser_ptr_->getScanParams(), laser_ptr_->getCornerAlgParams(), ranges_, line_list); - return laserscanutils::extractCorners(laser_ptr_->getScanParams(), laser_ptr_->getCornerAlgParams(), line_list, _corner_list); + std::list < laserscanutils::Line > line_list; + laserscanutils::extractLines(laser_ptr_->getScanParams(), laser_ptr_->getCornerAlgParams(), ranges_, line_list); + return laserscanutils::extractCorners(laser_ptr_->getScanParams(), laser_ptr_->getCornerAlgParams(), line_list, _corner_list); } unsigned int CaptureLaser2D::extractLines(std::list<laserscanutils::Line> & _line_list) const @@ -75,144 +71,226 @@ unsigned int CaptureLaser2D::extractLines(std::list<laserscanutils::Line> & _lin void CaptureLaser2D::createFeatures(std::list<laserscanutils::Corner> & _corner_list) { - // TODO: Sensor model + // TODO: Sensor model Eigen::Matrix4s cov_mat; Eigen::Vector4s meas; - + //init constant cov - cov_mat << 0.01, 0, 0, 0, - 0, 0.01, 0, 0, - 0, 0, 0.01, 0, - 0, 0, 0, 0.01; - + cov_mat << 0.01, 0, 0, 0, 0, 0.01, 0, 0, 0, 0, 0.01, 0, 0, 0, 0, 0.01; + //for each corner in the list create a feature - for (auto corner_it = _corner_list.begin(); corner_it != _corner_list.end(); corner_it ++) + for (auto corner_it = _corner_list.begin(); corner_it != _corner_list.end(); corner_it++) { - meas.head(2) = (*corner_it).pt_.head(2); - meas(2) = (*corner_it).orientation_; - meas(3) = (*corner_it).aperture_; - //TODO: add the rest of descriptors and struct atributes - this->addFeature( (FeatureBase*)(new FeatureCorner2D( meas, cov_mat ) ) ); + meas.head(2) = (*corner_it).pt_.head(2); + meas(2) = (*corner_it).orientation_; + meas(3) = (*corner_it).aperture_; + //TODO: add the rest of descriptors and struct atributes + this->addFeature((FeatureBase*) (new FeatureCorner2D(meas, cov_mat))); } } void CaptureLaser2D::establishConstraints() { - // Global transformation TODO: Change by a function - Eigen::Vector2s t_robot(*getFramePtr()->getPPtr()->getPtr(),*(getFramePtr()->getPPtr()->getPtr()+1)); - Eigen::Matrix2s R_robot = ((StateOrientation*)(getFramePtr()->getOPtr()))->getRotationMatrix().topLeftCorner<2,2>(); - WolfScalar& robot_orientation = *(getFramePtr()->getOPtr()->getPtr()); + // Global transformation TODO: Change by a function + Eigen::Vector2s t_robot = getFramePtr()->getPPtr()->getVector(); + Eigen::Matrix2s R_robot = ((StateOrientation*) (getFramePtr()->getOPtr()))->getRotationMatrix().topLeftCorner<2, 2>(); + WolfScalar& robot_orientation = *(getFramePtr()->getOPtr()->getPtr()); - // Sensor transformation - Eigen::Vector2s t_sensor = getSensorPtr()->getSensorPosition()->head(2); - Eigen::Matrix2s R_sensor = getSensorPtr()->getSensorRotation()->topLeftCorner<2,2>(); + // Sensor transformation + Eigen::Vector2s t_sensor = getSensorPtr()->getPPtr()->getVector(); + Eigen::Matrix2s R_sensor = getSensorPtr()->getOPtr()->getRotationMatrix().topLeftCorner<2, 2>(); //Brute force closest (xy and theta) landmark search //TODO: B&B // std::cout << "Brute force closest (xy and theta) landmark search: N features:" << getFeatureListPtr()->size() << std::endl; -// std::cout << "N landmark:" << getTop()->getMapPtr()->getLandmarkListPtr()->size() << std::endl; -// std::cout << "Vehicle transformation: " << std::endl; +// std::cout << "N landmark:" << getTop()->getMapPtr()->getLandmarkListPtr()->size() << std::endl; +// std::cout << "Vehicle transformation: " << std::endl; // std::cout << "t: " << t.transpose() << std::endl; // std::cout << "rot:" << R << std::endl; - for (auto feature_it = getFeatureListPtr()->begin(); feature_it != getFeatureListPtr()->end(); feature_it++ ) - { - WolfScalar max_distance_matching_sq = 0.5; - WolfScalar max_theta_matching = M_PI / 16; - WolfScalar min_distance_sq = max_distance_matching_sq; - - //Find the closest landmark to the feature - LandmarkCorner2D* correspondent_landmark = nullptr; - const Eigen::Vector2s& feature_position = (*feature_it)->getMeasurement().head(2); - const WolfScalar& feature_orientation = (*feature_it)->getMeasurement()(2); - const WolfScalar& feature_aperture = (*feature_it)->getMeasurement()(3); - - Eigen::Vector2s feature_global_position = R_robot * (R_sensor * feature_position + t_sensor) + t_robot; - WolfScalar feature_global_orientation = feature_orientation + robot_orientation + atan2(R_sensor(1,0),R_sensor(0,0)); - feature_global_orientation = (feature_global_orientation > 0 ? // fit in (-pi, pi] - fmod(feature_global_orientation+M_PI, 2 * M_PI)-M_PI : - fmod(feature_global_orientation-M_PI, 2 * M_PI)+M_PI); - -// std::cout << "-------- Feature: " << (*feature_it)->nodeId() << std::endl << -// feature_global_position.transpose() << -// "\t" << feature_global_orientation << -// "\t" << feature_aperture << std::endl; - for (auto landmark_it = getTop()->getMapPtr()->getLandmarkListPtr()->begin(); landmark_it != getTop()->getMapPtr()->getLandmarkListPtr()->end(); landmark_it++ ) - { - Eigen::Map<Eigen::Vector2s> landmark_position((*landmark_it)->getPPtr()->getPtr()); - WolfScalar& landmark_orientation = *((*landmark_it)->getOPtr()->getPtr()); - const WolfScalar& landmark_aperture = (*landmark_it)->getDescriptor()(0); - - // First check: APERTURE - //std::cout << " aperture diff: " << fabs(feature_aperture - landmark_aperture); - if (fabs(feature_aperture - landmark_aperture) < max_theta_matching) - { - //std::cout << " OK!" << std::endl; - - // Second check: SQUARED DISTANCE - WolfScalar distance_sq = (landmark_position-feature_global_position).squaredNorm(); - //std::cout << " distance squared: " << distance_sq; - if (distance_sq < min_distance_sq) - { - -// std::cout << "Close landmark candidate: " << (*landmark_it)->nodeId() << std::endl << -// landmark_position.transpose() << -// "\t" << landmark_orientation << -// "\t" << landmark_aperture << std::endl; - //std::cout << " OK!" << std::endl; - // Third check: ORIENTATION - WolfScalar theta_distance = fabs(fmod(fabs(landmark_orientation-feature_global_orientation)+M_PI, 2 * M_PI)-M_PI);// fit in (-pi, pi] + for (auto feature_it = getFeatureListPtr()->begin(); feature_it != getFeatureListPtr()->end(); feature_it++) + { + WolfScalar max_distance_matching_sq = 0.5; + WolfScalar max_theta_matching = M_PI / 16; + WolfScalar min_distance_sq = max_distance_matching_sq; + + //Find the closest landmark to the feature + LandmarkCorner2D* correspondent_landmark = nullptr; + const Eigen::Vector2s& feature_position = (*feature_it)->getMeasurement().head(2); + const WolfScalar& feature_orientation = (*feature_it)->getMeasurement()(2); + const WolfScalar& feature_aperture = (*feature_it)->getMeasurement()(3); + + Eigen::Vector2s feature_global_position = R_robot * (R_sensor * feature_position + t_sensor) + t_robot; + WolfScalar feature_global_orientation = feature_orientation + robot_orientation + atan2(R_sensor(1, 0), R_sensor(0, 0)); + feature_global_orientation = (feature_global_orientation > 0 ? // fit in (-pi, pi] + fmod(feature_global_orientation + M_PI, 2 * M_PI) - M_PI : fmod(feature_global_orientation - M_PI, 2 * M_PI) + M_PI); + +// std::cout << "-------- Feature: " << (*feature_it)->nodeId() << std::endl << feature_global_position.transpose() << "\t" << feature_global_orientation +// << "\t" << feature_aperture << std::endl; + for (auto landmark_it = getTop()->getMapPtr()->getLandmarkListPtr()->begin(); landmark_it != getTop()->getMapPtr()->getLandmarkListPtr()->end(); landmark_it++) + { + Eigen::Map<Eigen::Vector2s> landmark_position((*landmark_it)->getPPtr()->getPtr()); + WolfScalar& landmark_orientation = *((*landmark_it)->getOPtr()->getPtr()); + const WolfScalar& landmark_aperture = (*landmark_it)->getDescriptor()(0); + + // First check: APERTURE + // std::cout << " aperture diff: " << fabs(feature_aperture - landmark_aperture); + if (fabs(feature_aperture - landmark_aperture) < max_theta_matching) + { + //std::cout << " OK!" << std::endl; + + // MAHALANOBIS DISTANCE + WolfScalar mahalanobis_distance = computeMahalanobisDistance((*feature_it),(*landmark_it)); + + // Second check: SQUARED DISTANCE + WolfScalar distance_sq = (landmark_position - feature_global_position).squaredNorm(); + //std::cout << " distance squared: " << distance_sq; + if (distance_sq < min_distance_sq) + { +// std::cout << "Close landmark candidate: " << (*landmark_it)->nodeId() << std::endl << +// landmark_position.transpose() << +// "\t" << landmark_orientation << +// "\t" << landmark_aperture << std::endl; + //std::cout << " OK!" << std::endl; + // Third check: ORIENTATION + WolfScalar theta_distance = fabs(fmod(fabs(landmark_orientation - feature_global_orientation) + M_PI, 2 * M_PI) - M_PI); // fit in (-pi, pi] // std::cout << " orientation diff: " << theta_distance; - if (theta_distance < max_theta_matching) - { -// std::cout << " OK!" << std::endl; -// std::cout << "Closer landmark found (satisfying orientation and aperture)" << std::endl; - - correspondent_landmark = (LandmarkCorner2D*)(*landmark_it); - min_distance_sq = distance_sq; - } -// else -// std::cout << " KO" << std::endl; -// else -// std::cout << " KO" << std::endl; - } - } -// else -// std::cout << " KO" << std::endl; - } - if (correspondent_landmark == nullptr) - { + if (theta_distance < max_theta_matching) + { + // std::cout << " OK!" << std::endl; + // std::cout << "Closer landmark found (satisfying orientation and aperture)" << std::endl; + + correspondent_landmark = (LandmarkCorner2D*) (*landmark_it); + min_distance_sq = distance_sq; + } +// else +// std::cout << " KO" << std::endl; +// else +// std::cout << " KO" << std::endl; + } + } +// else +// std::cout << " KO" << std::endl; + } + if (correspondent_landmark == nullptr) + { // std::cout << "+++++ No landmark found. Creating a new one..." << std::endl; - StateBase* new_landmark_state_position = new StatePoint2D(getTop()->getNewStatePtr()); - getTop()->addState(new_landmark_state_position, feature_global_position); - StateBase* new_landmark_state_orientation = new StateTheta(getTop()->getNewStatePtr()); - getTop()->addState(new_landmark_state_orientation, Eigen::Map<Eigen::Vector1s>(&feature_global_orientation,1)); + StateBase* new_landmark_state_position = new StatePoint2D(getTop()->getNewStatePtr()); + getTop()->addState(new_landmark_state_position, feature_global_position); + StateBase* new_landmark_state_orientation = new StateTheta(getTop()->getNewStatePtr()); + getTop()->addState(new_landmark_state_orientation, Eigen::Map < Eigen::Vector1s > (&feature_global_orientation, 1)); - correspondent_landmark = new LandmarkCorner2D(new_landmark_state_position, new_landmark_state_orientation, feature_aperture); - LandmarkBase* corr_landmark(correspondent_landmark); - getTop()->getMapPtr()->addLandmark(corr_landmark); + correspondent_landmark = new LandmarkCorner2D(new_landmark_state_position, new_landmark_state_orientation, feature_aperture); + LandmarkBase* corr_landmark(correspondent_landmark); + getTop()->getMapPtr()->addLandmark(corr_landmark); -// std::cout << "Landmark created: " << getTop()->getMapPtr()->getLandmarkListPtr()->back()->nodeId() << std::endl << +// std::cout << "Landmark created: " << +// getTop()->getMapPtr()->getLandmarkListPtr()->back()->nodeId() << std::endl << // feature_global_position.transpose() << // "\t" << feature_global_orientation << // "\t" << feature_aperture << std::endl; - } - else - correspondent_landmark->hit(); - -// std::cout << "Creating new constraint: Landmark " << getTop()->getMapPtr()->getLandmarkListPtr()->back()->nodeId() << " & feature " << (*feature_it)->nodeId() << std::endl; - - // Add constraint to the correspondent landmark - (*feature_it)->addConstraint(new ConstraintCorner2DTheta(*feature_it, - correspondent_landmark, - getFramePtr()->getPPtr(),//_robotPPtr, - getFramePtr()->getOPtr(),//_robotOPtr, - correspondent_landmark->getPPtr(), //_landmarkPPtr, - correspondent_landmark->getOPtr())); //_landmarkOPtr, - } + } + else + correspondent_landmark->hit(); + + // std::cout << "Creating new constraint: Landmark " << getTop()->getMapPtr()->getLandmarkListPtr()->back()->nodeId() << " & feature " + // << (*feature_it)->nodeId() << std::endl; + + // Add constraint to the correspondent landmark + (*feature_it)->addConstraint(new ConstraintCorner2DTheta(*feature_it, correspondent_landmark, getFramePtr()->getPPtr(), //_robotPPtr, + getFramePtr()->getOPtr(), //_robotOPtr, + correspondent_landmark->getPPtr(), //_landmarkPPtr, + correspondent_landmark->getOPtr())); //_landmarkOPtr, + } } Eigen::VectorXs CaptureLaser2D::computePrior() const { - return Eigen::Vector3s(1,2,3); + return Eigen::Vector3s(1, 2, 3); } +WolfScalar CaptureLaser2D::computeMahalanobisDistance(const FeatureBase* _feature_ptr, const LandmarkBase* _landmark_ptr) +{ + FrameBase* frame_ptr = _feature_ptr->getFramePtr(); + unsigned int frame_p_size = frame_ptr->getPPtr()->getStateSize(); + unsigned int frame_o_size = frame_ptr->getOPtr()->getStateSize(); + unsigned int landmark_p_size = _landmark_ptr->getPPtr()->getStateSize(); + unsigned int landmark_o_size = _landmark_ptr->getOPtr()->getStateSize(); + + Eigen::Vector2s p_robot = getFramePtr()->getPPtr()->getVector(); + Eigen::Matrix2s R_robot = ((StateOrientation*) (getFramePtr()->getOPtr()))->getRotationMatrix().topLeftCorner<2,2>(); + Eigen::Vector2s p_sensor = getSensorPtr()->getPPtr()->getVector(); + Eigen::Matrix2s R_sensor = getSensorPtr()->getOPtr()->getRotationMatrix().topLeftCorner<2, 2>(); + Eigen::Vector2s p_landmark = _landmark_ptr->getPPtr()->getVector(); + + // Fill sigma matrix (upper diagonal only) + Eigen::MatrixXs Sigma(frame_p_size + frame_o_size + landmark_p_size + landmark_o_size, frame_p_size + frame_o_size + landmark_p_size + landmark_o_size); + + Eigen::Map<Eigen::MatrixXs> frame_p_frame_p_cov(&Sigma(0,0),frame_p_size,frame_p_size); + Eigen::Map<Eigen::MatrixXs> frame_p_frame_o_cov(&Sigma(0,frame_p_size),frame_p_size,frame_o_size); + Eigen::Map<Eigen::MatrixXs> frame_p_landmark_p_cov(&Sigma(0,frame_p_size+frame_o_size),frame_p_size,landmark_p_size); + Eigen::Map<Eigen::MatrixXs> frame_p_landmark_o_cov(&Sigma(0,frame_p_size+frame_o_size+landmark_p_size),frame_p_size,landmark_o_size); + getTop()->getCovarianceBlock(frame_ptr->getPPtr(), frame_ptr->getPPtr(), frame_p_frame_p_cov); + getTop()->getCovarianceBlock(frame_ptr->getPPtr(), frame_ptr->getOPtr(), frame_p_frame_o_cov); + getTop()->getCovarianceBlock(frame_ptr->getPPtr(), _landmark_ptr->getPPtr(), frame_p_landmark_p_cov); + getTop()->getCovarianceBlock(frame_ptr->getPPtr(), _landmark_ptr->getOPtr(), frame_p_landmark_o_cov); + + Eigen::Map<Eigen::MatrixXs> frame_o_frame_o_cov(&Sigma(frame_p_size,frame_p_size),frame_o_size,frame_o_size); + Eigen::Map<Eigen::MatrixXs> frame_o_landmark_p_cov(&Sigma(frame_p_size,frame_p_size+frame_o_size),frame_o_size,landmark_p_size); + Eigen::Map<Eigen::MatrixXs> frame_o_landmark_o_cov(&Sigma(frame_p_size,frame_p_size+frame_o_size+landmark_p_size),frame_o_size,landmark_o_size); + getTop()->getCovarianceBlock(frame_ptr->getOPtr(), frame_ptr->getOPtr(), frame_o_frame_o_cov); + getTop()->getCovarianceBlock(frame_ptr->getOPtr(), _landmark_ptr->getPPtr(), frame_o_landmark_p_cov); + getTop()->getCovarianceBlock(frame_ptr->getOPtr(), _landmark_ptr->getOPtr(), frame_o_landmark_o_cov); + + Eigen::Map<Eigen::MatrixXs> landmark_p_landmark_p_cov(&Sigma(frame_p_size+frame_o_size,frame_p_size+frame_o_size),landmark_p_size,landmark_p_size); + Eigen::Map<Eigen::MatrixXs> landmark_p_landmark_o_cov(&Sigma(frame_p_size+frame_o_size,frame_p_size+frame_o_size+landmark_p_size),landmark_p_size,landmark_o_size); + getTop()->getCovarianceBlock(_landmark_ptr->getPPtr(), _landmark_ptr->getPPtr(), landmark_p_landmark_p_cov); + getTop()->getCovarianceBlock(_landmark_ptr->getPPtr(), _landmark_ptr->getOPtr(), landmark_p_landmark_o_cov); + + Eigen::Map<Eigen::MatrixXs> landmark_o_landmark_o_cov(&Sigma(frame_p_size+frame_o_size+landmark_p_size,frame_p_size+frame_o_size+landmark_p_size),landmark_o_size,landmark_o_size); + getTop()->getCovarianceBlock(_landmark_ptr->getOPtr(), _landmark_ptr->getOPtr(), landmark_o_landmark_o_cov); + + // Jacobian + if (_landmark_ptr->getOPtr()->getStateType() == ST_THETA && frame_ptr->getOPtr()->getStateType() == ST_THETA) + { + Eigen::MatrixXs J = Eigen::MatrixXs::Zero(6,3); + WolfScalar theta_s_r = *getSensorPtr()->getOPtr()->getPtr() + *frame_ptr->getOPtr()->getPtr(); // Sum of theta_sensor and theta_robot + + J(0,0) = -cos(theta_s_r); + J(0,1) = sin(theta_s_r); + J(1,0) = -sin(theta_s_r); + J(1,1) = -cos(theta_s_r); + J(2,0) = -sin(theta_s_r) * (p_landmark(0) - p_robot(0)) - cos(theta_s_r) * (p_landmark(1) - p_robot(1)); + J(2,1) = cos(theta_s_r) * (p_landmark(0) - p_robot(0)) - sin(theta_s_r) * (p_landmark(1) - p_robot(1)); + J(2,2) = -1; + J(3,0) = cos(theta_s_r); + J(3,1) = -sin(theta_s_r); + J(4,0) = sin(theta_s_r); + J(4,1) = cos(theta_s_r); + J(5,2) = 1; + + // Feature-Landmark (euclidean) distance + const Eigen::Vector2s& feature_position = _feature_ptr->getMeasurement().head(2); + const WolfScalar& feature_orientation = _feature_ptr->getMeasurement()(2); + + Eigen::Vector2s landmark_local_position = R_sensor.transpose() * (R_robot.transpose() * (p_landmark - p_robot) - p_sensor); + WolfScalar landmark_local_orientation = *_landmark_ptr->getOPtr()->getPtr() - *frame_ptr->getOPtr()->getPtr() - *getSensorPtr()->getOPtr()->getPtr(); + + Eigen::Vector3s d_euclidean; + d_euclidean.head(2) = feature_position - landmark_local_position; + d_euclidean(2) = feature_orientation - landmark_local_orientation; + // fit in (-pi, pi] + d_euclidean(2) = (d_euclidean(2) > 0 ? fmod(d_euclidean(2) + M_PI, 2 * M_PI) - M_PI : fmod(d_euclidean(2) - M_PI, 2 * M_PI) + M_PI); + + // Feature-Landmark Mahalanobis distance + // covariance: Eigen::Matrix3s S_m = J * Sigma.selfadjointView<Eigen::Upper>() * J.transpose() + _feature_ptr->getMeasurementCovariance().topLeftCorner<3,3>(); + WolfScalar mahalanobis_distance = d_euclidean.transpose() * (J.transpose() * Sigma.selfadjointView<Eigen::Upper>() * J + _feature_ptr->getMeasurementCovariance().topLeftCorner<3,3>()).inverse() * d_euclidean; + std::cout << "mahalanobis_distance = " << mahalanobis_distance << std::endl; + return mahalanobis_distance; + } + else + { + std::cout << "ERROR: Jacobian using complex angles not computed..." << std::endl; //TODO + assert(false); + return 0; + } +} diff --git a/src/capture_laser_2D.h b/src/capture_laser_2D.h index 7cbc10f49..27d94f439 100644 --- a/src/capture_laser_2D.h +++ b/src/capture_laser_2D.h @@ -105,5 +105,7 @@ class CaptureLaser2D : public CaptureBase void establishConstraints(); virtual Eigen::VectorXs computePrior() const; + + WolfScalar computeMahalanobisDistance(const FeatureBase* _feature, const LandmarkBase* _landmark); }; #endif /* CAPTURE_LASER_2D_H_ */ diff --git a/src/capture_odom_2D.cpp b/src/capture_odom_2D.cpp index c784db7bb..d4d914a26 100644 --- a/src/capture_odom_2D.cpp +++ b/src/capture_odom_2D.cpp @@ -1,128 +1,109 @@ #include "capture_odom_2D.h" CaptureOdom2D::CaptureOdom2D(const TimeStamp& _ts, SensorBase* _sensor_ptr) : - CaptureRelative(_ts, _sensor_ptr) + CaptureRelative(_ts, _sensor_ptr) { // } CaptureOdom2D::CaptureOdom2D(const TimeStamp& _ts, SensorBase* _sensor_ptr, const Eigen::Vector3s& _data) : - CaptureRelative(_ts, _sensor_ptr, _data) + CaptureRelative(_ts, _sensor_ptr, _data) { - data_covariance_ = Eigen::Matrix3s::Zero(); - data_covariance_(0,0) = (_data(0) == 0 ? 1e-6 : _data(0))*((SensorOdom2D*)_sensor_ptr)->getDisplacementNoiseFactor(); - data_covariance_(1,1) = (_data(1) == 0 ? 1e-6 : _data(1))*((SensorOdom2D*)_sensor_ptr)->getDisplacementNoiseFactor(); - data_covariance_(2,2) = (_data(2) == 0 ? 1e-6 : _data(2))*((SensorOdom2D*)_sensor_ptr)->getRotationNoiseFactor(); + data_covariance_ = Eigen::Matrix3s::Zero(); + data_covariance_(0, 0) = (_data(0) == 0 ? 1e-6 : fabs(_data(0))) * ((SensorOdom2D*) _sensor_ptr)->getDisplacementNoiseFactor(); + data_covariance_(1, 1) = (_data(1) == 0 ? 1e-6 : fabs(_data(1))) * ((SensorOdom2D*) _sensor_ptr)->getDisplacementNoiseFactor(); + data_covariance_(2, 2) = (_data(2) == 0 ? 1e-6 : fabs(_data(2))) * ((SensorOdom2D*) _sensor_ptr)->getRotationNoiseFactor(); // std::cout << data_covariance_ << std::endl; } CaptureOdom2D::CaptureOdom2D(const TimeStamp& _ts, SensorBase* _sensor_ptr, const Eigen::Vector3s& _data, const Eigen::Matrix3s& _data_covariance) : - CaptureRelative(_ts, _sensor_ptr, _data, _data_covariance) + CaptureRelative(_ts, _sensor_ptr, _data, _data_covariance) { - // + // } CaptureOdom2D::~CaptureOdom2D() { - //std::cout << "Destroying GPS fix capture...\n"; + //std::cout << "Destroying GPS fix capture...\n"; } inline void CaptureOdom2D::processCapture() { - //std::cout << "CaptureOdom2D::addFeature..." << std::endl; - // ADD FEATURE - addFeature(new FeatureOdom2D(data_,data_covariance_)); + //std::cout << "CaptureOdom2D::addFeature..." << std::endl; + // ADD FEATURE + addFeature(new FeatureOdom2D(data_, data_covariance_)); - //std::cout << "CaptureOdom2D::addConstraints..." << std::endl; - // ADD CONSTRAINT - addConstraints(); + //std::cout << "CaptureOdom2D::addConstraints..." << std::endl; + // ADD CONSTRAINT + addConstraints(); } Eigen::VectorXs CaptureOdom2D::computePrior() const { - assert(up_node_ptr_ != nullptr && "This Capture is not linked to any frame"); - - if (getFramePtr()->getOPtr()->getStateType() == ST_COMPLEX_ANGLE) - { - Eigen::Vector4s prior; - Eigen::Map<Eigen::Vector4s> initial_pose(getFramePtr()->getPPtr()->getPtr()); - ///std::cout << "initial_pose: " << initial_pose.transpose() << std::endl; -// WolfScalar prior_2 = initial_pose(2) * cos(data_(1)) - initial_pose(3) * sin(data_(1)); -// WolfScalar prior_3 = initial_pose(2) * sin(data_(1)) + initial_pose(3) * cos(data_(1)); -// prior(0) = initial_pose(0) + data_(0) * prior_2; -// prior(1) = initial_pose(1) + data_(0) * prior_3; -// prior(2) = prior_2; -// prior(3) = prior_3; - prior(0) = initial_pose(0) + data_(0) * initial_pose(2) - data_(1) * initial_pose(3); - prior(1) = initial_pose(1) + data_(0) * initial_pose(3) + data_(1) * initial_pose(2); - prior(2) = initial_pose(2) * cos(data_(2)) - initial_pose(3) * sin(data_(2)); - prior(3) = initial_pose(2) * sin(data_(2)) + initial_pose(3) * cos(data_(2)); - //std::cout << "data_: " << data_.transpose() << std::endl; - //std::cout << "prior: " << prior.transpose() << std::endl; - - return prior; - } - else - { - Eigen::Vector3s prior; - Eigen::Map<Eigen::Vector3s> initial_pose(getFramePtr()->getPPtr()->getPtr()); - //std::cout << "initial_pose: " << initial_pose.transpose() << std::endl; - -// prior(0) = initial_pose(0) + data_(0) * cos(initial_pose(2) + (data_(1))); -// prior(1) = initial_pose(1) + data_(0) * sin(initial_pose(2) + (data_(1))); -// prior(2) = initial_pose(2) + data_(1); - prior(0) = initial_pose(0) + data_(0) * cos(initial_pose(2)) - data_(1) * sin(initial_pose(2)); - prior(1) = initial_pose(1) + data_(0) * sin(initial_pose(2)) + data_(1) * cos(initial_pose(2)); - prior(2) = initial_pose(2) + data_(2); - //std::cout << "data_: " << data_.transpose() << std::endl; - //std::cout << "prior: " << prior.transpose() << std::endl; - - return prior; - } - + assert(up_node_ptr_ != nullptr && "This Capture is not linked to any frame"); + + if (getFramePtr()->getOPtr()->getStateType() == ST_COMPLEX_ANGLE) + { + Eigen::Vector4s prior; + Eigen::Map<Eigen::Vector4s> initial_pose(getFramePtr()->getPPtr()->getPtr()); + ///std::cout << "initial_pose: " << initial_pose.transpose() << std::endl; + prior(0) = initial_pose(0) + data_(0) * initial_pose(2) - data_(1) * initial_pose(3); + prior(1) = initial_pose(1) + data_(0) * initial_pose(3) + data_(1) * initial_pose(2); + prior(2) = initial_pose(2) * cos(data_(2)) - initial_pose(3) * sin(data_(2)); + prior(3) = initial_pose(2) * sin(data_(2)) + initial_pose(3) * cos(data_(2)); + //std::cout << "data_: " << data_.transpose() << std::endl; + //std::cout << "prior: " << prior.transpose() << std::endl; + + return prior; + } + else + { + Eigen::Vector3s prior; + Eigen::Map<Eigen::Vector3s> initial_pose(getFramePtr()->getPPtr()->getPtr()); + //std::cout << "initial_pose: " << initial_pose.transpose() << std::endl; + prior(0) = initial_pose(0) + data_(0) * cos(initial_pose(2)) - data_(1) * sin(initial_pose(2)); + prior(1) = initial_pose(1) + data_(0) * sin(initial_pose(2)) + data_(1) * cos(initial_pose(2)); + prior(2) = initial_pose(2) + data_(2); + //std::cout << "data_: " << data_.transpose() << std::endl; + //std::cout << "prior: " << prior.transpose() << std::endl; + + return prior; + } } void CaptureOdom2D::addConstraints() { - assert(getFramePtr()->getNextFrame() != nullptr && "Trying to add odometry constraint in the last frame (there is no next frame)"); - - if (getFramePtr()->getOPtr()->getStateType() == ST_COMPLEX_ANGLE) - { - getFeatureListPtr()->front()->addConstraint(new ConstraintOdom2DComplexAngle(getFeatureListPtr()->front(), - getFramePtr()->getPPtr(), - getFramePtr()->getOPtr(), - getFramePtr()->getNextFrame()->getPPtr(), - getFramePtr()->getNextFrame()->getOPtr())); - } - else - { - getFeatureListPtr()->front()->addConstraint(new ConstraintOdom2DTheta(getFeatureListPtr()->front(), - getFramePtr()->getPPtr(), - getFramePtr()->getOPtr(), - getFramePtr()->getNextFrame()->getPPtr(), - getFramePtr()->getNextFrame()->getOPtr())); - } + assert(getFramePtr()->getNextFrame() != nullptr && "Trying to add odometry constraint in the last frame (there is no next frame)"); + + if (getFramePtr()->getOPtr()->getStateType() == ST_COMPLEX_ANGLE) + { + getFeatureListPtr()->front()->addConstraint(new ConstraintOdom2DComplexAngle(getFeatureListPtr()->front(), + getFramePtr()->getPPtr(), + getFramePtr()->getOPtr(), + getFramePtr()->getNextFrame()->getPPtr(), + getFramePtr()->getNextFrame()->getOPtr())); + } + else + { + getFeatureListPtr()->front()->addConstraint(new ConstraintOdom2DTheta(getFeatureListPtr()->front(), + getFramePtr()->getPPtr(), + getFramePtr()->getOPtr(), + getFramePtr()->getNextFrame()->getPPtr(), + getFramePtr()->getNextFrame()->getOPtr())); + } } void CaptureOdom2D::integrateCapture(CaptureRelative* _new_capture) { - //std::cout << "Trying to integrate CaptureOdom2D" << std::endl; - assert(dynamic_cast<CaptureOdom2D*>(_new_capture) && "Trying to integrate with a CaptureOdom2D a CaptureRelativePtr which is not CaptureOdom2D"); - -// data_(0) += _new_capture->getData()(0); -// data_(1) += _new_capture->getData()(1); - - //std::cout << "Integrate odoms: " << std::endl << data_.transpose() << std::endl << _new_capture->getData().transpose() << std::endl; - - data_(0) += (_new_capture->getData()(0) * cos(data_(2)) - _new_capture->getData()(1) * sin(data_(2))); - data_(1) += (_new_capture->getData()(0) * sin(data_(2)) + _new_capture->getData()(1) * cos(data_(2))); - data_(2) += _new_capture->getData()(2); - - //std::cout << "Integrated odoms: " << std::endl << data_.transpose() << std::endl; - - data_covariance_ += _new_capture->getDataCovariance(); - //std::cout << "integrated!" << std::endl; + assert(dynamic_cast<CaptureOdom2D*>(_new_capture) && "Trying to integrate with a CaptureOdom2D a CaptureRelativePtr which is not CaptureOdom2D"); + + //std::cout << "Integrate odoms: " << std::endl << data_.transpose() << std::endl << _new_capture->getData().transpose() << std::endl; + data_(0) += (_new_capture->getData()(0) * cos(data_(2)) - _new_capture->getData()(1) * sin(data_(2))); + data_(1) += (_new_capture->getData()(0) * sin(data_(2)) + _new_capture->getData()(1) * cos(data_(2))); + data_(2) += _new_capture->getData()(2); + data_covariance_ += _new_capture->getDataCovariance(); + //std::cout << "Integrated odoms: " << std::endl << data_.transpose() << std::endl << data_covariance_ << std::endl; } //void CaptureOdom2D::printSelf(unsigned int _ntabs, std::ostream & _ost) const @@ -134,5 +115,3 @@ void CaptureOdom2D::integrateCapture(CaptureRelative* _new_capture) // //_ost << "\tSensor intrinsic : ( " << sensor_ptr_->intrinsic().transpose() << " )" << std::endl; //} - - diff --git a/src/ceres_wrapper/ceres_manager.cpp b/src/ceres_wrapper/ceres_manager.cpp index 0cc8ea757..190eff4d0 100644 --- a/src/ceres_wrapper/ceres_manager.cpp +++ b/src/ceres_wrapper/ceres_manager.cpp @@ -4,8 +4,8 @@ CeresManager::CeresManager(ceres::Problem::Options _options) : ceres_problem_(new ceres::Problem(_options)) { ceres::Covariance::Options covariance_options; - covariance_options.algorithm_type = ceres::DENSE_SVD; - covariance_options.null_space_rank = -1; + covariance_options.algorithm_type = ceres::SUITE_SPARSE_QR;//ceres::DENSE_SVD; + //covariance_options.null_space_rank = -1; covariance_ = new ceres::Covariance(covariance_options); } @@ -37,11 +37,14 @@ ceres::Solver::Summary CeresManager::solve(const ceres::Solver::Options& _ceres_ void CeresManager::computeCovariances(WolfProblem* _problem_ptr) { + // CREATE DESIRED COVARIANCES LIST std::vector<std::pair<const double*, const double*>> covariance_blocks; - // Last frame state units - double* current_position_ptr = _problem_ptr->getTrajectoryPtr()->getFrameListPtr()->back()->getPPtr()->getPtr(); - double* current_orientation_ptr = _problem_ptr->getTrajectoryPtr()->getFrameListPtr()->back()->getOPtr()->getPtr(); + // Last frame + StateBase* current_position = _problem_ptr->getTrajectoryPtr()->getFrameListPtr()->back()->getPPtr(); + StateBase* current_orientation = _problem_ptr->getTrajectoryPtr()->getFrameListPtr()->back()->getOPtr(); + double* current_position_ptr = current_position->getPtr(); + double* current_orientation_ptr = current_orientation->getPtr(); covariance_blocks.push_back(std::make_pair(current_position_ptr,current_position_ptr)); covariance_blocks.push_back(std::make_pair(current_position_ptr,current_orientation_ptr)); covariance_blocks.push_back(std::make_pair(current_orientation_ptr,current_orientation_ptr)); @@ -53,25 +56,63 @@ void CeresManager::computeCovariances(WolfProblem* _problem_ptr) double* landmark_orientation_ptr = (*landmark_it)->getOPtr()->getPtr(); covariance_blocks.push_back(std::make_pair(landmark_position_ptr,landmark_position_ptr)); + covariance_blocks.push_back(std::make_pair(landmark_position_ptr,landmark_orientation_ptr)); + covariance_blocks.push_back(std::make_pair(landmark_orientation_ptr,landmark_orientation_ptr)); covariance_blocks.push_back(std::make_pair(landmark_position_ptr,current_position_ptr)); covariance_blocks.push_back(std::make_pair(landmark_position_ptr,current_orientation_ptr)); - covariance_blocks.push_back(std::make_pair(landmark_position_ptr,landmark_orientation_ptr)); - covariance_blocks.push_back(std::make_pair(landmark_orientation_ptr,landmark_orientation_ptr)); covariance_blocks.push_back(std::make_pair(landmark_orientation_ptr,current_position_ptr)); covariance_blocks.push_back(std::make_pair(landmark_orientation_ptr,current_orientation_ptr)); } + + // COMPUTE DESIRED COVARIANCES covariance_->Compute(covariance_blocks, ceres_problem_); - double c11[2 * 2]; - double c22[1 * 1]; - double c12[2 * 1]; - covariance_->GetCovarianceBlock(current_position_ptr, current_position_ptr, c11); - covariance_->GetCovarianceBlock(current_position_ptr, current_orientation_ptr, c12); - covariance_->GetCovarianceBlock(current_orientation_ptr, current_orientation_ptr, c22); + // STORE DESIRED COVARIANCES + // Last frame + Eigen::MatrixXs m_pp(current_position->getStateSize(),current_position->getStateSize()); + Eigen::MatrixXs m_oo(current_orientation->getStateSize(),current_orientation->getStateSize()); + Eigen::MatrixXs m_po(current_position->getStateSize(),current_orientation->getStateSize()); + + covariance_->GetCovarianceBlock(current_position_ptr, current_position_ptr, m_pp.data()); + covariance_->GetCovarianceBlock(current_position_ptr, current_orientation_ptr, m_po.data()); + covariance_->GetCovarianceBlock(current_orientation_ptr, current_orientation_ptr, m_oo.data()); -// std::cout << "COV\n: " << c11[0] << " " << c11[1] << " " << c12[0] << std::endl << -// c11[2] << " " << c11[3] << " " << c12[1] << std::endl << -// c12[0] << " " << c12[1] << " " << c22[0] << std::endl; + _problem_ptr->addCovarianceBlock(current_position, current_position, m_pp); + _problem_ptr->addCovarianceBlock(current_orientation, current_orientation, m_oo); + _problem_ptr->addCovarianceBlock(current_position, current_orientation, m_po); + + // Landmarks and cross-covariance with current frame + for(auto landmark_it = _problem_ptr->getMapPtr()->getLandmarkListPtr()->begin(); landmark_it!=_problem_ptr->getMapPtr()->getLandmarkListPtr()->end(); landmark_it++) + { + StateBase* landmark_position = (*landmark_it)->getPPtr(); + StateBase* landmark_orientation = (*landmark_it)->getOPtr(); + double* landmark_position_ptr = landmark_position->getPtr(); + double* landmark_orientation_ptr = landmark_orientation->getPtr(); + + Eigen::MatrixXs m_landmark_pp(landmark_position->getStateSize(),landmark_position->getStateSize()); + Eigen::MatrixXs m_landmark_po(landmark_position->getStateSize(),landmark_orientation->getStateSize()); + Eigen::MatrixXs m_landmark_oo(landmark_orientation->getStateSize(),landmark_orientation->getStateSize()); + Eigen::MatrixXs m_landmark_p_frame_p(landmark_position->getStateSize(),current_position->getStateSize()); + Eigen::MatrixXs m_landmark_p_frame_o(landmark_position->getStateSize(),current_orientation->getStateSize()); + Eigen::MatrixXs m_landmark_o_frame_p(landmark_orientation->getStateSize(),current_position->getStateSize()); + Eigen::MatrixXs m_landmark_o_frame_o(landmark_orientation->getStateSize(),current_orientation->getStateSize()); + + covariance_->GetCovarianceBlock(landmark_position_ptr, landmark_position_ptr, m_landmark_pp.data()); + covariance_->GetCovarianceBlock(landmark_position_ptr, landmark_orientation_ptr, m_landmark_po.data()); + covariance_->GetCovarianceBlock(landmark_orientation_ptr, landmark_orientation_ptr, m_landmark_oo.data()); + covariance_->GetCovarianceBlock(landmark_position_ptr, current_position_ptr, m_landmark_p_frame_p.data()); + covariance_->GetCovarianceBlock(landmark_position_ptr, current_orientation_ptr, m_landmark_p_frame_o.data()); + covariance_->GetCovarianceBlock(landmark_orientation_ptr, current_position_ptr, m_landmark_o_frame_p.data()); + covariance_->GetCovarianceBlock(landmark_orientation_ptr, current_orientation_ptr, m_landmark_o_frame_o.data()); + + _problem_ptr->addCovarianceBlock(landmark_position, landmark_position, m_landmark_pp); + _problem_ptr->addCovarianceBlock(landmark_position, landmark_orientation, m_landmark_po); + _problem_ptr->addCovarianceBlock(landmark_orientation, landmark_orientation, m_landmark_oo); + _problem_ptr->addCovarianceBlock(landmark_position, current_position, m_landmark_p_frame_p); + _problem_ptr->addCovarianceBlock(landmark_position, current_orientation, m_landmark_p_frame_o); + _problem_ptr->addCovarianceBlock(landmark_orientation, current_position, m_landmark_o_frame_p); + _problem_ptr->addCovarianceBlock(landmark_orientation, current_orientation, m_landmark_o_frame_o); + } } void CeresManager::update(WolfProblem* _problem_ptr) diff --git a/src/constraint_base.h b/src/constraint_base.h index 4824c8996..4bf7666b5 100644 --- a/src/constraint_base.h +++ b/src/constraint_base.h @@ -1,4 +1,3 @@ - #ifndef CONSTRAINT_BASE_H_ #define CONSTRAINT_BASE_H_ @@ -17,26 +16,26 @@ class NodeTerminus; #include "node_terminus.h" //class ConstraintBase -class ConstraintBase : public NodeLinked<FeatureBase,NodeTerminus> +class ConstraintBase : public NodeLinked<FeatureBase, NodeTerminus> { protected: ConstraintType type_; //type of constraint (types defined at wolf.h) const Eigen::VectorXs& measurement_; // TODO:TBD: pointer, map or copy of the feature measurement? const Eigen::MatrixXs& measurement_covariance_; // TODO:TBD: pointer, map or copy of the feature measurement covariance? - + public: /** \brief Constructor * * Constructor * - **/ + **/ ConstraintBase(FeatureBase* _ftr_ptr, ConstraintType _tp); /** \brief Destructor * * Destructor * - **/ + **/ virtual ~ConstraintBase(); /** \brief Returns the constraint type @@ -45,34 +44,34 @@ class ConstraintBase : public NodeLinked<FeatureBase,NodeTerminus> * **/ ConstraintType getConstraintType() const; - + /** \brief Returns a vector of scalar pointers to the first element of all state blocks involved in the constraint - * - * Returns a vector of scalar pointers to the first element of all state blocks involved in the constraint. - * - **/ + * + * Returns a vector of scalar pointers to the first element of all state blocks involved in the constraint. + * + **/ virtual const std::vector<WolfScalar*> getStateBlockPtrVector() = 0; /** \brief Returns a pointer to the feature measurement - * - * Returns a pointer to the feature measurement - * - **/ + * + * Returns a pointer to the feature measurement + * + **/ const Eigen::VectorXs& getMeasurement(); /** \brief Returns a pointer to its capture - * - * Returns a pointer to its capture - * - **/ - FeatureBase* getFeaturePtr() const; + * + * Returns a pointer to its capture + * + **/ + FeatureBase* getFeaturePtr() const; /** \brief Returns a pointer to its capture - * - * Returns a pointer to its capture - * - **/ - CaptureBase* getCapturePtr() const; + * + * Returns a pointer to its capture + * + **/ + CaptureBase* getCapturePtr() const; }; #endif diff --git a/src/constraint_corner_2D_theta.h b/src/constraint_corner_2D_theta.h index 94767310b..d3a0e6bbf 100644 --- a/src/constraint_corner_2D_theta.h +++ b/src/constraint_corner_2D_theta.h @@ -57,8 +57,8 @@ class ConstraintCorner2DTheta: public ConstraintSparse<3,2,1,2,1> // std::cout << "atan2: " << atan2(getCapturePtr()->getSensorPtr()->getSensorRotation()->transpose()(0,1),getCapturePtr()->getSensorPtr()->getSensorRotation()->transpose()(0,0)) << std::endl; // sensor transformation - Eigen::Matrix<T,2,1> sensor_position = getCapturePtr()->getSensorPtr()->getSensorPosition()->head(2).cast<T>(); - Eigen::Matrix<T,2,2> inverse_R_sensor = (getCapturePtr()->getSensorPtr()->getSensorRotation()->topLeftCorner<2,2>().transpose()).cast<T>(); + Eigen::Matrix<T,2,1> sensor_position = getCapturePtr()->getSensorPtr()->getPPtr()->getVector().head(2).cast<T>(); + Eigen::Matrix<T,2,2> inverse_R_sensor = (getCapturePtr()->getSensorPtr()->getOPtr()->getRotationMatrix().topLeftCorner<2,2>().transpose()).cast<T>(); Eigen::Matrix<T,2,2> inverse_R_robot; inverse_R_robot << cos(*_robotO), sin(*_robotO), @@ -74,9 +74,9 @@ class ConstraintCorner2DTheta: public ConstraintSparse<3,2,1,2,1> expected_landmark_relative_orientation = expected_landmark_relative_orientation + T(2*M_PI); // Residuals - _residuals[0] = (expected_landmark_relative_position(0) - T(measurement_(0))) / T(measurement_covariance_(0,0)); - _residuals[1] = (expected_landmark_relative_position(1) - T(measurement_(1))) / T(measurement_covariance_(1,1)); - _residuals[2] = (expected_landmark_relative_orientation - T(measurement_(2))) / T(100*measurement_covariance_(2,2)); + _residuals[0] = (expected_landmark_relative_position(0) - T(measurement_(0))) / T(sqrt(measurement_covariance_(0,0))); + _residuals[1] = (expected_landmark_relative_position(1) - T(measurement_(1))) / T(sqrt(measurement_covariance_(1,1))); + _residuals[2] = (expected_landmark_relative_orientation - T(measurement_(2))) / T(sqrt(measurement_covariance_(2,2))); // std::cout << "\nCONSTRAINT: " << nodeId() << std::endl; // std::cout << "Feature: " << getFeaturePtr()->nodeId() << std::endl; diff --git a/src/constraint_gps_2D.h b/src/constraint_gps_2D.h index f3e82559f..9b94e4a09 100644 --- a/src/constraint_gps_2D.h +++ b/src/constraint_gps_2D.h @@ -31,8 +31,8 @@ class ConstraintGPS2D: public ConstraintSparse<2,2> template <typename T> bool operator()(const T* const _x, T* _residuals) const { - _residuals[0] = (T(measurement_(0)) - _x[0]) / T(measurement_covariance_(0,0)); - _residuals[1] = (T(measurement_(1)) - _x[1]) / T(measurement_covariance_(1,1)); + _residuals[0] = (T(measurement_(0)) - _x[0]) / T(sqrt(measurement_covariance_(0,0))); + _residuals[1] = (T(measurement_(1)) - _x[1]) / T(sqrt(measurement_covariance_(1,1))); return true; } }; diff --git a/src/constraint_odom_2D_complex_angle.h b/src/constraint_odom_2D_complex_angle.h index 928df9f49..4597709e0 100644 --- a/src/constraint_odom_2D_complex_angle.h +++ b/src/constraint_odom_2D_complex_angle.h @@ -1,4 +1,3 @@ - #ifndef CONSTRAINT_ODOM_2D_COMPLEX_ANGLE_H_ #define CONSTRAINT_ODOM_2D_COMPLEX_ANGLE_H_ @@ -6,50 +5,50 @@ #include "wolf.h" #include "constraint_sparse.h" -class ConstraintOdom2DComplexAngle: public ConstraintSparse<3,2,2,2,2> +class ConstraintOdom2DComplexAngle : public ConstraintSparse<3, 2, 2, 2, 2> { - public: - static const unsigned int N_BLOCKS = 4; + public: + static const unsigned int N_BLOCKS = 4; - ConstraintOdom2DComplexAngle(FeatureBase* _ftr_ptr, WolfScalar* _block0Ptr, WolfScalar* _block1Ptr, WolfScalar* _block2Ptr, WolfScalar* _block3Ptr) : - ConstraintSparse<3,2,2,2,2>(_ftr_ptr,CTR_ODOM_2D_COMPLEX_ANGLE, _block0Ptr, _block1Ptr, _block2Ptr, _block3Ptr) - { - // - } + ConstraintOdom2DComplexAngle(FeatureBase* _ftr_ptr, WolfScalar* _block0Ptr, WolfScalar* _block1Ptr, WolfScalar* _block2Ptr, WolfScalar* _block3Ptr) : + ConstraintSparse<3, 2, 2, 2, 2>(_ftr_ptr, CTR_ODOM_2D_COMPLEX_ANGLE, _block0Ptr, _block1Ptr, _block2Ptr, _block3Ptr) + { + // + } - ConstraintOdom2DComplexAngle(FeatureBase* _ftr_ptr, StateBase* _state0Ptr, StateBase* _state1Ptr, StateBase* _state2Ptr, StateBase* _state3Ptr) : - ConstraintSparse<3,2,2,2,2>(_ftr_ptr,CTR_ODOM_2D_COMPLEX_ANGLE, _state0Ptr->getPtr(), _state1Ptr->getPtr(),_state2Ptr->getPtr(), _state3Ptr->getPtr()) - { - // - } + ConstraintOdom2DComplexAngle(FeatureBase* _ftr_ptr, StateBase* _state0Ptr, StateBase* _state1Ptr, StateBase* _state2Ptr, StateBase* _state3Ptr) : + ConstraintSparse<3, 2, 2, 2, 2>(_ftr_ptr, CTR_ODOM_2D_COMPLEX_ANGLE, _state0Ptr->getPtr(), _state1Ptr->getPtr(), _state2Ptr->getPtr(), _state3Ptr->getPtr()) + { + // + } virtual ~ConstraintOdom2DComplexAngle() - { - // - } - - template <typename T> - bool operator()(const T* const _p1, const T* const _o1, const T* const _p2, const T* const _o2, T* _residuals) const - { - // Expected measurement - // rotar per menys l'angle de primer _o1 - T expected_longitudinal = _o1[0]*(_p2[0]-_p1[0])+_o1[1]*(_p2[1]-_p1[1]); // cos(-o1)(x2-x1) - sin(-o1)(y2-y1) - T expected_lateral = -_o1[1]*(_p2[0]-_p1[0])+_o1[0]*(_p2[1]-_p1[1]); // sin(-o1)(x2-x1) + cos(-o1)(y2-y1) - T expected_rotation = atan2(_o2[1]*_o1[0] - _o2[0]*_o1[1], _o1[0]*_o2[0] + _o1[1]*_o2[1]); - - // Residuals - _residuals[0] = (expected_longitudinal - T(measurement_(0))) / T(measurement_covariance_(0,0)); - _residuals[1] = (expected_lateral - T(measurement_(1))) / T(measurement_covariance_(1,1)); - _residuals[2] = (expected_rotation - T(measurement_(2))) / T(measurement_covariance_(2,2)); - -// T expected_longitudinal = (_p2[0]-_p1[0])*(_p2[0]-_p1[0]) + (_p2[1]-_p1[1])*(_p2[1]-_p1[1]); //square of the range + { + // + } + + template<typename T> + bool operator()(const T* const _p1, const T* const _o1, const T* const _p2, const T* const _o2, T* _residuals) const + { + // Expected measurement + // rotar per menys l'angle de primer _o1 + T expected_longitudinal = _o1[0] * (_p2[0] - _p1[0]) + _o1[1] * (_p2[1] - _p1[1]); // cos(-o1)(x2-x1) - sin(-o1)(y2-y1) + T expected_lateral = -_o1[1] * (_p2[0] - _p1[0]) + _o1[0] * (_p2[1] - _p1[1]); // sin(-o1)(x2-x1) + cos(-o1)(y2-y1) + T expected_rotation = atan2(_o2[1] * _o1[0] - _o2[0] * _o1[1], _o1[0] * _o2[0] + _o1[1] * _o2[1]); + + // Residuals + _residuals[0] = (expected_longitudinal - T(measurement_(0))) / T(sqrt(measurement_covariance_(0, 0))); + _residuals[1] = (expected_lateral - T(measurement_(1))) / T(sqrt(measurement_covariance_(1, 1))); + _residuals[2] = (expected_rotation - T(measurement_(2))) / T(sqrt(measurement_covariance_(2, 2))); + +// T expected_longitudinal = (_p2[0]-_p1[0])*(_p2[0]-_p1[0]) + (_p2[1]-_p1[1])*(_p2[1]-_p1[1]); //square of the range // T expected_rotation = atan2(_o2[1]*_o1[0] - _o2[0]*_o1[1], _o1[0]*_o2[0] + _o1[1]*_o2[1]); - // Residuals + // Residuals // _residuals[0] = (expected_longitudinal - T(measurement_(0))*T(measurement_(0))) / T(measurement_covariance_(0,0)); // _residuals[1] = (expected_rotation - T(measurement_(1))) / T(measurement_covariance_(1,1)); - return true; - } + return true; + } }; #endif diff --git a/src/constraint_odom_2D_theta.h b/src/constraint_odom_2D_theta.h index f632e1b0e..9e2024207 100644 --- a/src/constraint_odom_2D_theta.h +++ b/src/constraint_odom_2D_theta.h @@ -1,4 +1,3 @@ - #ifndef CONSTRAINT_ODOM_2D_THETA_H_ #define CONSTRAINT_ODOM_2D_THETA_H_ @@ -6,51 +5,51 @@ #include "wolf.h" #include "constraint_sparse.h" -class ConstraintOdom2DTheta: public ConstraintSparse<3,2,1,2,1> +class ConstraintOdom2DTheta : public ConstraintSparse<3, 2, 1, 2, 1> { - public: - static const unsigned int N_BLOCKS = 4; - - ConstraintOdom2DTheta(FeatureBase*_ftr_ptr, WolfScalar* _block0Ptr, WolfScalar* _block1Ptr, WolfScalar* _block2Ptr, WolfScalar* _block3Ptr) : - ConstraintSparse<3,2,1,2,1>(_ftr_ptr,CTR_ODOM_2D_THETA, _block0Ptr, _block1Ptr, _block2Ptr, _block3Ptr) - { - // - } - - ConstraintOdom2DTheta(FeatureBase* _ftr_ptr, StateBase* _state0Ptr, StateBase* _state1Ptr, StateBase* _state2Ptr, StateBase* _state3Ptr) : - ConstraintSparse<3,2,1,2,1>(_ftr_ptr,CTR_ODOM_2D_THETA, _state0Ptr->getPtr(), _state1Ptr->getPtr(),_state2Ptr->getPtr(), _state3Ptr->getPtr()) - { - // - } - - virtual ~ConstraintOdom2DTheta() - { - // - } - - template <typename T> - bool operator()(const T* const _p1, const T* const _o1, const T* const _p2, const T* const _o2, T* _residuals) const - { - // Expected measurement - // rotar per menys l'angle de primer _o1 - T expected_longitudinal = cos(_o1[0])*(_p2[0]-_p1[0])+sin(_o1[0])*(_p2[1]-_p1[1]); // cos(-o1)(x2-x1) - sin(-o1)(y2-y1) - T expected_lateral = -sin(_o1[0])*(_p2[0]-_p1[0])+cos(_o1[0])*(_p2[1]-_p1[1]); // sin(-o1)(x2-x1) + cos(-o1)(y2-y1) - T expected_rotation = _o2[0]-_o1[0]; - - // Residuals - _residuals[0] = (expected_longitudinal - T(measurement_(0))) / T(measurement_covariance_(0,0)); - _residuals[1] = (expected_lateral - T(measurement_(1))) / T(measurement_covariance_(1,1)); - _residuals[2] = (expected_rotation - T(measurement_(2))) / T(measurement_covariance_(2,2)); - - // Expected measurement + public: + static const unsigned int N_BLOCKS = 4; + + ConstraintOdom2DTheta(FeatureBase*_ftr_ptr, WolfScalar* _block0Ptr, WolfScalar* _block1Ptr, WolfScalar* _block2Ptr, WolfScalar* _block3Ptr) : + ConstraintSparse<3, 2, 1, 2, 1>(_ftr_ptr, CTR_ODOM_2D_THETA, _block0Ptr, _block1Ptr, _block2Ptr, _block3Ptr) + { + // + } + + ConstraintOdom2DTheta(FeatureBase* _ftr_ptr, StateBase* _state0Ptr, StateBase* _state1Ptr, StateBase* _state2Ptr, StateBase* _state3Ptr) : + ConstraintSparse<3, 2, 1, 2, 1>(_ftr_ptr, CTR_ODOM_2D_THETA, _state0Ptr->getPtr(), _state1Ptr->getPtr(), _state2Ptr->getPtr(), _state3Ptr->getPtr()) + { + // + } + + virtual ~ConstraintOdom2DTheta() + { + // + } + + template<typename T> + bool operator()(const T* const _p1, const T* const _o1, const T* const _p2, const T* const _o2, T* _residuals) const + { + // Expected measurement + // rotar per menys l'angle de primer _o1 + T expected_longitudinal = cos(_o1[0]) * (_p2[0] - _p1[0]) + sin(_o1[0]) * (_p2[1] - _p1[1]); // cos(-o1)(x2-x1) - sin(-o1)(y2-y1) + T expected_lateral = -sin(_o1[0]) * (_p2[0] - _p1[0]) + cos(_o1[0]) * (_p2[1] - _p1[1]); // sin(-o1)(x2-x1) + cos(-o1)(y2-y1) + T expected_rotation = _o2[0] - _o1[0]; + + // Residuals + _residuals[0] = (expected_longitudinal - T(measurement_(0))) / T(sqrt(measurement_covariance_(0, 0))); + _residuals[1] = (expected_lateral - T(measurement_(1))) / T(sqrt(measurement_covariance_(1, 1))); + _residuals[2] = (expected_rotation - T(measurement_(2))) / T(sqrt(measurement_covariance_(2, 2))); + + // Expected measurement // T expected_range = (_p2[0]-_p1[0])*(_p2[0]-_p1[0]) + (_p2[1]-_p1[1])*(_p2[1]-_p1[1]); //square of the range -// T expected_rotation = _o2[0]-_o1[0]; +// T expected_rotation = _o2[0]-_o1[0]; // // // Residuals // _residuals[0] = (expected_range - T(measurement_(0))*T(measurement_(0))) / T(measurement_covariance_(0,0)); // _residuals[1] = (expected_rotation - T(measurement_(1))) / T(measurement_covariance_(1,1)); - return true; - } + return true; + } }; #endif diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt index 5f0cafb7e..d9a608578 100644 --- a/src/examples/CMakeLists.txt +++ b/src/examples/CMakeLists.txt @@ -19,8 +19,8 @@ ADD_EXECUTABLE(test_ceres_wrapper_jet_2_sensors test_ceres_wrapper_jet_2_sensors TARGET_LINK_LIBRARIES(test_ceres_wrapper_jet_2_sensors ${PROJECT_NAME}) # jet test manager -ADD_EXECUTABLE(test_ceres_manager test_ceres_manager.cpp) -TARGET_LINK_LIBRARIES(test_ceres_manager ${PROJECT_NAME}) +#ADD_EXECUTABLE(test_ceres_manager test_ceres_manager.cpp) +#TARGET_LINK_LIBRARIES(test_ceres_manager ${PROJECT_NAME}) # Testing a full wolf tree avoiding template classes for NodeLinked derived classes ADD_EXECUTABLE(test_ceres_odom_batch test_ceres_odom_batch.cpp) @@ -39,8 +39,8 @@ TARGET_LINK_LIBRARIES(test_ceres_odom_iterative ${PROJECT_NAME}) #TARGET_LINK_LIBRARIES(test_ceres_manager_tree ${PROJECT_NAME}) # test ceres covariance -ADD_EXECUTABLE(test_ceres_covariance test_ceres_covariance.cpp) -TARGET_LINK_LIBRARIES(test_ceres_covariance ${PROJECT_NAME}) +#ADD_EXECUTABLE(test_ceres_covariance test_ceres_covariance.cpp) +#TARGET_LINK_LIBRARIES(test_ceres_covariance ${PROJECT_NAME}) # IF (laser_scan_utils_FOUND) # ADD_EXECUTABLE(test_capture_laser_2D test_capture_laser_2D.cpp) diff --git a/src/examples/test_ceres_2_lasers.cpp b/src/examples/test_ceres_2_lasers.cpp index 12ad327fe..a6c34e50b 100644 --- a/src/examples/test_ceres_2_lasers.cpp +++ b/src/examples/test_ceres_2_lasers.cpp @@ -34,389 +34,384 @@ //function travel around void motionCampus(unsigned int ii, Cpose3d & pose, double& displacement_, double& rotation_) { - if (ii<=120) - { - displacement_ = 0.1; - rotation_ = 0; - } - else if ( (ii>120) && (ii<=170) ) - { - displacement_ = 0.2; - rotation_ = 1.8*M_PI/180; - } - else if ( (ii>170) && (ii<=220) ) - { - displacement_ = 0; - rotation_ = -1.8*M_PI/180; - } - else if ( (ii>220) && (ii<=310) ) - { - displacement_ = 0.1; - rotation_ = 0; - } - else if ( (ii>310) && (ii<=487) ) - { - displacement_ = 0.1; - rotation_ = -1.*M_PI/180; - } - else if ( (ii>487) && (ii<=600) ) - { - displacement_ = 0.2; - rotation_ = 0; - } - else if ( (ii>600) && (ii<=700) ) - { - displacement_ = 0.1; - rotation_ = -1.*M_PI/180; - } - else if ( (ii>700) && (ii<=780) ) - { - displacement_ = 0; - rotation_ = -1.*M_PI/180; - } - else - { - displacement_ = 0.3; - rotation_ = 0.0*M_PI/180; - } - - pose.moveForward(displacement_); - pose.rt.setEuler( pose.rt.head()+rotation_, pose.rt.pitch(), pose.rt.roll() ); + if (ii <= 120) + { + displacement_ = 0.1; + rotation_ = 0; + } + else if ((ii > 120) && (ii <= 170)) + { + displacement_ = 0.2; + rotation_ = 1.8 * M_PI / 180; + } + else if ((ii > 170) && (ii <= 220)) + { + displacement_ = 0; + rotation_ = -1.8 * M_PI / 180; + } + else if ((ii > 220) && (ii <= 310)) + { + displacement_ = 0.1; + rotation_ = 0; + } + else if ((ii > 310) && (ii <= 487)) + { + displacement_ = 0.1; + rotation_ = -1. * M_PI / 180; + } + else if ((ii > 487) && (ii <= 600)) + { + displacement_ = 0.2; + rotation_ = 0; + } + else if ((ii > 600) && (ii <= 700)) + { + displacement_ = 0.1; + rotation_ = -1. * M_PI / 180; + } + else if ((ii > 700) && (ii <= 780)) + { + displacement_ = 0; + rotation_ = -1. * M_PI / 180; + } + else + { + displacement_ = 0.3; + rotation_ = 0.0 * M_PI / 180; + } + + pose.moveForward(displacement_); + pose.rt.setEuler(pose.rt.head() + rotation_, pose.rt.pitch(), pose.rt.roll()); } int main(int argc, char** argv) { - std::cout << "\n ========= 2D Robot with odometry and 2 LIDARs ===========\n"; - - // USER INPUT ============================================================================================ - if (argc!=4 || atoi(argv[1])<1 || atoi(argv[1])>1100 || atoi(argv[2]) < 0 || atoi(argv[3]) < 0 || atoi(argv[3]) > 1) - { - std::cout << "Please call me with: [./test_ceres_manager NI PRINT ORIENTATION_MODE], where:" << std::endl; - std::cout << " - NI is the number of iterations (0 < NI < 1100)" << std::endl; - std::cout << " - WS is the window size (0 < WS)" << std::endl; - std::cout << " - ORIENTATION_MODE: 0 for theta, 1 for complex angle" << std::endl; - std::cout << "EXIT due to bad user input" << std::endl << std::endl; - return -1; - } - - unsigned int n_execution = (unsigned int) atoi(argv[1]); //number of iterations of the whole execution - unsigned int window_size = (unsigned int) atoi(argv[2]); - bool complex_angle = (bool) atoi(argv[3]); - - // INITIALIZATION ============================================================================================ - //init random generators - WolfScalar odom_std_factor= 0.1; - WolfScalar gps_std= 1; - std::default_random_engine generator(1); - std::normal_distribution<WolfScalar> distribution_odom(0.0, odom_std_factor); //odometry noise - std::normal_distribution<WolfScalar> distribution_gps(0.0, gps_std); //GPS noise - - //init google log - //google::InitGoogleLogging(argv[0]); - - // Ceres initialization - ceres::Solver::Options ceres_options; - ceres_options.minimizer_type = ceres::LINE_SEARCH;//ceres::TRUST_REGION; - ceres_options.max_line_search_step_contraction = 1e-3; - // ceres_options.minimizer_progress_to_stdout = false; - // ceres_options.line_search_direction_type = ceres::LBFGS; - // ceres_options.max_num_iterations = 100; - ceres::Problem::Options problem_options; - problem_options.cost_function_ownership = ceres::DO_NOT_TAKE_OWNERSHIP; - problem_options.loss_function_ownership = ceres::DO_NOT_TAKE_OWNERSHIP; - problem_options.local_parameterization_ownership = ceres::DO_NOT_TAKE_OWNERSHIP; - CeresManager* ceres_manager = new CeresManager(problem_options); - std::ofstream log_file, landmark_file; //output file - - // Faramotics stuff - Cpose3d viewPoint, devicePose, laser1Pose, laser2Pose, estimated_vehicle_pose, estimated_laser_1_pose, estimated_laser_2_pose; - vector<Cpose3d> devicePoses; - vector<float> scan1, scan2; - string modelFileName; - - //model and initial view point - //modelFileName = "/home/jvallve/iri-lab/faramotics/models/campusNordUPC.obj"; + std::cout << "\n ========= 2D Robot with odometry and 2 LIDARs ===========\n"; + + // USER INPUT ============================================================================================ + if (argc != 4 || atoi(argv[1]) < 1 || atoi(argv[1]) > 1100 || atoi(argv[2]) < 0 || atoi(argv[3]) < 0 || atoi(argv[3]) > 1) + { + std::cout << "Please call me with: [./test_ceres_manager NI PRINT ORIENTATION_MODE], where:" << std::endl; + std::cout << " - NI is the number of iterations (0 < NI < 1100)" << std::endl; + std::cout << " - WS is the window size (0 < WS)" << std::endl; + std::cout << " - ORIENTATION_MODE: 0 for theta, 1 for complex angle" << std::endl; + std::cout << "EXIT due to bad user input" << std::endl << std::endl; + return -1; + } + + unsigned int n_execution = (unsigned int) atoi(argv[1]); //number of iterations of the whole execution + unsigned int window_size = (unsigned int) atoi(argv[2]); + bool complex_angle = (bool) atoi(argv[3]); + + // INITIALIZATION ============================================================================================ + //init random generators + WolfScalar odom_std_factor = 0.1; + WolfScalar gps_std = 1; + std::default_random_engine generator(1); + std::normal_distribution<WolfScalar> distribution_odom(0.0, odom_std_factor); //odometry noise + std::normal_distribution<WolfScalar> distribution_gps(0.0, gps_std); //GPS noise + + //init google log + //google::InitGoogleLogging(argv[0]); + + // Ceres initialization + ceres::Solver::Options ceres_options; + ceres_options.minimizer_type = ceres::LINE_SEARCH; //ceres::TRUST_REGION; + ceres_options.max_line_search_step_contraction = 1e-3; + // ceres_options.minimizer_progress_to_stdout = false; + // ceres_options.line_search_direction_type = ceres::LBFGS; + // ceres_options.max_num_iterations = 100; + ceres::Problem::Options problem_options; + problem_options.cost_function_ownership = ceres::DO_NOT_TAKE_OWNERSHIP; + problem_options.loss_function_ownership = ceres::DO_NOT_TAKE_OWNERSHIP; + problem_options.local_parameterization_ownership = ceres::DO_NOT_TAKE_OWNERSHIP; + CeresManager* ceres_manager = new CeresManager(problem_options); + std::ofstream log_file, landmark_file; //output file + + // Faramotics stuff + Cpose3d viewPoint, devicePose, laser1Pose, laser2Pose, estimated_vehicle_pose, estimated_laser_1_pose, estimated_laser_2_pose; + vector < Cpose3d > devicePoses; + vector<float> scan1, scan2; + string modelFileName; + + //model and initial view point + modelFileName = "/home/jvallve/iri-lab/faramotics/models/campusNordUPC.obj"; //modelFileName = "/home/acoromin/dev/br/faramotics/models/campusNordUPC.obj"; - modelFileName = "/home/andreu/dev/faramotics/models/campusNordUPC.obj"; - devicePose.setPose(2,8,0.2,0,0,0); - viewPoint.setPose(devicePose); - viewPoint.moveForward(10); - viewPoint.rt.setEuler( viewPoint.rt.head()+M_PI/2, viewPoint.rt.pitch()+30.*M_PI/180., viewPoint.rt.roll() ); - viewPoint.moveForward(-15); - //glut initialization + //modelFileName = "/home/andreu/dev/faramotics/models/campusNordUPC.obj"; + devicePose.setPose(2, 8, 0.2, 0, 0, 0); + viewPoint.setPose(devicePose); + viewPoint.moveForward(10); + viewPoint.rt.setEuler(viewPoint.rt.head() + M_PI / 2, viewPoint.rt.pitch() + 30. * M_PI / 180., viewPoint.rt.roll()); + viewPoint.moveForward(-15); + //glut initialization faramotics::initGLUT(argc, argv); - - //create a viewer for the 3D model and scan points - CdynamicSceneRender* myRender = new CdynamicSceneRender(1200,700,90*M_PI/180,90*700.0*M_PI/(1200.0*180.0),0.2,100); - myRender->loadAssimpModel(modelFileName,true); //with wireframe - //create scanner and load 3D model - CrangeScan2D* myScanner = new CrangeScan2D(HOKUYO_UTM30LX_180DEG);//HOKUYO_UTM30LX_180DEG or LEUZE_RS4 - myScanner->loadAssimpModel(modelFileName); - - //variables - Eigen::Vector3s odom_reading; - Eigen::Vector2s gps_fix_reading; - Eigen::VectorXs pose_odom(3); //current odometry integred pose - Eigen::VectorXs ground_truth(n_execution*3); //all true poses - Eigen::VectorXs odom_trajectory(n_execution*3); //open loop trajectory - Eigen::VectorXs mean_times = Eigen::VectorXs::Zero(7); - clock_t t1, t2; - - // Wolf manager initialization - SensorOdom2D odom_sensor(Eigen::Vector6s::Zero(), odom_std_factor, odom_std_factor); - SensorGPSFix gps_sensor(Eigen::Vector6s::Zero(), gps_std); - Eigen::Vector6s laser_1_pose, laser_2_pose; - laser_1_pose << 1.2,0,0,0,0,0; //laser 1 - laser_2_pose << -1.2,0,0,0,0,M_PI; //laser 2 - SensorLaser2D laser_1_sensor(laser_1_pose); - SensorLaser2D laser_2_sensor(laser_2_pose); - - // Initial pose - pose_odom << 2,8,0; - ground_truth.head(3) = pose_odom; - odom_trajectory.head(3) = pose_odom; - - WolfManager* wolf_manager = new WolfManager(&odom_sensor, complex_angle, 1e6, pose_odom, 0.3, window_size); - - //std::cout << "START TRAJECTORY..." << std::endl; - // START TRAJECTORY ============================================================================================ - for (uint step=1; step < n_execution; step++) - { - //get init time - t2=clock(); - - // ROBOT MOVEMENT --------------------------- - //std::cout << "ROBOT MOVEMENT..." << std::endl; - // moves the device position - t1=clock(); - motionCampus(step, devicePose, odom_reading(0), odom_reading(2)); - odom_reading(1) = 0; - devicePoses.push_back(devicePose); - - - // SENSOR DATA --------------------------- - //std::cout << "SENSOR DATA..." << std::endl; - // store groundtruth - ground_truth.segment(step*3,3) << devicePose.pt(0), devicePose.pt(1), devicePose.rt.head(); - - // compute odometry - odom_reading(0) += distribution_odom(generator)*(odom_reading(0) == 0 ? 1e-6 : odom_reading(0)); - odom_reading(1) += distribution_odom(generator)*1e-6; - odom_reading(2) += distribution_odom(generator)*(odom_reading(2) == 0 ? 1e-6 : odom_reading(2)); - - // odometry integration - pose_odom(0) = pose_odom(0) + odom_reading(0) * cos(pose_odom(2)) - odom_reading(1) * sin(pose_odom(2)); - pose_odom(1) = pose_odom(1) + odom_reading(0) * sin(pose_odom(2)) + odom_reading(1) * cos(pose_odom(2)); - pose_odom(2) = pose_odom(2) + odom_reading(1); - odom_trajectory.segment(step*3,3) = pose_odom; - - // compute GPS - gps_fix_reading << devicePose.pt(0), devicePose.pt(1); - gps_fix_reading(0) += distribution_gps(generator); - gps_fix_reading(1) += distribution_gps(generator); - - //compute scans - scan1.clear(); - scan2.clear(); - // scan 1 - laser1Pose.setPose(devicePose); - laser1Pose.moveForward(laser_1_pose(0)); - myScanner->computeScan(laser1Pose,scan1); - // scan 2 - laser2Pose.setPose(devicePose); - laser2Pose.moveForward(laser_2_pose(0)); - laser2Pose.rt.setEuler( laser2Pose.rt.head()+M_PI, laser2Pose.rt.pitch(), laser2Pose.rt.roll() ); - myScanner->computeScan(laser2Pose,scan2); - - mean_times(0) += ((double)clock()-t1)/CLOCKS_PER_SEC; - - - // ADD CAPTURES --------------------------- - //std::cout << "ADD CAPTURES..." << std::endl; - t1=clock(); - // adding new sensor captures - wolf_manager->addCapture(new CaptureOdom2D(TimeStamp(), &odom_sensor, odom_reading));//, odom_std_factor * Eigen::MatrixXs::Identity(2,2))); + + //create a viewer for the 3D model and scan points + CdynamicSceneRender* myRender = new CdynamicSceneRender(1200, 700, 90 * M_PI / 180, 90 * 700.0 * M_PI / (1200.0 * 180.0), 0.2, 100); + myRender->loadAssimpModel(modelFileName, true); //with wireframe + //create scanner and load 3D model + CrangeScan2D* myScanner = new CrangeScan2D(HOKUYO_UTM30LX_180DEG); //HOKUYO_UTM30LX_180DEG or LEUZE_RS4 + myScanner->loadAssimpModel(modelFileName); + + //variables + Eigen::Vector3s odom_reading; + Eigen::Vector2s gps_fix_reading; + Eigen::VectorXs pose_odom(3); //current odometry integred pose + Eigen::VectorXs ground_truth(n_execution * 3); //all true poses + Eigen::VectorXs odom_trajectory(n_execution * 3); //open loop trajectory + Eigen::VectorXs mean_times = Eigen::VectorXs::Zero(7); + clock_t t1, t2; + + // Wolf manager initialization + Eigen::Vector3s odom_pose = Eigen::Vector3s::Zero(); + Eigen::Vector3s gps_pose = Eigen::Vector3s::Zero(); + Eigen::Vector3s laser_1_pose, laser_2_pose; + laser_1_pose << 1.2, 0, 0; //laser 1 + laser_2_pose << -1.2, 0, M_PI; //laser 2 + SensorOdom2D odom_sensor(new StatePoint2D(odom_pose.data()), new StateTheta(&odom_pose(2)), odom_std_factor, odom_std_factor); + SensorGPSFix gps_sensor(new StatePoint2D(gps_pose.data()), new StateTheta(&gps_pose(2)), gps_std); + SensorLaser2D laser_1_sensor(new StatePoint2D(laser_1_pose.data()), new StateTheta(&laser_1_pose(2))); + SensorLaser2D laser_2_sensor(new StatePoint2D(laser_2_pose.data()), new StateTheta(&laser_2_pose(2))); + + // Initial pose + pose_odom << 2, 8, 0; + ground_truth.head(3) = pose_odom; + odom_trajectory.head(3) = pose_odom; + + WolfManager* wolf_manager = new WolfManager(&odom_sensor, complex_angle, 1e3, pose_odom, Eigen::Matrix3s::Identity() * 0.01, 0.3, window_size); + + //std::cout << "START TRAJECTORY..." << std::endl; + // START TRAJECTORY ============================================================================================ + for (uint step = 1; step < n_execution; step++) + { + //get init time + t2 = clock(); + + // ROBOT MOVEMENT --------------------------- + //std::cout << "ROBOT MOVEMENT..." << std::endl; + // moves the device position + t1 = clock(); + motionCampus(step, devicePose, odom_reading(0), odom_reading(2)); + odom_reading(1) = 0; + devicePoses.push_back(devicePose); + + // SENSOR DATA --------------------------- + //std::cout << "SENSOR DATA..." << std::endl; + // store groundtruth + ground_truth.segment(step * 3, 3) << devicePose.pt(0), devicePose.pt(1), devicePose.rt.head(); + + // compute odometry + odom_reading(0) += distribution_odom(generator) * (odom_reading(0) == 0 ? 1e-6 : odom_reading(0)); + odom_reading(1) += distribution_odom(generator) * 1e-6; + odom_reading(2) += distribution_odom(generator) * (odom_reading(2) == 0 ? 1e-6 : odom_reading(2)); + + // odometry integration + pose_odom(0) = pose_odom(0) + odom_reading(0) * cos(pose_odom(2)) - odom_reading(1) * sin(pose_odom(2)); + pose_odom(1) = pose_odom(1) + odom_reading(0) * sin(pose_odom(2)) + odom_reading(1) * cos(pose_odom(2)); + pose_odom(2) = pose_odom(2) + odom_reading(1); + odom_trajectory.segment(step * 3, 3) = pose_odom; + + // compute GPS + gps_fix_reading << devicePose.pt(0), devicePose.pt(1); + gps_fix_reading(0) += distribution_gps(generator); + gps_fix_reading(1) += distribution_gps(generator); + + //compute scans + scan1.clear(); + scan2.clear(); + // scan 1 + laser1Pose.setPose(devicePose); + laser1Pose.moveForward(laser_1_pose(0)); + myScanner->computeScan(laser1Pose, scan1); + // scan 2 + laser2Pose.setPose(devicePose); + laser2Pose.moveForward(laser_2_pose(0)); + laser2Pose.rt.setEuler(laser2Pose.rt.head() + M_PI, laser2Pose.rt.pitch(), laser2Pose.rt.roll()); + myScanner->computeScan(laser2Pose, scan2); + + mean_times(0) += ((double) clock() - t1) / CLOCKS_PER_SEC; + + // ADD CAPTURES --------------------------- + //std::cout << "ADD CAPTURES..." << std::endl; + t1 = clock(); + // adding new sensor captures + wolf_manager->addCapture(new CaptureOdom2D(TimeStamp(), &odom_sensor, odom_reading)); //, odom_std_factor * Eigen::MatrixXs::Identity(2,2))); // wolf_manager->addCapture(new CaptureGPSFix(TimeStamp(), &gps_sensor, gps_fix_reading, gps_std * Eigen::MatrixXs::Identity(3,3))); - wolf_manager->addCapture(new CaptureLaser2D(TimeStamp(), &laser_1_sensor, scan1)); - wolf_manager->addCapture(new CaptureLaser2D(TimeStamp(), &laser_2_sensor, scan2)); + wolf_manager->addCapture(new CaptureLaser2D(TimeStamp(), &laser_1_sensor, scan1)); + wolf_manager->addCapture(new CaptureLaser2D(TimeStamp(), &laser_2_sensor, scan2)); // updating problem - wolf_manager->update(); - mean_times(1) += ((double)clock()-t1)/CLOCKS_PER_SEC; - - - // UPDATING CERES --------------------------- - //std::cout << "UPDATING CERES..." << std::endl; - t1=clock(); - // update state units and constraints in ceres - ceres_manager->update(wolf_manager->getProblemPtr()); - mean_times(2) += ((double)clock()-t1)/CLOCKS_PER_SEC; - - - // SOLVE OPTIMIZATION --------------------------- - //std::cout << "SOLVING..." << std::endl; - t1=clock(); - ceres::Solver::Summary summary = ceres_manager->solve(ceres_options); - //std::cout << summary.FullReport() << std::endl; - mean_times(3) += ((double)clock()-t1)/CLOCKS_PER_SEC; - - // COMPUTE COVARIANCES --------------------------- - //std::cout << "COMPUTING COVARIANCES..." << std::endl; - t1=clock(); - //ceres_manager->computeCovariances(wolf_manager->getProblemPtr()); - mean_times(4) += ((double)clock()-t1)/CLOCKS_PER_SEC; - - // DRAWING STUFF --------------------------- - t1=clock(); - // draw detected corners - std::list<laserscanutils::Corner> corner_list; - std::vector<double> corner_vector; - CaptureLaser2D last_scan(TimeStamp(), &laser_1_sensor, scan1); - last_scan.extractCorners(corner_list); - for (std::list<laserscanutils::Corner>::iterator corner_it = corner_list.begin(); corner_it != corner_list.end(); corner_it++ ) - { - corner_vector.push_back(corner_it->pt_(0)); - corner_vector.push_back(corner_it->pt_(1)); - } - myRender->drawCorners(laser1Pose,corner_vector); - - // draw landmarks - std::vector<double> landmark_vector; - for (auto landmark_it = wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->begin(); landmark_it != wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->end(); landmark_it++ ) - { - WolfScalar* position_ptr = (*landmark_it)->getPPtr()->getPtr(); - landmark_vector.push_back(*position_ptr); //x - landmark_vector.push_back(*(position_ptr+1)); //y - landmark_vector.push_back(0.2); //z - } - myRender->drawLandmarks(landmark_vector); - - // draw localization and sensors - estimated_vehicle_pose.setPose(wolf_manager->getVehiclePose()(0),wolf_manager->getVehiclePose()(1),0.2,wolf_manager->getVehiclePose()(2),0,0); - estimated_laser_1_pose.setPose(estimated_vehicle_pose); - estimated_laser_1_pose.moveForward(laser_1_pose(0)); - estimated_laser_2_pose.setPose(estimated_vehicle_pose); - estimated_laser_2_pose.moveForward(laser_2_pose(0)); - estimated_laser_2_pose.rt.setEuler( estimated_laser_2_pose.rt.head()+M_PI, estimated_laser_2_pose.rt.pitch(), estimated_laser_2_pose.rt.roll() ); - myRender->drawPoseAxisVector({estimated_vehicle_pose, estimated_laser_1_pose, estimated_laser_2_pose}); - - //Set view point and render the scene - //locate visualization view point, somewhere behind the device + wolf_manager->update(); + mean_times(1) += ((double) clock() - t1) / CLOCKS_PER_SEC; + + // UPDATING CERES --------------------------- + //std::cout << "UPDATING CERES..." << std::endl; + t1 = clock(); + // update state units and constraints in ceres + ceres_manager->update(wolf_manager->getProblemPtr()); + mean_times(2) += ((double) clock() - t1) / CLOCKS_PER_SEC; + + // SOLVE OPTIMIZATION --------------------------- + //std::cout << "SOLVING..." << std::endl; + t1 = clock(); + ceres::Solver::Summary summary = ceres_manager->solve(ceres_options); + //std::cout << summary.FullReport() << std::endl; + mean_times(3) += ((double) clock() - t1) / CLOCKS_PER_SEC; + + // COMPUTE COVARIANCES --------------------------- + //std::cout << "COMPUTING COVARIANCES..." << std::endl; + t1 = clock(); + ceres_manager->computeCovariances(wolf_manager->getProblemPtr()); + mean_times(4) += ((double) clock() - t1) / CLOCKS_PER_SEC; + + // DRAWING STUFF --------------------------- + t1 = clock(); + // draw detected corners + std::list < laserscanutils::Corner > corner_list; + std::vector<double> corner_vector; + CaptureLaser2D last_scan(TimeStamp(), &laser_1_sensor, scan1); + last_scan.extractCorners(corner_list); + for (std::list<laserscanutils::Corner>::iterator corner_it = corner_list.begin(); corner_it != corner_list.end(); corner_it++) + { + corner_vector.push_back(corner_it->pt_(0)); + corner_vector.push_back(corner_it->pt_(1)); + } + myRender->drawCorners(laser1Pose, corner_vector); + + // draw landmarks + std::vector<double> landmark_vector; + for (auto landmark_it = wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->begin(); landmark_it != wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->end(); landmark_it++) + { + WolfScalar* position_ptr = (*landmark_it)->getPPtr()->getPtr(); + landmark_vector.push_back(*position_ptr); //x + landmark_vector.push_back(*(position_ptr + 1)); //y + landmark_vector.push_back(0.2); //z + } + myRender->drawLandmarks(landmark_vector); + + // draw localization and sensors + estimated_vehicle_pose.setPose(wolf_manager->getVehiclePose()(0), wolf_manager->getVehiclePose()(1), 0.2, wolf_manager->getVehiclePose()(2), 0, 0); + estimated_laser_1_pose.setPose(estimated_vehicle_pose); + estimated_laser_1_pose.moveForward(laser_1_pose(0)); + estimated_laser_2_pose.setPose(estimated_vehicle_pose); + estimated_laser_2_pose.moveForward(laser_2_pose(0)); + estimated_laser_2_pose.rt.setEuler(estimated_laser_2_pose.rt.head() + M_PI, estimated_laser_2_pose.rt.pitch(), estimated_laser_2_pose.rt.roll()); + myRender->drawPoseAxisVector( { estimated_vehicle_pose, estimated_laser_1_pose, estimated_laser_2_pose }); + + //Set view point and render the scene + //locate visualization view point, somewhere behind the device // viewPoint.setPose(devicePose); // viewPoint.rt.setEuler( viewPoint.rt.head(), viewPoint.rt.pitch()+20.*M_PI/180., viewPoint.rt.roll() ); // viewPoint.moveForward(-5); - myRender->setViewPoint(viewPoint); - myRender->drawPoseAxis(devicePose); - myRender->drawScan(laser1Pose,scan1,180.*M_PI/180.,90.*M_PI/180.); //draw scan - myRender->render(); - mean_times(5) += ((double)clock()-t1)/CLOCKS_PER_SEC; - - // TIME MANAGEMENT --------------------------- - double dt = ((double)clock()-t2)/CLOCKS_PER_SEC; - mean_times(6) += dt; - if (dt < 0.1) - usleep(100000-1e6*dt); + myRender->setViewPoint(viewPoint); + myRender->drawPoseAxis(devicePose); + myRender->drawScan(laser1Pose, scan1, 180. * M_PI / 180., 90. * M_PI / 180.); //draw scan + myRender->render(); + mean_times(5) += ((double) clock() - t1) / CLOCKS_PER_SEC; + + // TIME MANAGEMENT --------------------------- + double dt = ((double) clock() - t2) / CLOCKS_PER_SEC; + mean_times(6) += dt; + if (dt < 0.1) + usleep(100000 - 1e6 * dt); // std::cout << "\nTree after step..." << std::endl; // wolf_manager->getProblemPtr()->print(); - } - - // DISPLAY RESULTS ============================================================================================ - mean_times /= n_execution; - std::cout << "\nSIMULATION AVERAGE LOOP DURATION [s]" << std::endl; - std::cout << " data generation: " << mean_times(0) << std::endl; - std::cout << " wolf managing: " << mean_times(1) << std::endl; - std::cout << " ceres managing: " << mean_times(2) << std::endl; - std::cout << " ceres optimization: " << mean_times(3) << std::endl; - std::cout << " ceres covariance: " << mean_times(4) << std::endl; - std::cout << " results drawing: " << mean_times(5) << std::endl; - std::cout << " loop time: " << mean_times(6) << std::endl; + } + + // DISPLAY RESULTS ============================================================================================ + mean_times /= n_execution; + std::cout << "\nSIMULATION AVERAGE LOOP DURATION [s]" << std::endl; + std::cout << " data generation: " << mean_times(0) << std::endl; + std::cout << " wolf managing: " << mean_times(1) << std::endl; + std::cout << " ceres managing: " << mean_times(2) << std::endl; + std::cout << " ceres optimization: " << mean_times(3) << std::endl; + std::cout << " ceres covariance: " << mean_times(4) << std::endl; + std::cout << " results drawing: " << mean_times(5) << std::endl; + std::cout << " loop time: " << mean_times(6) << std::endl; // std::cout << "\nTree before deleting..." << std::endl; // wolf_manager->getProblemPtr()->print(); - // Draw Final result ------------------------- - std::vector<double> landmark_vector; - for (auto landmark_it = wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->begin(); landmark_it != wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->end(); landmark_it++ ) - { - WolfScalar* position_ptr = (*landmark_it)->getPPtr()->getPtr(); - landmark_vector.push_back(*position_ptr); //x - landmark_vector.push_back(*(position_ptr+1)); //y - landmark_vector.push_back(0.2); //z - } - myRender->drawLandmarks(landmark_vector); + // Draw Final result ------------------------- + std::vector<double> landmark_vector; + for (auto landmark_it = wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->begin(); landmark_it != wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->end(); landmark_it++) + { + WolfScalar* position_ptr = (*landmark_it)->getPPtr()->getPtr(); + landmark_vector.push_back(*position_ptr); //x + landmark_vector.push_back(*(position_ptr + 1)); //y + landmark_vector.push_back(0.2); //z + } + myRender->drawLandmarks(landmark_vector); // viewPoint.setPose(devicePoses.front()); // viewPoint.moveForward(10); // viewPoint.rt.setEuler( viewPoint.rt.head()+M_PI/4, viewPoint.rt.pitch()+20.*M_PI/180., viewPoint.rt.roll() ); // viewPoint.moveForward(-10); - myRender->setViewPoint(viewPoint); - myRender->render(); - - // Print Final result in a file ------------------------- - // Vehicle poses - int i = 0; - Eigen::VectorXs state_poses(n_execution * 3); - for (auto frame_it = wolf_manager->getProblemPtr()->getTrajectoryPtr()->getFrameListPtr()->begin(); frame_it != wolf_manager->getProblemPtr()->getTrajectoryPtr()->getFrameListPtr()->end(); frame_it++ ) - { - if (complex_angle) - state_poses.segment(i,3) << *(*frame_it)->getPPtr()->getPtr(), *((*frame_it)->getPPtr()->getPtr()+1), atan2(*(*frame_it)->getOPtr()->getPtr(), *((*frame_it)->getOPtr()->getPtr()+1)); - else - state_poses.segment(i,3) << *(*frame_it)->getPPtr()->getPtr(), *((*frame_it)->getPPtr()->getPtr()+1), *(*frame_it)->getOPtr()->getPtr(); - i+=3; - } - - // Landmarks - i = 0; - Eigen::VectorXs landmarks(wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->size()*2); - for (auto landmark_it = wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->begin(); landmark_it != wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->end(); landmark_it++ ) - { - Eigen::Map<Eigen::Vector2s> landmark((*landmark_it)->getPPtr()->getPtr()); - landmarks.segment(i,2) = landmark; - i+=2; - } - - // Print log files - std::string filepath = getenv("HOME") + (complex_angle ? std::string("/Desktop/log_file_3.txt") : std::string("/Desktop/log_file_2.txt")); - log_file.open(filepath, std::ofstream::out); //open log file - - if (log_file.is_open()) - { - log_file << 0 << std::endl; - for (unsigned int ii = 0; ii<n_execution; ii++) - log_file << state_poses.segment(ii*3,3).transpose() - << "\t" << ground_truth.segment(ii*3,3).transpose() - << "\t" << (state_poses.segment(ii*3,3)-ground_truth.segment(ii*3,3)).transpose() - << "\t" << odom_trajectory.segment(ii*3,3).transpose() << std::endl; - log_file.close(); //close log file - std::cout << std::endl << "Result file " << filepath << std::endl; - } - else - std::cout << std::endl << "Failed to write the log file " << filepath << std::endl; - - std::string filepath2 = getenv("HOME") + (complex_angle ? std::string("/Desktop/landmarks_file_3.txt") : std::string("/Desktop/landmarks_file_2.txt")); - landmark_file.open(filepath2, std::ofstream::out); //open log file - - if (landmark_file.is_open()) - { - for (unsigned int ii = 0; ii<landmarks.size(); ii+=2) - landmark_file << landmarks.segment(ii,2).transpose() << std::endl; - landmark_file.close(); //close log file - std::cout << std::endl << "Landmark file " << filepath << std::endl; - } - else - std::cout << std::endl << "Failed to write the landmark file " << filepath << std::endl; - - std::cout << "Press any key for ending... " << std::endl << std::endl; - std::getchar(); + myRender->setViewPoint(viewPoint); + myRender->render(); + + // Print Final result in a file ------------------------- + // Vehicle poses + int i = 0; + Eigen::VectorXs state_poses(n_execution * 3); + for (auto frame_it = wolf_manager->getProblemPtr()->getTrajectoryPtr()->getFrameListPtr()->begin(); frame_it != wolf_manager->getProblemPtr()->getTrajectoryPtr()->getFrameListPtr()->end(); frame_it++) + { + if (complex_angle) + state_poses.segment(i, 3) << *(*frame_it)->getPPtr()->getPtr(), *((*frame_it)->getPPtr()->getPtr() + 1), atan2(*(*frame_it)->getOPtr()->getPtr(), *((*frame_it)->getOPtr()->getPtr() + 1)); + else + state_poses.segment(i, 3) << *(*frame_it)->getPPtr()->getPtr(), *((*frame_it)->getPPtr()->getPtr() + 1), *(*frame_it)->getOPtr()->getPtr(); + i += 3; + } + + // Landmarks + i = 0; + Eigen::VectorXs landmarks(wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->size() * 2); + for (auto landmark_it = wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->begin(); landmark_it != wolf_manager->getProblemPtr()->getMapPtr()->getLandmarkListPtr()->end(); landmark_it++) + { + Eigen::Map<Eigen::Vector2s> landmark((*landmark_it)->getPPtr()->getPtr()); + landmarks.segment(i, 2) = landmark; + i += 2; + } + + // Print log files + std::string filepath = getenv("HOME") + (complex_angle ? std::string("/Desktop/log_file_3.txt") : std::string("/Desktop/log_file_2.txt")); + log_file.open(filepath, std::ofstream::out); //open log file + + if (log_file.is_open()) + { + log_file << 0 << std::endl; + for (unsigned int ii = 0; ii < n_execution; ii++) + log_file << state_poses.segment(ii * 3, 3).transpose() << "\t" << ground_truth.segment(ii * 3, 3).transpose() << "\t" << (state_poses.segment(ii * 3, 3) - ground_truth.segment(ii * 3, 3)).transpose() << "\t" << odom_trajectory.segment(ii * 3, 3).transpose() << std::endl; + log_file.close(); //close log file + std::cout << std::endl << "Result file " << filepath << std::endl; + } + else + std::cout << std::endl << "Failed to write the log file " << filepath << std::endl; + + std::string filepath2 = getenv("HOME") + (complex_angle ? std::string("/Desktop/landmarks_file_3.txt") : std::string("/Desktop/landmarks_file_2.txt")); + landmark_file.open(filepath2, std::ofstream::out); //open log file + + if (landmark_file.is_open()) + { + for (unsigned int ii = 0; ii < landmarks.size(); ii += 2) + landmark_file << landmarks.segment(ii, 2).transpose() << std::endl; + landmark_file.close(); //close log file + std::cout << std::endl << "Landmark file " << filepath << std::endl; + } + else + std::cout << std::endl << "Failed to write the landmark file " << filepath << std::endl; + + std::cout << "Press any key for ending... " << std::endl << std::endl; + std::getchar(); delete myRender; delete myScanner; - delete wolf_manager; - std::cout << "wolf deleted" << std::endl; - delete ceres_manager; - std::cout << "ceres_manager deleted" << std::endl; + delete wolf_manager; + std::cout << "wolf deleted" << std::endl; + delete ceres_manager; + std::cout << "ceres_manager deleted" << std::endl; - std::cout << " ========= END ===========" << std::endl << std::endl; + std::cout << " ========= END ===========" << std::endl << std::endl; - //exit - return 0; + //exit + return 0; } diff --git a/src/frame_base.h b/src/frame_base.h index c52a5d9e6..7cd5ef3f3 100644 --- a/src/frame_base.h +++ b/src/frame_base.h @@ -45,7 +45,7 @@ class FrameBase : public NodeLinked<TrajectoryBase,CaptureBase> * \param _w_ptr StateBase pointer to the angular velocity (default: nullptr) * **/ - FrameBase(const TimeStamp& _ts, StateBase* _p_ptr = nullptr, StateBase* _o_ptr = nullptr, StateBase* _v_ptr = nullptr, StateBase* _w_ptr = nullptr); + FrameBase(const TimeStamp& _ts, StateBase* _p_ptr, StateBase* _o_ptr = nullptr, StateBase* _v_ptr = nullptr, StateBase* _w_ptr = nullptr); /** \brief Constructor with type, time stamp and state pointer * @@ -59,7 +59,7 @@ class FrameBase : public NodeLinked<TrajectoryBase,CaptureBase> * \param _w_ptr StateBase pointer to the angular velocity (default: nullptr) * **/ - FrameBase(const FrameType & _tp, const TimeStamp& _ts, StateBase* _p_ptr = nullptr, StateBase* _o_ptr = nullptr, StateBase* _v_ptr = nullptr, StateBase* _w_ptr = nullptr); + FrameBase(const FrameType & _tp, const TimeStamp& _ts, StateBase* _p_ptr, StateBase* _o_ptr = nullptr, StateBase* _v_ptr = nullptr, StateBase* _w_ptr = nullptr); /** \brief Destructor * diff --git a/src/landmark_base.h b/src/landmark_base.h index 33d678bb8..3b7d4d15d 100644 --- a/src/landmark_base.h +++ b/src/landmark_base.h @@ -1,4 +1,3 @@ - #ifndef LANDMARK_BASE_H_ #define LANDMARK_BASE_H_ @@ -25,76 +24,75 @@ class NodeTerminus; // //class LandmarkBase -class LandmarkBase : public NodeLinked<MapBase,NodeTerminus> +class LandmarkBase : public NodeLinked<MapBase, NodeTerminus> { - protected: - LandmarkType type_; //type of landmark. (types defined at wolf.h) - LandmarkStatus status_; //status of the landmark. (types defined at wolf.h) - unsigned int hit_count_; //counts how many features has been associated to this landmark - TimeStamp stamp_; // stamp of the creation of the landmark (and stamp of destruction when status is LANDMARK_OLD) - //StateBaseList st_list_; //List of pointers to the state corresponding to the landmark estimation - StateBase* p_ptr_; // Position state unit pointer - StateBase* o_ptr_; // Orientation state unit pointer - StateBase* v_ptr_; // Velocity state unit pointer - StateBase* w_ptr_; // Angular velocity state unit pointer - //TODO: accelerations? - Eigen::VectorXs descriptor_;//TODO: agree? - - public: - /** \brief Constructor with type, time stamp and the position state pointer - * - * Constructor with type, and state pointer - * \param _tp indicates landmark type.(types defined at wolf.h) - * \param _p_ptr StateBase pointer to the position - * \param _o_ptr StateBase pointer to the orientation (default: nullptr) - * \param _v_ptr StateBase pointer to the velocity (default: nullptr) - * \param _w_ptr StateBase pointer to the angular velocity (default: nullptr) - * - **/ - LandmarkBase(const LandmarkType & _tp , StateBase* _p_ptr, StateBase* _o_ptr = nullptr, StateBase* _v_ptr = nullptr, StateBase* _w_ptr = nullptr); - - /** \brief Constructor with type, time stamp and state list - * - * Constructor with type and state pointer list - * \param _tp indicates frame type. Generally either REGULAR_FRAME or KEY_FRAME. (types defined at wolf.h) - * \param _stp_list StateBase list of the landmark estimation - * - **/ - //LandmarkBase(const LandmarkType & _tp, const StateBaseList& _stp_list); - - /** \brief Destructor - * - * Destructor - * - **/ - virtual ~LandmarkBase(); - - void setStatus(LandmarkStatus _st); - - void hit(); - - void unhit(); - - void fix(); - - void unfix(); - - unsigned int getHits() const; - - StateBase* getPPtr() const; - - StateBase* getOPtr() const; - - StateBase* getVPtr() const; - - StateBase* getWPtr() const; - - void setDescriptor(const Eigen::VectorXs& _descriptor); - - const Eigen::VectorXs& getDescriptor() const; - - //const StateBase* getStatePtr() const; - - //const StateBaseList* getStateListPtr() const; + protected: + LandmarkType type_; //type of landmark. (types defined at wolf.h) + LandmarkStatus status_; //status of the landmark. (types defined at wolf.h) + unsigned int hit_count_; //counts how many features has been associated to this landmark + TimeStamp stamp_; // stamp of the creation of the landmark (and stamp of destruction when status is LANDMARK_OLD) + //StateBaseList st_list_; //List of pointers to the state corresponding to the landmark estimation + StateBase* p_ptr_; // Position state unit pointer + StateBase* o_ptr_; // Orientation state unit pointer + StateBase* v_ptr_; // Velocity state unit pointer + StateBase* w_ptr_; // Angular velocity state unit pointer + //TODO: accelerations? + Eigen::VectorXs descriptor_; //TODO: agree? + + public: + /** \brief Constructor with type, time stamp and the position state pointer + * + * Constructor with type, and state pointer + * \param _tp indicates landmark type.(types defined at wolf.h) + * \param _p_ptr StateBase pointer to the position + * \param _o_ptr StateBase pointer to the orientation (default: nullptr) + * \param _v_ptr StateBase pointer to the velocity (default: nullptr) + * \param _w_ptr StateBase pointer to the angular velocity (default: nullptr) + * + **/ + LandmarkBase(const LandmarkType & _tp, StateBase* _p_ptr, StateBase* _o_ptr = nullptr, StateBase* _v_ptr = nullptr, StateBase* _w_ptr = nullptr); + + /** \brief Constructor with type, time stamp and state list + * + * Constructor with type and state pointer list + * \param _tp indicates frame type. Generally either REGULAR_FRAME or KEY_FRAME. (types defined at wolf.h) + * \param _stp_list StateBase list of the landmark estimation + * + **/ + //LandmarkBase(const LandmarkType & _tp, const StateBaseList& _stp_list); + /** \brief Destructor + * + * Destructor + * + **/ + virtual ~LandmarkBase(); + + void setStatus(LandmarkStatus _st); + + void hit(); + + void unhit(); + + void fix(); + + void unfix(); + + unsigned int getHits() const; + + StateBase* getPPtr() const; + + StateBase* getOPtr() const; + + StateBase* getVPtr() const; + + StateBase* getWPtr() const; + + void setDescriptor(const Eigen::VectorXs& _descriptor); + + const Eigen::VectorXs& getDescriptor() const; + + //const StateBase* getStatePtr() const; + + //const StateBaseList* getStateListPtr() const; }; #endif diff --git a/src/node_linked.h b/src/node_linked.h index fb07972db..776e3c018 100644 --- a/src/node_linked.h +++ b/src/node_linked.h @@ -172,7 +172,6 @@ class NodeLinked : public NodeBase * TODO: Review if it could return a pointer to a derived class instead of NodeBase JVN: I tried to do so... * **/ - //virtual NodeBase* getTop(); virtual WolfProblem* getTop(); /** \brief Prints node information diff --git a/src/sensor_base.cpp b/src/sensor_base.cpp index fa72cfed0..221db8e06 100644 --- a/src/sensor_base.cpp +++ b/src/sensor_base.cpp @@ -1,57 +1,41 @@ #include "sensor_base.h" -SensorBase::SensorBase(const SensorType & _tp, const Eigen::Vector6s & _pose, const Eigen::VectorXs & _params) : - NodeBase("SENSOR"), - type_(_tp), - sensor_position_vehicle_(_pose.head(3)), - params_(_params.size()) +SensorBase::SensorBase(const SensorType & _tp, StateBase* _p_ptr, StateOrientation* _o_ptr, const Eigen::VectorXs & _params) : + NodeBase("SENSOR"), + type_(_tp), + p_ptr_(_p_ptr), + o_ptr_(_o_ptr), + params_(_params.size()) { - params_ = _params; - sensor_rotation_vehicle_ = Eigen::AngleAxisd(_pose(3), Eigen::Vector3d::UnitX()) * - Eigen::AngleAxisd(_pose(4), Eigen::Vector3d::UnitY()) * - Eigen::AngleAxisd(_pose(5), Eigen::Vector3d::UnitZ()); + params_ = _params; } -SensorBase::SensorBase(const SensorType & _tp, const Eigen::Vector6s & _pose, unsigned int _params_size) : - NodeBase("SENSOR"), - type_(_tp), - sensor_position_vehicle_(_pose.head(3)), - params_(_params_size) +SensorBase::SensorBase(const SensorType & _tp, StateBase* _p_ptr, StateOrientation* _o_ptr, unsigned int _params_size) : + NodeBase("SENSOR"), + type_(_tp), + p_ptr_(_p_ptr), + o_ptr_(_o_ptr), + params_(_params_size) { - sensor_rotation_vehicle_ = Eigen::AngleAxisd(_pose(3), Eigen::Vector3d::UnitX()) * - Eigen::AngleAxisd(_pose(4), Eigen::Vector3d::UnitY()) * - Eigen::AngleAxisd(_pose(5), Eigen::Vector3d::UnitZ()); + // } SensorBase::~SensorBase() { - //std::cout << "deleting SensorBase " << nodeId() << std::endl; + //std::cout << "deleting SensorBase " << nodeId() << std::endl; } const SensorType SensorBase::getSensorType() const { - return type_; + return type_; } -const Eigen::Vector3s * SensorBase::getSensorPosition() const +StateBase* SensorBase::getPPtr() const { - //std::cout << "getSensorPosition: " << sensor_position_vehicle_.transpose() << std::endl; - return & sensor_position_vehicle_; + return p_ptr_; } -const Eigen::Matrix3s * SensorBase::getSensorRotation() const -{ - //std::cout << "getSensorRotation: " << sensor_rotation_vehicle_ << std::endl; - return & sensor_rotation_vehicle_; -} - -void SensorBase::setSensorPose(const Eigen::Vector6s & _pose) +StateOrientation* SensorBase::getOPtr() const { - sensor_position_vehicle_ = _pose.head(3); - sensor_rotation_vehicle_ = Eigen::AngleAxisd(_pose(3), Eigen::Vector3d::UnitX()) * - Eigen::AngleAxisd(_pose(4), Eigen::Vector3d::UnitY()) * - Eigen::AngleAxisd(_pose(5), Eigen::Vector3d::UnitZ()); + return o_ptr_; } - - - diff --git a/src/sensor_base.h b/src/sensor_base.h index e7b1f55c7..0524f1d1c 100644 --- a/src/sensor_base.h +++ b/src/sensor_base.h @@ -12,30 +12,42 @@ class SensorBase : public NodeBase { - protected: - SensorType type_; //indicates sensor type. Enum defined at wolf.h - Eigen::Vector3s sensor_position_vehicle_;//sensor position in the vehicle frame - Eigen::Matrix3s sensor_rotation_vehicle_;//sensor rotation in the vehicle frame - // TODO: -// StateBase* p_ptr_; // sensor position state unit pointer -// StateOrientation* o_ptr_; // sensor orientation state unit pointer - Eigen::VectorXs params_; //sensor intrinsic params: offsets, scale factors, sizes, ... - //bool generate_prior_; //flag indicating if this sensor generates the prior or not - - public: - SensorBase(const SensorType & _tp, const Eigen::Vector6s & _pose, const Eigen::VectorXs & _params); - - SensorBase(const SensorType & _tp, const Eigen::Vector6s & _pose, unsigned int _params_size); - - ~SensorBase(); - - const SensorType getSensorType() const; - - const Eigen::Vector3s * getSensorPosition() const; - - const Eigen::Matrix3s * getSensorRotation() const; - - void setSensorPose(const Eigen::Vector6s & _pose); + protected: + SensorType type_; //indicates sensor type. Enum defined at wolf.h + StateBase* p_ptr_; // sensor position state unit pointer + StateOrientation* o_ptr_; // sensor orientation state unit pointer + Eigen::VectorXs params_;//sensor intrinsic params: offsets, scale factors, sizes, ... + + public: + /** \brief Constructor with parameter vector + * + * Constructor with parameter vector + * \param _tp Type of the sensor (types defined at wolf.h) + * \param _p_ptr StateBase pointer to the sensor position + * \param _o_ptr StateOrientation pointer to the sensor orientation + * \param _params Vector containing the sensor parameters + * + **/ + SensorBase(const SensorType & _tp, StateBase* _p_ptr, StateOrientation* _o_ptr, const Eigen::VectorXs & _params); + + /** \brief Constructor with parameter size + * + * Constructor with parameter vector + * \param _tp Type of the sensor (types defined at wolf.h) + * \param _p_ptr StateBase pointer to the sensor position + * \param _o_ptr StateOrientation pointer to the sensor orientation + * \param _params_size size of the vector containing the sensor parameters + * + **/ + SensorBase(const SensorType & _tp, StateBase* _p_ptr, StateOrientation* _o_ptr, unsigned int _params_size); + + ~SensorBase(); + + const SensorType getSensorType() const; + + StateBase* getPPtr() const; + + StateOrientation* getOPtr() const; }; #endif diff --git a/src/sensor_gps_fix.cpp b/src/sensor_gps_fix.cpp index f9a52cd49..b798dbb92 100644 --- a/src/sensor_gps_fix.cpp +++ b/src/sensor_gps_fix.cpp @@ -1,7 +1,7 @@ #include "sensor_gps_fix.h" -SensorGPSFix::SensorGPSFix(const Eigen::Vector6s & _sp, const double& _noise) : - SensorBase(GPS_FIX, _sp, Eigen::VectorXs::Constant(1,_noise)) +SensorGPSFix::SensorGPSFix(StateBase* _p_ptr, StateOrientation* _o_ptr, const double& _noise) : + SensorBase(GPS_FIX, _p_ptr, _o_ptr, Eigen::VectorXs::Constant(1,_noise)) { // } diff --git a/src/sensor_gps_fix.h b/src/sensor_gps_fix.h index d7fe44724..3b918a0e6 100644 --- a/src/sensor_gps_fix.h +++ b/src/sensor_gps_fix.h @@ -11,11 +11,12 @@ class SensorGPSFix : public SensorBase /** \brief Constructor with arguments * * Constructor with arguments - * \param _sp sensor 3D pose with respect to vehicle base frame + * \param _p_ptr StateBase pointer to the sensor position + * \param _o_ptr StateOrientation pointer to the sensor orientation * \param _noise noise standard deviation * **/ - SensorGPSFix(const Eigen::Vector6s & _sp, const double& _noise); + SensorGPSFix(StateBase* _p_ptr, StateOrientation* _o_ptr, const double& _noise); /** \brief Destructor * diff --git a/src/sensor_laser_2D.cpp b/src/sensor_laser_2D.cpp index f6f6c63d2..bb6ff38f3 100644 --- a/src/sensor_laser_2D.cpp +++ b/src/sensor_laser_2D.cpp @@ -7,8 +7,8 @@ // params_ << _angle_min, _angle_max, _angle_increment, _range_min, _range_max, _range_stdev, _time_increment, _scan_time; // } -SensorLaser2D::SensorLaser2D(const Eigen::Vector6s & _sp) : - SensorBase(LIDAR, _sp, 8) +SensorLaser2D::SensorLaser2D(StateBase* _p_ptr, StateOrientation* _o_ptr) : + SensorBase(LIDAR, _p_ptr, _o_ptr, 8) { setDefaultScanParams(); setDefaultCornerAlgParams(); diff --git a/src/sensor_laser_2D.h b/src/sensor_laser_2D.h index 83743a361..cae219d61 100644 --- a/src/sensor_laser_2D.h +++ b/src/sensor_laser_2D.h @@ -24,27 +24,12 @@ class SensorLaser2D : public SensorBase /** \brief Constructor with arguments * * Constructor with arguments - * \param _sp sensor 3D pose with respect to vehicle base frame - * \param _angle_min start angle of the scan [rad] - * \param _angle_max end angle of the scan [rad] - * \param _angle_increment angular distance between measurements [rad] - * \param _range_min minimum range value [m] - * \param _range_max maximum range value [m] - * \param _range_stdev range standard deviation [m] - * \param _time_increment time between beams [seconds] - * \param _scan_time time between scans [seconds] - * - **/ - //SensorLaser2D(const Eigen::VectorXs & _sp, WolfScalar _angle_min, WolfScalar _angle_max, WolfScalar _angle_increment, WolfScalar _range_min, WolfScalar _range_max, WolfScalar _range_stdev, WolfScalar _time_increment=0, WolfScalar _scan_time=0); - - /** \brief Constructor with arguments - * - * Constructor with arguments - * \param _sp sensor 3D pose with respect to vehicle base frame + * \param _p_ptr StateBase pointer to the sensor position + * \param _o_ptr StateOrientation pointer to the sensor orientation * \param _params struct with scan parameters. See laser_scan_utils library API for reference * **/ - SensorLaser2D(const Eigen::Vector6s & _sp); + SensorLaser2D(StateBase* _p_ptr, StateOrientation* _o_ptr); //SensorLaser2D(const Eigen::VectorXs & _sp, const laserscanutils::ScanParams & _params); /** \brief Destructor diff --git a/src/sensor_odom_2D.cpp b/src/sensor_odom_2D.cpp index c39546461..309ac30a7 100644 --- a/src/sensor_odom_2D.cpp +++ b/src/sensor_odom_2D.cpp @@ -1,7 +1,7 @@ #include "sensor_odom_2D.h" -SensorOdom2D::SensorOdom2D(const Eigen::Vector6s & _sp, const WolfScalar& _disp_noise_factor, const WolfScalar& _rot_noise_factor) : - SensorBase(ODOM_2D, _sp, 2) +SensorOdom2D::SensorOdom2D(StateBase* _p_ptr, StateOrientation* _o_ptr, const WolfScalar& _disp_noise_factor, const WolfScalar& _rot_noise_factor) : + SensorBase(ODOM_2D, _p_ptr, _o_ptr, 2) { params_ << _disp_noise_factor, _rot_noise_factor; } diff --git a/src/sensor_odom_2D.h b/src/sensor_odom_2D.h index 84491a928..4e37a2211 100644 --- a/src/sensor_odom_2D.h +++ b/src/sensor_odom_2D.h @@ -11,12 +11,13 @@ class SensorOdom2D : public SensorBase /** \brief Constructor with arguments * * Constructor with arguments - * \param _sp sensor 3D pose with respect to vehicle base frame + * \param _p_ptr StateBase pointer to the sensor position + * \param _o_ptr StateOrientation pointer to the sensor orientation * \param _disp_noise_factor displacement noise factor * \param _rot_noise_factor rotation noise factor * **/ - SensorOdom2D(const Eigen::Vector6s & _sp, const WolfScalar& _disp_noise_factor, const WolfScalar& _rot_noise_factor); + SensorOdom2D(StateBase* _p_ptr, StateOrientation* _o_ptr, const WolfScalar& _disp_noise_factor, const WolfScalar& _rot_noise_factor); /** \brief Destructor * diff --git a/src/state_base.h b/src/state_base.h index 84477fcd2..a31dd401f 100644 --- a/src/state_base.h +++ b/src/state_base.h @@ -50,6 +50,13 @@ class StateBase : public NodeBase **/ virtual WolfScalar* getPtr(); + /** \brief Returns a (mapped) vector of the state unit + * + * Returns a (mapped) vector of the state unit + * + **/ + virtual Eigen::Map<const Eigen::VectorXs> getVector() const = 0; + /** \brief Set the pointer of the first element of the state * * Set the pointer of the first element of the state diff --git a/src/state_complex_angle.cpp b/src/state_complex_angle.cpp index 05a8853c7..b2211a82f 100644 --- a/src/state_complex_angle.cpp +++ b/src/state_complex_angle.cpp @@ -39,6 +39,11 @@ Eigen::Matrix3s StateComplexAngle::getRotationMatrix() const return R; } +Eigen::Map<const Eigen::VectorXs> StateComplexAngle::getVector() const +{ + return Eigen::Map<const Eigen::VectorXs>(state_ptr_, BLOCK_SIZE); +} + void StateComplexAngle::print(unsigned int _ntabs, std::ostream& _ost) const { printTabs(_ntabs); diff --git a/src/state_complex_angle.h b/src/state_complex_angle.h index d4aab33c5..ee7fca41c 100644 --- a/src/state_complex_angle.h +++ b/src/state_complex_angle.h @@ -15,7 +15,7 @@ class StateComplexAngle : public StateOrientation { public: - static const unsigned int BLOCK_SIZE = 2; + static const unsigned int BLOCK_SIZE = 2; /** \brief Constructor with whole state storage and index where starts the state unit * @@ -62,6 +62,13 @@ class StateComplexAngle : public StateOrientation **/ virtual Eigen::Matrix3s getRotationMatrix() const; + /** \brief Returns a (mapped) vector of the state unit + * + * Returns a (mapped) vector of the state unit + * + **/ + virtual Eigen::Map<const Eigen::VectorXs> getVector() const; + /** \brief Prints all the elements of the state unit * * Prints all the elements of the state unit diff --git a/src/state_orientation.h b/src/state_orientation.h index df5ee6427..7a854b86d 100644 --- a/src/state_orientation.h +++ b/src/state_orientation.h @@ -1,4 +1,3 @@ - #ifndef STATE_ORIENTATION_H_ #define STATE_ORIENTATION_H_ @@ -14,37 +13,44 @@ //class StateOrientation class StateOrientation : public StateBase { - public: - + public: + /** \brief Constructor with whole state storage and index where starts the state unit - * + * * Constructor with whole state storage and index where starts the state unit * \param _st_remote is the whole state vector * \param _idx is the index of the first element of the state in the whole state vector - * + * **/ - StateOrientation(Eigen::VectorXs& _st_remote, const unsigned int _idx); + StateOrientation(Eigen::VectorXs& _st_remote, const unsigned int _idx); /** \brief Constructor with scalar pointer - * + * * Constructor with scalar pointer * \param _st_ptr is the pointer of the first element of the state unit - * + * **/ - StateOrientation(WolfScalar* _st_ptr); - + StateOrientation(WolfScalar* _st_ptr); + /** \brief Destructor - * + * * Destructor - * + * **/ virtual ~StateOrientation(); /** \brief Returns the 3x3 rotation matrix of the orientation - * - * Returns the 3x3 rotation matrix of the orientation - * - **/ - virtual Eigen::Matrix3s getRotationMatrix() const = 0; + * + * Returns the 3x3 rotation matrix of the orientation + * + **/ + virtual Eigen::Matrix3s getRotationMatrix() const = 0; + + /** \brief Returns a (mapped) vector of the state unit + * + * Returns a (mapped) vector of the state unit + * + **/ + virtual Eigen::Map<const Eigen::VectorXs> getVector() const = 0; }; #endif diff --git a/src/state_point.h b/src/state_point.h index 7f515cc3f..19ce416b7 100644 --- a/src/state_point.h +++ b/src/state_point.h @@ -81,14 +81,14 @@ class StatePoint : public StateBase return BLOCK_SIZE; } - /** \brief Returns the point in a vector + /** \brief Returns the point in a (mapped) vector * - * Returns the point in a vector + * Returns the point in a (mapped) vector * **/ - const Eigen::Matrix<WolfScalar, BLOCK_SIZE, 1>& getVector() const + virtual Eigen::Map<const Eigen::VectorXs> getVector() const { - return Eigen::Map<const Eigen::Matrix<WolfScalar, BLOCK_SIZE, 1>>(state_ptr_); + return Eigen::Map<const Eigen::VectorXs>(state_ptr_, BLOCK_SIZE); } /** \brief Prints all the elements of the state unit diff --git a/src/state_theta.cpp b/src/state_theta.cpp index b1e707b3e..ff2b851dc 100644 --- a/src/state_theta.cpp +++ b/src/state_theta.cpp @@ -1,50 +1,66 @@ - #include "state_theta.h" StateTheta::StateTheta(Eigen::VectorXs& _st_remote, const unsigned int _idx) : - StateOrientation(_st_remote, _idx) + StateOrientation(_st_remote, _idx) { - // + // } StateTheta::StateTheta(WolfScalar* _st_ptr) : - StateOrientation(_st_ptr) + StateOrientation(_st_ptr) { - // + // } StateTheta::~StateTheta() { - // + // } StateType StateTheta::getStateType() const { - return ST_THETA; + return ST_THETA; } unsigned int StateTheta::getStateSize() const { - return BLOCK_SIZE; + return BLOCK_SIZE; } Eigen::Matrix3s StateTheta::getRotationMatrix() const { - Eigen::Matrix3s R(Eigen::Matrix3s::Identity()); - R(0,0) = cos(*state_ptr_); - R(1,1) = cos(*state_ptr_); - R(0,1) = -sin(*state_ptr_); - R(1,0) = sin(*state_ptr_); + Eigen::Matrix3s R(Eigen::Matrix3s::Identity()); + R(0, 0) = cos(*state_ptr_); + R(1, 1) = cos(*state_ptr_); + R(0, 1) = -sin(*state_ptr_); + R(1, 0) = sin(*state_ptr_); + + //std::cout << "StateTheta::getRotationMatrix()" << R << std::endl; + return R; +} + +void StateTheta::getRotationMatrix(Eigen::Matrix3s& R) const +{ + R = Eigen::Matrix3s::Identity(); + R(0, 0) = cos(*state_ptr_); + R(1, 1) = cos(*state_ptr_); + R(0, 1) = -sin(*state_ptr_); + R(1, 0) = sin(*state_ptr_); + + //std::cout << "StateTheta::getRotationMatrix()" << R << std::endl; +} - return R; +Eigen::Map<const Eigen::VectorXs> StateTheta::getVector() const +{ + return Eigen::Map<const Eigen::VectorXs>(state_ptr_, 1); } void StateTheta::print(unsigned int _ntabs, std::ostream& _ost) const { - printTabs(_ntabs); - _ost << nodeLabel() << " " << nodeId() << std::endl; - printTabs(_ntabs); - for (uint i = 0; i < BLOCK_SIZE; i++) - _ost << *(this->state_ptr_+i) << " "; - _ost << std::endl; + printTabs(_ntabs); + _ost << nodeLabel() << " " << nodeId() << std::endl; + printTabs(_ntabs); + for (uint i = 0; i < BLOCK_SIZE; i++) + _ost << *(this->state_ptr_ + i) << " "; + _ost << std::endl; } diff --git a/src/state_theta.h b/src/state_theta.h index 6c76502f2..5de9d1176 100644 --- a/src/state_theta.h +++ b/src/state_theta.h @@ -1,4 +1,3 @@ - #ifndef STATE_THETA_H_ #define STATE_THETA_H_ @@ -14,59 +13,69 @@ //class StateTheta class StateTheta : public StateOrientation { - public: - static const unsigned int BLOCK_SIZE = 1; - + public: + static const unsigned int BLOCK_SIZE = 1; + + public: + /** \brief Constructor with whole state storage and index where starts the state unit - * + * * Constructor with whole state storage and index where starts the state unit * \param _st_remote is the whole state vector * \param _idx is the index of the first element of the state in the whole state vector - * + * **/ - StateTheta(Eigen::VectorXs& _st_remote, const unsigned int _idx); + StateTheta(Eigen::VectorXs& _st_remote, const unsigned int _idx); /** \brief Constructor with scalar pointer - * + * * Constructor with scalar pointer * \param _st_ptr is the pointer of the first element of the state unit - * + * **/ - StateTheta(WolfScalar* _st_ptr); - + StateTheta(WolfScalar* _st_ptr); + /** \brief Destructor - * + * * Destructor - * + * **/ virtual ~StateTheta(); - + /** \brief Returns the parametrization of the state unit - * - * Returns the parametrizationType (see wolf.h) of the state unit - * - **/ - virtual StateType getStateType() const; + * + * Returns the parametrizationType (see wolf.h) of the state unit + * + **/ + virtual StateType getStateType() const; - /** \brief Returns the state unit size - * - * Returns the parametrizationType (see wolf.h) of the state unit - * - **/ - virtual unsigned int getStateSize() const; + /** \brief Returns the state unit size + * + * Returns the parametrizationType (see wolf.h) of the state unit + * + **/ + virtual unsigned int getStateSize() const; /** \brief Returns the 3x3 rotation matrix of the orientation - * - * Returns the 3x3 rotation matrix of the orientation - * - **/ - virtual Eigen::Matrix3s getRotationMatrix() const; + * + * Returns the 3x3 rotation matrix of the orientation + * + **/ + virtual Eigen::Matrix3s getRotationMatrix() const; + void getRotationMatrix(Eigen::Matrix3s& R) const; + + /** \brief Returns a (mapped) vector of the state unit + * + * Returns a (mapped) vector of the state unit + * + **/ + virtual Eigen::Map<const Eigen::VectorXs> getVector() const; /** \brief Prints all the elements of the state unit - * - * Prints all the elements of the state unit - * - **/ - virtual void print(unsigned int _ntabs = 0, std::ostream& _ost = std::cout) const; + * + * Prints all the elements of the state unit + * + **/ + virtual void print(unsigned int _ntabs = 0, std::ostream& _ost = std::cout) const; }; #endif diff --git a/src/wolf.h b/src/wolf.h index bcef332a0..7f207ddd2 100644 --- a/src/wolf.h +++ b/src/wolf.h @@ -21,6 +21,7 @@ //includes from Eigen lib #include <eigen3/Eigen/Dense> #include <eigen3/Eigen/Geometry> +#include <eigen3/Eigen/Sparse> /** * \brief scalar type for the Wolf project @@ -84,7 +85,7 @@ typedef AngleAxis<WolfScalar> AngleAxiss; ///< Angle-Axis of rea typedef enum { TOP, ///< root node location. This is the one that commands jobs down the tree. - MID,///< middle nodes. These delegate jobs to lower nodes. + MID, ///< middle nodes. These delegate jobs to lower nodes. BOTTOM ///< lowest level nodes. These are the ones that do not delegate any longer and have to do the job. } NodeLocation; @@ -108,13 +109,13 @@ typedef enum * You may add items to this list as needed. Be concise with names, and document your entries. * */ -typedef enum +typedef enum { CTR_GPS_FIX_2D, ///< marks a 2D GPS Fix constraint. - CTR_ODOM_2D_COMPLEX_ANGLE, ///< marks a 2D Odometry using complex angles. - CTR_ODOM_2D_THETA, ///< marks a 2D Odometry using theta angles. - CTR_CORNER_2D_THETA ///< marks a 2D Odometry using theta angles. - + CTR_ODOM_2D_COMPLEX_ANGLE, ///< marks a 2D Odometry using complex angles. + CTR_ODOM_2D_THETA, ///< marks a 2D Odometry using theta angles. + CTR_CORNER_2D_THETA ///< marks a 2D Odometry using theta angles. + } ConstraintType; /** \brief Enumeration of all possible state parametrizations @@ -126,12 +127,12 @@ typedef enum */ typedef enum { - ST_POINT_1D, ///< A 1D point. No parametrization. - ST_POINT_2D, ///< A 2D point. No parametrization. - ST_POINT_3D, ///< A 3D point. No parametrization. - ST_THETA, ///< A 2D orientation represented by a single angle. No parametrization. - ST_COMPLEX_ANGLE, ///< A 2D orientation represented by a complex number. - ST_QUATERNION ///< A 3D orientation represented by a quaternion. + ST_POINT_1D, ///< A 1D point. No parametrization. + ST_POINT_2D, ///< A 2D point. No parametrization. + ST_POINT_3D, ///< A 3D point. No parametrization. + ST_THETA, ///< A 2D orientation represented by a single angle. No parametrization. + ST_COMPLEX_ANGLE, ///< A 2D orientation represented by a complex number. + ST_QUATERNION ///< A 3D orientation represented by a quaternion. } StateType; /** \brief Enumeration of all possible state status @@ -143,9 +144,9 @@ typedef enum */ typedef enum { - ST_ESTIMATED, ///< State in estimation (default) - ST_FIXED, ///< State fixed, estimated enough or fixed infrastructure. - ST_REMOVED ///< Removed state. TODO: is it useful? + ST_ESTIMATED, ///< State in estimation (default) + ST_FIXED, ///< State fixed, estimated enough or fixed infrastructure. + ST_REMOVED ///< Removed state. TODO: is it useful? } StateStatus; /** \brief Enumeration of all possible sensor types @@ -157,13 +158,13 @@ typedef enum */ typedef enum { - ODOM_2D, ///< Odometry measurement from encoders: displacement and rotation. - IMU, ///< Inertial measurement unit with 3 acceleros, 3 gyros - CAMERA, ///< Regular pinhole camera - GPS_FIX, ///< GPS fix calculated from a GPS receiver - GPS_RAW, ///< GPS pseudo ranges, doppler and satellite ephemerides - LIDAR, ///< Laser Range Finder, 2D - RADAR, ///< Radar + ODOM_2D, ///< Odometry measurement from encoders: displacement and rotation. + IMU, ///< Inertial measurement unit with 3 acceleros, 3 gyros + CAMERA, ///< Regular pinhole camera + GPS_FIX, ///< GPS fix calculated from a GPS receiver + GPS_RAW, ///< GPS pseudo ranges, doppler and satellite ephemerides + LIDAR, ///< Laser Range Finder, 2D + RADAR, ///< Radar ABSOLUTE_POSE ///< Full absolute pose (XYZ+quaternion) } SensorType; @@ -176,18 +177,18 @@ typedef enum */ typedef enum { - LANDMARK_POINT, ///< A point landmark, either 3D or 2D - LANDMARK_CORNER, ///< A corner landmark (2D) - LANDMARK_CONTAINER ///< A container landmark + LANDMARK_POINT, ///< A point landmark, either 3D or 2D + LANDMARK_CORNER, ///< A corner landmark (2D) + LANDMARK_CONTAINER ///< A container landmark } LandmarkType; typedef enum { - LANDMARK_CANDIDATE, ///< A landmark, just created. Association with it allowed, but not yet stablish an actual constraint for the solver - LANDMARK_ESTIMATED, ///< A landmark being estimated. Association with it allowed, stablishing actual constraints for the solver where both vehicle and landmark states are being estimated - LANDMARK_FIXED, ///< A landmark estimated. Association with it allowed, stablishing actual constraints for the solver, but its value remains static, no longer optimized - LANDMARK_OUT_OF_VIEW, ///< A landmark out of the field of view. Association with it is not allowed, so does not pose constraints for the solver - LANDMARK_OLD ///< An old landmark. Association with it not allowed, but old constraints can still be taken into account by the solver. + LANDMARK_CANDIDATE, ///< A landmark, just created. Association with it allowed, but not yet stablish an actual constraint for the solver + LANDMARK_ESTIMATED, ///< A landmark being estimated. Association with it allowed, stablishing actual constraints for the solver where both vehicle and landmark states are being estimated + LANDMARK_FIXED, ///< A landmark estimated. Association with it allowed, stablishing actual constraints for the solver, but its value remains static, no longer optimized + LANDMARK_OUT_OF_VIEW, ///< A landmark out of the field of view. Association with it is not allowed, so does not pose constraints for the solver + LANDMARK_OLD ///< An old landmark. Association with it not allowed, but old constraints can still be taken into account by the solver. } LandmarkStatus; /** \brief Pending status of a node @@ -199,9 +200,9 @@ typedef enum */ typedef enum { - NOT_PENDING, ///< A point landmark, either 3D or 2D - ADD_PENDING, ///< A corner landmark (2D) - UPDATE_PENDING ///< A container landmark + NOT_PENDING, ///< A point landmark, either 3D or 2D + ADD_PENDING, ///< A corner landmark (2D) + UPDATE_PENDING ///< A container landmark } PendingStatus; ///////////////////////////////////////////////////////////////////////// @@ -210,7 +211,6 @@ typedef enum // - forwards for pointers //class VehicleBase; - class NodeTerminus; class WolfProblem; class MapBase; @@ -230,10 +230,9 @@ class SensorBase; class SensorLaser2D; class TransSensor; class StateBase; -template <unsigned int SIZE> class StatePoint; +template<unsigned int SIZE> class StatePoint; class PinHole; - // - Vehicle // typedef std::shared_ptr<VehicleBase> VehicleShPtr; // typedef VehicleBase* VehiclePtr; @@ -304,8 +303,6 @@ typedef StatePoint<3> StatePoint3D; // - Pin hole - - ///** \brief Enumeration of all possible feature types // * // * Enumeration of all possible feature types. @@ -326,5 +323,4 @@ typedef StatePoint<3> StatePoint3D; // LIDAR_RAY ///< A single laser ray //} FeatureType; - #endif /* WOLF_H_ */ diff --git a/src/wolf_manager.h b/src/wolf_manager.h index 8e5e30f86..218c6969b 100644 --- a/src/wolf_manager.h +++ b/src/wolf_manager.h @@ -41,158 +41,171 @@ class WolfManager { - protected: - bool use_complex_angles_; - WolfProblem* problem_; - std::queue<CaptureBase*> new_captures_; - SensorBase* sensor_prior_; - unsigned int window_size_; - FrameBaseIter first_window_frame_; - CaptureRelative* last_capture_relative_; - CaptureRelative* second_last_capture_relative_; - WolfScalar new_frame_elapsed_time_; - - public: - WolfManager(SensorBase* _sensor_prior, const bool _complex_angle, const unsigned int& _state_length, const Eigen::VectorXs& _init_frame, const WolfScalar& _new_frame_elapsed_time=0.1, const unsigned int& _w_size=10) : - use_complex_angles_(_complex_angle), - problem_(new WolfProblem(_state_length)), - sensor_prior_(_sensor_prior), - window_size_(_w_size), - new_frame_elapsed_time_(_new_frame_elapsed_time), - last_capture_relative_(nullptr), - second_last_capture_relative_(nullptr) - { - createFrame(_init_frame, TimeStamp(0)); - problem_->getTrajectoryPtr()->getFrameListPtr()->back()->fix(); - } - - virtual ~WolfManager() - { - delete problem_; - } - - void createFrame(const Eigen::VectorXs& _frame_state, const TimeStamp& _time_stamp) - { - // Create frame and add it to the trajectory - StateBase* new_position = new StatePoint2D(problem_->getNewStatePtr()); - problem_->addState(new_position, _frame_state.head(2)); - - StateBase* new_orientation; - if (use_complex_angles_) - new_orientation = new StateComplexAngle(problem_->getNewStatePtr()); - else - new_orientation = new StateTheta(problem_->getNewStatePtr()); - - problem_->addState(new_orientation, _frame_state.tail(new_orientation->getStateSize())); - - problem_->getTrajectoryPtr()->addFrame(new FrameBase(_time_stamp, new_position, new_orientation)); - - // add a zero odometry capture (in order to integrate) - CaptureOdom2D* empty_odom = new CaptureOdom2D(_time_stamp,sensor_prior_,Eigen::Vector3s::Zero(),Eigen::Matrix3s::Zero()); - problem_->getTrajectoryPtr()->getFrameListPtr()->back()->addCapture(empty_odom); - second_last_capture_relative_ = last_capture_relative_; - last_capture_relative_ = (CaptureRelative*)(empty_odom); - } - - void addCapture(CaptureBase* _capture) - { - new_captures_.push(_capture); - //std::cout << "added new capture: " << _capture->nodeId() << "stamp: " << _capture->getTimeStamp().get() << std::endl; - } - - void update() - { - while (!new_captures_.empty()) - { - // EXTRACT NEW CAPTURE - CaptureBase* new_capture = new_captures_.front(); - new_captures_.pop(); - - // ODOMETRY SENSOR - if (new_capture->getSensorPtr() == sensor_prior_) + protected: + bool use_complex_angles_; + WolfProblem* problem_; + std::queue<CaptureBase*> new_captures_; + SensorBase* sensor_prior_; + unsigned int window_size_; + FrameBaseIter first_window_frame_; + CaptureRelative* last_capture_relative_; + CaptureRelative* second_last_capture_relative_; + WolfScalar new_frame_elapsed_time_; + + public: + WolfManager(SensorBase* _sensor_prior, const bool _complex_angle, const unsigned int& _state_length, const Eigen::VectorXs& _init_frame, + const Eigen::MatrixXs& _init_frame_cov, const WolfScalar& _new_frame_elapsed_time = 0.1, const unsigned int& _w_size = 10) : + use_complex_angles_(_complex_angle), + problem_(new WolfProblem(_state_length)), + sensor_prior_(_sensor_prior), + window_size_(_w_size), + new_frame_elapsed_time_(_new_frame_elapsed_time), + last_capture_relative_(nullptr), + second_last_capture_relative_(nullptr) { - // UPDATE LAST STATE FROM SECOND LAST (optimized) - if (second_last_capture_relative_ != nullptr) - problem_->getTrajectoryPtr()->getFrameListPtr()->back()->setState(second_last_capture_relative_->computePrior()); - - // INTEGRATE NEW ODOMETRY TO LAST FRAME - last_capture_relative_->integrateCapture((CaptureRelative*)(new_capture)); - - // INITIALIZE STAMP OF FIRST FRAME - //std::cout << "new TimeStamp - last Frame TimeStamp = " << new_capture->getTimeStamp().get() - problem_->getTrajectoryPtr()->getFrameListPtr()->back()->getTimeStamp().get() << std::endl; - if (problem_->getTrajectoryPtr()->getFrameListPtr()->back()->getTimeStamp().get() == 0) - problem_->getTrajectoryPtr()->getFrameListPtr()->back()->setTimeStamp(new_capture->getTimeStamp()); - - // NEW KEY FRAME (if enough time from last frame) - if (new_capture->getTimeStamp().get() - problem_->getTrajectoryPtr()->getFrameListPtr()->back()->getTimeStamp().get() > new_frame_elapsed_time_) - { - //std::cout << "store prev frame" << std::endl; - auto second_last_frame_ptr = problem_->getTrajectoryPtr()->getFrameListPtr()->back(); - - // NEW CURRENT FRAME - //std::cout << "new frame" << std::endl; - createFrame(last_capture_relative_->computePrior(), new_capture->getTimeStamp()); - - // COMPUTE PREVIOUS FRAME CAPTURES - //std::cout << "compute prev frame" << std::endl; - for (auto capture_it = second_last_frame_ptr->getCaptureListPtr()->begin(); capture_it != second_last_frame_ptr->getCaptureListPtr()->end(); capture_it++) - (*capture_it)->processCapture(); - - // WINDOW of FRAMES (remove or fix old frames) - //std::cout << "frame window" << std::endl; - if (problem_->getTrajectoryPtr()->getFrameListPtr()->size() > window_size_) - { - //std::cout << "frame fixing" << std::endl; - //problem_->getTrajectoryPtr()->removeFrame(problem_->getTrajectoryPtr()->getFrameListPtr()->begin()); - (*first_window_frame_)->fix(); - first_window_frame_++; - } + assert( ((!_complex_angle && _init_frame.size() == 3 && _init_frame_cov.cols() == 3 && _init_frame_cov.rows() == 3) || + (_complex_angle && _init_frame.size() == 4 && _init_frame_cov.cols() == 4 && _init_frame_cov.rows() == 4)) + && "Wrong init_frame state vector or covariance matrix size"); + + + // Set initial covariance with a fake ODOM 2D capture to a fix frame + createFrame(_init_frame, TimeStamp(0)); + problem_->getTrajectoryPtr()->getFrameListPtr()->back()->fix(); + last_capture_relative_->integrateCapture((CaptureRelative*)(new CaptureOdom2D(TimeStamp(0), + nullptr, + Eigen::Vector3s::Zero(), + _init_frame_cov))); + createFrame(_init_frame, TimeStamp(0)); + second_last_capture_relative_->processCapture(); + } + + virtual ~WolfManager() + { + delete problem_; + } + + void createFrame(const Eigen::VectorXs& _frame_state, const TimeStamp& _time_stamp) + { + // Create frame and add it to the trajectory + StateBase* new_position = new StatePoint2D(problem_->getNewStatePtr()); + problem_->addState(new_position, _frame_state.head(2)); + + StateBase* new_orientation; + if (use_complex_angles_) + new_orientation = new StateComplexAngle(problem_->getNewStatePtr()); else - first_window_frame_ = problem_->getTrajectoryPtr()->getFrameListPtr()->begin(); - } + new_orientation = new StateTheta(problem_->getNewStatePtr()); + + problem_->addState(new_orientation, _frame_state.tail(new_orientation->getStateSize())); + + problem_->getTrajectoryPtr()->addFrame(new FrameBase(_time_stamp, new_position, new_orientation)); + + // add a zero odometry capture (in order to integrate) + CaptureOdom2D* empty_odom = new CaptureOdom2D(_time_stamp, sensor_prior_, Eigen::Vector3s::Zero(), Eigen::Matrix3s::Zero()); + problem_->getTrajectoryPtr()->getFrameListPtr()->back()->addCapture(empty_odom); + second_last_capture_relative_ = last_capture_relative_; + last_capture_relative_ = (CaptureRelative*) (empty_odom); + } + + void addCapture(CaptureBase* _capture) + { + new_captures_.push(_capture); + //std::cout << "added new capture: " << _capture->nodeId() << "stamp: " << _capture->getTimeStamp().get() << std::endl; } - else + + void update() { - // ADD CAPTURE TO THE LAST FRAME (or substitute the same sensor previous capture) - //std::cout << "adding not odometry capture..." << std::endl; - bool same_sensor_capture_found = false; - for (auto capture_it = problem_->getTrajectoryPtr()->getFrameListPtr()->back()->getCaptureListPtr()->begin(); capture_it != problem_->getTrajectoryPtr()->getFrameListPtr()->back()->getCaptureListPtr()->end(); capture_it++) - { - if ((*capture_it)->getSensorPtr() == new_capture->getSensorPtr()) + while (!new_captures_.empty()) { - //std::cout << "removing previous capture" << std::endl; - //problem_->getTrajectoryPtr()->getFrameListPtr()->back()->removeCapture(capture_it); - same_sensor_capture_found = true; - //std::cout << "removed!" << std::endl; - break; + // EXTRACT NEW CAPTURE + CaptureBase* new_capture = new_captures_.front(); + new_captures_.pop(); + + // ODOMETRY SENSOR + if (new_capture->getSensorPtr() == sensor_prior_) + { + // UPDATE LAST STATE FROM SECOND LAST (optimized) TODO: see if it is necessary + if (second_last_capture_relative_ != nullptr) + problem_->getTrajectoryPtr()->getFrameListPtr()->back()->setState(second_last_capture_relative_->computePrior()); + + // INTEGRATE NEW ODOMETRY TO LAST FRAME + last_capture_relative_->integrateCapture((CaptureRelative*) (new_capture)); + + // INITIALIZE STAMP OF FIRST FRAME + //std::cout << "new TimeStamp - last Frame TimeStamp = " << new_capture->getTimeStamp().get() - problem_->getTrajectoryPtr()->getFrameListPtr()->back()->getTimeStamp().get() << std::endl; + if (problem_->getTrajectoryPtr()->getFrameListPtr()->back()->getTimeStamp().get() == 0) + problem_->getTrajectoryPtr()->getFrameListPtr()->back()->setTimeStamp(new_capture->getTimeStamp()); + + // NEW KEY FRAME (if enough time from last frame) + if (new_capture->getTimeStamp().get() - problem_->getTrajectoryPtr()->getFrameListPtr()->back()->getTimeStamp().get() > new_frame_elapsed_time_) + { + //std::cout << "store prev frame" << std::endl; + auto second_last_frame_ptr = problem_->getTrajectoryPtr()->getFrameListPtr()->back(); + + // NEW CURRENT FRAME + //std::cout << "new frame" << std::endl; + createFrame(last_capture_relative_->computePrior(), new_capture->getTimeStamp()); + + // COMPUTE PREVIOUS FRAME CAPTURES + //std::cout << "compute prev frame" << std::endl; + for (auto capture_it = second_last_frame_ptr->getCaptureListPtr()->begin(); capture_it != second_last_frame_ptr->getCaptureListPtr()->end(); capture_it++) + (*capture_it)->processCapture(); + + // WINDOW of FRAMES (remove or fix old frames) + //std::cout << "frame window" << std::endl; + if (problem_->getTrajectoryPtr()->getFrameListPtr()->size() > window_size_) + { + //std::cout << "frame fixing" << std::endl; + //problem_->getTrajectoryPtr()->removeFrame(problem_->getTrajectoryPtr()->getFrameListPtr()->begin()); + (*first_window_frame_)->fix(); + first_window_frame_++; + } + else + first_window_frame_ = problem_->getTrajectoryPtr()->getFrameListPtr()->begin(); + } + } + else + { + // ADD CAPTURE TO THE LAST FRAME (or substitute the same sensor previous capture) + //std::cout << "adding not odometry capture " << new_capture->nodeId() << std::endl; + bool same_sensor_capture_found = false; + for (auto capture_it = problem_->getTrajectoryPtr()->getFrameListPtr()->back()->getCaptureListPtr()->begin(); + capture_it != problem_->getTrajectoryPtr()->getFrameListPtr()->back()->getCaptureListPtr()->end(); capture_it++) + { + if ((*capture_it)->getSensorPtr() == new_capture->getSensorPtr()) + { + //std::cout << "removing previous capture" << std::endl; + //problem_->getTrajectoryPtr()->getFrameListPtr()->back()->removeCapture(capture_it); + same_sensor_capture_found = true; + //std::cout << "removed!" << std::endl; + break; + } + } + if (!same_sensor_capture_found) + problem_->getTrajectoryPtr()->getFrameListPtr()->back()->addCapture(new_capture); + } } - } - if (!same_sensor_capture_found) - problem_->getTrajectoryPtr()->getFrameListPtr()->back()->addCapture(new_capture); } - } - } - - Eigen::VectorXs getVehiclePose() - { - if (second_last_capture_relative_ != nullptr) - problem_->getTrajectoryPtr()->getFrameListPtr()->back()->setState(second_last_capture_relative_->computePrior()); - //std::cout << "getVehiclePose +++++++++++++++++++++++++\n"; - return last_capture_relative_->computePrior(); - } - - WolfProblem* getProblemPtr() - { - return problem_; - } - - void setWindowSize(const unsigned int& _size) - { - window_size_ = _size; - } - - void setNewFrameElapsedTime( const WolfScalar& _dt) - { - new_frame_elapsed_time_ = _dt; - } + + Eigen::VectorXs getVehiclePose() + { + if (second_last_capture_relative_ != nullptr) + problem_->getTrajectoryPtr()->getFrameListPtr()->back()->setState(second_last_capture_relative_->computePrior()); + return last_capture_relative_->computePrior(); + } + + WolfProblem* getProblemPtr() + { + return problem_; + } + + void setWindowSize(const unsigned int& _size) + { + window_size_ = _size; + } + + void setNewFrameElapsedTime(const WolfScalar& _dt) + { + new_frame_elapsed_time_ = _dt; + } }; diff --git a/src/wolf_problem.cpp b/src/wolf_problem.cpp index c0fa4baac..4a8c0b3c9 100644 --- a/src/wolf_problem.cpp +++ b/src/wolf_problem.cpp @@ -2,7 +2,8 @@ WolfProblem::WolfProblem(unsigned int _size) : NodeBase("WOLF_PROBLEM"), // - state_(_size), + state_(_size), + covariance_(_size,_size), state_idx_last_(0), location_(TOP), map_ptr_(new MapBase), @@ -18,6 +19,7 @@ WolfProblem::WolfProblem(unsigned int _size) : WolfProblem::WolfProblem(TrajectoryBase* _trajectory_ptr, MapBase* _map_ptr, unsigned int _size) : NodeBase("WOLF_PROBLEM"), // state_(_size), + covariance_(_size,_size), state_idx_last_(0), location_(TOP), map_ptr_(_map_ptr==nullptr ? new MapBase : _map_ptr), @@ -65,6 +67,66 @@ bool WolfProblem::addState(StateBase* _new_state_ptr, const Eigen::VectorXs& _ne return reallocated_; } +void WolfProblem::addCovarianceBlock(StateBase* _state1, StateBase* _state2, const Eigen::MatrixXs& _cov) +{ + assert(_state1 != nullptr && _state1->getPtr() != nullptr && _state1->getPtr() < state_.data() + state_idx_last_ && _state1->getPtr() > state_.data()); + assert(_state2 != nullptr && _state2->getPtr() != nullptr && _state2->getPtr() < state_.data() + state_idx_last_ && _state2->getPtr() > state_.data()); + + // Guarantee that we are updating the top triangular matrix (in cross covariance case) + bool flip = _state1->getPtr() > _state2->getPtr(); + StateBase* stateA = (flip ? _state2 : _state1); + StateBase* stateB = (flip ? _state1 : _state2); + unsigned int row = (stateA->getPtr() - state_.data()); + unsigned int col = (stateB->getPtr() - state_.data()); + unsigned int block_rows = stateA->getStateSize(); + unsigned int block_cols = stateB->getStateSize(); + + assert( block_rows == (flip ? _cov.cols() : _cov.rows()) && block_cols == (flip ? _cov.rows() : _cov.cols()) && "Bad covariance size in WolfProblem::addCovarianceBlock"); + + // STORE COVARIANCE + for (unsigned int i = 0; i < block_rows; i++) + for (unsigned int j = 0; j < block_cols; j++) + covariance_.coeffRef(i+row,j+col) = (flip ? _cov(j,i) : _cov(i,j)); +} + +void WolfProblem::getCovarianceBlock(StateBase* _state1, StateBase* _state2, Eigen::MatrixXs& _cov_block) const +{ + assert(_state1 != nullptr && _state1->getPtr() != nullptr && _state1->getPtr() < state_.data() + state_idx_last_ && _state1->getPtr() > state_.data()); + assert(_state2 != nullptr && _state2->getPtr() != nullptr && _state2->getPtr() < state_.data() + state_idx_last_ && _state2->getPtr() > state_.data()); + + // Guarantee that we are getting the top triangular matrix (in cross covariance case) + bool flip = _state1->getPtr() > _state2->getPtr(); + StateBase* stateA = (flip ? _state2 : _state1); + StateBase* stateB = (flip ? _state1 : _state2); + unsigned int row = (stateA->getPtr() - state_.data()); + unsigned int col = (stateB->getPtr() - state_.data()); + unsigned int block_rows = stateA->getStateSize(); + unsigned int block_cols = stateB->getStateSize(); + + assert(_cov_block.rows() == (flip ? block_cols : block_rows) && _cov_block.cols() == (flip ? block_rows : block_cols) && "Bad _cov_block matrix sizes"); + + _cov_block = (flip ? Eigen::MatrixXs(covariance_.block(row, col, block_rows, block_cols)) : Eigen::MatrixXs(covariance_.block(row, col, block_rows, block_cols)).transpose() ); +} + +void WolfProblem::getCovarianceBlock(StateBase* _state1, StateBase* _state2, Eigen::Map<Eigen::MatrixXs>& _cov_block) const +{ + assert(_state1 != nullptr && _state1->getPtr() != nullptr && _state1->getPtr() < state_.data() + state_idx_last_ && _state1->getPtr() > state_.data()); + assert(_state2 != nullptr && _state2->getPtr() != nullptr && _state2->getPtr() < state_.data() + state_idx_last_ && _state2->getPtr() > state_.data()); + + // Guarantee that we are getting the top triangular matrix (in cross covariance case) + bool flip = _state1->getPtr() > _state2->getPtr(); + StateBase* stateA = (flip ? _state2 : _state1); + StateBase* stateB = (flip ? _state1 : _state2); + unsigned int row = (stateA->getPtr() - state_.data()); + unsigned int col = (stateB->getPtr() - state_.data()); + unsigned int block_rows = stateA->getStateSize(); + unsigned int block_cols = stateB->getStateSize(); + + assert(_cov_block.rows() == (flip ? block_cols : block_rows) && _cov_block.cols() == (flip ? block_rows : block_cols) && "Bad _cov_block matrix sizes"); + + _cov_block = (flip ? Eigen::MatrixXs(covariance_.block(row, col, block_rows, block_cols)).transpose() : Eigen::MatrixXs(covariance_.block(row, col, block_rows, block_cols)) ); +} + void WolfProblem::removeState(StateBase* _state_ptr) { // TODO: Reordering? Mandatory for filtering... diff --git a/src/wolf_problem.h b/src/wolf_problem.h index 2a7066c99..62c5cfd7c 100644 --- a/src/wolf_problem.h +++ b/src/wolf_problem.h @@ -20,7 +20,8 @@ class WolfProblem: public NodeBase { protected: - Eigen::VectorXs state_; + Eigen::VectorXs state_; + Eigen::SparseMatrix<WolfScalar> covariance_; unsigned int state_idx_last_; NodeLocation location_;// TODO: should it be in node_base? MapBase* map_ptr_; @@ -37,14 +38,14 @@ class WolfProblem: public NodeBase * Constructor from state size * */ - WolfProblem(unsigned int _size=1e6); + WolfProblem(unsigned int _size=1e3); /** \brief Constructor from map and trajectory shared pointers * * Constructor from map and trajectory shared pointers * */ - WolfProblem(TrajectoryBase* _trajectory_ptr, MapBase* _map_ptr=nullptr, unsigned int _size=1e6); + WolfProblem(TrajectoryBase* _trajectory_ptr, MapBase* _map_ptr=nullptr, unsigned int _size=1e3); /** \brief Default destructor * @@ -60,6 +61,21 @@ class WolfProblem: public NodeBase */ bool addState(StateBase* _new_state, const Eigen::VectorXs& _new_state_values); + /** \brief Adds a new covariance block + * + * Adds a new covariance block + * + */ + void addCovarianceBlock(StateBase* _state1, StateBase* _state2, const Eigen::MatrixXs& _cov); + + /** \brief Gets a covariance block + * + * Gets a covariance block + * + */ + void getCovarianceBlock(StateBase* _state1, StateBase* _state2, Eigen::MatrixXs& _cov_block) const; + void getCovarianceBlock(StateBase* _state1, StateBase* _state2, Eigen::Map<Eigen::MatrixXs>& _cov_block) const; + /** \brief Removes a new state unit of the state * * Removes a new state unit of the state -- GitLab