49 if (smat.unit_quaternion().norm() < dso::SE3::Scalar(1e-10))
52 dso::Vec3f pos = smat.translation().cast<
float>();
53 dso::Mat33f rotation_matrix = smat.rotationMatrix().cast<
float>();
55 cv::Mat nmat(4, 4, CV_32F);
56 nmat.at<
float>(0, 0) = rotation_matrix(0, 0);
57 nmat.at<
float>(1, 0) = rotation_matrix(1, 0);
58 nmat.at<
float>(2, 0) = rotation_matrix(2, 0);
59 nmat.at<
float>(3, 0) = 0.0f;
60 nmat.at<
float>(0, 1) = rotation_matrix(0, 1);
61 nmat.at<
float>(1, 1) = rotation_matrix(1, 1);
62 nmat.at<
float>(2, 1) = rotation_matrix(2, 1);
63 nmat.at<
float>(3, 1) = 0.0f;
64 nmat.at<
float>(0, 2) = rotation_matrix(0, 2);
65 nmat.at<
float>(1, 2) = rotation_matrix(1, 2);
66 nmat.at<
float>(2, 2) = rotation_matrix(2, 2);
67 nmat.at<
float>(3, 2) = 0.0f;
68 nmat.at<
float>(0, 3) = pos.x();
69 nmat.at<
float>(1, 3) = pos.y();
70 nmat.at<
float>(2, 3) = pos.z();
71 nmat.at<
float>(3, 3) = 1.0f;
77 double modelview_matrix[16];
83 modelview_matrix[0] = mat.at<
float>(0, 0) * invx;
84 modelview_matrix[1] = mat.at<
float>(1, 0) * invx;
85 modelview_matrix[2] = mat.at<
float>(2, 0) * invx;
86 modelview_matrix[3] = 0.0;
88 modelview_matrix[4] = mat.at<
float>(0, 1);
89 modelview_matrix[5] = mat.at<
float>(1, 1);
90 modelview_matrix[6] = mat.at<
float>(2, 1);
91 modelview_matrix[7] = 0.0;
93 modelview_matrix[8] = mat.at<
float>(0, 2);
94 modelview_matrix[9] = mat.at<
float>(1, 2);
95 modelview_matrix[10] = mat.at<
float>(2, 2);
96 modelview_matrix[11] = 0.0;
98 modelview_matrix[12] = mat.at<
float>(0, 3);
99 modelview_matrix[13] = mat.at<
float>(1, 3);
100 modelview_matrix[14] = mat.at<
float>(2, 3);
101 modelview_matrix[15] = 1.0;
104 vec =
Vector3(
static_cast<float>(flip ? -modelview_matrix[12] : modelview_matrix[12]),
static_cast<float>(modelview_matrix[13]),
static_cast<float>(modelview_matrix[14]));
108cv::Mat
ExpSO3(
const float &x,
const float &y,
const float &z)
110 cv::Mat I = cv::Mat::eye(3, 3, CV_32F);
111 const float d2 = x * x + y * y + z * z;
112 const float d = sqrt(d2);
114 W = (cv::Mat_<float>(3, 3) << 0, -z, y, z, 0, -x, -y, x, 0);
117 return (I + W + 0.5f*W*W);
119 return (I + W * sin(d) / d + W * W*(1.0f - cos(d)) / d2);
124 return ExpSO3(v.at<
float>(0), v.at<
float>(1), v.at<
float>(2));
130 poseCamera.at<
float>(0, 0) / poseCamera.at<
float>(2, 0) * mk.at<
float>(0, 0) + mk.at<
float>(0, 2),
131 poseCamera.at<
float>(1, 0) / poseCamera.at<
float>(2, 0) * mk.at<
float>(1, 1) + mk.at<
float>(1, 2)
138 unsigned int maxPoints = std::min(800, (
int)vMPs.size());
140 std::vector<cv::Mat> vPoints;
141 vPoints.reserve(maxPoints);
142 std::vector<slamPoint> vPointMP;
143 vPointMP.reserve(maxPoints);
145 for (
size_t i = 0; i < maxPoints; i++)
150 vPoints.push_back(pMP.
point3d);
151 vPointMP.push_back(pMP);
155 const int N = vPoints.size();
161 std::vector<size_t> vAllIndices;
162 vAllIndices.reserve(N);
163 std::vector<size_t> vAvailableIndices;
165 for (
int i = 0; i < N; i++)
167 vAllIndices.push_back(i);
170 float bestDist = 1e10;
171 std::vector<float> bestvDist;
174 for (
int n = 0; n < iterations; n++)
176 vAvailableIndices = vAllIndices;
178 cv::Mat A(3, 4, CV_32F);
179 A.col(3) = cv::Mat::ones(3, 1, CV_32F);
182 for (
short i = 0; i < 3; ++i)
184 int randi =
Random(0, vAvailableIndices.size() - 1);
186 int idx = vAvailableIndices[randi];
188 A.row(i).colRange(0, 3) = vPoints[idx].t();
190 vAvailableIndices[randi] = vAvailableIndices.back();
191 vAvailableIndices.pop_back();
195 cv::SVDecomp(A, w, u, vt, cv::SVD::MODIFY_A | cv::SVD::FULL_UV);
197 const float a = vt.at<
float>(3, 0);
198 const float b = vt.at<
float>(3, 1);
199 const float c = vt.at<
float>(3, 2);
200 const float d = vt.at<
float>(3, 3);
202 std::vector<float> vDistances(N, 0);
204 const float f = 1.0f / sqrt(a*a + b * b + c * c + d * d);
206 for (
int i = 0; i < N; i++)
208 vDistances[i] = fabs(vPoints[i].at<float>(0)*a + vPoints[i].at<float>(1)*b + vPoints[i].at<float>(2)*c + d)*f;
211 std::vector<float> vSorted = vDistances;
212 std::sort(vSorted.begin(), vSorted.end());
214 int nth = std::max((
int)(0.2*N), 20);
215 const float medianDist = vSorted[nth];
217 if (medianDist < bestDist)
219 bestDist = medianDist;
220 bestvDist = vDistances;
225 const float th = 1.4 * bestDist;
226 std::vector<bool> vbInliers(N,
false);
228 for (
int i = 0; i < N; i++)
230 if (bestvDist[i] < th)
237 std::vector<slamPoint> vInlierMPs(nInliers);
239 for (
int i = 0; i < N; i++)
243 vInlierMPs[nin] = vPointMP[i];
248 campos.copyTo(
mMTcw);
250 mRang = -3.14f / 2 + ((float)rand() / RAND_MAX)*3.14f;
257 const int N =
mMvMPs.size();
260 cv::Mat A = cv::Mat(N, 4, CV_32F);
261 A.col(3) = cv::Mat::ones(N, 1, CV_32F);
263 mOrigin = cv::Mat::zeros(3, 1, CV_32F);
266 for (
int i = 0; i < N; i++)
273 A.row(nPoints).colRange(0, 3) = Xw.t();
284 cv::SVDecomp(A, w, u, vt, cv::SVD::MODIFY_A | cv::SVD::FULL_UV);
286 float a = vt.at<
float>(3, 0);
287 float b = vt.at<
float>(3, 1);
288 float c = vt.at<
float>(3, 2);
291 const float f = 1.0f / sqrt(a * a + b * b + c * c);
296 cv::Mat Oc = -
mMTcw.colRange(0, 3).rowRange(0, 3).t() *
mMTcw.rowRange(0, 3).col(3);
300 if ((
mXC.at<
float>(0) * a +
mXC.at<
float>(1) * b +
mXC.at<
float>(2) * c) < 0)
307 const float nx = a * f;
308 const float ny = b * f;
309 const float nz = c * f;
311 mNormal = (cv::Mat_<float>(3, 1) << nx, ny, nz);
314 up = (cv::Mat_<float>(3, 1) << 0.0f, 1.0f, 0.0f);
317 const float sa = cv::norm(v);
318 const float ca = up.dot(
mNormal);
319 const float ang = atan2(sa, ca);
321 mTpw = cv::Mat::eye(4, 4, CV_32F);
324 ExpSO3(v*ang / sa).copyTo(
mTpw.rowRange(0, 3).colRange(0, 3));
337 mInitialized =
false;
342 dso::setting_solverMode = SOLVER_FIX_LAMBDA | SOLVER_ORTHOGONALIZE_X_LATER;
343 dso::setting_solverModeDelta = 0.00001;
344 dso::setting_forceAceptStep =
true;
345 dso::goStepByStep =
false;
346 dso::setting_useExposure =
true;
347 dso::setting_realTimeMaxKF =
true;
348 dso::setting_use_stereo =
false;
349 dso::stereo_weight = 0;
351 dso::setting_use_imu_track =
false;
352 dso::setting_use_imu =
false;
353 dso::imu_weight = 0.5;
354 dso::imu_weight_tracker = 0.1;
355 dso::AccCov = dso::Mat33::Identity();
356 dso::AccRandomWalkNoise = dso::Mat33::Identity();
357 dso::GyrCov = dso::Mat33::Identity();
358 dso::GyrRandomWalkNoise = dso::Mat33::Identity();
360 dso::setting_use_optimize =
true;
361 dso::setting_use_Dmargin =
true;
363 dso::disableAllDisplay =
true;
364 dso::setting_render_plotTrackingFull =
false;
365 dso::setting_render_renderWindowFrames =
false;
366 dso::setting_logStuff =
false;
367 dso::setting_debugout_runquiet =
true;
368 dso::setting_desiredImmatureDensity = 500;
369 dso::setting_desiredPointDensity = 650;
370 dso::setting_minFrames = 2;
371 dso::setting_maxFrames = 4;
372 dso::setting_maxOptIterations = 3;
373 dso::setting_minOptIterations = 1;
374 dso::setting_minPointsRemaining = 0.05f;
375 dso::setting_maxLogAffFacInWindow = 0.7f;
376 dso::setting_kfGlobalWeight = 4.0;
377 dso::setting_maxAffineWeight = 2.0;
378 dso::setting_maxIMUSamples = 10000;
380 dso::setting_maxPixSearch = 0.027f;
381 dso::setting_minTraceQuality = 4.0f;
382 dso::setting_minTraceTestRadius = 3;
383 dso::setting_GNItsOnPointActivation = 3;
384 dso::setting_trace_stepsize = 1.0f;
385 dso::setting_trace_GNIterations = 3;
386 dso::setting_trace_GNThreshold = 0.1f;
387 dso::setting_trace_extraSlackOnTH = 1.2f;
388 dso::setting_trace_slackInterval = 1.5f;
389 dso::setting_trace_minImprovementFactor = 2.0f;
391 dso::setting_photometricCalibration = 0;
400 dso::multiThreading =
true;
401 dso::sparsityFactor = 4;
403 mCamParams.inWidth = 0;
404 mCamParams.inHeight = 0;
418 for (dso::IOWrap::Output3DWrapper* ow : mSlam->outputWrapper)
426 SAFE_DELETE(mUndistorter);
436 mInitialized =
false;
439void Sslam::publishGraph(
const std::map<uint64_t, Eigen::Vector2i, std::less<uint64_t>, Eigen::aligned_allocator<std::pair<const uint64_t, Eigen::Vector2i>>> &connectivity)
445 float fx = HCalib->fxl();
446 float fy = HCalib->fyl();
447 float cx = HCalib->cxl();
448 float cy = HCalib->cyl();
449 float fxi = 1.0f / fx;
450 float fyi = 1.0f / fy;
451 float cxi = -cx / fx;
452 float cyi = -cy / fy;
454 cv::Mat camtoworld(4, 4, CV_32F);
455 for (dso::FrameHessian* fh : frames)
457 Sophus2Cv((dso::T_WR_align.inverse() * fh->shell->camToWorld).inverse(), camtoworld);
459 if (camtoworld.empty())
462 for (dso::PointHessian* ph : fh->pointHessians)
486 if (ph->idepth_scaled < 0)
489 if ((ph->status == dso::PointHessian::MARGINALIZED) || (ph->status == dso::PointHessian::ACTIVE))
491 float depth = 1.0f / ph->idepth;
492 float x = (ph->u * fxi + cxi) * depth;
493 float y = (ph->v * fyi + cyi) * depth;
494 float z = depth * (1 + 2 * fxi);
496 cv::Mat pm4 = camtoworld.inv() * cv::Mat(cv::Vec4f(x, y, z, 1.0));
497 cv::Mat pm(cv::Point3f(pm4.at<
float>(0), pm4.at<
float>(1), pm4.at<
float>(2)));
502 dspt.
color = cv::Scalar(0, 0, 255);
503 dspt.
point2d = cv::Point2i(ph->u, ph->v);
504 dspt.
depth = ph->idepth_scaled;
506 boost::mutex::scoped_lock lock(mDebugMutex);
507 if (mCloudPoints.size() > dso::setting_desiredPointDensity * 3)
508 mCloudPoints.erase(mCloudPoints.begin());
510 mCloudPoints.push_back(dspt);
518 cv::Mat camtoworld(4, 4, CV_32F);
519 Sophus2Cv((dso::T_WR_align.inverse() * frame->camToWorld).inverse(), camtoworld);
521 if (camtoworld.empty())
524 camtoworld.copyTo(mCameraWorld);
526 if ((mCloudPoints.size() > dso::setting_desiredPointDensity) && !mInitialized && !mCameraWorld.empty() && !mSlam->isLost && mSlam->initialized && !mSlam->initFailed)
528 boost::mutex::scoped_lock lock(mDebugMutex);
530 cv::Mat plane2w = p.
DetectPlane(mCameraWorld, mCloudPoints, 50);
531 if (!plane2w.empty())
534 mPlane2World = plane2w;
539 if (mInitialized && frame->poseValid && !mPlane2World.empty())
541 mPlane2Camera = camtoworld * mPlane2World;
543 mPrevCamPos = mLastCamPos;
544 mPrevCamQuat = mLastCamQuat;
548 camtoworld.at<
float>(0, 3) = mPlane2Camera.at<
float>(0, 3);
549 camtoworld.at<
float>(1, 3) = mPlane2Camera.at<
float>(1, 3);
550 camtoworld.at<
float>(2, 3) = mPlane2Camera.at<
float>(2, 3);
559 std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
560 mLastUpdate = std::chrono::duration<double, std::milli>(t1 - mLastTimeFrame).count();
588void Sslam::BuildCameraParam(
const aruco::CameraParameters &camparam)
594 float maxsize =
static_cast<float>(std::max(camparam.CamSize.width, camparam.CamSize.height));
596 scale = 320.0f / maxsize;
598 mScaleX =
static_cast<float>(
firstPO2From((
float)camparam.CamSize.width * scale)) /
static_cast<float>(camparam.CamSize.width);
599 mScaleY =
static_cast<float>(
firstPO2From((
float)camparam.CamSize.height * scale)) /
static_cast<float>(camparam.CamSize.height);
601 mCamParams.type = dso::Model_FOV;
602 mCamParams.rectify = dso::Rectify_Crop;
604 mCamParams.inWidth = (int)(
static_cast<float>(camparam.CamSize.width) * mScaleX);
605 mCamParams.inHeight = (int)(
static_cast<float>(camparam.CamSize.height) * mScaleY);
607 mCamParams.outWidth = mCamParams.inWidth;
608 mCamParams.outHeight = mCamParams.inHeight;
611 mCamParams.fx = camparam.CameraMatrix.at<
float>(0, 0) * mScaleX;
612 mCamParams.fy = camparam.CameraMatrix.at<
float>(1, 1) * mScaleY;
614 mCamParams.cx = camparam.CameraMatrix.at<
float>(0, 2) * mScaleX;
615 mCamParams.cy = camparam.CameraMatrix.at<
float>(1, 2) * mScaleY;
617 mCamParams.omega = 0.0f;
620void Sslam::InitDetector()
626 mSlam->blockUntilMappingIsFinished();
627 std::vector<dso::IOWrap::Output3DWrapper*> wraps = mSlam->outputWrapper;
629 boost::mutex::scoped_lock lock(mResetMutex);
632 for (dso::IOWrap::Output3DWrapper* ow : wraps)
635 SAFE_DELETE(mUndistorter);
636 mUndistorter = dso::Undistort::getUndistorter(mCamParams,
"",
"");
638 dso::setGlobalCalib((
int)mUndistorter->getSize()[0], (
int)mUndistorter->getSize()[1], mUndistorter->getK().cast<
float>());
640 float fsize = (float)mUndistorter->getSize()[0] + (float)mUndistorter->getSize()[1];
641 dso::setting_maxShiftWeightT = 0.04f * fsize;
642 dso::setting_maxShiftWeightR = 0.0f * fsize;
643 dso::setting_maxShiftWeightRT = 0.02f * fsize;
645 mSlam =
new dso::FullSystem();
646 mSlam->outputWrapper = wraps;
650 boost::mutex::scoped_lock lock(mResetMutex);
651 SAFE_DELETE(mUndistorter);
652 mUndistorter = dso::Undistort::getUndistorter(mCamParams,
"",
"");
654 dso::setGlobalCalib((
int)mUndistorter->getSize()[0], (
int)mUndistorter->getSize()[1], mUndistorter->getK().cast<
float>());
656 float fsize = (float)mUndistorter->getSize()[0] + (float)mUndistorter->getSize()[1];
657 dso::setting_maxShiftWeightT = 0.04f * fsize;
658 dso::setting_maxShiftWeightR = 0.0f * fsize;
659 dso::setting_maxShiftWeightRT = 0.02f * fsize;
661 mSlam =
new dso::FullSystem();
662 mSlam->outputWrapper.push_back(
this);
665 mSlam->linearizeOperation =
true;
667 if (mUndistorter && mUndistorter->photometricUndist != 0)
668 mSlam->setGammaFunction(mUndistorter->photometricUndist->getG());
670 catch (std::exception &)
675 mLastTimeFrame = std::chrono::steady_clock::now();
677 mInitialized =
false;
682 boost::mutex::scoped_lock lock(mDebugMutex);
683 mCloudPoints.clear();
689 if (mLastUpdate == 0.0)
692 double frame = 1.0 / mLastUpdate;
693 double lerpcoef = frame * std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - mLastTimeFrame).count();
694 lerpcoef = std::min(lerpcoef, 1.0);
696 Vector3 lerpVec = mPrevCamPos + ((mLastCamPos - mPrevCamPos) * lerpcoef);
702 if (mLastUpdate == 0.0)
705 double frame = 1.0 / mLastUpdate;
706 double lerpcoef = frame * std::chrono::duration<double, std::milli>(std::chrono::steady_clock::now() - mLastTimeFrame).count();
707 lerpcoef = std::min(lerpcoef, 1.0);
719 mCloudPoints.clear();
721 mInitialized =
false;
726 for (dso::IOWrap::Output3DWrapper* ow : mSlam->outputWrapper)
733 mLastTimeFrame = std::chrono::steady_clock::now();
736 SAFE_DELETE(mUndistorter);
741 if (mSlam && !image.empty())
750 if (!mCameraWorld.empty())
752 boost::mutex::scoped_lock lock(mDebugMutex);
753 for (
unsigned int i = 0; i < mCloudPoints.size(); i++)
758 cv::Mat pm4 = mCameraWorld * cv::Mat(cv::Vec4f(spt.
point3d.at<
float>(0), spt.
point3d.at<
float>(1), spt.
point3d.at<
float>(2), 1.0));
764 if (!mCentroid.empty() && mInitialized)
766 std::vector<cv::Mat> axisPoints(4);
767 axisPoints[0] = (cv::Mat_ <float>(4, 1) << 0.0, 0, 0, 1);
768 axisPoints[1] = (cv::Mat_ <float>(4, 1) << 0.3, 0, 0, 1);
769 axisPoints[2] = (cv::Mat_ <float>(4, 1) << 0.0, 0.3, 0, 1);
770 axisPoints[3] = (cv::Mat_ <float>(4, 1) << 0, 0, 0.3, 1);
771 std::vector<cv::Point2f> drawPoints(4);
772 for (
int i = 0; i < 4; i++)
774 axisPoints[i] = mPlane2Camera * axisPoints[i];
778 cv::line(image, drawPoints[0], drawPoints[1], cv::Scalar(250, 0, 0), 5);
779 cv::line(image, drawPoints[0], drawPoints[2], cv::Scalar(0, 250, 0), 5);
780 cv::line(image, drawPoints[0], drawPoints[3], cv::Scalar(0, 0, 250), 5);
787 cv::equalizeHist(mLastData.
gray, mLastData.
gray);
788 dso::MinimalImageB minImg((
int)mLastData.
gray.cols, (
int)mLastData.
gray.rows, (
unsigned char*)mLastData.
gray.data);
789 dso::ImageAndExposure* undistImg = mUndistorter->undistort<
unsigned char>(&minImg, 1, mLastData.
timeStamp, 1.0f);
790 dso::SE3 groundTruth;
796 groundTruth.setQuaternion(dso::Quat_d(quat.
w, quat.
x, quat.
y, quat.
z));
800 std::vector<dso::ImuData> imuCpy;
811 mSlam->addActiveFrame(undistImg, 0, mFrameIdx, groundTruth, imuCpy);
814 SAFE_DELETE(undistImg);
816 if (!mInitialized || mSlam->initFailed || !mSlam->initialized || mSlam->isLost)
832 nsize.width = (int)((
float)mLastData.
gray.cols * mScaleX);
833 nsize.height = (int)((
float)mLastData.
gray.rows * mScaleY);
837 if (!mSlam || (nsize.width != mCamParams.inWidth) || (nsize.height != mCamParams.inHeight) ||
838 (mSlam && mSlam->initialized && mSlam->initFailed) || (mSlam && (mFrameIdx > 50) && (!mSlam->initialized || mSlam->isLost)))
849 if ((mScaleX != 1.0f) || (mScaleY != 1.0f))
850 cv::resize(mLastData.
gray, mLastData.
gray, cv::Size(mCamParams.inWidth, mCamParams.inHeight), 0, 0, cv::INTER_LINEAR);
853 if (!mLastData.
image.empty() && mSlam && mUndistorter && (dso::pyrLevelsUsed >= 3))
861 boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
int Random(int mi, int mx)
BtQuaternion GetCameraQuat()
std::vector< ArImuData > GetCameraImu() const
aruco::CameraParameters GetCameraParameter()
aruco::CameraParameters camParam
void GetLastData(LASTDATA &data)
static ArManager * GetInstance()
static BtQuaternion Slerp(float fT, const BtQuaternion &rkP, const BtQuaternion &rkQ, bool shortestPath)
static const BtQuaternion IDENTITY
static BtQuaternion FromRotationMatrix(double rotMatrix[16], bool reverseX=false, bool reverseY=true)
cv::Mat DetectPlane(cv::Mat campos, std::vector< slamPoint > &vMPs, const int iterations)
std::vector< slamPoint > mMvMPs
virtual void publishKeyframes(std::vector< dso::FrameHessian * > &frames, bool final, dso::CalibHessian *HCalib) override
virtual void reset() override
virtual void pushDepthImage(dso::MinimalImageB3 *image) override
virtual void join() override
virtual void pushLiveFrame(dso::FrameHessian *image) override
virtual bool needPushDepthImage() override
Vector3 GetCameraPosition()
virtual void publishGraph(const std::map< uint64_t, Eigen::Vector2i, std::less< uint64_t >, Eigen::aligned_allocator< std::pair< const uint64_t, Eigen::Vector2i > > > &connectivity) override
BtQuaternion GetCameraOrientation()
void DrawLandmarks(cv::Mat image)
virtual void publishCamPose(dso::FrameShell *frame, dso::CalibHessian *HCalib) override
void StartThreading(std::function< void()> threadFunction)
void cvMatToQuatAndPos(const cv::Mat mat, BtQuaternion &quat, Vector3 &vec, bool invertx=false, bool flip=false)
void Sophus2Cv(const dso::SE3 &smat, cv::Mat &mat)
cv::Mat ExpSO3(const float &x, const float &y, const float &z)
cv::Point2f Camera2Pixel(cv::Mat poseCamera, cv::Mat mk)
uint32 firstPO2From(uint32 n)