00001
00002
00003
00004
00005
00006
00007 #include <mrpt/version.h>
00008 #include <mrpt_bridge/utils.h>
00009 #include <mrpt_rbpf_slam/mrpt_rbpf_slam.h>
00010
00011 #if MRPT_VERSION >= 0x199
00012 #include <mrpt/serialization/CArchive.h>
00013 #endif
00014
00015 namespace mrpt_rbpf_slam {
00016 PFslam::~PFslam() {
00017 try {
00018 std::string sOutMap = "mrpt_rbpfslam_";
00019 mrpt::system::TTimeParts parts;
00020 mrpt::system::timestampToParts(mrpt::system::now(), parts, true);
00021 sOutMap +=
00022 mrpt::format("%04u-%02u-%02u_%02uh%02um%02us", (unsigned int)parts.year,
00023 (unsigned int)parts.month, (unsigned int)parts.day,
00024 (unsigned int)parts.hour, (unsigned int)parts.minute,
00025 (unsigned int)parts.second);
00026 sOutMap += ".simplemap";
00027
00028 sOutMap = mrpt::system::fileNameStripInvalidChars(sOutMap);
00029 if (mrpt::system::directoryExists(options_.simplemap_path_prefix)) {
00030 sOutMap = options_.simplemap_path_prefix + sOutMap;
00031 } else {
00032 std::cerr << "Folder " << options_.simplemap_path_prefix
00033 << " doesn't exist, cannot save simplemap there! Default "
00034 "'~/.ros/' path will be used.\n";
00035 }
00036 std::cout << "Saving built map " << sOutMap << "\n";
00037 mapBuilder_.saveCurrentMapToFile(sOutMap);
00038 } catch (const std::exception &e) {
00039 std::cerr << "Exception: " << e.what() << "\n";
00040 }
00041 }
00042
00043 void PFslam::readIniFile(const std::string &ini_filename) {
00044 #if MRPT_VERSION >= 0x199
00045 mrpt::config::CConfigFile iniFile(ini_filename);
00046 #else
00047 mrpt::utils::CConfigFile iniFile(ini_filename);
00048 #endif
00049 options_.rbpfMappingOptions_.loadFromConfigFile(iniFile,
00050 "MappingApplication");
00051 options_.rbpfMappingOptions_.dumpToConsole();
00052 }
00053
00054 void PFslam::readRawlog(
00055 const std::string &rawlog_filename,
00056 std::vector<std::pair<mrpt::obs::CActionCollection,
00057 mrpt::obs::CSensoryFrame>> &data) {
00058 size_t rawlogEntry = 0;
00059 #if MRPT_VERSION >= 0x199
00060 mrpt::io::CFileGZInputStream rawlog_stream(rawlog_filename);
00061 auto rawlogFile = mrpt::serialization::archiveFrom(rawlog_stream);
00062 #else
00063 mrpt::utils::CFileGZInputStream rawlogFile(rawlog_filename);
00064 #endif
00065 mrpt::obs::CActionCollection::Ptr action;
00066 mrpt::obs::CSensoryFrame::Ptr observations;
00067
00068 for (;;) {
00069 if (mrpt::system::os::kbhit()) {
00070 char c = mrpt::system::os::getch();
00071 if (c == 27)
00072 break;
00073 }
00074
00075
00076
00077 if (!mrpt::obs::CRawlog::readActionObservationPair(
00078 rawlogFile, action, observations, rawlogEntry)) {
00079 break;
00080 }
00081 data.emplace_back(*action, *observations);
00082 }
00083 }
00084
00085 void PFslam::observation(
00086 const mrpt::obs::CSensoryFrame::ConstPtr sensory_frame,
00087 const mrpt::obs::CObservationOdometry::ConstPtr odometry) {
00088 action_ = mrpt::obs::CActionCollection::Create();
00089 mrpt::obs::CActionRobotMovement2D odom_move;
00090 odom_move.timestamp = sensory_frame->getObservationByIndex(0)->timestamp;
00091
00092 if (odometry) {
00093 if (odomLastObservation_.empty()) {
00094 odomLastObservation_ = odometry->odometry;
00095 }
00096
00097 mrpt::poses::CPose2D incOdoPose = odometry->odometry - odomLastObservation_;
00098 odomLastObservation_ = odometry->odometry;
00099 odom_move.computeFromOdometry(incOdoPose, options_.motion_model_options_);
00100 action_->insert(odom_move);
00101 }
00102 }
00103
00104 void PFslam::initSlam(PFslam::Options options) {
00105 log4cxx::LoggerPtr ros_logger =
00106 log4cxx::Logger::getLogger(ROSCONSOLE_DEFAULT_NAME);
00107 mapBuilder_.setVerbosityLevel(
00108 mrpt_bridge::rosLoggerLvlToMRPTLoggerLvl(ros_logger->getLevel()));
00109 mapBuilder_.logging_enable_console_output = false;
00110 #if MRPT_VERSION < 0x199
00111 mapBuilder_.logRegisterCallback(static_cast<output_logger_callback_t>(
00112 &mrpt_bridge::mrptToROSLoggerCallback_mrpt_15));
00113 #else
00114 mapBuilder_.logRegisterCallback(static_cast<output_logger_callback_t>(
00115 &mrpt_bridge::mrptToROSLoggerCallback));
00116 #endif
00117 mapBuilder_.options.enableMapUpdating = true;
00118 mapBuilder_.options.debugForceInsertion = false;
00119
00120 #if MRPT_VERSION >= 0x199
00121 mrpt::random::getRandomGenerator().randomize();
00122 #else
00123 mrpt::random::randomGenerator.randomize();
00124 #endif
00125
00126 options_ = std::move(options);
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 }
00149
00150 void PFslam::init3Dwindow() {
00151 #if MRPT_HAS_WXWIDGETS
00152 if (options_.SHOW_PROGRESS_IN_WINDOW_) {
00153 win3D_ = mrpt::gui::CDisplayWindow3D::Create(
00154 "RBPF-SLAM @ MRPT C++ Library", options_.PROGRESS_WINDOW_WIDTH_,
00155 options_.PROGRESS_WINDOW_HEIGHT_);
00156 win3D_->setCameraZoom(40);
00157 win3D_->setCameraAzimuthDeg(-50);
00158 win3D_->setCameraElevationDeg(70);
00159 }
00160 #endif
00161 }
00162 void PFslam::run3Dwindow() {
00163
00164 if (options_.SHOW_PROGRESS_IN_WINDOW_ && win3D_) {
00165
00166 metric_map_ = mapBuilder_.mapPDF.getCurrentMostLikelyMetricMap();
00167 mapBuilder_.mapPDF.getEstimatedPosePDF(curPDF);
00168 mrpt::opengl::COpenGLScene::Ptr scene;
00169 scene = mrpt::opengl::COpenGLScene::Create();
00170
00171
00172 mrpt::opengl::CGridPlaneXY::Ptr groundPlane =
00173 mrpt::opengl::CGridPlaneXY::Create(-200, 200, -200, 200, 0, 5);
00174 groundPlane->setColor(0.4, 0.4, 0.4);
00175 scene->insert(groundPlane);
00176
00177
00178 if (options_.CAMERA_3DSCENE_FOLLOWS_ROBOT_) {
00179 mrpt::opengl::CCamera::Ptr objCam = mrpt::opengl::CCamera::Create();
00180 mrpt::poses::CPose3D robotPose;
00181 curPDF.getMean(robotPose);
00182
00183 objCam->setPointingAt(robotPose);
00184 objCam->setAzimuthDegrees(-30);
00185 objCam->setElevationDegrees(30);
00186 scene->insert(objCam);
00187 }
00188
00189 mrpt::opengl::CSetOfObjects::Ptr objs =
00190 mrpt::opengl::CSetOfObjects::Create();
00191 metric_map_->getAs3DObject(objs);
00192 scene->insert(objs);
00193
00194
00195 size_t M = mapBuilder_.mapPDF.particlesCount();
00196 mrpt::opengl::CSetOfLines::Ptr objLines =
00197 mrpt::opengl::CSetOfLines::Create();
00198 objLines->setColor(0, 1, 1);
00199 for (size_t i = 0; i < M; i++) {
00200 std::deque<mrpt::math::TPose3D> path;
00201 mapBuilder_.mapPDF.getPath(i, path);
00202
00203 float x0 = 0, y0 = 0, z0 = 0;
00204 for (size_t k = 0; k < path.size(); k++) {
00205 objLines->appendLine(x0, y0, z0 + 0.001, path[k].x, path[k].y,
00206 path[k].z + 0.001);
00207 x0 = path[k].x;
00208 y0 = path[k].y;
00209 z0 = path[k].z;
00210 }
00211 }
00212 scene->insert(objLines);
00213
00214
00215 mrpt::poses::CPose3D lastMeanPose;
00216 float minDistBtwPoses = -1;
00217 std::deque<mrpt::math::TPose3D> dummyPath;
00218 mapBuilder_.mapPDF.getPath(0, dummyPath);
00219 for (int k = (int)dummyPath.size() - 1; k >= 0; k--) {
00220 mrpt::poses::CPose3DPDFParticles poseParts;
00221 mapBuilder_.mapPDF.getEstimatedPosePDFAtTime(k, poseParts);
00222
00223 #if MRPT_VERSION >= 0x199
00224 const auto [COV, meanPose] = poseParts.getCovarianceAndMean();
00225 #else
00226 mrpt::poses::CPose3D meanPose;
00227 mrpt::math::CMatrixDouble66 COV;
00228 poseParts.getCovarianceAndMean(COV, meanPose);
00229 #endif
00230
00231 if (meanPose.distanceTo(lastMeanPose) > minDistBtwPoses) {
00232 mrpt::math::CMatrixDouble33 COV3 =
00233 #if MRPT_VERSION >= 0x199
00234 COV.blockCopy<3, 3>(0, 0);
00235 #else
00236 COV.block(0, 0, 3, 3);
00237 #endif
00238
00239 minDistBtwPoses = 6 * sqrt(COV3(0, 0) + COV3(1, 1));
00240
00241 mrpt::opengl::CEllipsoid::Ptr objEllip =
00242 mrpt::opengl::CEllipsoid::Create();
00243 objEllip->setLocation(meanPose.x(), meanPose.y(), meanPose.z() + 0.001);
00244 objEllip->setCovMatrix(COV3, COV3(2, 2) == 0 ? 2 : 3);
00245
00246 objEllip->setColor(0, 0, 1);
00247 objEllip->enableDrawSolid3D(false);
00248 scene->insert(objEllip);
00249
00250 lastMeanPose = meanPose;
00251 }
00252 }
00253
00254 mrpt::opengl::COpenGLScene::Ptr &scenePtr = win3D_->get3DSceneAndLock();
00255 scenePtr = scene;
00256 win3D_->unlockAccess3DScene();
00257 win3D_->forceRepaint();
00258 }
00259 }
00260 }