00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef GRAPH_MANAGER_H_
00026 #define GRAPH_MANAGER_H_
00027
00028 #include <ros/ros.h>
00029 #include <tf/transform_broadcaster.h>
00030 #include "node.h"
00031 #include "ColorOctomapServer.h"
00032 #include <Eigen/Core>
00033 #include <Eigen/Geometry>
00034 #include <opencv2/core/core.hpp>
00035 #include <opencv2/features2d/features2d.hpp>
00036 #include <map>
00037 #include <QObject>
00038 #include <QString>
00039 #include <QMatrix4x4>
00040 #include <QList>
00041 #include <QMap>
00042 #include <QMutex>
00043
00044 #include <iostream>
00045 #include <sstream>
00046 #include <string>
00047 #include <ctime>
00048 #include <memory>
00049 #include <utility>
00050 #include "parameter_server.h"
00051
00052
00053 #ifdef DO_FEATURE_OPTIMIZATION
00054 #include "landmark.h"
00055 #endif
00056
00057
00058 #include "g2o/core/sparse_optimizer.h"
00059
00060
00061 #include "g2o/types/slam3d/parameter_camera.h"
00062 #include "g2o/types/slam2d/vertex_se2.h"
00063
00064 #include "g2o/core/hyper_dijkstra.h"
00065 #include "g2o/core/robust_kernel_impl.h"
00066
00067 namespace tf {
00068 class TransformListener;
00069 }
00070
00071
00073 typedef std::map<int, Node* >::iterator graph_it;
00074 typedef std::set<g2o::HyperGraph::Edge*> EdgeSet;
00075 typedef g2o::HyperGraph::EdgeSet::iterator EdgeSet_it;
00076 typedef std::map<int, Node* >::iterator graph_it;
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00089 class GraphManager : public QObject {
00090 Q_OBJECT
00091 Q_SIGNALS:
00093 void newTransformationMatrix(QString);
00094 void sendFinished();
00095 void setGUIInfo(QString message);
00096 void setGUIStatus(QString message);
00097 void setPointCloud(pointcloud_type * pc, QMatrix4x4 transformation);
00098 void setFeatures(const std::vector<Eigen::Vector4f, Eigen::aligned_allocator<Eigen::Vector4f> >*);
00099 void updateTransforms(QList<QMatrix4x4>* transformations);
00100 void setGUIInfo2(QString message);
00101 void setGraphEdges(const QList<QPair<int, int> >* edge_list);
00102 void deleteLastNode();
00103 void resetGLViewer();
00104 void setGraph(const g2o::OptimizableGraph*);
00105 void iamBusy(int id, const char* message, int max);
00106 void progress(int id, const char* message, int val);
00107 void renderableOctomap(Renderable* r);
00108
00109 public Q_SLOTS:
00111 void reset();
00113 void deleteLastFrame();
00114 void clearPointCloud(pointcloud_type const * pc);
00115 void clearPointClouds();
00116 void reducePointCloud(pointcloud_type const * pc);
00119 double optimizeGraph(double iter = -1, bool nonthreaded=false);
00120 void printEdgeErrors(QString);
00124 unsigned int pruneEdgesWithErrorAbove(float);
00125 void sanityCheck(float);
00126 void toggleMapping(bool);
00127 void filterNodesByPosition(float x, float y, float z);
00128
00129
00131 void sendAllClouds(bool threaded_if_available=true);
00134 void saveBagfileAsync(QString filename);
00136 void saveBagfile(QString filename);
00138 void saveIndividualClouds(QString file_basename, bool threaded=true);
00140 void saveAllClouds(QString filename, bool threaded=true);
00142 void saveAllFeatures(QString filename, bool threaded = true);
00144 void saveOctomap(QString filename, bool threaded = true);
00146 void saveTrajectory(QString filebasename, bool with_ground_truth = false);
00148 void saveG2OGraph(QString filename);
00150 void occupancyFilterClouds();
00151
00152 public:
00153 GraphManager();
00154 ~GraphManager();
00155
00161 bool addNode(Node* newNode);
00162
00165 void addOdometry(ros::Time timestamp, tf::TransformListener* listener);
00171 bool nodeComparisons(Node* newNode,
00172 QMatrix4x4& curr_motion_estimate,
00173 bool& edge_to_keyframe);
00174
00175 void firstNode(Node* new_node);
00176
00178 g2o::HyperGraph::VertexSet camera_vertices;
00180 g2o::HyperGraph::EdgeSet cam_cam_edges_;
00183
00185 g2o::HyperGraph::EdgeSet odometry_edges_;
00186 g2o::HyperGraph::EdgeSet current_match_edges_;
00187
00188 #ifdef DO_FEATURE_OPTIMIZATION
00189 g2o::HyperGraph::EdgeSet cam_lm_edges;
00190 g2o::HyperGraph::VertexSet landmark_vertices;
00191 #endif
00192
00194 void drawFeatureFlow(cv::Mat& canvas,
00195 cv::Scalar line_color = cv::Scalar(255,0,0,0),
00196 cv::Scalar circle_color = cv::Scalar(0,0,255,0));
00197
00198
00199 void drawFeatureFlow(cv::Mat& canvas_flow, cv::Mat& canvas_features,
00200 cv::Scalar line_color = cv::Scalar(255,0,0,0),
00201 cv::Scalar circle_color = cv::Scalar(0,0,255,0));
00202
00204 bool isBusy();
00205
00208 void deleteFeatureInformation();
00210 void writeOctomap(QString filename) const;
00211 void setOptimizerVerbose(bool verbose);
00212
00215 void setEmpiricalCovariances();
00216 protected:
00217
00219 void resetGraph();
00221 double optimizeGraphImpl(double max_iter);
00222
00225 bool updateCloudOrigin(Node* node);
00227 void createOptimizer(std::string backend, g2o::SparseOptimizer* optimizer = NULL);
00229 MatchingResult curr_best_result_;
00230
00232 tf::StampedTransform computeFixedToBaseTransform(Node* node, bool invert);
00237 QList<int> getPotentialEdgeTargetsWithDijkstra(const Node* new_node, int sequential_targets, int geodesic_targets, int sampled_targets = 5, int predecessor_id = -1, bool include_predecessor = false);
00238
00239
00240
00242 void localizationUpdate(Node* new_node, QMatrix4x4 motion_estimate);
00243 #ifdef DO_FEATURE_OPTIMIZATION
00244 std::vector<Landmark> landmarks;
00245 void updateLandmarks(const MatchingResult& match_result, Node* old_node, Node* new_node);
00246 int next_landmark_id;
00247
00248 void mergeLandmarks(Landmark *lm_1, Landmark *lm_2);
00249 void printLandmarkStatistic();
00250 void updateProjectionEdges();
00251 void updateLandmarkInGraph(Landmark* lm);
00252 void removeFeaturesFromGraph();
00253 #endif
00254
00255
00256 #ifdef DO_LOOP_CLOSING
00257 void createSearchTree();
00258 void createSearchTree(const std::vector<int>& node_ids);
00259
00260 void getNeighbours(int node_id, uint neighbour_cnt, std::vector<std::pair<int,float> >& neighbours);
00261
00262 cv::flann::Index *tree;
00263 cv::Mat all_descriptors;
00264
00265 std::set<std::pair<int,int> > tested_pairs;
00266 std::set<std::pair<int,int> > matched_pairs;
00267
00268 void loopClosingTest();
00269 uint descriptor_length;
00270 uint total_descriptor_count;
00271 int *descriptor_to_node;
00272 #endif
00273
00275 bool addEdgeToG2O(const LoadedEdge3D& edge, Node* n1, Node* n2, bool good_edge, bool set_estimate, QMatrix4x4& motion_estimate);
00277 bool addOdometryEdgeToG2O(const LoadedEdge3D& edge, Node* n1, Node* n2, QMatrix4x4& motion_estimate);
00278
00279
00280 void deleteCameraFrame(int id);
00281
00283 void broadcastTransform(const tf::StampedTransform& computed_motion);
00284
00286 void broadcastLatestTransform(const ros::TimerEvent& event) const;
00287
00290 tf::StampedTransform stampedTransformInWorldFrame(const Node* node,
00291 const tf::Transform& computed_motion) const;
00292
00294 void addKeyframe(int id);
00295
00296 int last_added_cam_vertex_id(){
00297 return graph_[graph_.size()-1]->vertex_id_;
00298 }
00299
00300 int nodeId2VertexId(int node_id){
00301 assert(graph_.find(node_id) != graph_.end());
00302 return graph_[node_id]->vertex_id_;
00303 }
00305 QList<QMatrix4x4>* getAllPosesAsMatrixList() const;
00307 QList<QPair<int, int> >* getGraphEdges();
00308
00309
00310 QList<QPair<int, int> > current_edges_;
00311
00312
00313
00314
00315 double geodesicDiscount(g2o::HyperDijkstra& hypdij, const MatchingResult& mr);
00317 void setEmpiricalCovariancesForEdgeSet(EdgeSet& edges);
00318
00319 g2o::SparseOptimizer* optimizer_;
00320
00321 ros::Publisher marker_pub_;
00322 ros::Publisher ransac_marker_pub_;
00323 ros::Publisher whole_cloud_pub_;
00324 ros::Publisher batch_cloud_pub_;
00325 ros::Publisher online_cloud_pub_;
00326
00328 ros::Timer timer_;
00330 mutable tf::TransformBroadcaster br_;
00331 tf::Transform computed_motion_;
00332 tf::Transform init_base_pose_;
00333 tf::StampedTransform latest_transform_cache_;
00334
00336 typedef std::pair<int, Node*> GraphNodeType;
00337
00338 std::map<int, Node* > graph_;
00339 bool reset_request_;
00340 unsigned int marker_id_;
00341 bool batch_processing_runs_;
00342 bool process_node_runs_;
00343 bool localization_only_;
00345 QMutex optimizer_mutex_;
00347 QMutex optimization_mutex_;
00348
00349 QList<int> keyframe_ids_;
00350
00351
00352 unsigned int loop_closures_edges, sequential_edges;
00353 unsigned int next_seq_id;
00354 unsigned int next_vertex_id;
00355 std::string current_backend_;
00356 int earliest_loop_closure_node_;
00357 ColorOctomapServer co_server_;
00358
00359
00360 void sendAllCloudsImpl();
00362 void saveAllCloudsToFile(QString filename);
00364 void saveAllFeaturesToFile(QString filename);
00366 void saveIndividualCloudsToFile(QString filename);
00367 void saveOctomapImpl(QString filename);
00368 void renderToOctomap(Node* node);
00369 void pointCloud2MeshFile(QString filename, pointcloud_type full_cloud);
00370 void savePlyFile(QString filename, pointcloud_normal_type& full_cloud);
00371
00372
00374 void visualizeGraphEdges() const;
00376 void visualizeGraphNodes() const;
00378 void visualizeGraphIds() const;
00380 void visualizeFeatureFlow3D(unsigned int marker_id = 0, bool draw_outlier = true);
00381
00382 g2o::RobustKernelHuber robust_kernel_;
00383
00384 g2o::SparseOptimizer::Vertex* calibration_vertex_;
00385
00386
00387
00388
00389 unsigned int last_odom_time_;
00390
00391 };
00392
00394 void publishCloud(Node* node, ros::Time timestamp, ros::Publisher pub);
00395
00396
00397 #endif