From 13e38e0590f65c7ded79cf21912c69cb3ed25ea5 Mon Sep 17 00:00:00 2001 From: raphaelchang Date: Thu, 19 Sep 2019 01:15:49 -0400 Subject: [PATCH] it all works --- CMakeLists.txt | 29 ++++++++++++- launch/slam_eval.launch | 52 ++++++++++++++++++++++++ src/data/frame.cc | 8 ++-- src/module/reconstruction_module.cc | 2 +- src/module/stereo_module.cc | 12 ++++-- src/module/stereo_module.h | 2 +- src/odometry/pnp.cc | 8 +++- src/omni_slam_slam_eval_node.cc | 13 ++++++ src/reconstruction/triangulator.cc | 4 ++ src/ros/odometry_eval.h | 3 +- src/ros/slam_eval.cc | 63 +++++++++++++++++++++++++++++ src/ros/slam_eval.h | 34 ++++++++++++++++ src/ros/stereo_eval.cc | 2 + src/ros/tracking_eval.cc | 23 ++++++++--- src/ros/tracking_eval.h | 3 ++ 15 files changed, 238 insertions(+), 20 deletions(-) create mode 100644 launch/slam_eval.launch create mode 100644 src/omni_slam_slam_eval_node.cc create mode 100644 src/ros/slam_eval.cc create mode 100644 src/ros/slam_eval.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d02ace0..b7c53a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,6 @@ project(omni_slam_eval) set(CMAKE_VERBOSE_MAKEFILE FALSE) -add_definitions("-std=c++17") if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) endif (NOT CMAKE_BUILD_TYPE) @@ -109,6 +108,16 @@ add_executable(omni_slam_stereo_eval_node src/omni_slam_stereo_eval_node.cc ) +add_executable(omni_slam_slam_eval_node + src/ros/slam_eval.cc + src/ros/stereo_eval.cc + src/ros/odometry_eval.cc + src/ros/reconstruction_eval.cc + src/ros/tracking_eval.cc + src/ros/eval_base.cc + src/omni_slam_slam_eval_node.cc +) + target_link_libraries(omni_slam_tracking_eval_node PUBLIC omni_slam_eval_lib ${catkin_LIBRARIES} ${OpenCV_LIBS} @@ -154,12 +163,22 @@ target_link_libraries(omni_slam_stereo_eval_node PUBLIC omni_slam_eval_lib ${CERES_LIBRARIES} ) +target_link_libraries(omni_slam_slam_eval_node PUBLIC omni_slam_eval_lib + ${catkin_LIBRARIES} + ${OpenCV_LIBS} + ${HDF5_CXX_LIBRARIES} + ${OpenMP_CXX_FLAGS} + ${PCL_LIBRARIES} + ${CERES_LIBRARIES} +) + target_compile_options(omni_slam_tracking_eval_node PUBLIC ${OpenMP_CXX_FLAGS}) target_compile_options(omni_slam_matching_eval_node PUBLIC ${OpenMP_CXX_FLAGS}) target_compile_options(omni_slam_reconstruction_eval_node PUBLIC ${OpenMP_CXX_FLAGS}) target_compile_options(omni_slam_odometry_eval_node PUBLIC ${OpenMP_CXX_FLAGS}) target_compile_options(omni_slam_stereo_eval_node PUBLIC ${OpenMP_CXX_FLAGS}) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} -ggdb") +target_compile_options(omni_slam_slam_eval_node PUBLIC ${OpenMP_CXX_FLAGS}) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} -std=c++17") install(TARGETS omni_slam_tracking_eval_node ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} @@ -190,3 +209,9 @@ install(TARGETS omni_slam_stereo_eval_node LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} ) + +install(TARGETS omni_slam_slam_eval_node + ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} +) diff --git a/launch/slam_eval.launch b/launch/slam_eval.launch new file mode 100644 index 0000000..2345d5f --- /dev/null +++ b/launch/slam_eval.launch @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + camera_model: '$(arg camera_model)' + camera_parameters: $(arg camera_params) + detector_type: 'GFTT' + detector_parameters: {maxCorners: 5000, qualityLevel: 0.001, minDistance: 5, blockSize: 5} + tracker_window_size: 128 + tracker_num_scales: 4 + tracker_checker_epipolar_threshold: 0.008 + tracker_checker_iterations: 1000 + tracker_delta_pixel_error_threshold: 0.0 + tracker_error_threshold: 20.0 + min_features_per_region: 100 + pnp_inlier_threshold: 3.0 + pnp_iterations: 3000 + max_reprojection_error: 5.0 + min_triangulation_angle: 3.0 + bundle_adjustment_max_iterations: 1000 + bundle_adjustment_loss_coefficient: 0.05 + bundle_adjustment_logging: true + bundle_adjustment_num_threads: 20 + stereo_matcher_window_size: 256 + stereo_matcher_num_scales: 5 + stereo_matcher_error_threshold: 20 + stereo_matcher_epipolar_threshold: 0.008 + stereo_tf_t: [2.0, 0.0, 0.0] + stereo_tf_r: [0.0, 0.0, 0.0, 1.0] + + + + + diff --git a/src/data/frame.cc b/src/data/frame.cc index fa4eb6f..2e35b63 100644 --- a/src/data/frame.cc +++ b/src/data/frame.cc @@ -15,7 +15,7 @@ Frame::Frame(cv::Mat &image, cv::Mat &stereo_image, cv::Mat &depth_image, Matrix depthImage_(depth_image.clone()), pose_(pose), invPose_(util::TFUtil::InversePoseMatrix(pose)), - stereoPose_(stereo_pose), + stereoPose_(util::TFUtil::InversePoseMatrix(stereo_pose)), timeSec_(time), cameraModel_(camera_model) { @@ -28,7 +28,7 @@ Frame::Frame(cv::Mat &image, cv::Mat &stereo_image, Matrix &stereo : id_(lastFrameId_++), image_(image.clone()), stereoImage_(stereo_image.clone()), - stereoPose_(stereo_pose), + stereoPose_(util::TFUtil::InversePoseMatrix(stereo_pose)), timeSec_(time), cameraModel_(camera_model) { @@ -54,7 +54,7 @@ Frame::Frame(cv::Mat &image, cv::Mat &stereo_image, cv::Mat &depth_image, Matrix image_(image.clone()), stereoImage_(stereo_image.clone()), depthImage_(depth_image.clone()), - stereoPose_(stereo_pose), + stereoPose_(util::TFUtil::InversePoseMatrix(stereo_pose)), timeSec_(time), cameraModel_(camera_model) { @@ -82,7 +82,7 @@ Frame::Frame(cv::Mat &image, cv::Mat &stereo_image, Matrix &pose, stereoImage_(stereo_image.clone()), pose_(pose), invPose_(util::TFUtil::InversePoseMatrix(pose)), - stereoPose_(stereo_pose), + stereoPose_(util::TFUtil::InversePoseMatrix(stereo_pose)), timeSec_(time), cameraModel_(camera_model) { diff --git a/src/module/reconstruction_module.cc b/src/module/reconstruction_module.cc index 79a4794..276e342 100644 --- a/src/module/reconstruction_module.cc +++ b/src/module/reconstruction_module.cc @@ -47,7 +47,7 @@ void ReconstructionModule::BundleAdjust(std::vector &landmarks) { bundleAdjuster_->Optimize(landmarks); - for (int i = 0; i < landmarks.size(); i++) + for (int i = 0; i < lastLandmarksSize_; i++) { if (landmarks[i].HasEstimatedPosition()) { diff --git a/src/module/stereo_module.cc b/src/module/stereo_module.cc index aa92baa..d3b63b8 100644 --- a/src/module/stereo_module.cc +++ b/src/module/stereo_module.cc @@ -1,5 +1,7 @@ #include "stereo_module.h" +#include + using namespace std; namespace omni_slam @@ -33,7 +35,8 @@ void StereoModule::Update(data::Frame &frame, std::vector &landm { Matrix framePose = frame.HasEstimatedPose() ? frame.GetEstimatedPose() : frame.GetPose(); double depth = (landmark.GetEstimatedPosition() - framePose.block<3, 1>(0, 3)).norm(); - visualization_.AddMatch(feat1->GetKeypoint().pt, feat2->GetKeypoint().pt, depth); + double depthGnd = (landmark.GetGroundTruth() - frame.GetPose().block<3, 1>(0, 3)).norm(); + visualization_.AddMatch(feat1->GetKeypoint().pt, feat2->GetKeypoint().pt, depth, depthGnd); } } frameNum_++; @@ -55,12 +58,15 @@ void StereoModule::Visualization::Init(cv::Size img_size) curDepth_ = cv::Mat::zeros(img_size, CV_8UC3); } -void StereoModule::Visualization::AddMatch(cv::Point2f pt1, cv::Point2f pt2, double depth) +void StereoModule::Visualization::AddMatch(cv::Point2f pt1, cv::Point2f pt2, double depth, double depthGnd) { + double err = std::abs(depth - depthGnd) / depthGnd; + err = min(err, 1.0); + depth = min(depth, maxDepth_); cv::circle(curMask_, pt1, 3, cv::Scalar(255, 0, 0), -1); cv::circle(curMask_, pt2 + cv::Point2f(curMask_.cols / 2., 0), 3, cv::Scalar(255, 0, 0), -1); cv::line(curMask_, pt1, pt2 + cv::Point2f(curMask_.cols / 2., 0), cv::Scalar(255, 0, 0), 1); - cv::circle(curDepth_, pt1, 2, cv::Scalar(depth / maxDepth_ * 255, depth / maxDepth_ * 255, depth / maxDepth_ * 255)); + cv::circle(curDepth_, pt1, 2, cv::Scalar((depth / maxDepth_ - err) * 255, (depth / maxDepth_ - err) * 255, depth / maxDepth_ * 255)); } void StereoModule::Visualization::Draw(cv::Mat &img, const cv::Mat &stereo_img) diff --git a/src/module/stereo_module.h b/src/module/stereo_module.h index f3c6f19..4aa6794 100644 --- a/src/module/stereo_module.h +++ b/src/module/stereo_module.h @@ -38,7 +38,7 @@ class StereoModule { public: void Init(cv::Size img_size); - void AddMatch(cv::Point2f pt1, cv::Point2f pt2, double depth); + void AddMatch(cv::Point2f pt1, cv::Point2f pt2, double depth, double depthGnd); void Draw(cv::Mat &img, const cv::Mat &stereo_img); private: diff --git a/src/odometry/pnp.cc b/src/odometry/pnp.cc index 2fa2eab..355d85d 100644 --- a/src/odometry/pnp.cc +++ b/src/odometry/pnp.cc @@ -36,11 +36,15 @@ int PNP::Compute(const std::vector &landmarks, data::Frame &fram { if (landmark.IsObservedInFrame(frame.GetID())) { - if (landmark.HasEstimatedPosition()) + if (frame.HasStereoImage() && landmark.HasEstimatedPosition() && landmark.GetStereoObservationByFrameID(landmark.GetFirstFrameID()) != nullptr) { xs.push_back(landmark.GetEstimatedPosition()); } - else if (landmark.HasGroundTruth()) + else if (!frame.HasStereoImage() && landmark.HasEstimatedPosition()) + { + xs.push_back(landmark.GetEstimatedPosition()); + } + else if (!frame.HasStereoImage() && landmark.HasGroundTruth()) { xs.push_back(landmark.GetGroundTruth()); } diff --git a/src/omni_slam_slam_eval_node.cc b/src/omni_slam_slam_eval_node.cc new file mode 100644 index 0000000..3db749a --- /dev/null +++ b/src/omni_slam_slam_eval_node.cc @@ -0,0 +1,13 @@ +#include "ros/slam_eval.h" + +int main(int argc, char *argv[]) +{ + ros::init(argc, argv, "omni_slam_slam_eval_node"); + + omni_slam::ros::SLAMEval slam_eval; + slam_eval.Run(); + + return 0; +} + + diff --git a/src/reconstruction/triangulator.cc b/src/reconstruction/triangulator.cc index 4ba1256..2e260a1 100644 --- a/src/reconstruction/triangulator.cc +++ b/src/reconstruction/triangulator.cc @@ -20,6 +20,10 @@ int Triangulator::Triangulate(std::vector &landmarks) const for (auto it = landmarks.begin(); it < landmarks.end(); it++) { data::Landmark &landmark = *it; + if (landmark.HasEstimatedPosition() && landmark.GetStereoObservationByFrameID(landmark.GetFirstFrameID()) != nullptr) + { + continue; + } Vector3d point; if (TriangulateNViews(landmark.GetObservations(), point)) { diff --git a/src/ros/odometry_eval.h b/src/ros/odometry_eval.h index d86814f..f654387 100644 --- a/src/ros/odometry_eval.h +++ b/src/ros/odometry_eval.h @@ -27,10 +27,11 @@ class OdometryEval : public virtual TrackingEval virtual void GetResultsData(std::map>> &data); virtual void Visualize(cv_bridge::CvImagePtr &base_img); + void PublishOdometry(); + std::unique_ptr odometryModule_; private: - void PublishOdometry(); ::ros::Publisher odometryPublisher_; ::ros::Publisher odometryGndPublisher_; diff --git a/src/ros/slam_eval.cc b/src/ros/slam_eval.cc new file mode 100644 index 0000000..876b8cb --- /dev/null +++ b/src/ros/slam_eval.cc @@ -0,0 +1,63 @@ +#include "slam_eval.h" + +#include "odometry/pnp.h" +#include "optimization/bundle_adjuster.h" +#include "module/tracking_module.h" + +#include "geometry_msgs/PoseStamped.h" +#include "nav_msgs/Path.h" + +using namespace std; + +namespace omni_slam +{ +namespace ros +{ + +SLAMEval::SLAMEval(const ::ros::NodeHandle &nh, const ::ros::NodeHandle &nh_private) + : OdometryEval(nh, nh_private), ReconstructionEval(nh, nh_private), StereoEval(nh, nh_private) +{ +} + +void SLAMEval::InitPublishers() +{ + OdometryEval::InitPublishers(); + ReconstructionEval::InitPublishers(); + StereoEval::InitPublishers(); +} + +void SLAMEval::ProcessFrame(unique_ptr &&frame) +{ + trackingModule_->Update(frame); + odometryModule_->Update(trackingModule_->GetLandmarks(), *trackingModule_->GetFrames().back()); + reconstructionModule_->Update(trackingModule_->GetLandmarks()); + trackingModule_->Redetect(); + stereoModule_->Update(*trackingModule_->GetFrames().back(), trackingModule_->GetLandmarks()); +} + +void SLAMEval::Finish() +{ + ReconstructionEval::Finish(); + PublishOdometry(); +} + +void SLAMEval::GetResultsData(std::map>> &data) +{ +} + +void SLAMEval::Visualize(cv_bridge::CvImagePtr &base_img) +{ + visualized_ = false; + ReconstructionEval::Visualize(base_img); + OdometryEval::Visualize(base_img); +} + +void SLAMEval::Visualize(cv_bridge::CvImagePtr &base_img, cv_bridge::CvImagePtr &base_stereo_img) +{ + Visualize(base_img); + StereoEval::Visualize(base_img, base_stereo_img); +} + +} +} + diff --git a/src/ros/slam_eval.h b/src/ros/slam_eval.h new file mode 100644 index 0000000..3e43a29 --- /dev/null +++ b/src/ros/slam_eval.h @@ -0,0 +1,34 @@ +#ifndef _SLAM_EVAL_H_ +#define _SLAM_EVAL_H_ + +#include "odometry_eval.h" +#include "reconstruction_eval.h" +#include "stereo_eval.h" +#include +#include + +namespace omni_slam +{ +namespace ros +{ + +class SLAMEval : public OdometryEval, ReconstructionEval, StereoEval +{ +public: + SLAMEval(const ::ros::NodeHandle &nh, const ::ros::NodeHandle &nh_private); + SLAMEval() : SLAMEval(::ros::NodeHandle(), ::ros::NodeHandle("~")) {} + +private: + void InitPublishers(); + + void ProcessFrame(std::unique_ptr &&frame); + void Finish(); + void GetResultsData(std::map>> &data); + void Visualize(cv_bridge::CvImagePtr &base_img); + void Visualize(cv_bridge::CvImagePtr &base_img, cv_bridge::CvImagePtr &base_stereo_img); +}; + +} +} + +#endif /* _SLAM_EVAL_H_ */ diff --git a/src/ros/stereo_eval.cc b/src/ros/stereo_eval.cc index 230f78f..281bee6 100644 --- a/src/ros/stereo_eval.cc +++ b/src/ros/stereo_eval.cc @@ -50,8 +50,10 @@ void StereoEval::GetResultsData(std::mapimage.clone(); stereoModule_->Visualize(base_img->image, base_stereo_img->image); matchedImagePublisher_.publish(base_img->toImageMsg()); + base_img->image = orig; } } diff --git a/src/ros/tracking_eval.cc b/src/ros/tracking_eval.cc index dbb7976..f2ddeff 100644 --- a/src/ros/tracking_eval.cc +++ b/src/ros/tracking_eval.cc @@ -55,11 +55,16 @@ TrackingEval::TrackingEval(const ::ros::NodeHandle &nh, const ::ros::Nod template void TrackingEval::InitPublishers() { - EvalBase::InitPublishers(); + if (!pubInitialized_) + { + EvalBase::InitPublishers(); + + string outputTopic; + this->nhp_.param("tracked_image_topic", outputTopic, string("/omni_slam/tracked")); + trackedImagePublisher_ = this->imageTransport_.advertise(outputTopic, 2); - string outputTopic; - this->nhp_.param("tracked_image_topic", outputTopic, string("/omni_slam/tracked")); - trackedImagePublisher_ = this->imageTransport_.advertise(outputTopic, 2); + pubInitialized_ = true; + } } template @@ -88,8 +93,14 @@ void TrackingEval::GetResultsData(std::map void TrackingEval::Visualize(cv_bridge::CvImagePtr &base_img) { - trackingModule_->Visualize(base_img->image); - trackedImagePublisher_.publish(base_img->toImageMsg()); + if (!visualized_) + { + cv::Mat orig = base_img->image.clone(); + trackingModule_->Visualize(base_img->image); + trackedImagePublisher_.publish(base_img->toImageMsg()); + base_img->image = orig; + visualized_ = true; + } } template class TrackingEval; diff --git a/src/ros/tracking_eval.h b/src/ros/tracking_eval.h index d7a8226..e8af811 100644 --- a/src/ros/tracking_eval.h +++ b/src/ros/tracking_eval.h @@ -30,6 +30,9 @@ class TrackingEval : public virtual EvalBase std::unique_ptr trackingModule_; + bool visualized_{false}; + bool pubInitialized_{false}; + private: image_transport::Publisher trackedImagePublisher_; };