30#include "SD_SLAM/extra/utils.h"
32#include <opencv2/core/eigen.hpp>
34const float eps = 1e-4;
35cv::Mat
ExpSO3(
const float &x,
const float &y,
const float &z)
37 cv::Mat I = cv::Mat::eye(3, 3, CV_32F);
38 const float d2 = x * x + y * y + z * z;
39 const float d = sqrt(d2);
41 W = (cv::Mat_<float>(3, 3) << 0, -z, y, z, 0, -x, -y, x, 0);
44 return (I + W + 0.5f*W*W);
46 return (I + W * sin(d) / d + W * W*(1.0f - cos(d)) / d2);
51 return ExpSO3(v.at<
float>(0), v.at<
float>(1), v.at<
float>(2));
57 poseCamera.at<
float>(0, 0) / poseCamera.at<
float>(2, 0)*mk.at<
float>(0, 0) + mk.at<
float>(0, 2),
58 poseCamera.at<
float>(1, 0) / poseCamera.at<
float>(2, 0)*mk.at<
float>(1, 1) + mk.at<
float>(1, 2)
62cv::Mat
Plane::DetectPlane(
const cv::Mat Tcw,
const std::vector<SD_SLAM::MapPoint*> &vMPs,
const int iterations)
65 std::vector<cv::Mat> vPoints;
66 vPoints.reserve(vMPs.size());
67 std::vector<SD_SLAM::MapPoint*> vPointMP;
68 vPointMP.reserve(vMPs.size());
70 for (
size_t i = 0; i < vMPs.size(); i++)
72 SD_SLAM::MapPoint* pMP = vMPs[i];
73 if (pMP && !pMP->isBad())
75 if (pMP->Observations() > 5)
77 Eigen::Vector3d Pos = pMP->GetWorldPos();
78 cv::Mat pos(cv::Point3f(Pos(0), Pos(1), Pos(2)));
79 vPoints.push_back(pos);
80 vPointMP.push_back(pMP);
85 const int N = vPoints.size();
91 std::vector<size_t> vAllIndices;
92 vAllIndices.reserve(N);
93 std::vector<size_t> vAvailableIndices;
95 for (
int i = 0; i < N; i++)
97 vAllIndices.push_back(i);
100 float bestDist = 1e10;
101 std::vector<float> bestvDist;
104 for (
int n = 0; n < iterations; n++)
106 vAvailableIndices = vAllIndices;
108 cv::Mat A(3, 4, CV_32F);
109 A.col(3) = cv::Mat::ones(3, 1, CV_32F);
112 for (
short i = 0; i < 3; ++i)
114 int randi = SD_SLAM::Random(0, vAvailableIndices.size() - 1);
116 int idx = vAvailableIndices[randi];
118 A.row(i).colRange(0, 3) = vPoints[idx].t();
120 vAvailableIndices[randi] = vAvailableIndices.back();
121 vAvailableIndices.pop_back();
125 cv::SVDecomp(A, w, u, vt, cv::SVD::MODIFY_A | cv::SVD::FULL_UV);
127 const float a = vt.at<
float>(3, 0);
128 const float b = vt.at<
float>(3, 1);
129 const float c = vt.at<
float>(3, 2);
130 const float d = vt.at<
float>(3, 3);
132 std::vector<float> vDistances(N, 0);
134 const float f = 1.0f / sqrt(a*a + b * b + c * c + d * d);
136 for (
int i = 0; i < N; i++)
138 vDistances[i] = fabs(vPoints[i].at<float>(0)*a + vPoints[i].at<float>(1)*b + vPoints[i].at<float>(2)*c + d)*f;
141 std::vector<float> vSorted = vDistances;
142 std::sort(vSorted.begin(), vSorted.end());
144 int nth = std::max((
int)(0.2*N), 20);
145 const float medianDist = vSorted[nth];
147 if (medianDist < bestDist)
149 bestDist = medianDist;
150 bestvDist = vDistances;
155 const float th = 1.4 * bestDist;
156 std::vector<bool> vbInliers(N,
false);
158 for (
int i = 0; i < N; i++)
160 if (bestvDist[i] < th)
167 std::vector<SD_SLAM::MapPoint*> vInlierMPs(nInliers, NULL);
169 for (
int i = 0; i < N; i++)
173 vInlierMPs[nin] = vPointMP[i];
180 mRang = -3.14f / 2 + ((float)rand() / RAND_MAX)*3.14f;
187 const int N =
mMvMPs.size();
190 cv::Mat A = cv::Mat(N, 4, CV_32F);
191 A.col(3) = cv::Mat::ones(N, 1, CV_32F);
193 mOrigin = cv::Mat::zeros(3, 1, CV_32F);
196 for (
int i = 0; i < N; i++)
198 SD_SLAM::MapPoint* pMP =
mMvMPs[i];
201 Eigen::Vector3d Pos = pMP->GetWorldPos();
202 cv::Mat Xw(cv::Point3f(Pos(0), Pos(1), Pos(2)));
204 A.row(nPoints).colRange(0, 3) = Xw.t();
211 cv::SVDecomp(A, w, u, vt, cv::SVD::MODIFY_A | cv::SVD::FULL_UV);
213 float a = vt.at<
float>(3, 0);
214 float b = vt.at<
float>(3, 1);
215 float c = vt.at<
float>(3, 2);
218 const float f = 1.0f / sqrt(a * a + b * b + c * c);
223 cv::Mat Oc = -
mMTcw.colRange(0, 3).rowRange(0, 3).t() *
mMTcw.rowRange(0, 3).col(3);
227 if ((
mXC.at<
float>(0) * a +
mXC.at<
float>(1) * b +
mXC.at<
float>(2) * c) < 0)
234 const float nx = a * f;
235 const float ny = b * f;
236 const float nz = c * f;
238 mNormal = (cv::Mat_<float>(3, 1) << nx, ny, nz);
241 up = (cv::Mat_<float>(3, 1) << 0.0f, 1.0f, 0.0f);
244 const float sa = cv::norm(v);
245 const float ca = up.dot(
mNormal);
246 const float ang = atan2(sa, ca);
247 mTpw = cv::Mat::eye(4, 4, CV_32F);
250 ExpSO3(v*ang / sa).copyTo(
mTpw.rowRange(0, 3).colRange(0, 3));
261 mInitialized =
false;
262 mPlane2World = cv::Mat::eye(4, 4, CV_32F);
264 SD_SLAM::Config ¶ms = SD_SLAM::Config::GetInstance();
265 params.SetCameraIntrinsics(640, 480, 640, 640, 320, 240);
266 params.SetUsePattern(
false);
267 params.SetOrbParameters(600);
287void Sslam::BuildCameraParam(
const aruco::CameraParameters &camparam)
290 int maxsize = std::max(camparam.CamSize.width, camparam.CamSize.height);
292 mScale = 640.0f / (float)maxsize;
295 SD_SLAM::Config ¶ms = SD_SLAM::Config::GetInstance();
296 double f = std::max((
int)(
static_cast<float>(camparam.CamSize.width) * mScale), (
int)(
static_cast<float>(camparam.CamSize.height) * mScale));
297 params.SetCameraIntrinsics((
int)(
static_cast<float>(camparam.CamSize.width) * mScale), (
int)(
static_cast<float>(camparam.CamSize.height) * mScale), f, f, (
int)(
static_cast<float>(camparam.CamSize.width) * mScale * 0.5f), (
int)(
static_cast<float>(camparam.CamSize.height) * mScale * 0.5f));
299 int wlvl = SD_SLAM::Config::Width();
300 int hlvl = SD_SLAM::Config::Height();
302 while (wlvl % 2 == 0 && hlvl % 2 == 0 && wlvl*hlvl > 5000 && pyrLevels < 12)
309 params.SetPyrLevels(pyrLevels);
312void Sslam::InitDetector()
314 boost::unique_lock<boost::recursive_mutex> ld(mUpdateMutex);
324 mSlam =
new SD_SLAM::System(SD_SLAM::System::MONOCULAR,
true);
325 mSlam->DeactivateLocalizationMode();
328 catch (std::exception &)
333 mInitialized =
false;
359 if (mSlam && !image.empty() && !mCameraWorld.empty())
362 const std::vector<SD_SLAM::MapPoint*> mapPoints = mSlam->GetMap()->GetAllMapPoints();
363 cv::Scalar color(0, 255, 0);
365 for (
unsigned int i = 0; i < mapPoints.size(); i++)
367 SD_SLAM::MapPoint* pMP = mapPoints[i];
368 if (pMP && (pMP->Observations() >= 3))
370 Eigen::Vector3d Pos = pMP->GetWorldPos();
371 cv::Mat pm4 = mCameraWorld * cv::Mat(cv::Vec4f(Pos(0), Pos(1), Pos(2), 1.0));
372 cv::circle(image,
Camera2Pixel(pm4, mLastData.camParam.CameraMatrix), 2, color);
376 if (!mCentroid.empty() && (mSlam->GetTrackingState() == 2))
378 std::vector<cv::Mat> axisPoints(4);
379 axisPoints[0] = (cv::Mat_ <float>(4, 1) << 0.0, 0, 0, 1);
380 axisPoints[1] = (cv::Mat_ <float>(4, 1) << 0.3, 0, 0, 1);
381 axisPoints[2] = (cv::Mat_ <float>(4, 1) << 0.0, 0.3, 0, 1);
382 axisPoints[3] = (cv::Mat_ <float>(4, 1) << 0, 0, 0.3, 1);
383 std::vector<cv::Point2f> drawPoints(4);
384 for (
int i = 0; i < 4; i++)
386 axisPoints[i] = mPlane2Camera * axisPoints[i];
387 drawPoints[i] =
Camera2Pixel(axisPoints[i], mLastData.camParam.CameraMatrix);
390 cv::line(image, drawPoints[0], drawPoints[1], cv::Scalar(250, 0, 0), 5);
391 cv::line(image, drawPoints[0], drawPoints[2], cv::Scalar(0, 250, 0), 5);
392 cv::line(image, drawPoints[0], drawPoints[3], cv::Scalar(0, 0, 250), 5);
428 switch (mSlam->GetTrackingState())
430 case -1: {cv::putText(image,
"SYSTEM NOT READY", cv::Point(100, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1); }
break;
431 case 0: {cv::putText(image,
"NO IMAGES YET", cv::Point(100, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1); }
break;
432 case 1: {cv::putText(image,
"SLAM NOT INITIALIZED", cv::Point(100, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1); }
break;
433 case 2: {cv::putText(image,
"SLAM ON", cv::Point(100, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 1);
break; }
434 case 3: {cv::putText(image,
"SLAM LOST", cv::Point(100, 50), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1);
break; }
443 int prevState = mSlam->GetTrackingState();
446 boost::unique_lock<boost::recursive_mutex> ld(mUpdateMutex);
448 Eigen::Matrix4d epose = mSlam->TrackMonocular(mLastData.
gray);
450 eigen2cv(epose, cpose);
451 cpose.convertTo(pose, CV_32F);
453 if (mSlam->MapChanged() || (mSlam->GetTrackingState() < 2))
455 mInitialized =
false;
462 pose.copyTo(mCameraWorld);
464 if (pose.empty() || (mSlam->GetTrackingState() != 2))
468 if ((prevState == 2) && (mSlam->GetTrackingState() == 3))
469 mTimestamp = std::chrono::steady_clock::now();
471 double passed = std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::steady_clock::now() - mTimestamp).count();
472 if ((mSlam->GetTrackingState() == 3) && (passed > 4))
480 const std::vector<SD_SLAM::MapPoint*> vpMPs = mSlam->GetMap()->GetAllMapPoints();
482 if (vpMPs.size() > 200)
484 mPlane2World = mplane.
DetectPlane(pose, vpMPs, 50);
486 if (!mPlane2World.empty())
490 mPlane2Camera = pose * mPlane2World;
496 mPlane2Camera = pose * mPlane2World;
499 if (!mInitialized || pose.empty())
506 cv::Mat camtoplane = mPlane2Camera.inv();
508 double modelview_matrix[16];
509 modelview_matrix[0] = -camtoplane.at<
float>(0, 0);
510 modelview_matrix[1] = -camtoplane.at<
float>(1, 0);
511 modelview_matrix[2] = -camtoplane.at<
float>(2, 0);
512 modelview_matrix[3] = 0.0;
514 modelview_matrix[4] = camtoplane.at<
float>(0, 1);
515 modelview_matrix[5] = camtoplane.at<
float>(1, 1);
516 modelview_matrix[6] = camtoplane.at<
float>(2, 1);
517 modelview_matrix[7] = 0.0;
519 modelview_matrix[8] = camtoplane.at<
float>(0, 2);
520 modelview_matrix[9] = camtoplane.at<
float>(1, 2);
521 modelview_matrix[10] = camtoplane.at<
float>(2, 2);
522 modelview_matrix[11] = 0.0;
524 modelview_matrix[12] = camtoplane.at<
float>(0, 3);
525 modelview_matrix[13] = camtoplane.at<
float>(1, 3);
526 modelview_matrix[14] = camtoplane.at<
float>(2, 3);
527 modelview_matrix[15] = 1.0;
530 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]));
550 if (!mSlam || (((
int)((
float)mLastData.camParam.CamSize.width * mScale)) != SD_SLAM::Config::Width() || ((
int)((
float)mLastData.camParam.CamSize.height * mScale)) != SD_SLAM::Config::Height()))
557 BuildCameraParam(mLastData.camParam);
562 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);
567 if (!mLastData.
image.empty() && mSlam)
575 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)
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)
cv::Mat ExpSO3(const float &x, const float &y, const float &z)
cv::Point2f Camera2Pixel(cv::Mat poseCamera, cv::Mat mk)