31#include "ORB_SLAM2/Random.h"
37#define GetCurrentDir _getcwd
40#define GetCurrentDir getcwd
45 char buff[FILENAME_MAX];
47 std::string current_working_dir(buff);
49 for (
unsigned int i = 0; i < current_working_dir.length(); i++)
51 if (current_working_dir.substr(i, 1) ==
"\\")
52 current_working_dir.replace(i, 1,
"/");
54 return current_working_dir;
57const float eps = 1e-4;
58cv::Mat
ExpSO3(
const float &x,
const float &y,
const float &z)
60 cv::Mat I = cv::Mat::eye(3, 3, CV_32F);
61 const float d2 = x * x + y * y + z * z;
62 const float d = sqrt(d2);
64 W = (cv::Mat_<float>(3, 3) << 0, -z, y, z, 0, -x, -y, x, 0);
67 return (I + W + 0.5f*W*W);
69 return (I + W * sin(d) / d + W * W*(1.0f - cos(d)) / d2);
74 return ExpSO3(v.at<
float>(0), v.at<
float>(1), v.at<
float>(2));
80 poseCamera.at<
float>(0, 0) / poseCamera.at<
float>(2, 0)*mk.at<
float>(0, 0) + mk.at<
float>(0, 2),
81 poseCamera.at<
float>(1, 0) / poseCamera.at<
float>(2, 0)*mk.at<
float>(1, 1) + mk.at<
float>(1, 2)
85cv::Mat
Plane::DetectPlane(
const cv::Mat Tcw,
const std::vector<ORB_SLAM2::MapPoint*> &vMPs,
const int iterations)
88 std::vector<cv::Mat> vPoints;
89 vPoints.reserve(vMPs.size());
90 std::vector<ORB_SLAM2::MapPoint*> vPointMP;
91 vPointMP.reserve(vMPs.size());
93 for (
size_t i = 0; i < vMPs.size(); i++)
95 ORB_SLAM2::MapPoint* pMP = vMPs[i];
98 if (pMP->Observations() > 5)
100 vPoints.push_back(pMP->GetWorldPos());
101 vPointMP.push_back(pMP);
106 const int N = vPoints.size();
112 std::vector<size_t> vAllIndices;
113 vAllIndices.reserve(N);
114 std::vector<size_t> vAvailableIndices;
116 for (
int i = 0; i < N; i++)
118 vAllIndices.push_back(i);
121 float bestDist = 1e10;
122 std::vector<float> bestvDist;
125 for (
int n = 0; n < iterations; n++)
127 vAvailableIndices = vAllIndices;
129 cv::Mat A(3, 4, CV_32F);
130 A.col(3) = cv::Mat::ones(3, 1, CV_32F);
133 for (
short i = 0; i < 3; ++i)
137 int idx = vAvailableIndices[randi];
139 A.row(i).colRange(0, 3) = vPoints[idx].t();
141 vAvailableIndices[randi] = vAvailableIndices.back();
142 vAvailableIndices.pop_back();
146 cv::SVDecomp(A, w, u, vt, cv::SVD::MODIFY_A | cv::SVD::FULL_UV);
148 const float a = vt.at<
float>(3, 0);
149 const float b = vt.at<
float>(3, 1);
150 const float c = vt.at<
float>(3, 2);
151 const float d = vt.at<
float>(3, 3);
153 std::vector<float> vDistances(N, 0);
155 const float f = 1.0f / sqrt(a*a + b * b + c * c + d * d);
157 for (
int i = 0; i < N; i++)
159 vDistances[i] = fabs(vPoints[i].at<float>(0)*a + vPoints[i].at<float>(1)*b + vPoints[i].at<float>(2)*c + d)*f;
162 std::vector<float> vSorted = vDistances;
163 std::sort(vSorted.begin(), vSorted.end());
165 int nth = std::max((
int)(0.2*N), 20);
166 const float medianDist = vSorted[nth];
168 if (medianDist < bestDist)
170 bestDist = medianDist;
171 bestvDist = vDistances;
176 const float th = 1.4 * bestDist;
177 std::vector<bool> vbInliers(N,
false);
179 for (
int i = 0; i < N; i++)
181 if (bestvDist[i] < th)
188 std::vector<ORB_SLAM2::MapPoint*> vInlierMPs(nInliers, NULL);
190 for (
int i = 0; i < N; i++)
194 vInlierMPs[nin] = vPointMP[i];
201 mRang = -3.14f / 2 + ((float)rand() / RAND_MAX)*3.14f;
208 const int N =
mMvMPs.size();
211 cv::Mat A = cv::Mat(N, 4, CV_32F);
212 A.col(3) = cv::Mat::ones(N, 1, CV_32F);
214 mOrigin = cv::Mat::zeros(3, 1, CV_32F);
217 for (
int i = 0; i < N; i++)
219 ORB_SLAM2::MapPoint* pMP =
mMvMPs[i];
222 cv::Mat Xw = pMP->GetWorldPos();
224 A.row(nPoints).colRange(0, 3) = Xw.t();
231 cv::SVDecomp(A, w, u, vt, cv::SVD::MODIFY_A | cv::SVD::FULL_UV);
233 float a = vt.at<
float>(3, 0);
234 float b = vt.at<
float>(3, 1);
235 float c = vt.at<
float>(3, 2);
238 const float f = 1.0f / sqrt(a * a + b * b + c * c);
243 cv::Mat Oc = -
mMTcw.colRange(0, 3).rowRange(0, 3).t() *
mMTcw.rowRange(0, 3).col(3);
247 if ((
mXC.at<
float>(0) * a +
mXC.at<
float>(1) * b +
mXC.at<
float>(2) * c) < 0)
254 const float nx = a * f;
255 const float ny = b * f;
256 const float nz = c * f;
258 mNormal = (cv::Mat_<float>(3, 1) << nx, ny, nz);
261 up = (cv::Mat_<float>(3, 1) << 0.0f, 1.0f, 0.0f);
264 const float sa = cv::norm(v);
265 const float ca = up.dot(
mNormal);
266 const float ang = atan2(sa, ca);
267 mTpw = cv::Mat::eye(4, 4, CV_32F);
270 ExpSO3(v*ang / sa).copyTo(
mTpw.rowRange(0, 3).colRange(0, 3));
282 mInitialized =
false;
283 mPlane2World = cv::Mat::eye(4, 4, CV_32F);
286 mParams.Camera.width = 640;
287 mParams.Camera.height = 480;
288 mParams.Camera.fx = 640.0;
289 mParams.Camera.fy = 640.0;
290 mParams.Camera.cx = 320.0;
291 mParams.Camera.cy = 240.0;
292 mParams.Camera.k1 = 0.0;
293 mParams.Camera.k2 = 0.0;
294 mParams.Camera.p1 = 0.0;
295 mParams.Camera.p2 = 0.0;
296 mParams.Camera.k3 = 0.0;
297 mParams.Camera.bf = 0.0;
298 mParams.Camera.fps = 30.0;
299 mParams.Camera.RGB = 1;
301 mParams.ORBextractor.nFeatures = 800;
302 mParams.ORBextractor.nLevels = 8;
303 mParams.ORBextractor.scaleFactor = 1.2;
304 mParams.ORBextractor.iniThFAST = 20;
305 mParams.ORBextractor.minThFAST = 7;
307 mParams.DepthMapFactor = 1.0;
310 std::string strVocFile;
312 strVocFile = CopyFileFromAssetToSD(
"btdata/orbvoc.bin",
"orbvoc.bin",
"btdata");
317 mVocabulary =
new ORB_SLAM2::ORBVocabulary();
318 mVocabulary->loadFromBinaryFile(strVocFile);
331 SAFE_DELETE(mVocabulary);
339void Sslam::BuildCameraParam(
const aruco::CameraParameters &camparam)
343 int maxsize = std::max(camparam.CamSize.width, camparam.CamSize.height);
345 mScale = 640.0f / (float)maxsize;
372 mParams.Camera.width = (int)((
float)camparam.CamSize.width * mScale);
373 mParams.Camera.height = (int)((
float)camparam.CamSize.height * mScale);
375 mParams.Camera.cx =
static_cast<float>(mParams.Camera.width) * 0.5f;
376 mParams.Camera.cy =
static_cast<float>(mParams.Camera.height) * 0.5f;
378 float f = std::max(mParams.Camera.width, mParams.Camera.height);
379 mParams.Camera.fx = f;
380 mParams.Camera.fy = f;
382 int wlvl = mParams.Camera.width;
383 int hlvl = mParams.Camera.height;
385 while (wlvl % 2 == 0 && hlvl % 2 == 0 && wlvl*hlvl > 5000 && pyrLevels < 12)
392 mParams.ORBextractor.nLevels = pyrLevels;
395void Sslam::InitDetector()
397 boost::unique_lock<boost::recursive_mutex> ld(mUpdateMutex);
407 mSlam =
new ORB_SLAM2::System(mVocabulary, mParams, ORB_SLAM2::System::MONOCULAR,
false);
408 mSlam->DeactivateLocalizationMode();
411 catch (std::exception &)
416 mInitialized =
false;
443 if (mSlam && !image.empty())
446 std::vector<cv::KeyPoint> keypts = mSlam->GetTrackedKeyPointsUn();
447 cv::Scalar color(0, 255, 0);
449 for (
unsigned int i = 0; i < keypts.size(); i++)
451 cv::KeyPoint kp = keypts[i];
452 cv::circle(image, kp.pt / mScale, 2, color);
455 if (!mCentroid.empty() && (mSlam->GetTrackingState() == 2))
457 ORB_SLAM2::Tracking* tracker = mSlam->GetTracker();
459 std::vector<cv::Mat> axisPoints(4);
460 axisPoints[0] = (cv::Mat_ <float>(4, 1) << 0.0, 0, 0, 1);
461 axisPoints[1] = (cv::Mat_ <float>(4, 1) << 0.3, 0, 0, 1);
462 axisPoints[2] = (cv::Mat_ <float>(4, 1) << 0.0, 0.3, 0, 1);
463 axisPoints[3] = (cv::Mat_ <float>(4, 1) << 0, 0, 0.3, 1);
464 std::vector<cv::Point2f> drawPoints(4);
465 for (
int i = 0; i < 4; i++)
467 axisPoints[i] = mPlane2Camera * axisPoints[i];
468 drawPoints[i] =
Camera2Pixel(axisPoints[i], tracker->GetCalibrationMatrix());
471 cv::line(image, drawPoints[0] / mScale, drawPoints[1] / mScale, cv::Scalar(250, 0, 0), 5);
472 cv::line(image, drawPoints[0] / mScale, drawPoints[2] / mScale, cv::Scalar(0, 250, 0), 5);
473 cv::line(image, drawPoints[0] / mScale, drawPoints[3] / mScale, cv::Scalar(0, 0, 250), 5);
509 switch (mSlam->GetTrackingState())
511 case -1: {cv::putText(image,
"SYSTEM NOT READY", cv::Point(20, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1); }
break;
512 case 0: {cv::putText(image,
"NO IMAGES YET", cv::Point(20, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1); }
break;
513 case 1: {cv::putText(image,
"SLAM NOT INITIALIZED", cv::Point(20, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1); }
break;
514 case 2: {cv::putText(image,
"SLAM ON", cv::Point(20, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 1);
break; }
515 case 3: {cv::putText(image,
"SLAM LOST", cv::Point(20, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1);
break; }
524 int prevState = mSlam->GetTrackingState();
527 boost::unique_lock<boost::recursive_mutex> ld(mUpdateMutex);
528 pose = mSlam->TrackMonocular(mLastData.
gray, mTimestamp);
529 if (mSlam->MapChanged() || (mSlam->GetTrackingState() < 2))
531 mInitialized =
false;
540 if ((mFullInit < 10) && (mSlam->GetTrackingState() == 2))
542 else if (mSlam->GetTrackingState() != 2)
549 if (pose.empty() || (mSlam->GetTrackingState() != 2))
558 const std::vector<ORB_SLAM2::MapPoint*> vpMPs = mSlam->GetTracker()->GetMap()->GetAllMapPoints();
559 const std::vector<ORB_SLAM2::MapPoint*> vpTMPs = mSlam->GetTrackedMapPoints();
560 if (vpMPs.size() > 150)
562 mPlane2World = mplane.
DetectPlane(pose, vpTMPs, 50);
564 if (!mPlane2World.empty())
568 mPlane2Camera = pose * mPlane2World;
574 mPlane2Camera = pose * mPlane2World;
577 if (!mInitialized || pose.empty())
584 cv::Mat camtoplane = mPlane2Camera.inv();
586 double modelview_matrix[16];
587 modelview_matrix[0] = -camtoplane.at<
float>(0, 0);
588 modelview_matrix[1] = -camtoplane.at<
float>(1, 0);
589 modelview_matrix[2] = -camtoplane.at<
float>(2, 0);
590 modelview_matrix[3] = 0.0;
592 modelview_matrix[4] = camtoplane.at<
float>(0, 1);
593 modelview_matrix[5] = camtoplane.at<
float>(1, 1);
594 modelview_matrix[6] = camtoplane.at<
float>(2, 1);
595 modelview_matrix[7] = 0.0;
597 modelview_matrix[8] = camtoplane.at<
float>(0, 2);
598 modelview_matrix[9] = camtoplane.at<
float>(1, 2);
599 modelview_matrix[10] = camtoplane.at<
float>(2, 2);
600 modelview_matrix[11] = 0.0;
602 modelview_matrix[12] = camtoplane.at<
float>(0, 3);
603 modelview_matrix[13] = camtoplane.at<
float>(1, 3);
604 modelview_matrix[14] = camtoplane.at<
float>(2, 3);
605 modelview_matrix[15] = 1.0;
608 mLastCamPos =
Vector3(
static_cast<float>(mLastData.
reversedBitmap ? -modelview_matrix[12] : modelview_matrix[12]), static_cast<float>(modelview_matrix[13]), static_cast<float>(modelview_matrix[14]));
616 std::chrono::steady_clock::time_point lastTimeStamp = std::chrono::steady_clock::now();
631 if (!mSlam || (((
int)((
float)mLastData.camParam.CamSize.width * mScale)) != mParams.Camera.width || ((
int)((
float)mLastData.camParam.CamSize.height * mScale)) != mParams.Camera.height))
638 BuildCameraParam(mLastData.camParam);
640 lastTimeStamp = std::chrono::steady_clock::now();
644 cv::resize(mLastData.
gray, mLastData.
gray, cv::Size((
int)((
float)mLastData.
gray.cols * mScale), (
int)((
float)mLastData.
gray.rows * mScale)), 0, 0, cv::INTER_LINEAR);
649 if (!mLastData.
image.empty() && mSlam)
651 std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
652 double ttrack = std::chrono::duration_cast<std::chrono::duration<double>>(t1 - lastTimeStamp).count();
653 mTimestamp += ttrack;
654 lastTimeStamp = std::chrono::steady_clock::now();
661 boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
void GetLastData(LASTDATA &data)
static ArManager * GetInstance()
static BtQuaternion FromRotationMatrix(double rotMatrix[16], bool reverseX=false, bool reverseY=true)
static int RandomInt(int min, int max)
cv::Mat DetectPlane(cv::Mat campos, std::vector< slamPoint > &vMPs, const int iterations)
std::vector< slamPoint > mMvMPs
Vector3 GetCameraPosition()
BtQuaternion GetCameraOrientation()
void DrawLandmarks(cv::Mat image)
cv::Mat ExpSO3(const float &x, const float &y, const float &z)
cv::Point2f Camera2Pixel(cv::Mat poseCamera, cv::Mat mk)
std::string GetCurrentWorkingDir(void)
cv::Mat ExpSO3(const float &x, const float &y, const float &z)
cv::Point2f Camera2Pixel(cv::Mat poseCamera, cv::Mat mk)