Edit EKF and VO pipline to publish the odometry as soon as algorithm initialized. And VO will not save those frames that do not have features.
This commit is contained in:
@@ -93,11 +93,7 @@ public:
|
|||||||
|
|
||||||
/// Transforms point coordinates in world-frame (w) to camera pixel coordinates (c).
|
/// Transforms point coordinates in world-frame (w) to camera pixel coordinates (c).
|
||||||
inline Vector2d w2c(const Vector3d& xyz_w) const {
|
inline Vector2d w2c(const Vector3d& xyz_w) const {
|
||||||
Eigen::Matrix<double,3,3> R;
|
return cam_->world2cam( T_f_w_.se3()*xyz_w);
|
||||||
R<<T_f_w_.T2_.rotation_matrix()(0,0),1e-19,T_f_w_.T2_.rotation_matrix()(0,1),
|
|
||||||
1e-19,1.0,1e-19,
|
|
||||||
T_f_w_.T2_.rotation_matrix()(1,0),1e-19,T_f_w_.T2_.rotation_matrix()(1,1);
|
|
||||||
return cam_->world2cam( SE3(R,Vector3d(T_f_w_.T2_.translation()(0),1e-19,T_f_w_.T2_.translation()(1)))*xyz_w);
|
|
||||||
}
|
}
|
||||||
/// Transforms point coordinates in world-frame (w) to camera pixel coordinates (c).
|
/// Transforms point coordinates in world-frame (w) to camera pixel coordinates (c).
|
||||||
inline Vector2d w2px(const Vector3d& xyz_w) const { return cam_->world2cam( xyz_w ); }
|
inline Vector2d w2px(const Vector3d& xyz_w) const { return cam_->world2cam( xyz_w ); }
|
||||||
@@ -110,35 +106,22 @@ public:
|
|||||||
|
|
||||||
/// Transforms point coordinates in world-frame (w) to camera-frams (f).
|
/// Transforms point coordinates in world-frame (w) to camera-frams (f).
|
||||||
inline Vector3d w2f(const Vector3d& xyz_w) const {
|
inline Vector3d w2f(const Vector3d& xyz_w) const {
|
||||||
Eigen::Matrix<double,3,3> R;
|
return Vector3d(T_f_w_.se3()*xyz_w);
|
||||||
R<<T_f_w_.T2_.rotation_matrix()(0,0),1e-19,T_f_w_.T2_.rotation_matrix()(0,1),
|
|
||||||
1e-19,1.0,1e-19,
|
|
||||||
T_f_w_.T2_.rotation_matrix()(1,0),1e-19,T_f_w_.T2_.rotation_matrix()(1,1);
|
|
||||||
return Vector3d(SE3(R,Vector3d(T_f_w_.T2_.translation()(0),1e-19,T_f_w_.T2_.translation()(1)))*xyz_w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms point from frame unit sphere (f) frame to world coordinate frame (w).
|
/// Transforms point from frame unit sphere (f) frame to world coordinate frame (w).
|
||||||
inline Vector3d f2w(const Vector3d& f) const {
|
inline Vector3d f2w(const Vector3d& f) const {
|
||||||
Eigen::Matrix<double,3,3> R;
|
return getSE3Inv() * f;
|
||||||
R<<T_f_w_.T2_.rotation_matrix()(0,0),1e-19,T_f_w_.T2_.rotation_matrix()(0,1),
|
|
||||||
1e-19,1.0,1e-19,
|
|
||||||
T_f_w_.T2_.rotation_matrix()(1,0),1e-19,T_f_w_.T2_.rotation_matrix()(1,1);
|
|
||||||
return SE3(R,Vector3d(T_f_w_.T2_.translation()(0),1e-19,T_f_w_.T2_.translation()(1))).inverse() * f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Projects Point from unit sphere (f) in camera pixels (c).
|
/// Projects Point from unit sphere (f) in camera pixels (c).
|
||||||
inline Vector2d f2c(const Vector3d& f) const { return cam_->world2cam( f ); }
|
inline Vector2d f2c(const Vector3d& f) const { return cam_->world2cam( f ); }
|
||||||
|
|
||||||
/// Return the pose of the frame in the (w)orld coordinate frame.
|
/// Return the pose of the frame in the (w)orld coordinate frame.
|
||||||
inline Vector2d pos() const { return T_f_w_.T2_.translation(); }
|
inline Vector2d pos() const { return T_f_w_.se2().translation(); }
|
||||||
|
|
||||||
inline SE3 se3() const{
|
inline SE3 se3() const{
|
||||||
Eigen::Matrix<double,3,3> R;
|
return T_f_w_.se3();
|
||||||
R<<T_f_w_.getSE2().rotation_matrix()(0,0),1e-19,T_f_w_.getSE2().rotation_matrix()(0,1),
|
|
||||||
1e-19,1.0,1e-19,
|
|
||||||
T_f_w_.getSE2().rotation_matrix()(1,0),1e-19,T_f_w_.getSE2().rotation_matrix()(1,1);
|
|
||||||
SE3 out(R,Vector3d(T_f_w_.getSE2().translation()(0),1e-19,T_f_w_.getSE2().translation()(1)));
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline SE3 getSE3Inv() const{
|
inline SE3 getSE3Inv() const{
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ public:
|
|||||||
//std::shared_ptr<Imu_Integration> imu_integPtr_; //Integration of IMU
|
//std::shared_ptr<Imu_Integration> imu_integPtr_; //Integration of IMU
|
||||||
void UpdateIMU(double* value,const ros::Time& time);
|
void UpdateIMU(double* value,const ros::Time& time);
|
||||||
void UpdateCmd(double* value,const ros::Time& time);
|
void UpdateCmd(double* value,const ros::Time& time);
|
||||||
|
UKF ukfPtr_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
vk::AbstractCamera* cam_; //!< Camera model, can be ATAN, Pinhole or Ocam (see vikit).
|
vk::AbstractCamera* cam_; //!< Camera model, can be ATAN, Pinhole or Ocam (see vikit).
|
||||||
@@ -76,7 +77,6 @@ protected:
|
|||||||
DepthFilter* depth_filter_; //!< Depth estimation algorithm runs in a parallel thread and is used to initialize new 3D points.
|
DepthFilter* depth_filter_; //!< Depth estimation algorithm runs in a parallel thread and is used to initialize new 3D points.
|
||||||
opencl* gpu_fast_;
|
opencl* gpu_fast_;
|
||||||
ros::Time time_;
|
ros::Time time_;
|
||||||
UKF ukfPtr_;
|
|
||||||
|
|
||||||
/// Initialize the visual odometry algorithm.
|
/// Initialize the visual odometry algorithm.
|
||||||
virtual void initialize();
|
virtual void initialize();
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ namespace svo
|
|||||||
const double PI = 3.14159265;
|
const double PI = 3.14159265;
|
||||||
class SE2_5: public SE2{
|
class SE2_5: public SE2{
|
||||||
public:
|
public:
|
||||||
SE2 T2_;
|
|
||||||
SE2_5(SE2&& se2):T2_(se2){
|
SE2_5(SE2&& se2):T2_(se2){
|
||||||
}
|
}
|
||||||
SE2_5(SE2& se2):T2_(se2){
|
SE2_5(SE2& se2):T2_(se2){
|
||||||
@@ -87,17 +86,31 @@ namespace svo
|
|||||||
-sin(pitch),cos(pitch);
|
-sin(pitch),cos(pitch);
|
||||||
T2_=SE2(R,Vector2d(x,z));
|
T2_=SE2(R,Vector2d(x,z));
|
||||||
};
|
};
|
||||||
SE2 getSE2() const{
|
SE2 se2() const{
|
||||||
return T2_;
|
return T2_;
|
||||||
}
|
}
|
||||||
SE2 inverse() const{
|
SE2 inverse() const{
|
||||||
double yaw=atan(T2_.rotation_matrix()(0,1)/T2_.rotation_matrix()(0,0));
|
double yaw=atan(T2_.rotation_matrix()(0,1)/T2_.rotation_matrix()(0,0));
|
||||||
return SE2(yaw+PI,T2_.translation());
|
if(yaw<0.0)
|
||||||
|
yaw=M_PI-yaw;
|
||||||
|
else
|
||||||
|
yaw=yaw-M_PI;
|
||||||
|
return SE2(yaw,-1.0*T2_.translation());
|
||||||
}
|
}
|
||||||
double pitch()const{
|
double pitch()const{
|
||||||
return atan(T2_.rotation_matrix()(0,1)/T2_.rotation_matrix()(0,0));
|
return atan(T2_.rotation_matrix()(0,1)/T2_.rotation_matrix()(0,0));
|
||||||
}
|
}
|
||||||
|
SE3 se3() const{
|
||||||
|
Eigen::Matrix<double,3,3> R;
|
||||||
|
R<<T2_.rotation_matrix()(0,0),0.0,T2_.rotation_matrix()(0,1),
|
||||||
|
0.0,1.0,0.0,
|
||||||
|
T2_.rotation_matrix()(1,0),0.0,T2_.rotation_matrix()(1,1);
|
||||||
|
return SE3(R,Vector3d(T2_.translation()(0),1e-19,T2_.translation()(1)));
|
||||||
|
}
|
||||||
~SE2_5(){}
|
~SE2_5(){}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SE2 T2_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Frame;
|
class Frame;
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ int getBestSearchLevel(
|
|||||||
const Matrix2d& A_cur_ref,
|
const Matrix2d& A_cur_ref,
|
||||||
const int max_level);
|
const int max_level);
|
||||||
|
|
||||||
void warpAffine(
|
bool warpAffine(
|
||||||
const Matrix2d& A_cur_ref,
|
const Matrix2d& A_cur_ref,
|
||||||
const cv::Mat& img_ref,
|
const cv::Mat& img_ref,
|
||||||
const Vector2d& px_ref,
|
const Vector2d& px_ref,
|
||||||
|
|||||||
@@ -56,8 +56,6 @@ public:
|
|||||||
E(2)=state_(2)+dt*dpitch-state_h_(2);
|
E(2)=state_(2)+dt*dpitch-state_h_(2);
|
||||||
k=cov_h_*H.transpose()*(H*cov_h_*H.transpose()+Q).inverse();
|
k=cov_h_*H.transpose()*(H*cov_h_*H.transpose()+Q).inverse();
|
||||||
state_=state_h_+k*E;
|
state_=state_h_+k*E;
|
||||||
if(fabs(state_(2)-yaw_t_1_)>M_PI_4)state_(2)-=M_PI;
|
|
||||||
if(fabs(state_(2))>2*M_PI)state_(2)-=2.0*int(0.5*state_(2)/M_PI)*M_PI;
|
|
||||||
cov_=(Eigen::MatrixXd::Identity(3,3)-k*H)*cov_h_;
|
cov_=(Eigen::MatrixXd::Identity(3,3)-k*H)*cov_h_;
|
||||||
state_h_(2)=state_(2)+dt*dpitch;
|
state_h_(2)=state_(2)+dt*dpitch;
|
||||||
state_h_(1)=state_(1)+0.5*pow(dt,2)*(ddz*cos(state_(2))-ddx*sin(state_(2)));
|
state_h_(1)=state_(1)+0.5*pow(dt,2)*(ddz*cos(state_(2))-ddx*sin(state_(2)));
|
||||||
@@ -90,8 +88,6 @@ public:
|
|||||||
E<<x-state_h_(0),z-state_h_(1),pitch-state_h_(2);
|
E<<x-state_h_(0),z-state_h_(1),pitch-state_h_(2);
|
||||||
k=cov_h_*H.transpose()*(H*cov_h_*H.transpose()+Q).inverse();
|
k=cov_h_*H.transpose()*(H*cov_h_*H.transpose()+Q).inverse();
|
||||||
state_=state_h_+(k*E);
|
state_=state_h_+(k*E);
|
||||||
if(fabs(state_(2)-yaw_t_1_)>M_PI_4)state_(2)-=M_PI;
|
|
||||||
if(fabs(state_(2))>2*M_PI)state_(2)-=2.0*int(0.5*state_(2)/M_PI)*M_PI;
|
|
||||||
cov_=(Eigen::MatrixXd::Identity(3,3)-k*H)*cov_h_;
|
cov_=(Eigen::MatrixXd::Identity(3,3)-k*H)*cov_h_;
|
||||||
yaw_t_1_=state_(2);
|
yaw_t_1_=state_(2);
|
||||||
predict_up=false;
|
predict_up=false;
|
||||||
@@ -131,10 +127,27 @@ public:
|
|||||||
std::pair<Eigen::Matrix<double,3,3>,svo::SE2_5> UpdateSvo(double x,double z,double pitch,size_t match,ros::Time& time) {
|
std::pair<Eigen::Matrix<double,3,3>,svo::SE2_5> UpdateSvo(double x,double z,double pitch,size_t match,ros::Time& time) {
|
||||||
while(lock)usleep(5);
|
while(lock)usleep(5);
|
||||||
lock=true;
|
lock=true;
|
||||||
if(filter_->predict_up)filter_->correct(x,z,pitch,match,1e-9*time.toNSec());
|
if(pitch<0.0)
|
||||||
|
pitch=M_PI-pitch;
|
||||||
|
else
|
||||||
|
pitch=pitch-M_PI;
|
||||||
|
if(filter_->predict_up)filter_->correct(-x,-z,pitch,match,1e-9*time.toNSec());
|
||||||
lock=false;
|
lock=false;
|
||||||
return std::pair<Eigen::Matrix<double,3,3>,svo::SE2_5>(filter_->cov_,svo::SE2_5(filter_->state_(0),filter_->state_(1),filter_->state_(2)));
|
double pitch_f;
|
||||||
|
if(filter_->state_(0)<0.0)
|
||||||
|
pitch_f=M_PI-filter_->state_(2);
|
||||||
|
else
|
||||||
|
pitch_f=filter_->state_(2)-M_PI;
|
||||||
|
return std::pair<Eigen::Matrix<double,3,3>,svo::SE2_5>(filter_->cov_,svo::SE2_5(-filter_->state_(0),-filter_->state_(1),pitch_f));
|
||||||
};
|
};
|
||||||
|
std::pair<Eigen::Matrix<double,3,3>,svo::SE2_5> get_location(){
|
||||||
|
double pitch_f;
|
||||||
|
if(filter_->state_(0)<0.0)
|
||||||
|
pitch_f=M_PI-filter_->state_(2);
|
||||||
|
else
|
||||||
|
pitch_f=filter_->state_(2)-M_PI;
|
||||||
|
return std::pair<Eigen::Matrix<double,3,3>,svo::SE2_5>(filter_->cov_,svo::SE2_5(-filter_->state_(0),-filter_->state_(1),pitch_f));
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
Base* filter_= nullptr;
|
Base* filter_= nullptr;
|
||||||
bool lock=false;
|
bool lock=false;
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ interpolateMat_32f(const cv::Mat& mat, float u, float v)
|
|||||||
inline float
|
inline float
|
||||||
interpolateMat_8u(const cv::Mat& mat, float u, float v)
|
interpolateMat_8u(const cv::Mat& mat, float u, float v)
|
||||||
{
|
{
|
||||||
assert(mat.type()==CV_8U);
|
if(mat.empty())return 0.0;
|
||||||
|
if(mat.type()!=CV_8U)return 0.0;
|
||||||
int x = floor(u);
|
int x = floor(u);
|
||||||
int y = floor(v);
|
int y = floor(v);
|
||||||
float subpix_x = u-x;
|
float subpix_x = u-x;
|
||||||
@@ -55,6 +56,8 @@ interpolateMat_8u(const cv::Mat& mat, float u, float v)
|
|||||||
|
|
||||||
const int stride = mat.step.p[0];
|
const int stride = mat.step.p[0];
|
||||||
unsigned char* ptr = mat.data + y*stride + x;
|
unsigned char* ptr = mat.data + y*stride + x;
|
||||||
|
if(isnan(w00) || isnan(w01 )||isnan( w10) || isnan(w11) || isinf(w00) || isinf(w01)|| isinf(w10)|| isinf(w11))return 0.0;
|
||||||
|
if(ptr[0] == NULL || ptr[1]== NULL || ptr[stride]==NULL ||ptr[stride+1]==NULL)return 0.0;
|
||||||
return w00*ptr[0] + w01*ptr[stride] + w10*ptr[1] + w11*ptr[stride+1];
|
return w00*ptr[0] + w01*ptr[stride] + w10*ptr[1] + w11*ptr[stride+1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <image_transport/image_transport.h>
|
#include <image_transport/image_transport.h>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <gpu_svo/ukf.h>
|
||||||
|
|
||||||
namespace svo {
|
namespace svo {
|
||||||
|
|
||||||
@@ -54,18 +55,9 @@ public:
|
|||||||
~Visualizer() {};
|
~Visualizer() {};
|
||||||
|
|
||||||
void publishMinimal(
|
void publishMinimal(
|
||||||
const cv::Mat& img,
|
UKF& ukf,
|
||||||
const FramePtr& frame,
|
|
||||||
const FrameHandlerMono& slam,
|
|
||||||
const double timestamp);
|
const double timestamp);
|
||||||
|
|
||||||
void visualizeMarkers(
|
|
||||||
const FramePtr& frame,
|
|
||||||
const set<FramePtr>& core_kfs,
|
|
||||||
const Map& map);
|
|
||||||
|
|
||||||
void removeDeletedPts(const Map& map);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace svo
|
} // end namespace svo
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ svo:
|
|||||||
init_min_tracked: 100
|
init_min_tracked: 100
|
||||||
init_min_disparity: 30
|
init_min_disparity: 30
|
||||||
structureoptim_max_pts: 50
|
structureoptim_max_pts: 50
|
||||||
kfselect_mindist: 0.001
|
kfselect_mindist: 0.01
|
||||||
poseoptim_thresh: 4.0
|
poseoptim_thresh: 4.0
|
||||||
ACC_noise: 0.001 #acc white noise in continuous in EKF
|
ACC_noise: 0.5 #acc white noise in continuous in EKF
|
||||||
GYO_noise: 0.001 #gyro white noise in continuous in EKF
|
GYO_noise: 0.001 #gyro white noise in continuous in EKF
|
||||||
svo_ekf: 100 #Svo noise that will be devided by number of Reprojected points after opmization in EKF
|
svo_ekf: 1.5 #Svo noise that will be devided by number of Reprojected points after opmization in EKF
|
||||||
Cmd_Cov: 0.001 #control vector noise in EKF
|
Cmd_Cov: 1.0 #control vector noise in EKF
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ void DepthFilter::updateSeeds(FramePtr frame)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// check if point is visible in the current image
|
// check if point is visible in the current image
|
||||||
SE2 T(it->ftr->frame->T_f_w_.getSE2() * frame->T_f_w_.inverse());
|
SE2 T(it->ftr->frame->T_f_w_.se2() * frame->T_f_w_.inverse());
|
||||||
Eigen::Matrix<double,3,3> R;
|
Eigen::Matrix<double,3,3> R;
|
||||||
R<<T.rotation_matrix()(0,0),0.0,T.rotation_matrix()(0,1),
|
R<<T.rotation_matrix()(0,0),0.0,T.rotation_matrix()(0,1),
|
||||||
0.0,1.0,0.0,
|
0.0,1.0,0.0,
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ bool align1D(
|
|||||||
int u_r = floor(u);
|
int u_r = floor(u);
|
||||||
int v_r = floor(v);
|
int v_r = floor(v);
|
||||||
if(u_r < halfpatch_size_ || v_r < halfpatch_size_ || u_r >= cur_img.cols-halfpatch_size_ || v_r >= cur_img.rows-halfpatch_size_){
|
if(u_r < halfpatch_size_ || v_r < halfpatch_size_ || u_r >= cur_img.cols-halfpatch_size_ || v_r >= cur_img.rows-halfpatch_size_){
|
||||||
std::cout<<"not in bach size\n";
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ void FrameHandlerMono::addImage(const cv::Mat& img, const double timestamp,const
|
|||||||
map_.getClosestKeyframe(last_frame_));
|
map_.getClosestKeyframe(last_frame_));
|
||||||
|
|
||||||
// set last frame
|
// set last frame
|
||||||
last_frame_ = new_frame_;
|
if(!new_frame_->fts_.empty() || stage_ != STAGE_DEFAULT_FRAME)last_frame_ = new_frame_;
|
||||||
new_frame_.reset();
|
new_frame_.reset();
|
||||||
// finish processing
|
// finish processing
|
||||||
finishFrameProcessingCommon(last_frame_->id_, res, last_frame_->nObs());
|
finishFrameProcessingCommon(last_frame_->id_, res, last_frame_->nObs());
|
||||||
@@ -103,16 +103,18 @@ FrameHandlerMono::UpdateResult FrameHandlerMono::processFirstFrame()
|
|||||||
new_frame_->setKeyframe();
|
new_frame_->setKeyframe();
|
||||||
map_.addKeyframe(new_frame_);
|
map_.addKeyframe(new_frame_);
|
||||||
stage_ = STAGE_SECOND_FRAME;
|
stage_ = STAGE_SECOND_FRAME;
|
||||||
ukfPtr_.UpdateSvo(new_frame_->T_f_w_.getSE2().translation()(0),new_frame_->T_f_w_.getSE2().translation()(1),new_frame_->T_f_w_.pitch(),1000,time_);
|
ukfPtr_.UpdateSvo(new_frame_->T_f_w_.se2().translation()(0),new_frame_->T_f_w_.se2().translation()(1),new_frame_->T_f_w_.pitch(),1000,time_);
|
||||||
SVO_INFO_STREAM("Init: Selected first frame.");
|
SVO_INFO_STREAM("Init: Selected first frame.");
|
||||||
return RESULT_IS_KEYFRAME;
|
return RESULT_IS_KEYFRAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameHandlerBase::UpdateResult FrameHandlerMono::processSecondFrame()
|
FrameHandlerBase::UpdateResult FrameHandlerMono::processSecondFrame()
|
||||||
{
|
{
|
||||||
new_frame_->T_f_w_ = last_frame_->T_f_w_;
|
auto init_f= ukfPtr_.get_location();
|
||||||
|
new_frame_->T_f_w_=init_f.second;
|
||||||
|
new_frame_->Cov_ = init_f.first;
|
||||||
initialization::InitResult res = klt_homography_init_->addSecondFrame(new_frame_);
|
initialization::InitResult res = klt_homography_init_->addSecondFrame(new_frame_);
|
||||||
auto result=ukfPtr_.UpdateSvo(new_frame_->T_f_w_.getSE2().translation()(0),new_frame_->T_f_w_.getSE2().translation()(1),new_frame_->T_f_w_.pitch(),1000,time_);
|
auto result=ukfPtr_.UpdateSvo(new_frame_->T_f_w_.se2().translation()(0),new_frame_->T_f_w_.se2().translation()(1),new_frame_->T_f_w_.pitch(),1000,time_);
|
||||||
new_frame_->T_f_w_ = result.second;
|
new_frame_->T_f_w_ = result.second;
|
||||||
new_frame_->Cov_ = result.first;
|
new_frame_->Cov_ = result.first;
|
||||||
if(res == initialization::NO_KEYFRAME)
|
if(res == initialization::NO_KEYFRAME)
|
||||||
@@ -133,28 +135,31 @@ FrameHandlerBase::UpdateResult FrameHandlerMono::processSecondFrame()
|
|||||||
|
|
||||||
FrameHandlerBase::UpdateResult FrameHandlerMono::processFrame()
|
FrameHandlerBase::UpdateResult FrameHandlerMono::processFrame()
|
||||||
{
|
{
|
||||||
new_frame_->T_f_w_ = last_frame_->T_f_w_;
|
auto init_f= ukfPtr_.get_location();
|
||||||
|
new_frame_->T_f_w_=init_f.second;
|
||||||
|
new_frame_->Cov_ = init_f.first;
|
||||||
// sparse image align
|
// sparse image align
|
||||||
SparseImgAlign img_align(Config::kltMaxLevel(), Config::kltMinLevel(),
|
SparseImgAlign img_align(Config::kltMaxLevel(), Config::kltMinLevel(),
|
||||||
30, SparseImgAlign::LevenbergMarquardt, false, false);
|
30, SparseImgAlign::LevenbergMarquardt, false, false);
|
||||||
img_align.run(last_frame_, new_frame_);
|
if(img_align.run(last_frame_, new_frame_)==0)return RESULT_FAILURE;
|
||||||
reprojector_.reprojectMap(new_frame_, overlap_kfs_);
|
reprojector_.reprojectMap(new_frame_, overlap_kfs_);
|
||||||
size_t sfba_n_edges_final=0;
|
size_t sfba_n_edges_final=0;
|
||||||
double sfba_thresh, sfba_error_init, sfba_error_final;
|
double sfba_thresh, sfba_error_init, sfba_error_final;
|
||||||
pose_optimizer::optimizeGaussNewton(
|
pose_optimizer::optimizeGaussNewton(
|
||||||
Config::poseOptimThresh(), Config::poseOptimNumIter(), false,
|
Config::poseOptimThresh(), Config::poseOptimNumIter(), false,
|
||||||
new_frame_, sfba_thresh, sfba_error_init, sfba_error_final, sfba_n_edges_final);
|
new_frame_, sfba_thresh, sfba_error_init, sfba_error_final, sfba_n_edges_final);
|
||||||
if((last_frame_->T_f_w_.getSE2().translation()-new_frame_->T_f_w_.getSE2().translation()).norm()>0.1){
|
if((last_frame_->T_f_w_.se2().translation()-new_frame_->T_f_w_.se2().translation()).norm()>2.0 || fabs(last_frame_->T_f_w_.pitch()-new_frame_->T_f_w_.pitch())>M_PI){
|
||||||
new_frame_->T_f_w_ = last_frame_->T_f_w_;
|
new_frame_=last_frame_;
|
||||||
|
return RESULT_NO_KEYFRAME;
|
||||||
}
|
}
|
||||||
auto result=ukfPtr_.UpdateSvo(new_frame_->T_f_w_.getSE2().translation()(0),
|
auto result=ukfPtr_.UpdateSvo(new_frame_->T_f_w_.se2().translation()(0),
|
||||||
new_frame_->T_f_w_.getSE2().translation()(1),new_frame_->T_f_w_.pitch(),sfba_n_edges_final,time_);
|
new_frame_->T_f_w_.se2().translation()(1),new_frame_->T_f_w_.pitch(),sfba_n_edges_final,time_);
|
||||||
new_frame_->T_f_w_ =result.second;
|
new_frame_->T_f_w_ =result.second;
|
||||||
new_frame_->Cov_ = result.first;
|
new_frame_->Cov_ = result.first;
|
||||||
std::cout<<"Reprojection Map nPoint: "<<overlap_kfs_.back().second
|
std::cout<<"Reprojection Map nPoint: "<<overlap_kfs_.back().second
|
||||||
<<"\tnCell: "<<reprojector_.n_trials_<<"\t nMatches: "<<reprojector_.n_matches_
|
<<"\tnCell: "<<reprojector_.n_trials_<<"\t nMatches: "<<reprojector_.n_matches_
|
||||||
<<"\tReprojected points after opmization: "<<sfba_n_edges_final<<"\t distance between two frames: "<<
|
<<"\tReprojected points after opmization: "<<sfba_n_edges_final<<"\t distance between two frames: "<<
|
||||||
(last_frame_->T_f_w_.getSE2().translation()-new_frame_->T_f_w_.getSE2().translation()).norm()<<'\n';
|
(last_frame_->T_f_w_.se2().translation()-new_frame_->T_f_w_.se2().translation()).norm()<<'\n';
|
||||||
if(sfba_n_edges_final < Config::qualityMinFts() || reprojector_.n_matches_ < Config::qualityMinFts()){
|
if(sfba_n_edges_final < Config::qualityMinFts() || reprojector_.n_matches_ < Config::qualityMinFts()){
|
||||||
return RESULT_NO_KEYFRAME;
|
return RESULT_NO_KEYFRAME;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,9 +69,9 @@ InitResult KltHomographyInit::addSecondFrame(FramePtr frame_cur)
|
|||||||
depth_vec.push_back((xyz_in_cur_[i]).z());
|
depth_vec.push_back((xyz_in_cur_[i]).z());
|
||||||
double scene_depth_median = vk::getMedian(depth_vec);
|
double scene_depth_median = vk::getMedian(depth_vec);
|
||||||
double scale = Config::mapScale()/scene_depth_median;
|
double scale = Config::mapScale()/scene_depth_median;
|
||||||
frame_cur->T_f_w_ = SE2_5(T_cur_from_ref_.getSE2() * frame_ref_->T_f_w_.getSE2());
|
frame_cur->T_f_w_ = SE2_5(T_cur_from_ref_.se2() * frame_ref_->T_f_w_.se2());
|
||||||
frame_cur->T_f_w_.T2_.translation() = -frame_cur->T_f_w_.getSE2().rotation_matrix()*(frame_ref_->pos() + scale*(frame_cur->pos() - frame_ref_->pos()));
|
frame_cur->T_f_w_ = SE2_5(SE2(frame_cur->T_f_w_.se2().rotation_matrix(),
|
||||||
//frame_cur->T_f_w_.T2_.translation() = frame_cur->T_f_w_.getSE2().rotation_matrix()*(frame_ref_->pos() + scale*(frame_cur->pos() - frame_ref_->pos()));
|
-frame_cur->T_f_w_.se2().rotation_matrix()*(frame_ref_->pos() + scale*(frame_cur->pos() - frame_ref_->pos()))));
|
||||||
// For each inlier create 3D point and add feature in both frames
|
// For each inlier create 3D point and add feature in both frames
|
||||||
SE3 T_world_cur = frame_cur->getSE3Inv();
|
SE3 T_world_cur = frame_cur->getSE3Inv();
|
||||||
for(vector<int>::iterator it=inliers_.begin(); it!=inliers_.end(); ++it)
|
for(vector<int>::iterator it=inliers_.begin(); it!=inliers_.end(); ++it)
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ void Map::getCloseKeyframes(
|
|||||||
{
|
{
|
||||||
close_kfs.push_back(
|
close_kfs.push_back(
|
||||||
std::make_pair(
|
std::make_pair(
|
||||||
kf, (frame->T_f_w_.getSE2().translation()-kf->T_f_w_.getSE2().translation()).norm()));
|
kf, (frame->T_f_w_.se2().translation()-kf->T_f_w_.se2().translation()).norm()));
|
||||||
break; // this keyframe has an overlapping field of view -> add to close_kfs
|
break; // this keyframe has an overlapping field of view -> add to close_kfs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ int getBestSearchLevel(
|
|||||||
return search_level;
|
return search_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
void warpAffine(
|
bool warpAffine(
|
||||||
const Matrix2d& A_cur_ref,
|
const Matrix2d& A_cur_ref,
|
||||||
const cv::Mat& img_ref,
|
const cv::Mat& img_ref,
|
||||||
const Vector2d& px_ref,
|
const Vector2d& px_ref,
|
||||||
@@ -78,14 +78,14 @@ void warpAffine(
|
|||||||
const int halfpatch_size,
|
const int halfpatch_size,
|
||||||
uint8_t* patch)
|
uint8_t* patch)
|
||||||
{
|
{
|
||||||
|
if(patch==NULL || img_ref.empty())return false;
|
||||||
const int patch_size = halfpatch_size*2 ;
|
const int patch_size = halfpatch_size*2 ;
|
||||||
const Matrix2f A_ref_cur = A_cur_ref.inverse().cast<float>();
|
const Matrix2f A_ref_cur = A_cur_ref.inverse().cast<float>();
|
||||||
if(isnan(A_ref_cur(0,0)))
|
if(isnan(A_ref_cur(0,0)))
|
||||||
{
|
{
|
||||||
printf("Affine warp is NaN, probably camera has no translation\n"); // TODO
|
printf("Affine warp is NaN, probably camera has no translation\n"); // TODO
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform the warp on a larger patch.
|
// Perform the warp on a larger patch.
|
||||||
uint8_t* patch_ptr = patch;
|
uint8_t* patch_ptr = patch;
|
||||||
const Vector2f px_ref_pyr = px_ref.cast<float>() / (1<<level_ref);
|
const Vector2f px_ref_pyr = px_ref.cast<float>() / (1<<level_ref);
|
||||||
@@ -96,13 +96,16 @@ void warpAffine(
|
|||||||
Vector2f px_patch(x-halfpatch_size, y-halfpatch_size);
|
Vector2f px_patch(x-halfpatch_size, y-halfpatch_size);
|
||||||
px_patch *= (1<<search_level);
|
px_patch *= (1<<search_level);
|
||||||
const Vector2f px(A_ref_cur*px_patch + px_ref_pyr);
|
const Vector2f px(A_ref_cur*px_patch + px_ref_pyr);
|
||||||
if (px[0]<0 || px[1]<0 || px[0]>=img_ref.cols-1 || px[1]>=img_ref.rows-1)
|
if(patch_ptr == nullptr)continue;
|
||||||
|
if (px[0]<1 || px[1]<1 || px[0]>=img_ref.cols-1 || px[1]>=img_ref.rows-1){
|
||||||
*patch_ptr = 0;
|
*patch_ptr = 0;
|
||||||
else
|
}else{
|
||||||
*patch_ptr = (uint8_t) vk::interpolateMat_8u(img_ref, px[0], px[1]);
|
*patch_ptr = (uint8_t) vk::interpolateMat_8u(img_ref, px[0], px[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace warp
|
} // namespace warp
|
||||||
|
|
||||||
@@ -117,7 +120,7 @@ bool depthFromTriangulation(
|
|||||||
if(AtA.determinant() < 0.000001)
|
if(AtA.determinant() < 0.000001)
|
||||||
return false;
|
return false;
|
||||||
const Vector2d depth2 = - AtA.inverse()*A.transpose()*T_search_ref.translation();
|
const Vector2d depth2 = - AtA.inverse()*A.transpose()*T_search_ref.translation();
|
||||||
depth = fabs(depth2[0]);
|
depth = fabs(depth2[0]/depth2[1]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,35 +145,36 @@ bool Matcher::findMatchDirect(
|
|||||||
if(!ref_ftr_->frame->cam_->isInFrame(
|
if(!ref_ftr_->frame->cam_->isInFrame(
|
||||||
ref_ftr_->px.cast<int>()/(1<<ref_ftr_->level), halfpatch_size_+2, ref_ftr_->level))
|
ref_ftr_->px.cast<int>()/(1<<ref_ftr_->level), halfpatch_size_+2, ref_ftr_->level))
|
||||||
return false;
|
return false;
|
||||||
|
if(ref_ftr_->frame->img_pyr_.empty())return false;
|
||||||
|
if(ref_ftr_->frame->img_pyr_[ref_ftr_->level].empty())return false;
|
||||||
// warp affine
|
// warp affine
|
||||||
warp::getWarpMatrixAffine(
|
warp::getWarpMatrixAffine(
|
||||||
*ref_ftr_->frame->cam_, *cur_frame.cam_, ref_ftr_->px, ref_ftr_->f,
|
*ref_ftr_->frame->cam_, *cur_frame.cam_, ref_ftr_->px, ref_ftr_->f,
|
||||||
(Vector3d(ref_ftr_->frame->pos()(0),0.0,ref_ftr_->frame->pos()(1)) - pt.pos_).norm(),
|
(Vector3d(ref_ftr_->frame->pos()(0),0.0,ref_ftr_->frame->pos()(1)) - pt.pos_).norm(),
|
||||||
cur_frame.se3() * ref_ftr_->frame->getSE3Inv(), ref_ftr_->level, A_cur_ref_);
|
cur_frame.se3() * ref_ftr_->frame->getSE3Inv(), ref_ftr_->level, A_cur_ref_);
|
||||||
search_level_ = warp::getBestSearchLevel(A_cur_ref_, Config::nPyrLevels()-1);
|
search_level_ = warp::getBestSearchLevel(A_cur_ref_, Config::nPyrLevels()-1);
|
||||||
warp::warpAffine(A_cur_ref_, ref_ftr_->frame->img_pyr_[ref_ftr_->level], ref_ftr_->px,
|
if(!warp::warpAffine(A_cur_ref_, ref_ftr_->frame->img_pyr_[ref_ftr_->level], ref_ftr_->px,
|
||||||
ref_ftr_->level, search_level_, halfpatch_size_+1, patch_with_border_);
|
ref_ftr_->level, search_level_, halfpatch_size_+1, patch_with_border_))return false;
|
||||||
createPatchFromPatchWithBorder();
|
createPatchFromPatchWithBorder();
|
||||||
|
|
||||||
// px_cur should be set
|
// px_cur should be set
|
||||||
Vector2d px_scaled(px_cur/(1<<search_level_));
|
Vector2d px_scaled(px_cur/(1<<search_level_));
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if(ref_ftr_->type == Feature::EDGELET)
|
// if(ref_ftr_->type == Feature::EDGELET)
|
||||||
{
|
//{
|
||||||
Vector2d dir_cur(A_cur_ref_*ref_ftr_->grad);
|
// Vector2d dir_cur(A_cur_ref_*ref_ftr_->grad);
|
||||||
dir_cur.normalize();
|
// dir_cur.normalize();
|
||||||
success = feature_alignment::align1D(
|
// success = feature_alignment::align1D(
|
||||||
cur_frame.img_pyr_[search_level_], dir_cur.cast<float>(),
|
// cur_frame.img_pyr_[search_level_], dir_cur.cast<float>(),
|
||||||
patch_with_border_, patch_, options_.align_max_iter, px_scaled, h_inv_);
|
// patch_with_border_, patch_, options_.align_max_iter, px_scaled, h_inv_);
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
success = feature_alignment::align2D(
|
success = feature_alignment::align2D(
|
||||||
cur_frame.img_pyr_[search_level_], patch_with_border_, patch_,
|
cur_frame.img_pyr_[search_level_], patch_with_border_, patch_,
|
||||||
options_.align_max_iter, px_scaled);
|
options_.align_max_iter, px_scaled);
|
||||||
}
|
// }
|
||||||
px_cur = px_scaled * (1<<search_level_);
|
px_cur = px_scaled * (1<<search_level_);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
@@ -185,24 +189,19 @@ bool Matcher::findEpipolarMatchDirect(
|
|||||||
double& depth)
|
double& depth)
|
||||||
{
|
{
|
||||||
if(isnan(d_min) || isnan(d_max))return false;
|
if(isnan(d_min) || isnan(d_max))return false;
|
||||||
SE2 T(cur_frame.T_f_w_.getSE2() * ref_frame.T_f_w_.inverse());
|
SE2_5 T_cur_ref(cur_frame.T_f_w_.se2() * ref_frame.T_f_w_.inverse());
|
||||||
Eigen::Matrix<double,3,3> R;
|
|
||||||
R<<T.rotation_matrix()(0,0),0.0,T.rotation_matrix()(0,1),
|
|
||||||
0.0,1.0,0.0,
|
|
||||||
T.rotation_matrix()(1,0),0.0,T.rotation_matrix()(1,1);
|
|
||||||
SE3 T_cur_ref(R,Vector3d(T.translation()(0),0.0,T.translation()(1)));
|
|
||||||
int zmssd_best = PatchScore::threshold();
|
int zmssd_best = PatchScore::threshold();
|
||||||
Vector2d uv_best;
|
Vector2d uv_best;
|
||||||
|
|
||||||
// Compute start and end of epipolar line in old_kf for match search, on unit plane!
|
// Compute start and end of epipolar line in old_kf for match search, on unit plane!
|
||||||
Vector2d A = vk::project2d(T_cur_ref * (ref_ftr.f*d_min));
|
Vector2d A = vk::project2d(T_cur_ref.se3() * (ref_ftr.f*d_min));
|
||||||
Vector2d B = vk::project2d(T_cur_ref * (ref_ftr.f*d_max));
|
Vector2d B = vk::project2d(T_cur_ref.se3() * (ref_ftr.f*d_max));
|
||||||
epi_dir_ = A - B;
|
epi_dir_ = A - B;
|
||||||
|
|
||||||
// Compute affine warp matrix
|
// Compute affine warp matrix
|
||||||
warp::getWarpMatrixAffine(
|
warp::getWarpMatrixAffine(
|
||||||
*ref_frame.cam_, *cur_frame.cam_, ref_ftr.px, ref_ftr.f,
|
*ref_frame.cam_, *cur_frame.cam_, ref_ftr.px, ref_ftr.f,
|
||||||
d_estimate, T_cur_ref, ref_ftr.level, A_cur_ref_);
|
d_estimate, T_cur_ref.se3(), ref_ftr.level, A_cur_ref_);
|
||||||
|
|
||||||
// feature pre-selection
|
// feature pre-selection
|
||||||
reject_ = false;
|
reject_ = false;
|
||||||
@@ -225,13 +224,12 @@ bool Matcher::findEpipolarMatchDirect(
|
|||||||
|
|
||||||
|
|
||||||
// Warp reference patch at ref_level
|
// Warp reference patch at ref_level
|
||||||
warp::warpAffine(A_cur_ref_, ref_frame.img_pyr_[ref_ftr.level], ref_ftr.px,
|
if(!warp::warpAffine(A_cur_ref_, ref_frame.img_pyr_[ref_ftr.level], ref_ftr.px,
|
||||||
ref_ftr.level, search_level_, halfpatch_size_+1, patch_with_border_);
|
ref_ftr.level, search_level_, halfpatch_size_+1, patch_with_border_))return false;
|
||||||
createPatchFromPatchWithBorder();
|
createPatchFromPatchWithBorder();
|
||||||
|
if(epi_length_ < 5.0)
|
||||||
if(epi_length_ < 2.0)
|
|
||||||
{
|
{
|
||||||
px_cur_ = (px_A+px_B)/2.0;
|
px_cur_ = (px_A+px_B)/5.0;
|
||||||
Vector2d px_scaled(px_cur_/(1<<search_level_));
|
Vector2d px_scaled(px_cur_/(1<<search_level_));
|
||||||
bool res;
|
bool res;
|
||||||
if(options_.align_1d)
|
if(options_.align_1d)
|
||||||
@@ -245,7 +243,7 @@ bool Matcher::findEpipolarMatchDirect(
|
|||||||
if(res)
|
if(res)
|
||||||
{
|
{
|
||||||
px_cur_ = px_scaled*(1<<search_level_);
|
px_cur_ = px_scaled*(1<<search_level_);
|
||||||
if(depthFromTriangulation(T_cur_ref, ref_ftr.f, cur_frame.cam_->cam2world(px_cur_), depth))
|
if(depthFromTriangulation(T_cur_ref.se3(), ref_ftr.f, cur_frame.cam_->cam2world(px_cur_), depth))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -314,13 +312,13 @@ bool Matcher::findEpipolarMatchDirect(
|
|||||||
if(res)
|
if(res)
|
||||||
{
|
{
|
||||||
px_cur_ = px_scaled*(1<<search_level_);
|
px_cur_ = px_scaled*(1<<search_level_);
|
||||||
if(depthFromTriangulation(T_cur_ref, ref_ftr.f, cur_frame.cam_->cam2world(px_cur_), depth))
|
if(depthFromTriangulation(T_cur_ref.se3(), ref_ftr.f, cur_frame.cam_->cam2world(px_cur_), depth))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
px_cur_ = cur_frame.cam_->world2cam(uv_best);
|
px_cur_ = cur_frame.cam_->world2cam(uv_best);
|
||||||
if(depthFromTriangulation(T_cur_ref, ref_ftr.f, vk::unproject2d(uv_best).normalized(), depth))
|
if(depthFromTriangulation(T_cur_ref.se3(), ref_ftr.f, vk::unproject2d(uv_best).normalized(), depth))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -99,21 +99,19 @@ bool Point::getCloseViewObs(const Vector2d& framepos, Feature*& ftr) const
|
|||||||
{
|
{
|
||||||
// TODO: get frame with same point of view AND same pyramid level!
|
// TODO: get frame with same point of view AND same pyramid level!
|
||||||
Vector3d obs_dir(Vector3d(framepos(0),0.0,framepos(1)) - pos_); obs_dir.normalize();
|
Vector3d obs_dir(Vector3d(framepos(0),0.0,framepos(1)) - pos_); obs_dir.normalize();
|
||||||
auto min_it=obs_.begin();
|
auto max_it=obs_.begin();
|
||||||
double min_cos_angle = 0;
|
double max_cos_angle = 1;
|
||||||
for(auto it=obs_.begin(), ite=obs_.end(); it!=ite; ++it)
|
for(auto it=obs_.begin(), ite=obs_.end(); it!=ite; ++it)
|
||||||
{
|
{
|
||||||
Vector3d dir(Vector3d((*it)->frame->pos()(0),0.0,(*it)->frame->pos()(1)) - pos_); dir.normalize();
|
Vector3d dir(Vector3d((*it)->frame->pos()(0),0.0,(*it)->frame->pos()(1)) - pos_); dir.normalize();
|
||||||
double cos_angle = obs_dir.dot(dir);
|
double cos_angle = obs_dir.dot(dir);
|
||||||
if(cos_angle > min_cos_angle)
|
if(cos_angle < max_cos_angle)
|
||||||
{
|
{
|
||||||
min_cos_angle = cos_angle;
|
max_cos_angle = cos_angle;
|
||||||
min_it = it;
|
max_it = it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ftr = *min_it;
|
ftr = *max_it;
|
||||||
if(min_cos_angle < 0.5) // assume that observations larger than 60° are useless
|
|
||||||
return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,9 +121,9 @@ void optimizeGaussNewton(
|
|||||||
// update the model
|
// update the model
|
||||||
T_old = frame->T_f_w_;
|
T_old = frame->T_f_w_;
|
||||||
if(direction){
|
if(direction){
|
||||||
frame->T_f_w_=SE2_5(SE2::exp(dT)*(T_old.getSE2()));
|
frame->T_f_w_=SE2_5(SE2::exp(dT)*(T_old.se2()));
|
||||||
}else{
|
}else{
|
||||||
frame->T_f_w_=SE2_5(SE2::exp(-1.0*dT)*(T_old.getSE2()));
|
frame->T_f_w_=SE2_5(SE2::exp(-1.0*dT)*(T_old.se2()));
|
||||||
}
|
}
|
||||||
chi2 = new_chi2;
|
chi2 = new_chi2;
|
||||||
if(verbose)
|
if(verbose)
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ void Reprojector::reprojectMap(
|
|||||||
list< pair<FramePtr,double> > close_kfs;
|
list< pair<FramePtr,double> > close_kfs;
|
||||||
map_.getCloseKeyframes(frame, close_kfs);
|
map_.getCloseKeyframes(frame, close_kfs);
|
||||||
|
|
||||||
std::cout<<"The number of closed frames: "<<std::to_string(close_kfs.size())<<'\n';
|
|
||||||
// Sort KFs with overlap according to their closeness
|
// Sort KFs with overlap according to their closeness
|
||||||
close_kfs.sort(boost::bind(&std::pair<FramePtr, double>::second, _1) <
|
close_kfs.sort(boost::bind(&std::pair<FramePtr, double>::second, _1) <
|
||||||
boost::bind(&std::pair<FramePtr, double>::second, _2));
|
boost::bind(&std::pair<FramePtr, double>::second, _2));
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ size_t SparseImgAlign::run(FramePtr ref_frame, FramePtr cur_frame)
|
|||||||
|
|
||||||
if(ref_frame->fts_.empty())
|
if(ref_frame->fts_.empty())
|
||||||
{
|
{
|
||||||
SVO_WARN_STREAM("SparseImgAlign: no features to track!");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,8 +53,7 @@ size_t SparseImgAlign::run(FramePtr ref_frame, FramePtr cur_frame)
|
|||||||
cur_frame_ = cur_frame;
|
cur_frame_ = cur_frame;
|
||||||
ref_patch_cache_ = cv::Mat(ref_frame_->fts_.size(), patch_area_, CV_32F);
|
ref_patch_cache_ = cv::Mat(ref_frame_->fts_.size(), patch_area_, CV_32F);
|
||||||
jacobian_cache_.resize(Eigen::NoChange, ref_patch_cache_.rows*patch_area_);
|
jacobian_cache_.resize(Eigen::NoChange, ref_patch_cache_.rows*patch_area_);
|
||||||
//visible_fts_.resize(ref_patch_cache_.rows, false); // TODO: should it be reset at each level?
|
SE2 T_cur_from_ref(cur_frame_->T_f_w_.se2() * ref_frame_->T_f_w_.inverse());
|
||||||
SE2 T_cur_from_ref(cur_frame_->T_f_w_.getSE2() * ref_frame_->T_f_w_.inverse());
|
|
||||||
for(level_=max_level_; level_>=min_level_; --level_)
|
for(level_=max_level_; level_>=min_level_; --level_)
|
||||||
{
|
{
|
||||||
visible_fts_.resize(ref_patch_cache_.rows, false); // TODO: should it be reset at each level?
|
visible_fts_.resize(ref_patch_cache_.rows, false); // TODO: should it be reset at each level?
|
||||||
@@ -66,7 +64,7 @@ size_t SparseImgAlign::run(FramePtr ref_frame, FramePtr cur_frame)
|
|||||||
printf("\nPYRAMID LEVEL %i\n---------------\n", level_);
|
printf("\nPYRAMID LEVEL %i\n---------------\n", level_);
|
||||||
optimize(T_cur_from_ref);
|
optimize(T_cur_from_ref);
|
||||||
}
|
}
|
||||||
cur_frame_->T_f_w_ = SE2_5(T_cur_from_ref * ref_frame_->T_f_w_.getSE2());
|
cur_frame_->T_f_w_ = SE2_5(T_cur_from_ref * ref_frame_->T_f_w_.se2());
|
||||||
|
|
||||||
return n_meas_/patch_area_;
|
return n_meas_/patch_area_;
|
||||||
}
|
}
|
||||||
@@ -251,7 +249,7 @@ void SparseImgAlign::update(
|
|||||||
const ModelType& T_curold_from_ref,
|
const ModelType& T_curold_from_ref,
|
||||||
ModelType& T_curnew_from_ref)
|
ModelType& T_curnew_from_ref)
|
||||||
{
|
{
|
||||||
T_curnew_from_ref = T_curold_from_ref * SE2::exp(-1.0*x_);
|
T_curnew_from_ref = T_curold_from_ref * SE2::exp(-0.25*x_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SparseImgAlign::startIteration()
|
void SparseImgAlign::startIteration()
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <gpu_svo/timer.h>
|
#include <gpu_svo/timer.h>
|
||||||
#include <gpu_svo/output_helper.h>
|
#include <gpu_svo/output_helper.h>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <gpu_svo/ukf.h>
|
||||||
|
|
||||||
namespace svo {
|
namespace svo {
|
||||||
|
|
||||||
@@ -40,9 +41,7 @@ Visualizer() :
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Visualizer::publishMinimal(
|
void Visualizer::publishMinimal(
|
||||||
const cv::Mat& img,
|
UKF& ukf,
|
||||||
const FramePtr& frame,
|
|
||||||
const FrameHandlerMono& slam,
|
|
||||||
const double timestamp)
|
const double timestamp)
|
||||||
{
|
{
|
||||||
++trace_id_;
|
++trace_id_;
|
||||||
@@ -50,63 +49,33 @@ void Visualizer::publishMinimal(
|
|||||||
header_msg.frame_id = "/world";
|
header_msg.frame_id = "/world";
|
||||||
header_msg.seq = trace_id_;
|
header_msg.seq = trace_id_;
|
||||||
header_msg.stamp = ros::Time(timestamp);
|
header_msg.stamp = ros::Time(timestamp);
|
||||||
if(pub_pose_with_cov_.getNumSubscribers() > 0 && slam.stage() == FrameHandlerBase::STAGE_DEFAULT_FRAME)
|
if(pub_pose_with_cov_.getNumSubscribers() > 0)
|
||||||
{
|
{
|
||||||
// publish cam in world frame (Estimated odometry in the worls frame)
|
// publish cam in world frame (Estimated odometry in the worls frame)
|
||||||
Quaterniond q(AngleAxisd(frame->T_f_w_.pitch(), Vector3d::UnitZ()));
|
auto odom=ukf.get_location();
|
||||||
|
Quaterniond q(AngleAxisd(odom.second.pitch()+M_PI_2, Vector3d::UnitZ()));
|
||||||
geometry_msgs::PoseWithCovarianceStampedPtr msg_pose_with_cov(new geometry_msgs::PoseWithCovarianceStamped);
|
geometry_msgs::PoseWithCovarianceStampedPtr msg_pose_with_cov(new geometry_msgs::PoseWithCovarianceStamped);
|
||||||
msg_pose_with_cov->header = header_msg;
|
msg_pose_with_cov->header = header_msg;
|
||||||
msg_pose_with_cov->pose.pose.position.x = frame->se3().translation().x();
|
msg_pose_with_cov->pose.pose.position.x = -odom.second.se2().translation()(0);
|
||||||
msg_pose_with_cov->pose.pose.position.y = frame->se3().translation().z();
|
msg_pose_with_cov->pose.pose.position.y = -odom.second.se2().translation()(1);
|
||||||
msg_pose_with_cov->pose.pose.position.z = 0.0;
|
msg_pose_with_cov->pose.pose.position.z = 0.0;
|
||||||
msg_pose_with_cov->pose.pose.orientation.x = q.x();
|
msg_pose_with_cov->pose.pose.orientation.x = q.x();
|
||||||
msg_pose_with_cov->pose.pose.orientation.y = q.y();
|
msg_pose_with_cov->pose.pose.orientation.y = q.y();
|
||||||
msg_pose_with_cov->pose.pose.orientation.z = q.z();
|
msg_pose_with_cov->pose.pose.orientation.z = q.z();
|
||||||
msg_pose_with_cov->pose.pose.orientation.w = q.w();
|
msg_pose_with_cov->pose.pose.orientation.w = q.w();
|
||||||
msg_pose_with_cov->pose.covariance = {frame->Cov_(0,0),frame->Cov_(0,1),0.0,0.0,frame->Cov_(0,2),0.0,
|
msg_pose_with_cov->pose.covariance = {odom.first(0,0),odom.first(0,1),0.0,0.0,odom.first(0,2),0.0,
|
||||||
frame->Cov_(1,0),frame->Cov_(1,1),0.0,0.0,frame->Cov_(1,2),0.0,
|
odom.first(1,0),odom.first(1,1),0.0,0.0,odom.first(1,2),0.0,
|
||||||
0.0,0.0,0.0000001,0.0,0.0,0.0,
|
0.0,0.0,0.0000001,0.0,0.0,0.0,
|
||||||
0.0,0.0,0.0,0.0000001,0.0,0.0,
|
0.0,0.0,0.0,0.0000001,0.0,0.0,
|
||||||
frame->Cov_(2,0),frame->Cov_(2,1),0.0,0.0,frame->Cov_(2,2),0.0,
|
odom.first(2,0),odom.first(2,1),0.0,0.0,odom.first(2,2),0.0,
|
||||||
0.0,0.0,0.0,0.0,0.0,0.0000001};
|
0.0,0.0,0.0,0.0,0.0,0.0000001};
|
||||||
pub_pose_with_cov_.publish(msg_pose_with_cov);
|
pub_pose_with_cov_.publish(msg_pose_with_cov);
|
||||||
if(pub_frames_.getNumSubscribers() > 0 || pub_points_.getNumSubscribers() > 0){
|
if(pub_frames_.getNumSubscribers() > 0 || pub_points_.getNumSubscribers() > 0){
|
||||||
publishPointMarker(
|
publishPointMarker(
|
||||||
pub_points_, Eigen::Vector3d(frame->se3().translation().x(),frame->se3().translation().z(),0.0), "trajectory",
|
pub_points_, Eigen::Vector3d(-odom.second.se2().translation()(0),-odom.second.se2().translation()(1),0.0), "trajectory",
|
||||||
ros::Time::now(), trace_id_, 0, 0.01, Vector3d(0.,0.,0.5));
|
ros::Time::now(), trace_id_, 0, 0.01, Vector3d(0.,0.,0.5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Visualizer::visualizeMarkers(
|
|
||||||
const FramePtr& frame,
|
|
||||||
const set<FramePtr>& core_kfs,
|
|
||||||
const Map& map)
|
|
||||||
{
|
|
||||||
if(frame == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
publishTfTransform(
|
|
||||||
frame->se3()*T_world_from_vision_.inverse(),
|
|
||||||
ros::Time(frame->timestamp_), "cam_pos", "world", br_);
|
|
||||||
|
|
||||||
if(pub_frames_.getNumSubscribers() > 0 || pub_points_.getNumSubscribers() > 0)
|
|
||||||
{
|
|
||||||
publishPointMarker(
|
|
||||||
pub_points_, T_world_from_vision_*Vector3d(frame->pos()(0),0.0,frame->pos()(1)), "trajectory",
|
|
||||||
ros::Time::now(), trace_id_, 0, 0.006, Vector3d(0.,0.,0.5));
|
|
||||||
removeDeletedPts(map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Visualizer::removeDeletedPts(const Map& map)
|
|
||||||
{
|
|
||||||
if(pub_points_.getNumSubscribers() > 0)
|
|
||||||
{
|
|
||||||
for(list<Point*>::const_iterator it=map.trash_points_.begin(); it!=map.trash_points_.end(); ++it)
|
|
||||||
publishPointMarker(pub_points_, Vector3d(), "pts", ros::Time::now(), (*it)->id_, 2, 0.006, Vector3d());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace gpu_svo
|
} // end namespace gpu_svo
|
||||||
|
|||||||
@@ -108,9 +108,6 @@ void VoNode::imgCb(const sensor_msgs::ImageConstPtr& msg)
|
|||||||
auto start=std::chrono::steady_clock::now();
|
auto start=std::chrono::steady_clock::now();
|
||||||
cv::Mat img=cv_bridge::toCvShare(msg, "mono8")->image;
|
cv::Mat img=cv_bridge::toCvShare(msg, "mono8")->image;
|
||||||
vo_->addImage(img, msg->header.stamp.toSec(),msg->header.stamp);
|
vo_->addImage(img, msg->header.stamp.toSec(),msg->header.stamp);
|
||||||
visualizer_.publishMinimal(img, vo_->lastFrame(), *vo_, msg->header.stamp.toSec());
|
|
||||||
if(vo_->stage() == svo::FrameHandlerMono::STAGE_PAUSED)
|
|
||||||
usleep(100000);
|
|
||||||
#if VIO_DEBUG
|
#if VIO_DEBUG
|
||||||
fprintf(log_, ",,,,,,,%s,%f,%f,%f\n",std::to_string(std::chrono::duration<double>(std::chrono::steady_clock::now()-start).count()).c_str(),vo_->lastFrame()->T_f_w_.translation()(0),
|
fprintf(log_, ",,,,,,,%s,%f,%f,%f\n",std::to_string(std::chrono::duration<double>(std::chrono::steady_clock::now()-start).count()).c_str(),vo_->lastFrame()->T_f_w_.translation()(0),
|
||||||
vo_->lastFrame()->T_f_w_.translation()(1),
|
vo_->lastFrame()->T_f_w_.translation()(1),
|
||||||
@@ -158,6 +155,7 @@ void VoNode::imuCb(const sensor_msgs::ImuPtr &imu) {
|
|||||||
#endif
|
#endif
|
||||||
vo_->UpdateIMU(imu_in,imu->header.stamp);
|
vo_->UpdateIMU(imu_in,imu->header.stamp);
|
||||||
imu_time_=imu->header.stamp;
|
imu_time_=imu->header.stamp;
|
||||||
|
visualizer_.publishMinimal(vo_->ukfPtr_, imu->header.stamp.toSec());
|
||||||
}
|
}
|
||||||
void VoNode::cmdCb(const geometry_msgs::TwistPtr &cmd) {
|
void VoNode::cmdCb(const geometry_msgs::TwistPtr &cmd) {
|
||||||
double _cmd[3]={cmd->linear.x,cmd->linear.y,cmd->angular.z};
|
double _cmd[3]={cmd->linear.x,cmd->linear.y,cmd->angular.z};
|
||||||
|
|||||||
Reference in New Issue
Block a user