/** * This file is part of ORB-SLAM2. * * Copyright (C) 2014-2016 Raúl Mur-Artal (University of Zaragoza) * For more information see * * ORB-SLAM2 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ORB-SLAM2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ORB-SLAM2. If not, see . */ #include "Tracking.h" #include #include #include "ORBmatcher.h" #include "FrameDrawer.h" #include "Converter.h" #include "Map.h" #include "Initializer.h" #include "Optimizer.h" #include "PnPsolver.h" #include #include #include using namespace std; namespace ORB_SLAM2 { Tracking::Tracking(System *pSys, ORBVocabulary *pVoc, FrameDrawer *pFrameDrawer, MapDrawer *pMapDrawer, Map *pMap, KeyFrameDatabase *pKFDB, const string &strSettingPath, const int sensor) : mState(NO_IMAGES_YET), mSensor(sensor), mbOnlyTracking(false), mbVO(false), mpORBVocabulary(pVoc), mpKeyFrameDB(pKFDB), mpInitializer(static_cast(NULL)), mpSystem(pSys), mpViewer(NULL), mpFrameDrawer(pFrameDrawer), mpMapDrawer(pMapDrawer), mpMap(pMap), mnLastRelocFrameId(0) { // Load camera parameters from settings file cv::FileStorage fSettings(strSettingPath, cv::FileStorage::READ); float fx = fSettings["Camera.fx"]; float fy = fSettings["Camera.fy"]; float cx = fSettings["Camera.cx"]; float cy = fSettings["Camera.cy"]; cv::Mat K = cv::Mat::eye(3, 3, CV_32F); K.at(0, 0) = fx; K.at(1, 1) = fy; K.at(0, 2) = cx; K.at(1, 2) = cy; K.copyTo(mK); cv::Mat DistCoef(4, 1, CV_32F); DistCoef.at(0) = fSettings["Camera.k1"]; DistCoef.at(1) = fSettings["Camera.k2"]; DistCoef.at(2) = fSettings["Camera.p1"]; DistCoef.at(3) = fSettings["Camera.p2"]; const float k3 = fSettings["Camera.k3"]; if (k3 != 0) { DistCoef.resize(5); DistCoef.at(4) = k3; } DistCoef.copyTo(mDistCoef); mbf = fSettings["Camera.bf"]; float fps = fSettings["Camera.fps"]; if (fps == 0) fps = 30; // Max/Min Frames to insert keyframes and to check relocalisation mMinFrames = 0; mMaxFrames = fps; cout << endl << "Camera Parameters: " << endl; cout << "- fx: " << fx << endl; cout << "- fy: " << fy << endl; cout << "- cx: " << cx << endl; cout << "- cy: " << cy << endl; cout << "- k1: " << DistCoef.at(0) << endl; cout << "- k2: " << DistCoef.at(1) << endl; if (DistCoef.rows == 5) cout << "- k3: " << DistCoef.at(4) << endl; cout << "- p1: " << DistCoef.at(2) << endl; cout << "- p2: " << DistCoef.at(3) << endl; cout << "- fps: " << fps << endl; int nRGB = fSettings["Camera.RGB"]; mbRGB = nRGB; if (mbRGB) cout << "- color order: RGB (ignored if grayscale)" << endl; else cout << "- color order: BGR (ignored if grayscale)" << endl; // Load ORB parameters m_bev_K = (cv::Mat_(3, 3) << 608.0 / 50.0, 0, 304, 0, 608.0 / 50.0, 608, 0, 0, 1); m_bev_K_invers = (cv::Mat_(3, 3) << 50.0 / 608.0, 0, -25, 0, 50.0 / 608.0, -50, 0, 0, 1); int nFeatures = fSettings["ORBextractor.nFeatures"]; float fScaleFactor = fSettings["ORBextractor.scaleFactor"]; int nLevels = fSettings["ORBextractor.nLevels"]; int fIniThFAST = fSettings["ORBextractor.iniThFAST"]; int fMinThFAST = fSettings["ORBextractor.minThFAST"]; mpORBextractorLeft = new ORBextractor(nFeatures, fScaleFactor, nLevels, fIniThFAST, fMinThFAST); if (sensor == System::STEREO) mpORBextractorRight = new ORBextractor(nFeatures, fScaleFactor, nLevels, fIniThFAST, fMinThFAST); if (sensor == System::MONOCULAR) mpIniORBextractor = new ORBextractor(2 * nFeatures, fScaleFactor, nLevels, fIniThFAST, fMinThFAST); cout << endl << "ORB Extractor Parameters: " << endl; cout << "- Number of Features: " << nFeatures << endl; cout << "- Scale Levels: " << nLevels << endl; cout << "- Scale Factor: " << fScaleFactor << endl; cout << "- Initial Fast Threshold: " << fIniThFAST << endl; cout << "- Minimum Fast Threshold: " << fMinThFAST << endl; if (sensor == System::STEREO || sensor == System::RGBD) { mThDepth = mbf * (float)fSettings["ThDepth"] / fx; cout << endl << "Depth Threshold (Close/Far Points): " << mThDepth << endl; } if (sensor == System::RGBD) { mDepthMapFactor = fSettings["DepthMapFactor"]; if (fabs(mDepthMapFactor) < 1e-5) mDepthMapFactor = 1; else mDepthMapFactor = 1.0f / mDepthMapFactor; } mMap_car = cv::Mat::zeros(1000, 1000, CV_8UC3); } void Tracking::SetLocalMapper(LocalMapping *pLocalMapper) { mpLocalMapper = pLocalMapper; } void Tracking::SetLoopClosing(LoopClosing *pLoopClosing) { mpLoopClosing = pLoopClosing; } void Tracking::SetViewer(Viewer *pViewer) { mpViewer = pViewer; } cv::Mat Tracking::GrabImageStereo(const cv::Mat &imRectLeft, const cv::Mat &imRectRight, const double ×tamp, vector> &vvLabel, cv::Mat &imbev, double &delta_t) { mbcreateKeyFrame = false; mdelta_t = delta_t; mImGray = imRectLeft; mImRGB = imRectLeft; cv::Mat imGrayRight = imRectRight; if (mImGray.channels() == 3) { if (mbRGB) { cvtColor(mImGray, mImGray, CV_RGB2GRAY); cvtColor(imGrayRight, imGrayRight, CV_RGB2GRAY); } else { cvtColor(mImGray, mImGray, CV_BGR2GRAY); cvtColor(imGrayRight, imGrayRight, CV_BGR2GRAY); } } else if (mImGray.channels() == 4) { if (mbRGB) { cvtColor(mImGray, mImGray, CV_RGBA2GRAY); cvtColor(imGrayRight, imGrayRight, CV_RGBA2GRAY); } else { cvtColor(mImGray, mImGray, CV_BGRA2GRAY); cvtColor(imGrayRight, imGrayRight, CV_BGRA2GRAY); } } // 过去到当前帧 cv::Mat Velocity; bool state = false; cv::Mat CamPosePredict = cv::Mat::eye(4, 4, CV_32FC1); if (mState == NO_IMAGES_YET) { mState = NOT_INITIALIZED; } if (mState == NOT_INITIALIZED) state = true; if (!state) { Velocity = Tracking::GetVelocity(); // 这里是匀速运动模型,使用上一帧作为当前估计 if (Velocity.empty()) Velocity = cv::Mat::zeros(4, 4, CV_32FC1) = cv::Mat::zeros(4, 4, CV_32FC1); CamPosePredict = Velocity * mLastFrame_Tcw; } updateCarState(); // 更新车辆状态 mCurrentFrame = Frame(mImGray, imGrayRight, timestamp, mpORBextractorLeft, mpORBextractorRight, mpORBVocabulary, mK, mDistCoef, mbf, mThDepth, vvLabel, CamPosePredict, state, mvpCar); Track(); // cout << "当前位置: " << mCurrentFrame.mTcw.at(0, 3) << " " << mCurrentFrame.mTcw.at(1, 3) << " " << mCurrentFrame.mTcw.at(2, 3) << endl; mCurrentFrame.mTcw.copyTo(mLastFrame_Tcw); return mCurrentFrame.mTcw.clone(); } cv::Mat Tracking::GrabImageRGBD(const cv::Mat &imRGB, const cv::Mat &imD, const double ×tamp, const vector> &vvLabel) { mImGray = imRGB; cv::Mat imDepth = imD; if (mImGray.channels() == 3) { if (mbRGB) cvtColor(mImGray, mImGray, CV_RGB2GRAY); else cvtColor(mImGray, mImGray, CV_BGR2GRAY); } else if (mImGray.channels() == 4) { if (mbRGB) cvtColor(mImGray, mImGray, CV_RGBA2GRAY); else cvtColor(mImGray, mImGray, CV_BGRA2GRAY); } if ((fabs(mDepthMapFactor - 1.0f) > 1e-5) || imDepth.type() != CV_32F) imDepth.convertTo(imDepth, CV_32F, mDepthMapFactor); // 获得相对位姿,进行模板匹配 --by钟 cv::Mat Velocity = cv::Mat::zeros(4, 4, CV_32FC1); cv::Mat Lastframe = cv::Mat::zeros(imD.size(), CV_8UC1); bool state = false; if (mState == NO_IMAGES_YET) { mState = NOT_INITIALIZED; } if (mState == NOT_INITIALIZED) state = true; if (!state) { Velocity = Tracking::GetVelocity(); mLastFrame.mframe.copyTo(Lastframe); } mCurrentFrame = Frame(mImGray, imDepth, timestamp, mpORBextractorLeft, mpORBVocabulary, mK, mDistCoef, mbf, mThDepth, vvLabel, Velocity, state, Lastframe, mDepthMapFactor, imRGB); Track(); return mCurrentFrame.mTcw.clone(); } cv::Mat Tracking::GrabImageMonocular(const cv::Mat &im, const double ×tamp) { mImGray = im; if (mImGray.channels() == 3) { if (mbRGB) cvtColor(mImGray, mImGray, CV_RGB2GRAY); else cvtColor(mImGray, mImGray, CV_BGR2GRAY); } else if (mImGray.channels() == 4) { if (mbRGB) cvtColor(mImGray, mImGray, CV_RGBA2GRAY); else cvtColor(mImGray, mImGray, CV_BGRA2GRAY); } if (mState == NOT_INITIALIZED || mState == NO_IMAGES_YET) mCurrentFrame = Frame(mImGray, timestamp, mpIniORBextractor, mpORBVocabulary, mK, mDistCoef, mbf, mThDepth); else mCurrentFrame = Frame(mImGray, timestamp, mpORBextractorLeft, mpORBVocabulary, mK, mDistCoef, mbf, mThDepth); Track(); return mCurrentFrame.mTcw.clone(); } void Tracking::Track() { if (mState == NO_IMAGES_YET) { mState = NOT_INITIALIZED; } mLastProcessedState = mState; // Get Map Mutex -> Map cannot be changed unique_lock lock(mpMap->mMutexMapUpdate); if (mState == NOT_INITIALIZED) { if (mSensor == System::STEREO || mSensor == System::RGBD) StereoInitialization(); else MonocularInitialization(); mpFrameDrawer->Update(this); if (mState != OK) return; } else { // System is initialized. Track Frame. bool bOK; // Initial camera pose estimation using motion model or relocalization (if tracking is lost) if (!mbOnlyTracking) { // Local Mapping is activated. This is the normal behaviour, unless // you explicitly activate the "only tracking" mode. if (mState == OK) { // Local Mapping might have changed some MapPoints tracked in last frame CheckReplacedInLastFrame(); if (mVelocity.empty() || mCurrentFrame.mnId < mnLastRelocFrameId + 2) { bOK = TrackReferenceKeyFrame(); } else { bOK = TrackWithMotionModel(); if (!bOK) bOK = TrackReferenceKeyFrame(); } } else { bOK = Relocalization(); } } else { // Localization Mode: Local Mapping is deactivated if (mState == LOST) { bOK = Relocalization(); } else { if (!mbVO) { // In last frame we tracked enough MapPoints in the map if (!mVelocity.empty()) { bOK = TrackWithMotionModel(); } else { bOK = TrackReferenceKeyFrame(); } } else { // In last frame we tracked mainly "visual odometry" points. // We compute two camera poses, one from motion model and one doing relocalization. // If relocalization is sucessfull we choose that solution, otherwise we retain // the "visual odometry" solution. bool bOKMM = false; bool bOKReloc = false; vector vpMPsMM; vector vbOutMM; cv::Mat TcwMM; if (!mVelocity.empty()) { bOKMM = TrackWithMotionModel(); vpMPsMM = mCurrentFrame.mvpMapPoints; vbOutMM = mCurrentFrame.mvbOutlier; TcwMM = mCurrentFrame.mTcw.clone(); } bOKReloc = Relocalization(); if (bOKMM && !bOKReloc) { mCurrentFrame.SetPose(TcwMM); mCurrentFrame.mvpMapPoints = vpMPsMM; mCurrentFrame.mvbOutlier = vbOutMM; if (mbVO) { for (int i = 0; i < mCurrentFrame.N; i++) { if (mCurrentFrame.mvpMapPoints[i] && !mCurrentFrame.mvbOutlier[i]) { mCurrentFrame.mvpMapPoints[i]->IncreaseFound(); } } } } else if (bOKReloc) { mbVO = false; } bOK = bOKReloc || bOKMM; } } } mCurrentFrame.mpReferenceKF = mpReferenceKF; // If we have an initial estimation of the camera pose and matching. Track the local map. if (!mbOnlyTracking) { if (bOK) bOK = TrackLocalMap(); } else { // mbVO true means that there are few matches to MapPoints in the map. We cannot retrieve // a local map and therefore we do not perform TrackLocalMap(). Once the system relocalizes // the camera we will use the local map again. if (bOK && !mbVO) bOK = TrackLocalMap(); } if (bOK) mState = OK; else mState = LOST; // Update drawer mpFrameDrawer->Update(this); // If tracking were good, check if we insert a keyframe if (bOK) { // Update motion model if (!mLastFrame.mTcw.empty()) { cv::Mat LastTwc = cv::Mat::eye(4, 4, CV_32F); mLastFrame.GetRotationInverse().copyTo(LastTwc.rowRange(0, 3).colRange(0, 3)); mLastFrame.GetCameraCenter().copyTo(LastTwc.rowRange(0, 3).col(3)); mVelocity = mCurrentFrame.mTcw * LastTwc; } else mVelocity = cv::Mat(); mpMapDrawer->SetCurrentCameraPose(mCurrentFrame.mTcw); // Clean VO matches for (int i = 0; i < mCurrentFrame.N; i++) { MapPoint *pMP = mCurrentFrame.mvpMapPoints[i]; if (pMP) if (pMP->Observations() < 1) { mCurrentFrame.mvbOutlier[i] = false; mCurrentFrame.mvpMapPoints[i] = static_cast(NULL); } } // Delete temporal MapPoints for (list::iterator lit = mlpTemporalPoints.begin(), lend = mlpTemporalPoints.end(); lit != lend; lit++) { MapPoint *pMP = *lit; delete pMP; } mlpTemporalPoints.clear(); Track_Car(); // Check if we need to insert a new keyframe if (NeedNewKeyFrame()) { mbcreateKeyFrame = true; CreateNewKeyFrame(); } // We allow points with high innovation (considererd outliers by the Huber Function) // pass to the new keyframe, so that bundle adjustment will finally decide // if they are outliers or not. We don't want next frame to estimate its position // with those points so we discard them in the frame. for (int i = 0; i < mCurrentFrame.N; i++) { if (mCurrentFrame.mvpMapPoints[i] && mCurrentFrame.mvbOutlier[i]) mCurrentFrame.mvpMapPoints[i] = static_cast(NULL); } } // Reset if the camera get lost soon after initialization if (mState == LOST) { if (mpMap->KeyFramesInMap() <= 5) { cout << "Track lost soon after initialisation, reseting..." << endl; mpSystem->Reset(); return; } } if (!mCurrentFrame.mpReferenceKF) mCurrentFrame.mpReferenceKF = mpReferenceKF; mLastFrame = Frame(mCurrentFrame); } // Store frame pose information to retrieve the complete camera trajectory afterwards. if (!mCurrentFrame.mTcw.empty()) { cv::Mat Tcr = mCurrentFrame.mTcw * mCurrentFrame.mpReferenceKF->GetPoseInverse(); mlRelativeFramePoses.push_back(Tcr); mlpReferences.push_back(mpReferenceKF); mlFrameTimes.push_back(mCurrentFrame.mTimeStamp); mlbLost.push_back(mState == LOST); } else { // This can happen if tracking is lost mlRelativeFramePoses.push_back(mlRelativeFramePoses.back()); mlpReferences.push_back(mlpReferences.back()); mlFrameTimes.push_back(mlFrameTimes.back()); mlbLost.push_back(mState == LOST); } } void Tracking::Track_Car() { // 重新获得需要跟踪车辆的个数 int n_Car = mvpCar.size(); mvvCarV.clear(); // 添加观测,新建车辆模型 for (int i = 0; i < mCurrentFrame.mvvLabel.size(); i++) { vector bbox = mCurrentFrame.mvvLabel[i]; if (bbox[0] == -1) continue; if (mCurrentFrame.mvCarMatches[i] >= 0) { Car *car = mvpCar[mCurrentFrame.mvCarMatches[i]]; // step1:更新最近观测帧 car->updateObservations(mCurrentFrame.mnId); // step2: 更新目标框对应关系 // pair p1(mCurrentFrame.mnId, index); // car->mv_pair_connect.push_back(p1); car->setTrackedState(true); // 跟像跟踪状态 // step3: 更新世界位置和速度 car->updateState(bbox, mCurrentFrame.mRwc, mCurrentFrame.mOw, mdelta_t); } } // 跟踪丢失车辆并更新数据库所有车辆的轨迹 for (int j = 0; j < n_Car; j++) { Car *car = mvpCar[j]; if (!car->isBad() && !car->isTracked()) { car->update_untracked_Car(); } if (!car->isBad()) { car->updatetraj(); double v = car->get_Vel(mdelta_t); // 对mvvCarV 添加 u,v,vel Get_Motion_Car_V(car); } } } void Tracking::updateCarState() { for (int i = 0; i < mvpCar.size(); i++) { auto car = mvpCar[i]; if (car->isErro()) { mvpCar.erase(mvpCar.begin() + i); mpMap->EraseMapCar(car); delete car; i--; continue; } car->InCreaseFound(mLastFrame_Tcw); car->setTrackedState(false); // 设置当前跟踪状态,还没开始跟踪 car->updateTrackState(mCurrentFrame.mnId + 1); // 设置跟踪是否丢失 PredictCarPos(car); // 预测车辆位置 } } void Tracking::StereoInitialization() { if (mCurrentFrame.N > 500) { // Set Frame pose to the origin mCurrentFrame.SetPose(cv::Mat::eye(4, 4, CV_32F)); // Create KeyFrame KeyFrame *pKFini = new KeyFrame(mCurrentFrame, mpMap, mpKeyFrameDB); // Insert KeyFrame in the map mpMap->AddKeyFrame(pKFini); // Create MapPoints and asscoiate to KeyFrame for (int i = 0; i < mCurrentFrame.N; i++) { float z = mCurrentFrame.mvDepth[i]; if (z > 0) { cv::Mat x3D = mCurrentFrame.UnprojectStereo(i); MapPoint *pNewMP = new MapPoint(x3D, pKFini, mpMap); pNewMP->AddObservation(pKFini, i); pKFini->AddMapPoint(pNewMP, i); pNewMP->ComputeDistinctiveDescriptors(); pNewMP->UpdateNormalAndDepth(); mpMap->AddMapPoint(pNewMP); mCurrentFrame.mvpMapPoints[i] = pNewMP; } } for (int i = 0; i < mCurrentFrame.mvvLabel.size(); i++) { if (mCurrentFrame.mvCarMatches[i] == -2) { Car *new_car = new Car(mCurrentFrame, mCurrentFrame.mvvLabel[i]); mvpCar.push_back(new_car); mpMap->AddMapCar(new_car); } } cout << "New map created with " << mpMap->MapPointsInMap() << " points" << endl; cout << "New map created with " << mpMap->GetAllMapCars().size() << " Cars" << endl; mpLocalMapper->InsertKeyFrame(pKFini); mLastFrame = Frame(mCurrentFrame); mnLastKeyFrameId = mCurrentFrame.mnId; mpLastKeyFrame = pKFini; mvpLocalKeyFrames.push_back(pKFini); mvpLocalMapPoints = mpMap->GetAllMapPoints(); mpReferenceKF = pKFini; mCurrentFrame.mpReferenceKF = pKFini; mpMap->SetReferenceMapPoints(mvpLocalMapPoints); mpMap->mvpKeyFrameOrigins.push_back(pKFini); mpMapDrawer->SetCurrentCameraPose(mCurrentFrame.mTcw); mState = OK; } } void Tracking::MonocularInitialization() { if (!mpInitializer) { // Set Reference Frame if (mCurrentFrame.mvKeys.size() > 100) { mInitialFrame = Frame(mCurrentFrame); mLastFrame = Frame(mCurrentFrame); mvbPrevMatched.resize(mCurrentFrame.mvKeysUn.size()); for (size_t i = 0; i < mCurrentFrame.mvKeysUn.size(); i++) mvbPrevMatched[i] = mCurrentFrame.mvKeysUn[i].pt; if (mpInitializer) delete mpInitializer; mpInitializer = new Initializer(mCurrentFrame, 1.0, 200); fill(mvIniMatches.begin(), mvIniMatches.end(), -1); return; } } else { // Try to initialize if ((int)mCurrentFrame.mvKeys.size() <= 100) { delete mpInitializer; mpInitializer = static_cast(NULL); fill(mvIniMatches.begin(), mvIniMatches.end(), -1); return; } // Find correspondences ORBmatcher matcher(0.9, true); int nmatches = matcher.SearchForInitialization(mInitialFrame, mCurrentFrame, mvbPrevMatched, mvIniMatches, 100); // Check if there are enough correspondences if (nmatches < 100) { delete mpInitializer; mpInitializer = static_cast(NULL); return; } cv::Mat Rcw; // Current Camera Rotation cv::Mat tcw; // Current Camera Translation vector vbTriangulated; // Triangulated Correspondences (mvIniMatches) if (mpInitializer->Initialize(mCurrentFrame, mvIniMatches, Rcw, tcw, mvIniP3D, vbTriangulated)) { for (size_t i = 0, iend = mvIniMatches.size(); i < iend; i++) { if (mvIniMatches[i] >= 0 && !vbTriangulated[i]) { mvIniMatches[i] = -1; nmatches--; } } // Set Frame Poses mInitialFrame.SetPose(cv::Mat::eye(4, 4, CV_32F)); cv::Mat Tcw = cv::Mat::eye(4, 4, CV_32F); Rcw.copyTo(Tcw.rowRange(0, 3).colRange(0, 3)); tcw.copyTo(Tcw.rowRange(0, 3).col(3)); mCurrentFrame.SetPose(Tcw); CreateInitialMapMonocular(); } } } void Tracking::CreateInitialMapMonocular() { // Create KeyFrames KeyFrame *pKFini = new KeyFrame(mInitialFrame, mpMap, mpKeyFrameDB); KeyFrame *pKFcur = new KeyFrame(mCurrentFrame, mpMap, mpKeyFrameDB); pKFini->ComputeBoW(); pKFcur->ComputeBoW(); // Insert KFs in the map mpMap->AddKeyFrame(pKFini); mpMap->AddKeyFrame(pKFcur); // Create MapPoints and asscoiate to keyframes for (size_t i = 0; i < mvIniMatches.size(); i++) { if (mvIniMatches[i] < 0) continue; // Create MapPoint. cv::Mat worldPos(mvIniP3D[i]); MapPoint *pMP = new MapPoint(worldPos, pKFcur, mpMap); pKFini->AddMapPoint(pMP, i); pKFcur->AddMapPoint(pMP, mvIniMatches[i]); pMP->AddObservation(pKFini, i); pMP->AddObservation(pKFcur, mvIniMatches[i]); pMP->ComputeDistinctiveDescriptors(); pMP->UpdateNormalAndDepth(); // Fill Current Frame structure mCurrentFrame.mvpMapPoints[mvIniMatches[i]] = pMP; mCurrentFrame.mvbOutlier[mvIniMatches[i]] = false; // Add to Map mpMap->AddMapPoint(pMP); } // Update Connections pKFini->UpdateConnections(); pKFcur->UpdateConnections(); // Bundle Adjustment cout << "New Map created with " << mpMap->MapPointsInMap() << " points" << endl; Optimizer::GlobalBundleAdjustemnt(mpMap, 20); // Set median depth to 1 float medianDepth = pKFini->ComputeSceneMedianDepth(2); float invMedianDepth = 1.0f / medianDepth; if (medianDepth < 0 || pKFcur->TrackedMapPoints(1) < 100) { cout << "Wrong initialization, reseting..." << endl; Reset(); return; } // Scale initial baseline cv::Mat Tc2w = pKFcur->GetPose(); Tc2w.col(3).rowRange(0, 3) = Tc2w.col(3).rowRange(0, 3) * invMedianDepth; pKFcur->SetPose(Tc2w); // Scale points vector vpAllMapPoints = pKFini->GetMapPointMatches(); for (size_t iMP = 0; iMP < vpAllMapPoints.size(); iMP++) { if (vpAllMapPoints[iMP]) { MapPoint *pMP = vpAllMapPoints[iMP]; pMP->SetWorldPos(pMP->GetWorldPos() * invMedianDepth); } } mpLocalMapper->InsertKeyFrame(pKFini); mpLocalMapper->InsertKeyFrame(pKFcur); mCurrentFrame.SetPose(pKFcur->GetPose()); mnLastKeyFrameId = mCurrentFrame.mnId; mpLastKeyFrame = pKFcur; mvpLocalKeyFrames.push_back(pKFcur); mvpLocalKeyFrames.push_back(pKFini); mvpLocalMapPoints = mpMap->GetAllMapPoints(); mpReferenceKF = pKFcur; mCurrentFrame.mpReferenceKF = pKFcur; mLastFrame = Frame(mCurrentFrame); mpMap->SetReferenceMapPoints(mvpLocalMapPoints); mpMapDrawer->SetCurrentCameraPose(pKFcur->GetPose()); mpMap->mvpKeyFrameOrigins.push_back(pKFini); mState = OK; } void Tracking::CheckReplacedInLastFrame() { for (int i = 0; i < mLastFrame.N; i++) { MapPoint *pMP = mLastFrame.mvpMapPoints[i]; if (pMP) { MapPoint *pRep = pMP->GetReplaced(); if (pRep) { mLastFrame.mvpMapPoints[i] = pRep; } } } } bool Tracking::TrackReferenceKeyFrame() { // Compute Bag of Words vector mCurrentFrame.ComputeBoW(); // We perform first an ORB matching with the reference keyframe // If enough matches are found we setup a PnP solver ORBmatcher matcher(0.7, true); vector vpMapPointMatches; int nmatches = matcher.SearchByBoW(mpReferenceKF, mCurrentFrame, vpMapPointMatches); if (nmatches < 15) return false; mCurrentFrame.mvpMapPoints = vpMapPointMatches; mCurrentFrame.SetPose(mLastFrame.mTcw); Optimizer::PoseOptimization(&mCurrentFrame); // Discard outliers int nmatchesMap = 0; for (int i = 0; i < mCurrentFrame.N; i++) { if (mCurrentFrame.mvpMapPoints[i]) { if (mCurrentFrame.mvbOutlier[i]) { MapPoint *pMP = mCurrentFrame.mvpMapPoints[i]; mCurrentFrame.mvpMapPoints[i] = static_cast(NULL); mCurrentFrame.mvbOutlier[i] = false; pMP->mbTrackInView = false; pMP->mnLastFrameSeen = mCurrentFrame.mnId; nmatches--; } else if (mCurrentFrame.mvpMapPoints[i]->Observations() > 0) nmatchesMap++; } } return nmatchesMap >= 10; } void Tracking::UpdateLastFrame() { // Update pose according to reference keyframe KeyFrame *pRef = mLastFrame.mpReferenceKF; cv::Mat Tlr = mlRelativeFramePoses.back(); mLastFrame.SetPose(Tlr * pRef->GetPose()); if (mnLastKeyFrameId == mLastFrame.mnId || mSensor == System::MONOCULAR || !mbOnlyTracking) return; // Create "visual odometry" MapPoints // We sort points according to their measured depth by the stereo/RGB-D sensor vector> vDepthIdx; vDepthIdx.reserve(mLastFrame.N); for (int i = 0; i < mLastFrame.N; i++) { float z = mLastFrame.mvDepth[i]; if (z > 0) { vDepthIdx.push_back(make_pair(z, i)); } } if (vDepthIdx.empty()) return; sort(vDepthIdx.begin(), vDepthIdx.end()); // We insert all close points (depthObservations() < 1) { bCreateNew = true; } if (bCreateNew) { cv::Mat x3D = mLastFrame.UnprojectStereo(i); MapPoint *pNewMP = new MapPoint(x3D, mpMap, &mLastFrame, i); mLastFrame.mvpMapPoints[i] = pNewMP; mlpTemporalPoints.push_back(pNewMP); nPoints++; } else { nPoints++; } if (vDepthIdx[j].first > mThDepth && nPoints > 100) break; } } bool Tracking::TrackWithMotionModel() { ORBmatcher matcher(0.9, true); // Update last frame pose according to its reference keyframe // Create "visual odometry" points if in Localization Mode UpdateLastFrame(); mCurrentFrame.SetPose(mVelocity * mLastFrame.mTcw); fill(mCurrentFrame.mvpMapPoints.begin(), mCurrentFrame.mvpMapPoints.end(), static_cast(NULL)); // Project points seen in previous frame int th; if (mSensor != System::STEREO) th = 15; else th = 7; int nmatches = matcher.SearchByProjection(mCurrentFrame, mLastFrame, th, mSensor == System::MONOCULAR); // If few matches, uses a wider window search if (nmatches < 20) { fill(mCurrentFrame.mvpMapPoints.begin(), mCurrentFrame.mvpMapPoints.end(), static_cast(NULL)); nmatches = matcher.SearchByProjection(mCurrentFrame, mLastFrame, 2 * th, mSensor == System::MONOCULAR); } if (nmatches < 20) return false; // Optimize frame pose with all matches // Optimizer::PoseOptimization(&mCurrentFrame); Optimizer::PoseOptimizationWithCars(&mCurrentFrame); // Discard outliers int nmatchesMap = 0; for (int i = 0; i < mCurrentFrame.N; i++) { if (mCurrentFrame.mvpMapPoints[i]) { if (mCurrentFrame.mvbOutlier[i]) { MapPoint *pMP = mCurrentFrame.mvpMapPoints[i]; mCurrentFrame.mvpMapPoints[i] = static_cast(NULL); mCurrentFrame.mvbOutlier[i] = false; pMP->mbTrackInView = false; pMP->mnLastFrameSeen = mCurrentFrame.mnId; nmatches--; } else if (mCurrentFrame.mvpMapPoints[i]->Observations() > 0) nmatchesMap++; } } if (mbOnlyTracking) { mbVO = nmatchesMap < 10; return nmatches > 20; } return nmatchesMap >= 10; } bool Tracking::TrackLocalMap() { // We have an estimation of the camera pose and some map points tracked in the frame. // We retrieve the local map and try to find matches to points in the local map. UpdateLocalMap(); SearchLocalPoints(); // Optimize Pose // Optimizer::PoseOptimization(&mCurrentFrame); Optimizer::PoseOptimizationWithCars(&mCurrentFrame); mnMatchesInliers = 0; // Update MapPoints Statistics for (int i = 0; i < mCurrentFrame.N; i++) { if (mCurrentFrame.mvpMapPoints[i]) { if (!mCurrentFrame.mvbOutlier[i]) { mCurrentFrame.mvpMapPoints[i]->IncreaseFound(); if (!mbOnlyTracking) { if (mCurrentFrame.mvpMapPoints[i]->Observations() > 0) mnMatchesInliers++; } else mnMatchesInliers++; } else if (mSensor == System::STEREO) mCurrentFrame.mvpMapPoints[i] = static_cast(NULL); } } // Decide if the tracking was succesful // More restrictive if there was a relocalization recently if (mCurrentFrame.mnId < mnLastRelocFrameId + mMaxFrames && mnMatchesInliers < 50) return false; if (mnMatchesInliers < 30) return false; else return true; } bool Tracking::NeedNewKeyFrame() { if (mbOnlyTracking) return false; // If Local Mapping is freezed by a Loop Closure do not insert keyframes if (mpLocalMapper->isStopped() || mpLocalMapper->stopRequested()) return false; const int nKFs = mpMap->KeyFramesInMap(); // Do not insert keyframes if not enough frames have passed from last relocalisation if (mCurrentFrame.mnId < mnLastRelocFrameId + mMaxFrames && nKFs > mMaxFrames) return false; // Tracked MapPoints in the reference keyframe int nMinObs = 3; if (nKFs <= 2) nMinObs = 2; int nRefMatches = mpReferenceKF->TrackedMapPoints(nMinObs); // Local Mapping accept keyframes? bool bLocalMappingIdle = mpLocalMapper->AcceptKeyFrames(); // Check how many "close" points are being tracked and how many could be potentially created. int nNonTrackedClose = 0; int nTrackedClose = 0; if (mSensor != System::MONOCULAR) { for (int i = 0; i < mCurrentFrame.N; i++) { if (mCurrentFrame.mvDepth[i] > 0 && mCurrentFrame.mvDepth[i] < mThDepth) { if (mCurrentFrame.mvpMapPoints[i] && !mCurrentFrame.mvbOutlier[i]) nTrackedClose++; else nNonTrackedClose++; } } } bool bNeedToInsertClose = (nTrackedClose < 100) && (nNonTrackedClose > 70); // Thresholds float thRefRatio = 0.75f; if (nKFs < 2) thRefRatio = 0.4f; if (mSensor == System::MONOCULAR) thRefRatio = 0.9f; // Condition 1a: More than "MaxFrames" have passed from last keyframe insertion const bool c1a = mCurrentFrame.mnId >= mnLastKeyFrameId + mMaxFrames; // Condition 1b: More than "MinFrames" have passed and Local Mapping is idle const bool c1b = (mCurrentFrame.mnId >= mnLastKeyFrameId + mMinFrames && bLocalMappingIdle); // Condition 1c: tracking is weak const bool c1c = mSensor != System::MONOCULAR && (mnMatchesInliers < nRefMatches * 0.25 || bNeedToInsertClose); // Condition 2: Few tracked points compared to reference keyframe. Lots of visual odometry compared to map matches. const bool c2 = ((mnMatchesInliers < nRefMatches * thRefRatio || bNeedToInsertClose) && mnMatchesInliers > 15); if ((c1a || c1b || c1c) && c2) { // If the mapping accepts keyframes, insert keyframe. // Otherwise send a signal to interrupt BA if (bLocalMappingIdle) { return true; } else { mpLocalMapper->InterruptBA(); if (mSensor != System::MONOCULAR) { if (mpLocalMapper->KeyframesInQueue() < 3) return true; else return false; } else return false; } } else return false; } void Tracking::CreateNewKeyFrame() { if (!mpLocalMapper->SetNotStop(true)) return; KeyFrame *pKF = new KeyFrame(mCurrentFrame, mpMap, mpKeyFrameDB); mpReferenceKF = pKF; mCurrentFrame.mpReferenceKF = pKF; if (mSensor != System::MONOCULAR) { mCurrentFrame.UpdatePoseMatrices(); // We sort points by the measured depth by the stereo/RGBD sensor. // We create all those MapPoints whose depth < mThDepth. // If there are less than 100 close points we create the 100 closest. vector> vDepthIdx; vDepthIdx.reserve(mCurrentFrame.N); for (int i = 0; i < mCurrentFrame.N; i++) { float z = mCurrentFrame.mvDepth[i]; if (z > 0) { vDepthIdx.push_back(make_pair(z, i)); } } if (!vDepthIdx.empty()) { sort(vDepthIdx.begin(), vDepthIdx.end()); int nPoints = 0; for (size_t j = 0; j < vDepthIdx.size(); j++) { int i = vDepthIdx[j].second; bool bCreateNew = false; MapPoint *pMP = mCurrentFrame.mvpMapPoints[i]; if (!pMP) bCreateNew = true; else if (pMP->Observations() < 1) { bCreateNew = true; mCurrentFrame.mvpMapPoints[i] = static_cast(NULL); } if (bCreateNew) { cv::Mat x3D = mCurrentFrame.UnprojectStereo(i); MapPoint *pNewMP = new MapPoint(x3D, pKF, mpMap); pNewMP->AddObservation(pKF, i); pKF->AddMapPoint(pNewMP, i); pNewMP->ComputeDistinctiveDescriptors(); pNewMP->UpdateNormalAndDepth(); mpMap->AddMapPoint(pNewMP); mCurrentFrame.mvpMapPoints[i] = pNewMP; nPoints++; } else { nPoints++; } if (vDepthIdx[j].first > mThDepth && nPoints > 100) break; } } } for (int i = 0; i < mCurrentFrame.mvvLabel.size(); i++) { if (mCurrentFrame.mvCarMatches[i] == -2) { Car *new_car = new Car(mCurrentFrame, mCurrentFrame.mvvLabel[i]); mvpCar.push_back(new_car); mpMap->AddMapCar(new_car); } } mpLocalMapper->InsertKeyFrame(pKF); mpLocalMapper->SetNotStop(false); mnLastKeyFrameId = mCurrentFrame.mnId; mpLastKeyFrame = pKF; } void Tracking::SearchLocalPoints() { // Do not search map points already matched for (vector::iterator vit = mCurrentFrame.mvpMapPoints.begin(), vend = mCurrentFrame.mvpMapPoints.end(); vit != vend; vit++) { MapPoint *pMP = *vit; if (pMP) { if (pMP->isBad()) { *vit = static_cast(NULL); } else { pMP->IncreaseVisible(); pMP->mnLastFrameSeen = mCurrentFrame.mnId; pMP->mbTrackInView = false; } } } int nToMatch = 0; // Project points in frame and check its visibility for (vector::iterator vit = mvpLocalMapPoints.begin(), vend = mvpLocalMapPoints.end(); vit != vend; vit++) { MapPoint *pMP = *vit; if (pMP->mnLastFrameSeen == mCurrentFrame.mnId) continue; if (pMP->isBad()) continue; // Project (this fills MapPoint variables for matching) if (mCurrentFrame.isInFrustum(pMP, 0.5)) { pMP->IncreaseVisible(); nToMatch++; } } if (nToMatch > 0) { ORBmatcher matcher(0.8); int th = 1; if (mSensor == System::RGBD) th = 3; // If the camera has been relocalised recently, perform a coarser search if (mCurrentFrame.mnId < mnLastRelocFrameId + 2) th = 5; matcher.SearchByProjection(mCurrentFrame, mvpLocalMapPoints, th); } } void Tracking::UpdateLocalMap() { // This is for visualization mpMap->SetReferenceMapPoints(mvpLocalMapPoints); // Update UpdateLocalKeyFrames(); UpdateLocalPoints(); } void Tracking::UpdateLocalPoints() { mvpLocalMapPoints.clear(); for (vector::const_iterator itKF = mvpLocalKeyFrames.begin(), itEndKF = mvpLocalKeyFrames.end(); itKF != itEndKF; itKF++) { KeyFrame *pKF = *itKF; const vector vpMPs = pKF->GetMapPointMatches(); for (vector::const_iterator itMP = vpMPs.begin(), itEndMP = vpMPs.end(); itMP != itEndMP; itMP++) { MapPoint *pMP = *itMP; if (!pMP) continue; if (pMP->mnTrackReferenceForFrame == mCurrentFrame.mnId) continue; if (!pMP->isBad()) { mvpLocalMapPoints.push_back(pMP); pMP->mnTrackReferenceForFrame = mCurrentFrame.mnId; } } } } void Tracking::UpdateLocalKeyFrames() { // Each map point vote for the keyframes in which it has been observed map keyframeCounter; for (int i = 0; i < mCurrentFrame.N; i++) { if (mCurrentFrame.mvpMapPoints[i]) { MapPoint *pMP = mCurrentFrame.mvpMapPoints[i]; if (!pMP->isBad()) { const map observations = pMP->GetObservations(); for (map::const_iterator it = observations.begin(), itend = observations.end(); it != itend; it++) keyframeCounter[it->first]++; } else { mCurrentFrame.mvpMapPoints[i] = NULL; } } } if (keyframeCounter.empty()) return; int max = 0; KeyFrame *pKFmax = static_cast(NULL); mvpLocalKeyFrames.clear(); mvpLocalKeyFrames.reserve(3 * keyframeCounter.size()); // All keyframes that observe a map point are included in the local map. Also check which keyframe shares most points for (map::const_iterator it = keyframeCounter.begin(), itEnd = keyframeCounter.end(); it != itEnd; it++) { KeyFrame *pKF = it->first; if (pKF->isBad()) continue; if (it->second > max) { max = it->second; pKFmax = pKF; } mvpLocalKeyFrames.push_back(it->first); pKF->mnTrackReferenceForFrame = mCurrentFrame.mnId; } // Include also some not-already-included keyframes that are neighbors to already-included keyframes for (vector::const_iterator itKF = mvpLocalKeyFrames.begin(), itEndKF = mvpLocalKeyFrames.end(); itKF != itEndKF; itKF++) { // Limit the number of keyframes if (mvpLocalKeyFrames.size() > 80) break; KeyFrame *pKF = *itKF; const vector vNeighs = pKF->GetBestCovisibilityKeyFrames(10); for (vector::const_iterator itNeighKF = vNeighs.begin(), itEndNeighKF = vNeighs.end(); itNeighKF != itEndNeighKF; itNeighKF++) { KeyFrame *pNeighKF = *itNeighKF; if (!pNeighKF->isBad()) { if (pNeighKF->mnTrackReferenceForFrame != mCurrentFrame.mnId) { mvpLocalKeyFrames.push_back(pNeighKF); pNeighKF->mnTrackReferenceForFrame = mCurrentFrame.mnId; break; } } } const set spChilds = pKF->GetChilds(); for (set::const_iterator sit = spChilds.begin(), send = spChilds.end(); sit != send; sit++) { KeyFrame *pChildKF = *sit; if (!pChildKF->isBad()) { if (pChildKF->mnTrackReferenceForFrame != mCurrentFrame.mnId) { mvpLocalKeyFrames.push_back(pChildKF); pChildKF->mnTrackReferenceForFrame = mCurrentFrame.mnId; break; } } } KeyFrame *pParent = pKF->GetParent(); if (pParent) { if (pParent->mnTrackReferenceForFrame != mCurrentFrame.mnId) { mvpLocalKeyFrames.push_back(pParent); pParent->mnTrackReferenceForFrame = mCurrentFrame.mnId; break; } } } if (pKFmax) { mpReferenceKF = pKFmax; mCurrentFrame.mpReferenceKF = mpReferenceKF; } } bool Tracking::Relocalization() { // Compute Bag of Words Vector mCurrentFrame.ComputeBoW(); // Relocalization is performed when tracking is lost // Track Lost: Query KeyFrame Database for keyframe candidates for relocalisation vector vpCandidateKFs = mpKeyFrameDB->DetectRelocalizationCandidates(&mCurrentFrame); if (vpCandidateKFs.empty()) return false; const int nKFs = vpCandidateKFs.size(); // We perform first an ORB matching with each candidate // If enough matches are found we setup a PnP solver ORBmatcher matcher(0.75, true); vector vpPnPsolvers; vpPnPsolvers.resize(nKFs); vector> vvpMapPointMatches; vvpMapPointMatches.resize(nKFs); vector vbDiscarded; vbDiscarded.resize(nKFs); int nCandidates = 0; for (int i = 0; i < nKFs; i++) { KeyFrame *pKF = vpCandidateKFs[i]; if (pKF->isBad()) vbDiscarded[i] = true; else { int nmatches = matcher.SearchByBoW(pKF, mCurrentFrame, vvpMapPointMatches[i]); if (nmatches < 15) { vbDiscarded[i] = true; continue; } else { PnPsolver *pSolver = new PnPsolver(mCurrentFrame, vvpMapPointMatches[i]); pSolver->SetRansacParameters(0.99, 10, 300, 4, 0.5, 5.991); vpPnPsolvers[i] = pSolver; nCandidates++; } } } // Alternatively perform some iterations of P4P RANSAC // Until we found a camera pose supported by enough inliers bool bMatch = false; ORBmatcher matcher2(0.9, true); while (nCandidates > 0 && !bMatch) { for (int i = 0; i < nKFs; i++) { if (vbDiscarded[i]) continue; // Perform 5 Ransac Iterations vector vbInliers; int nInliers; bool bNoMore; PnPsolver *pSolver = vpPnPsolvers[i]; cv::Mat Tcw = pSolver->iterate(5, bNoMore, vbInliers, nInliers); // If Ransac reachs max. iterations discard keyframe if (bNoMore) { vbDiscarded[i] = true; nCandidates--; } // If a Camera Pose is computed, optimize if (!Tcw.empty()) { Tcw.copyTo(mCurrentFrame.mTcw); set sFound; const int np = vbInliers.size(); for (int j = 0; j < np; j++) { if (vbInliers[j]) { mCurrentFrame.mvpMapPoints[j] = vvpMapPointMatches[i][j]; sFound.insert(vvpMapPointMatches[i][j]); } else mCurrentFrame.mvpMapPoints[j] = NULL; } int nGood = Optimizer::PoseOptimization(&mCurrentFrame); if (nGood < 10) continue; for (int io = 0; io < mCurrentFrame.N; io++) if (mCurrentFrame.mvbOutlier[io]) mCurrentFrame.mvpMapPoints[io] = static_cast(NULL); // If few inliers, search by projection in a coarse window and optimize again if (nGood < 50) { int nadditional = matcher2.SearchByProjection(mCurrentFrame, vpCandidateKFs[i], sFound, 10, 100); if (nadditional + nGood >= 50) { nGood = Optimizer::PoseOptimization(&mCurrentFrame); // If many inliers but still not enough, search by projection again in a narrower window // the camera has been already optimized with many points if (nGood > 30 && nGood < 50) { sFound.clear(); for (int ip = 0; ip < mCurrentFrame.N; ip++) if (mCurrentFrame.mvpMapPoints[ip]) sFound.insert(mCurrentFrame.mvpMapPoints[ip]); nadditional = matcher2.SearchByProjection(mCurrentFrame, vpCandidateKFs[i], sFound, 3, 64); // Final optimization if (nGood + nadditional >= 50) { nGood = Optimizer::PoseOptimization(&mCurrentFrame); for (int io = 0; io < mCurrentFrame.N; io++) if (mCurrentFrame.mvbOutlier[io]) mCurrentFrame.mvpMapPoints[io] = NULL; } } } } // If the pose is supported by enough inliers stop ransacs and continue if (nGood >= 50) { bMatch = true; break; } } } } if (!bMatch) { return false; } else { mnLastRelocFrameId = mCurrentFrame.mnId; return true; } } bool Tracking::needCreate(vector &bbox, int &index, int &n) { cout << "enter need Create" << endl; vector pts2; cv::Point PointArray1[4], PointArray2[4]; Tracking::get_bbx(bbox, pts2, 1.5); // 当前检测的目标框 if (bbox[1] < 338 && bbox[1] > 270 && bbox[2] > 558) { return 0; } PointArray2[0] = pts2[0]; // 存放第二个预测框 PointArray2[1] = pts2[1]; PointArray2[2] = pts2[2]; PointArray2[3] = pts2[3]; float max_iou = 0.0; for (int i = 0; i < n; i++) { Car *car = mvpCar[i]; if (!car->isBad()) { if (car->isTracked()) { continue; } vector vmbboxPose = car->mvmBboxWorldPosePredict; // 目标框估计位置 vector vp_bev; Tracking::world2bev(vmbboxPose, vp_bev, mCurrentFrame.mTcw); // 车辆投影到当前bev PointArray1[0] = vp_bev[0]; // 存放第二个预测框 PointArray1[1] = vp_bev[1]; PointArray1[2] = vp_bev[2]; PointArray1[3] = vp_bev[3]; // cout << vp_bev << " " << pts2[0] << endl; // TODO 问题 float IOU = get_IOU(PointArray1, PointArray2); if (max_iou < IOU) max_iou = IOU; double th; if (car->mnVisual > 1) { th = 0.8; } else { th = 0.2; } if (IOU > th) // 匹配上就不需要创建了,这里会更新车辆位置、速度 { // step1:更新最近观测帧 car->updateObservations(mCurrentFrame.mnId); // step2: 更新目标框对应关系 pair p1(mCurrentFrame.mnId, index); car->mv_pair_connect.push_back(p1); car->setTrackedState(true); // 跟像跟踪状态 // step3: 更新世界位置和速度 car->updateState(bbox, mCurrentFrame.mRwc, mCurrentFrame.mOw, mdelta_t); break; } } } return (max_iou == 0); } void Tracking::get_bbx(const vector &label1, std ::vector &pts, double scale) { cv::Point p1, p2, p3, p4; double x = label1[1]; double y = label1[2]; double w = label1[3]; double l = label1[4]; double yaw = label1[7]; double cos_yaw, sin_yaw; w = w * scale; l = l * scale; cos_yaw = cos(yaw); sin_yaw = sin(yaw); // front left p1.x = x - w / 2 * cos_yaw - l / 2 * sin_yaw; p1.y = y - w / 2 * sin_yaw + l / 2 * cos_yaw; // rear left p2.x = x - w / 2 * cos_yaw + l / 2 * sin_yaw; p2.y = y - w / 2 * sin_yaw - l / 2 * cos_yaw; // rear right p3.x = x + w / 2 * cos_yaw + l / 2 * sin_yaw; p3.y = y + w / 2 * sin_yaw - l / 2 * cos_yaw; // front right p4.x = x + w / 2 * cos_yaw - l / 2 * sin_yaw; p4.y = y + w / 2 * sin_yaw + l / 2 * cos_yaw; pts.push_back(p1); pts.push_back(p2); pts.push_back(p3); pts.push_back(p4); } float Tracking::get_IOU(cv::Point *PointArray1, cv::Point *PointArray2) { cv::Mat img = cv::Mat::zeros(608, 608, CV_8UC3); cv::Mat tmp; vector idx; cv::fillConvexPoly(img, PointArray1, 4, cv::Scalar(255, 0, 0)); cv::cvtColor(img, tmp, CV_RGB2GRAY); cv::findNonZero(tmp, idx); float area1 = idx.size(); cv::Mat img2 = cv::Mat::zeros(img.size(), CV_8UC3); cv::fillConvexPoly(img2, PointArray2, 4, cv::Scalar(0, 255, 0)); cv::cvtColor(img2, tmp, CV_RGB2GRAY); cv::findNonZero(tmp, idx); float area2 = idx.size(); cv::fillConvexPoly(img2, PointArray1, 4, cv::Scalar(0, 0, 255)); cv::cvtColor(img2, tmp, CV_RGB2GRAY); cv::findNonZero(tmp, idx); float union_area = idx.size(); float inter_area = area1 + area2 - union_area; float IOU = 0.0; if (area1 != 0) { IOU = inter_area / area1; } return IOU; } void Tracking::PredictCarPos(Car *car) { if (!car->isBad()) { car->mvmBboxWorldPosePredict.clear(); for (auto t : car->mvmBboxWorldPose) { cv::Mat tmp = car->mRcl * t + car->mtcl; car->mvmBboxWorldPosePredict.push_back(tmp); } } // car->mmPredWorldPos = car->mmVelocity * car->mWorldPos; } void Tracking::Reset() { cout << "System Reseting" << endl; if (mpViewer) { mpViewer->RequestStop(); while (!mpViewer->isStopped()) usleep(3000); } // Reset Local Mapping cout << "Reseting Local Mapper..."; mpLocalMapper->RequestReset(); cout << " done" << endl; // Reset Loop Closing cout << "Reseting Loop Closing..."; mpLoopClosing->RequestReset(); cout << " done" << endl; // Clear BoW Database cout << "Reseting Database..."; mpKeyFrameDB->clear(); cout << " done" << endl; // Clear Map (this erase MapPoints and KeyFrames) mpMap->clear(); KeyFrame::nNextId = 0; Frame::nNextId = 0; mState = NO_IMAGES_YET; if (mpInitializer) { delete mpInitializer; mpInitializer = static_cast(NULL); } mlRelativeFramePoses.clear(); mlpReferences.clear(); mlFrameTimes.clear(); mlbLost.clear(); if (mpViewer) mpViewer->Release(); } void Tracking::ChangeCalibration(const string &strSettingPath) { cv::FileStorage fSettings(strSettingPath, cv::FileStorage::READ); float fx = fSettings["Camera.fx"]; float fy = fSettings["Camera.fy"]; float cx = fSettings["Camera.cx"]; float cy = fSettings["Camera.cy"]; cv::Mat K = cv::Mat::eye(3, 3, CV_32F); K.at(0, 0) = fx; K.at(1, 1) = fy; K.at(0, 2) = cx; K.at(1, 2) = cy; K.copyTo(mK); cv::Mat DistCoef(4, 1, CV_32F); DistCoef.at(0) = fSettings["Camera.k1"]; DistCoef.at(1) = fSettings["Camera.k2"]; DistCoef.at(2) = fSettings["Camera.p1"]; DistCoef.at(3) = fSettings["Camera.p2"]; const float k3 = fSettings["Camera.k3"]; if (k3 != 0) { DistCoef.resize(5); DistCoef.at(4) = k3; } DistCoef.copyTo(mDistCoef); mbf = fSettings["Camera.bf"]; Frame::mbInitialComputations = true; } void Tracking::InformOnlyTracking(const bool &flag) { mbOnlyTracking = flag; } // bev视图,当前到bev世界坐标转换 void Tracking::bev_current_bevworld(cv::Point &p_c, cv::Point &p_l, cv::Mat &T12) { cv::Mat R12, t12; R12 = T12.rowRange(0, 3).colRange(0, 3); t12 = T12.rowRange(0, 3).col(3); cv::Mat p_uv_c_bev, p_cam_c_bev, p_cam_c_cam, p_cam_l_cam, p_cam_l_bev, p_uv_l_bev; p_uv_c_bev = cv::Mat::zeros(3, 1, CV_32FC1); p_cam_c_bev = cv::Mat::zeros(3, 1, CV_32FC1); p_cam_c_cam = cv::Mat::zeros(3, 1, CV_32FC1); p_cam_l_cam = cv::Mat::zeros(3, 1, CV_32FC1); p_cam_l_bev = cv::Mat::zeros(3, 1, CV_32FC1); p_uv_l_bev = cv::Mat::zeros(3, 1, CV_32FC1); // p_uv_c_bev bev视图,当前current,像素uv坐标系 p_uv_c_bev.at(0, 0) = p_c.x; // 取bev像素坐标 p_uv_c_bev.at(1, 0) = p_c.y; p_uv_c_bev.at(2, 0) = 1.0; p_cam_c_bev = m_bev_K_invers * p_uv_c_bev; // bev像素坐标转bev相机坐标 cv::Mat R = (cv::Mat_(3, 3) << 1, 0, 0, 0, 0, 1, 0, -1, 0); p_cam_c_cam = R * p_cam_c_bev; // bev相机坐标转cam的相机坐标 p_cam_l_cam = R12 * p_cam_c_cam + t12; // 当前cam相机坐标转到过去的cam相机坐标 // p_cam_l_cam.at(1, 0) = 1.0; p_cam_l_bev = R.t() * p_cam_l_cam; // 过去cam相机坐标转过去bev相机坐标 p_uv_l_bev = m_bev_K * p_cam_l_bev; // 过去bev相机坐标转过去bev像素坐标 p_l.x = p_uv_l_bev.at(0, 0) / p_cam_l_bev.at(2, 0); p_l.y = p_uv_l_bev.at(1, 0) / p_cam_l_bev.at(2, 0); } void Tracking::Get_Motion_Car_V(Car *car) { double vel = 3.6 * car->get_Vel(mdelta_t); // km/h float z = car->mCarWorldPose.at(2, 0); float x = car->mCarWorldPose.at(0, 0); float y = car->mCarWorldPose.at(1, 0); cv::Mat car_wo = (cv::Mat_(3, 1) << x, y, z); cv::Mat car_co = mCurrentFrame.mRcw * car_wo + mCurrentFrame.mtcw; // 转相机坐标系 int u, v; float fx, fy, cx, cy; fx = mK.at(0, 0); fy = mK.at(1, 1); cx = mK.at(0, 2); cy = mK.at(1, 2); u = fx * (car_co.at(0, 0) - 0.8) / (car_co.at(2, 0) - 1) + cx; v = fy * (car_co.at(1, 0) - 0) / (car_co.at(2, 0) - 1) + cy; vector tmp; tmp.push_back(u); tmp.push_back(v); tmp.push_back(vel); mvvCarV.push_back(tmp); } void Tracking::world2bev(vector &vm_3d_w, vector &vp_bev, cv::Mat &Tcw) // 世界坐标转bev像素 { for (auto p_3d_w : vm_3d_w) { cv::Mat Rcw, tcw, R_ij; cv::Mat p_3d_w_mat = cv::Mat::zeros(3, 1, CV_32FC1); cv::Point p_bev; p_3d_w_mat.at(0, 0) = p_3d_w.at(0, 0); // 取bev像素坐标 p_3d_w_mat.at(1, 0) = p_3d_w.at(1, 0); p_3d_w_mat.at(2, 0) = p_3d_w.at(2, 0); Rcw = Tcw.rowRange(0, 3).colRange(0, 3); tcw = Tcw.rowRange(0, 3).col(3); cv::Mat p_3d_c, p_3d_bev, p_uv_bev; p_3d_c = Rcw * p_3d_w_mat + tcw; // 世界坐标转相机坐标 cv::Mat Rbc = (cv::Mat_(3, 3) << 1, 0, 0, 0, 0, -1, 0, 1, 0); // 相机转bev的矩阵 p_3d_bev = Rbc * p_3d_c; // 相机转bev p_3d_bev.at(2, 0) = 1.0; // 归一 p_uv_bev = m_bev_K * p_3d_bev; // 过去bev相机坐标转过去bev像素坐标 p_bev.x = p_uv_bev.at(0, 0) / p_3d_bev.at(2, 0); p_bev.y = p_uv_bev.at(1, 0) / p_3d_bev.at(2, 0); vp_bev.push_back(p_bev); } } } // namespace ORB_SLAM