├── .gitattributes
├── src
├── cMap.cpp
├── cSystem.cpp
├── cViewer.cpp
├── cConverter.cpp
├── cMapPoint.cpp
├── cORBmatcher.cpp
├── cTracking.cpp
├── cLoopClosing.cpp
├── cMapPublisher.cpp
├── mdBRIEFextractorOct.cpp
├── cMultiKeyFrameDatabase.cpp
├── camDriver.cpp
├── camSubscriber.cpp
├── misc.cpp
├── g2o_MultiCol_sim3_expmap.cpp
├── imuDriver.cpp
├── cam_model_omni.cpp
├── cMultiFramePublisher.cpp
├── cam_system_omni.cpp
├── cMultiInitializer.cpp
├── cMultiFrame.cpp
├── cSim3Solver.cpp
└── cOptimizerLoopStuff.cpp
├── include
├── cMapPoint.h
├── cSystem.h
├── cViewer.h
├── cORBmatcher.h
├── cSim3Solver.h
├── cLocalMapping.h
├── cLoopClosing.h
├── cMapPublisher.h
├── cORBVocabulary.h
├── cMultiInitializer.h
├── mdBRIEFextractorOct.h
├── cMultiFramePublisher.h
├── cMultiKeyFrameDatabase.h
├── cMap.h
├── cORBextractor.h
├── cOptimizer.h
├── cConverter.h
├── cMultiFrame.h
├── g2o_MultiCol_vertices_edges.h
├── misc.h
├── cam_system_omni.h
├── cTracking.h
├── cam_model_omni.h
├── g2o_MultiCol_sim3_expmap.h
├── cMultiKeyFrame.h
└── mdBRIEFextractor.h
├── resources
├── MultiCol.png
├── singleCamera.png
├── BodyFrameConcept.png
└── MultiCol_as_hypergraph.png
├── Examples
├── Lafida
│ ├── multi_col_slam_lafida
│ ├── mult_col_slam_lafida.cpp
│ ├── InteriorOrientationFisheye1.yaml
│ ├── InteriorOrientationFisheye2.yaml
│ ├── MultiCamSys_Calibration.yaml
│ ├── InteriorOrientationFisheye0.yaml
│ ├── Slam_Settings_indoor3.yaml
│ ├── Slam_Settings_indoor4.yaml
│ ├── Slam_Settings_indoor2.yaml
│ └── Slam_Settings_indoor1.yaml
└── ROS
│ └── MultiCol-SLAM
│ ├── manifest.xml
│ ├── include
│ └── camNodelet.h
│ ├── CMakeLists.txt
│ └── src
│ ├── ros_multi_backup.cc
│ └── ros_multi.cc
├── README.md
└── CMakeLists.txt
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.C++ linguist-detectable=true
2 | *.CMake linguist-detectable=false
3 |
--------------------------------------------------------------------------------
/src/cMap.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/src/cMap.cpp
--------------------------------------------------------------------------------
/src/cSystem.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/src/cSystem.cpp
--------------------------------------------------------------------------------
/src/cViewer.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/src/cViewer.cpp
--------------------------------------------------------------------------------
/include/cMapPoint.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/cMapPoint.h
--------------------------------------------------------------------------------
/include/cSystem.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/cSystem.h
--------------------------------------------------------------------------------
/include/cViewer.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/cViewer.h
--------------------------------------------------------------------------------
/src/cConverter.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/src/cConverter.cpp
--------------------------------------------------------------------------------
/src/cMapPoint.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/src/cMapPoint.cpp
--------------------------------------------------------------------------------
/src/cORBmatcher.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/src/cORBmatcher.cpp
--------------------------------------------------------------------------------
/src/cTracking.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/src/cTracking.cpp
--------------------------------------------------------------------------------
/include/cORBmatcher.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/cORBmatcher.h
--------------------------------------------------------------------------------
/include/cSim3Solver.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/cSim3Solver.h
--------------------------------------------------------------------------------
/src/cLoopClosing.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/src/cLoopClosing.cpp
--------------------------------------------------------------------------------
/src/cMapPublisher.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/src/cMapPublisher.cpp
--------------------------------------------------------------------------------
/include/cLocalMapping.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/cLocalMapping.h
--------------------------------------------------------------------------------
/include/cLoopClosing.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/cLoopClosing.h
--------------------------------------------------------------------------------
/include/cMapPublisher.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/cMapPublisher.h
--------------------------------------------------------------------------------
/include/cORBVocabulary.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/cORBVocabulary.h
--------------------------------------------------------------------------------
/resources/MultiCol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/resources/MultiCol.png
--------------------------------------------------------------------------------
/resources/singleCamera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/resources/singleCamera.png
--------------------------------------------------------------------------------
/include/cMultiInitializer.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/cMultiInitializer.h
--------------------------------------------------------------------------------
/include/mdBRIEFextractorOct.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/mdBRIEFextractorOct.h
--------------------------------------------------------------------------------
/src/mdBRIEFextractorOct.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/src/mdBRIEFextractorOct.cpp
--------------------------------------------------------------------------------
/include/cMultiFramePublisher.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/cMultiFramePublisher.h
--------------------------------------------------------------------------------
/resources/BodyFrameConcept.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/resources/BodyFrameConcept.png
--------------------------------------------------------------------------------
/src/cMultiKeyFrameDatabase.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/src/cMultiKeyFrameDatabase.cpp
--------------------------------------------------------------------------------
/include/cMultiKeyFrameDatabase.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/include/cMultiKeyFrameDatabase.h
--------------------------------------------------------------------------------
/resources/MultiCol_as_hypergraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/resources/MultiCol_as_hypergraph.png
--------------------------------------------------------------------------------
/Examples/Lafida/multi_col_slam_lafida:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/Examples/Lafida/multi_col_slam_lafida
--------------------------------------------------------------------------------
/Examples/Lafida/mult_col_slam_lafida.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Varun-Haris/Multi-Camera-SLAM/HEAD/Examples/Lafida/mult_col_slam_lafida.cpp
--------------------------------------------------------------------------------
/Examples/ROS/MultiCol-SLAM/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MultiCol
5 |
6 |
7 | Abhihsek Ravi
8 | GPLv3
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/Examples/Lafida/InteriorOrientationFisheye1.yaml:
--------------------------------------------------------------------------------
1 | %YAML:1.0
2 |
3 | # Camera Parameters. Adjust them!
4 | # Camera calibration parameters cam right
5 | Camera.Iw: 754
6 | Camera.Ih: 480
7 |
8 | Camera.nrpol: 5
9 | Camera.nrinvpol: 12
10 |
11 | Camera.a0:-209.071570423477
12 | Camera.a1: 0.0
13 | Camera.a2: 0.00216428966944475
14 | Camera.a3: -4.82076123755912e-06
15 | Camera.a4: 1.91902225328321e-08
16 |
17 | Camera.pol0: 294.569975726124
18 | Camera.pol1: 148.608451179358
19 | Camera.pol2: -12.8584962393538
20 | Camera.pol3: 28.8889327437629
21 | Camera.pol4: 6.33883105861485
22 | Camera.pol5:-0.89043629163529
23 | Camera.pol6: 12.3786448516946
24 | Camera.pol7: 0.165754338732521
25 | Camera.pol8: -7.71927140996498
26 | Camera.pol9: 0.995360127219927
27 | Camera.pol10: 3.74959014924028
28 | Camera.pol11: 1.01240838118284
29 |
30 | Camera.c: 1.00025900216253
31 | Camera.d: -0.0123492665428806
32 | Camera.e: 0.012594227848688
33 |
34 | Camera.u0: 378.722262294544
35 | Camera.v0: 253.62515782861
36 |
37 | # create a mirror mask for fisheye cameras
38 | Camera.mirrorMask: 1
--------------------------------------------------------------------------------
/Examples/Lafida/InteriorOrientationFisheye2.yaml:
--------------------------------------------------------------------------------
1 | %YAML:1.0
2 |
3 | # Camera Parameters. Adjust them!
4 | # Camera calibration parameters cam left
5 | Camera.Iw: 754
6 | Camera.Ih: 480
7 |
8 | Camera.nrpol: 5
9 | Camera.nrinvpol: 12
10 |
11 | Camera.a0: -208.409533164304
12 | Camera.a1: 0.0
13 | Camera.a2: 0.00225243935068085
14 | Camera.a3: -5.55430532694086e-06
15 | Camera.a4: 2.07875001352451e-08
16 |
17 | Camera.pol0: 293.775776115273
18 | Camera.pol1: 147.35852428463
19 | Camera.pol2: -14.3964307215767
20 | Camera.pol3: 29.078338589251
21 | Camera.pol4: 6.03461468718202
22 | Camera.pol5:-2.07410652721192
23 | Camera.pol6: 13.4359111214281
24 | Camera.pol7: 0.984397095348803
25 | Camera.pol8: -8.64924421339311
26 | Camera.pol9: 0.491570292475276
27 | Camera.pol10: 3.92296807229949
28 | Camera.pol11: 1.10563269391099
29 |
30 | Camera.c: 0.99992772614797
31 | Camera.d: 0.0334716840387143
32 | Camera.e: -0.0332451389561491
33 |
34 | Camera.u0: 372.796912405235
35 | Camera.v0: 225.645071214684
36 |
37 | # create a mirror mask for fisheye cameras
38 | Camera.mirrorMask: 1
39 |
--------------------------------------------------------------------------------
/Examples/Lafida/MultiCamSys_Calibration.yaml:
--------------------------------------------------------------------------------
1 | %YAML:1.0
2 |
3 | # Multi-camera calibration matrices (M_c)
4 | # rotation elements are in cayley parametrization
5 | CameraSystem.nrCams: 3
6 | # camera back
7 | CameraSystem.cam1_1: -0.0238361786473007 #r1
8 | CameraSystem.cam1_2: -2.05998171167958 #r2
9 | CameraSystem.cam1_3: 0.695126790868671 #r3
10 | CameraSystem.cam1_4: -0.140202124607334 #t1
11 | CameraSystem.cam1_5: 0.0219677971160655 #t2
12 | CameraSystem.cam1_6: -0.0226322662838432 #t3
13 | # camera right
14 | CameraSystem.cam2_1: -0.0103943566650926 #r1
15 | CameraSystem.cam2_2: 1.12505249943085 #r2
16 | CameraSystem.cam2_3: -0.402901183146028 #r3
17 | CameraSystem.cam2_4: 0.108753418890423 #t1
18 | CameraSystem.cam2_5: 0.0636197216520153 #t2
19 | CameraSystem.cam2_6: 0.0657911760105832 #t3
20 | # camera left
21 | CameraSystem.cam3_1: 0 #r1
22 | CameraSystem.cam3_2: 0 #r2
23 | CameraSystem.cam3_3: 0 #r3
24 | CameraSystem.cam3_4: -0.00157612288268783 #t1
25 | CameraSystem.cam3_5: 0.103615531247527 #t2
26 | CameraSystem.cam3_6: 0.201416323496156 #t3
27 |
28 |
29 |
--------------------------------------------------------------------------------
/Examples/Lafida/InteriorOrientationFisheye0.yaml:
--------------------------------------------------------------------------------
1 | %YAML:1.0
2 |
3 | # Camera Parameters. Adjust them!
4 | # Camera calibration parameters camera back
5 | Camera.Iw: 754
6 | Camera.Ih: 480
7 |
8 | # hyperparameters
9 | Camera.nrpol: 5
10 | Camera.nrinvpol: 12
11 |
12 | # forward polynomial f(\rho)
13 | Camera.a0: -209.200757992065
14 | Camera.a1: 0.0
15 | Camera.a2: 0.00213741670953883
16 | Camera.a3: -4.2203617319086e-06
17 | Camera.a4: 1.77146086919594e-08
18 |
19 | # backward polynomial rho(\theta)
20 | Camera.pol0: 293.667187375663
21 | Camera.pol1: 149.982043337335
22 | Camera.pol2: -10.448650568161
23 | Camera.pol3: 28.2295300683376
24 | Camera.pol4: 7.13365723186292
25 | Camera.pol5: 0.056303218962532
26 | Camera.pol6: 10.4144677485333
27 | Camera.pol7: 0.166354960773665
28 | Camera.pol8: -5.86858687381081
29 | Camera.pol9: 1.18165998645705
30 | Camera.pol10: 3.1108311354746
31 | Camera.pol11: 0.810799620714366
32 |
33 | # affine matrix
34 | Camera.c: 0.999626131079017
35 | Camera.d: -0.0034775192597376
36 | Camera.e: 0.00385134991673147
37 |
38 | # principal point
39 | Camera.u0: 392.219508388648
40 | Camera.v0: 243.494438476351
41 |
42 | # create a mirror mask for fisheye cameras
43 | Camera.mirrorMask: 1
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Examples/ROS/MultiCol-SLAM/include/camNodelet.h:
--------------------------------------------------------------------------------
1 | #ifndef CAMNODELET_H
2 | #define CAMNODELET_H
3 |
4 | // Standard c++ headers
5 | #include
6 | #include
7 | #include
8 |
9 | // ROS related headers
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | // OpenCV headers
18 | #include
19 | #include
20 | #include "opencv2/features2d.hpp"
21 | #include "opencv2/xfeatures2d.hpp"
22 | #include "opencv2/core/core.hpp"
23 | #include "opencv2/imgproc/imgproc.hpp"
24 |
25 | using namespace std;
26 | using namespace cv;
27 |
28 | class camSubs{
29 | public:
30 | ros::NodeHandle nh;
31 | image_transport::Subscriber sub, sub1, sub2;
32 | image_transport::ImageTransport it;
33 | cv::Mat frame1, frame2, frame3;
34 | std_msgs::Header header1, header2, header3;
35 |
36 | camSubs();
37 | void imageCbWeb(const sensor_msgs::ImageConstPtr& msg);
38 | void imageCbUsb1(const sensor_msgs::ImageConstPtr& msg);
39 | void imageCbUsb2(const sensor_msgs::ImageConstPtr& msg);
40 | }; //End of class
41 |
42 | #endif
43 |
--------------------------------------------------------------------------------
/src/camDriver.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | using namespace cv;
7 |
8 | class driver{
9 | public:
10 | ros::NodeHandle nh;
11 | image_transport::Publisher pub, pub1, pub2;
12 |
13 | driver(){
14 | image_transport::ImageTransport it(nh);
15 | this->pub = it.advertise("camera/image/webcam", 1);
16 | this->pub1 = it.advertise("camera/image/usb1", 1);
17 | this->pub2 = it.advertise("camera/image/usb2", 1);
18 | }
19 |
20 | void publishMsg(sensor_msgs::ImagePtr msg, sensor_msgs::ImagePtr msg1, sensor_msgs::ImagePtr msg2){
21 | this->pub.publish(msg);
22 | this->pub1.publish(msg1);
23 | this->pub2.publish(msg2);
24 | }
25 | };
26 |
27 | int main(int argc, char** argv){
28 | ros::init(argc, argv, "Driver"); //Driver node
29 | ros::NodeHandle n;
30 | uint32_t i=0;
31 | VideoCapture cap, cam1, cam2;
32 |
33 | cap.open("/dev/video0");
34 | cam1.open("/dev/video1");
35 | cam2.open("/dev/video2");
36 | if(!cap.isOpened() || !cam1.isOpened() || !cam2.isOpened()){
37 | return -1;
38 | }
39 |
40 | driver *camDrive = new driver;
41 | Mat frame, frame1, frame2;
42 | while(ros::ok()){
43 | cap >> frame;
44 | cam1 >> frame1;
45 | cam2 >> frame2;
46 |
47 | sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", frame).toImageMsg();
48 | msg->header.stamp = ros::Time::now(); //Adding timestamp
49 | msg->header.seq = i; //Adding sequence number
50 | msg->header.frame_id = "Webcam integrated";
51 |
52 | sensor_msgs::ImagePtr msg1 = cv_bridge::CvImage(std_msgs::Header(), "bgr8", frame1).toImageMsg();
53 | msg1->header.stamp = ros::Time::now(); //Adding timestamp
54 | msg1->header.seq = i; //Adding sequence number
55 | msg1->header.frame_id = "USB cam 1";
56 |
57 | sensor_msgs::ImagePtr msg2 = cv_bridge::CvImage(std_msgs::Header(), "bgr8", frame2).toImageMsg();
58 | msg2->header.stamp = ros::Time::now(); //Adding timestamp
59 | msg2->header.seq = i; //Adding sequence number
60 | msg2->header.frame_id = "USB cam 2";
61 |
62 | camDrive->publishMsg(msg, msg1, msg2);
63 | i++;
64 | }
65 | return 0;
66 | }
67 |
--------------------------------------------------------------------------------
/Examples/Lafida/Slam_Settings_indoor3.yaml:
--------------------------------------------------------------------------------
1 | %YAML:1.0
2 | # Camera frames per second
3 | Camera.fps: 25.0
4 |
5 | # Color order of the images (0: BGR, 1: RGB. It is ignored if images are grayscale)
6 | Camera.RGB: 1
7 |
8 | #--------------------------------------------------------------------------------------------
9 | ### Changing the parameters below could seriously degradate the performance of the system
10 |
11 | # 0-> ORB, 1->dBRIEF
12 | extractor.usemdBRIEF: 0
13 |
14 | # 1-> learn masks, 0 don't (mdBRIEF)
15 | extractor.masks: 0
16 |
17 | # 1-> use Agast, 0 don't
18 | extractor.useAgast: 0
19 |
20 | # 0,1,2,(3 is only possible for agast)
21 | extractor.fastAgastType: 2
22 |
23 | # Extractor: 32 -> ORB , (16/32/64) -> dBRIEF and mdBRIEF
24 | extractor.descSize: 32
25 |
26 | # Extractor: Number of features per image
27 | extractor.nFeatures: 400
28 |
29 | # Extractor: Scale factor between levels in the scale pyramid
30 | extractor.scaleFactor: 1.2
31 |
32 | # Extractor: Number of levels in the scale pyramid
33 | extractor.nLevels: 8
34 |
35 | # Extractor: FAST threshold (lower less restrictive)
36 | extractor.fastTh: 20
37 |
38 | # Extractor: Score to sort features. 0 -> Harris Score, 1 -> FAST Score
39 | extractor.nScoreType: 0
40 |
41 | # Constant Velocity Motion Model (0 - disabled, 1 - enabled [recommended])
42 | UseMotionModel: 1
43 |
44 |
45 |
46 | #--------------------------------------------------------------------------------------------
47 | # current trajectory to get evaluated
48 | traj2Eval: 3
49 | # run x (we need multiple runs to evaluate the accuracy because SLAM is not deterministic)
50 | trajrun: 1
51 |
52 | #------------------------------
53 | ### initial frame Traj3
54 | traj.StartFrame: 1
55 | traj.EndFrame: 1015
56 | #------------------------------
57 |
58 | #--------------------------------------------------------------------------------------------
59 | # Viewer settings
60 | Viewer.MultiKeyFrameSize: 0.05
61 | Viewer.MultiKeyFrameLineWidth: 1
62 | Viewer.GraphLineWidth: 0.9
63 | Viewer.PointSize: 2
64 | Viewer.CameraSize: 0.08
65 | Viewer.CameraLineWidth: 3
66 | Viewer.ViewpointX: 1.0
67 | Viewer.ViewpointY: 1.0
68 | Viewer.ViewpointZ: 1.0
69 | Viewer.ViewpointF: 500.0
70 | Viewer.DrawNrCams: 2
--------------------------------------------------------------------------------
/Examples/Lafida/Slam_Settings_indoor4.yaml:
--------------------------------------------------------------------------------
1 | %YAML:1.0
2 | # Camera frames per second
3 | Camera.fps: 25.0
4 |
5 | # Color order of the images (0: BGR, 1: RGB. It is ignored if images are grayscale)
6 | Camera.RGB: 1
7 |
8 | #--------------------------------------------------------------------------------------------
9 | ### Changing the parameters below could seriously degradate the performance of the system
10 |
11 | # 0-> ORB, 1->dBRIEF
12 | extractor.usemdBRIEF: 0
13 |
14 | # 1-> learn masks, 0 don't (mdBRIEF)
15 | extractor.masks: 0
16 |
17 | # 1-> use Agast, 0 don't
18 | extractor.useAgast: 0
19 |
20 | # 0,1,2,(3 is only possible for agast)
21 | extractor.fastAgastType: 2
22 |
23 | # Extractor: 32 -> ORB , (16/32/64) -> dBRIEF and mdBRIEF
24 | extractor.descSize: 32
25 |
26 | # Extractor: Number of features per image
27 | extractor.nFeatures: 400
28 |
29 | # Extractor: Scale factor between levels in the scale pyramid
30 | extractor.scaleFactor: 1.2
31 |
32 | # Extractor: Number of levels in the scale pyramid
33 | extractor.nLevels: 8
34 |
35 | # Extractor: FAST threshold (lower less restrictive)
36 | extractor.fastTh: 20
37 |
38 | # Extractor: Score to sort features. 0 -> Harris Score, 1 -> FAST Score
39 | extractor.nScoreType: 0
40 |
41 | # Constant Velocity Motion Model (0 - disabled, 1 - enabled [recommended])
42 | UseMotionModel: 1
43 |
44 |
45 |
46 | #--------------------------------------------------------------------------------------------
47 | # current trajectory to get evaluated
48 | traj2Eval: 4
49 | # run x (we need multiple runs to evaluate the accuracy because SLAM is not deterministic)
50 | trajrun: 1
51 |
52 | ### trajectory options
53 | #------------------------------
54 | ### initial frame Traj 1
55 | traj.StartFrame: 1
56 | traj.EndFrame: 1629
57 | #------------------------------
58 |
59 | #--------------------------------------------------------------------------------------------
60 | # Viewer settings
61 | Viewer.MultiKeyFrameSize: 0.08
62 | Viewer.MultiKeyFrameLineWidth: 2
63 | Viewer.GraphLineWidth: 1
64 | Viewer.PointSize: 3
65 | Viewer.CameraSize: 0.1
66 | Viewer.CameraLineWidth: 3
67 | Viewer.ViewpointX: 1.0
68 | Viewer.ViewpointY: 1.0
69 | Viewer.ViewpointZ: 1.0
70 | Viewer.ViewpointF: 500.0
71 | Viewer.DrawNrCams: 2
--------------------------------------------------------------------------------
/Examples/Lafida/Slam_Settings_indoor2.yaml:
--------------------------------------------------------------------------------
1 | %YAML:1.0
2 | # Camera frames per second
3 | Camera.fps: 25.0
4 |
5 | # Color order of the images (0: BGR, 1: RGB. It is ignored if images are grayscale)
6 | Camera.RGB: 1
7 |
8 | #--------------------------------------------------------------------------------------------
9 | ### Changing the parameters below could seriously degradate the performance of the system
10 |
11 | # 0-> ORB, 1->dBRIEF
12 | extractor.usemdBRIEF: 0
13 |
14 | # 1-> learn masks, 0 don't (mdBRIEF)
15 | extractor.masks: 0
16 |
17 | # 1-> use Agast, 0 don't
18 | extractor.useAgast: 0
19 |
20 | # 0,1,2,(3 is only possible for agast)
21 | extractor.fastAgastType: 2
22 |
23 | # Extractor: 32 -> ORB , (16/32/64) -> dBRIEF and mdBRIEF
24 | extractor.descSize: 32
25 |
26 | # Extractor: Number of features per image
27 | extractor.nFeatures: 400
28 |
29 | # Extractor: Scale factor between levels in the scale pyramid
30 | extractor.scaleFactor: 1.2
31 |
32 | # Extractor: Number of levels in the scale pyramid
33 | extractor.nLevels: 8
34 |
35 | # Extractor: FAST threshold (lower less restrictive)
36 | extractor.fastTh: 20
37 |
38 | # Extractor: Score to sort features. 0 -> Harris Score, 1 -> FAST Score
39 | extractor.nScoreType: 0
40 |
41 | # Constant Velocity Motion Model (0 - disabled, 1 - enabled [recommended])
42 | UseMotionModel: 1
43 |
44 |
45 |
46 | #--------------------------------------------------------------------------------------------
47 | # current trajectory to get evaluated
48 | traj2Eval: 2
49 | # run x (we need multiple runs to evaluate the accuracy because SLAM is not deterministic)
50 | trajrun: 1
51 |
52 | ### trajectory options
53 | #------------------------------
54 | ### initial frame Traj 2
55 | traj.StartFrame: 1
56 | traj.EndFrame: 899
57 | #------------------------------
58 |
59 | #--------------------------------------------------------------------------------------------
60 | # Viewer settings
61 | Viewer.MultiKeyFrameSize: 0.05
62 | Viewer.MultiKeyFrameLineWidth: 1
63 | Viewer.GraphLineWidth: 0.9
64 | Viewer.PointSize: 2
65 | Viewer.CameraSize: 0.08
66 | Viewer.CameraLineWidth: 3
67 | Viewer.ViewpointX: 1.0
68 | Viewer.ViewpointY: 1.0
69 | Viewer.ViewpointZ: 1.0
70 | Viewer.ViewpointF: 500.0
71 | Viewer.DrawNrCams: 2
--------------------------------------------------------------------------------
/Examples/Lafida/Slam_Settings_indoor1.yaml:
--------------------------------------------------------------------------------
1 | %YAML:1.0
2 | # Camera frames per second
3 | Camera.fps: 25.0
4 |
5 | # Color order of the images (0: BGR, 1: RGB. It is ignored if images are grayscale)
6 | Camera.RGB: 1
7 |
8 | #--------------------------------------------------------------------------------------------
9 | ### Changing the parameters below could seriously degradate the performance of the system
10 |
11 | # 0-> ORB, 1->dBRIEF
12 | extractor.usemdBRIEF: 0
13 |
14 | # 1-> learn masks, 0 don't (mdBRIEF)
15 | extractor.masks: 0
16 |
17 | # 1-> use Agast, 0 don't
18 | extractor.useAgast: 0
19 |
20 | # 0,1,2,(3 is only possible for agast)
21 | extractor.fastAgastType: 2
22 |
23 | # Extractor: 32 -> ORB , (16/32/64) -> dBRIEF and mdBRIEF
24 | extractor.descSize: 32
25 |
26 | # Extractor: Number of features per image
27 | extractor.nFeatures: 400
28 |
29 | # Extractor: Scale factor between levels in the scale pyramid
30 | extractor.scaleFactor: 1.2
31 |
32 | # Extractor: Number of levels in the scale pyramid
33 | extractor.nLevels: 8
34 |
35 | # Extractor: FAST threshold (lower less restrictive)
36 | extractor.fastTh: 20
37 |
38 | # Extractor: Score to sort features. 0 -> Harris Score, 1 -> FAST Score
39 | extractor.nScoreType: 0
40 |
41 | # Constant Velocity Motion Model (0 - disabled, 1 - enabled [recommended])
42 | UseMotionModel: 1
43 |
44 |
45 |
46 | #--------------------------------------------------------------------------------------------
47 | # current trajectory to get evaluated
48 | traj2Eval: 1
49 | # run x (we need multiple runs to evaluate the accuracy because SLAM is not deterministic)
50 | trajrun: 1
51 |
52 | ### trajectory options
53 | #------------------------------
54 | ### initial frame Traj 1
55 | traj.StartFrame: 25
56 | traj.EndFrame: 759
57 | #traj.EndFrame: 100
58 | #------------------------------
59 |
60 | #--------------------------------------------------------------------------------------------
61 | # Viewer settings
62 | Viewer.MultiKeyFrameSize: 0.05
63 | Viewer.MultiKeyFrameLineWidth: 1
64 | Viewer.GraphLineWidth: 0.9
65 | Viewer.PointSize: 2
66 | Viewer.CameraSize: 0.08
67 | Viewer.CameraLineWidth: 3
68 | Viewer.ViewpointX: 1.0
69 | Viewer.ViewpointY: 1.0
70 | Viewer.ViewpointZ: 1.0
71 | Viewer.ViewpointF: 500.0
72 | Viewer.DrawNrCams: 3
--------------------------------------------------------------------------------
/src/camSubscriber.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | class camSubs{
9 | public:
10 | ros::NodeHandle nh;
11 | image_transport::Subscriber sub, sub1, sub2;
12 | image_transport::ImageTransport it;
13 |
14 | camSubs():it(nh){
15 | this->sub = it.subscribe("camera/image/webcam", 1, &camSubs::imageCbWeb, this);
16 | this->sub1 = it.subscribe("camera/image/usb1", 1, &camSubs::imageCbUsb1, this);
17 | this->sub2 = it.subscribe("camera/image/usb2", 1, &camSubs::imageCbUsb2, this);
18 | ROS_INFO("Subscriber setup!!");
19 | }
20 |
21 | void imageCbWeb(const sensor_msgs::ImageConstPtr& msg){
22 | std::cout << "webcam header : \n" << msg->header << std::endl;
23 | try{
24 | cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image);
25 | cv::waitKey(1);
26 | }
27 | catch(cv_bridge::Exception& e){
28 | ROS_ERROR("Couldn't get image due to %s",e.what());
29 | }
30 | }
31 |
32 | void imageCbUsb1(const sensor_msgs::ImageConstPtr& msg){
33 | std::cout << "usb1 header : \n" << msg->header << std::endl;
34 | try{
35 | cv::imshow("view1", cv_bridge::toCvShare(msg, "bgr8")->image);
36 | cv::waitKey(1);
37 | }
38 | catch(cv_bridge::Exception& e){
39 | ROS_ERROR("Couldn't get image due to %s",e.what());
40 | }
41 | }
42 |
43 | void imageCbUsb2(const sensor_msgs::ImageConstPtr& msg){
44 | std::cout << "usb2 header : \n" << msg->header << std::endl;
45 | try{
46 | cv::imshow("view2", cv_bridge::toCvShare(msg, "bgr8")->image);
47 | cv::waitKey(1);
48 | }
49 | catch(cv_bridge::Exception& e){
50 | ROS_ERROR("Couldn't get image due to %s",e.what());
51 | }
52 | }
53 | };
54 |
55 | int main(int argc, char** argv){
56 | ros::init(argc, argv, "Image_Listener");
57 | ros::NodeHandle n;
58 |
59 | cv::namedWindow("view");
60 | cv::startWindowThread();
61 |
62 | cv::namedWindow("view1");
63 | cv::startWindowThread();
64 |
65 | cv::namedWindow("view2");
66 | cv::startWindowThread();
67 |
68 | camSubs *Subs = new camSubs;
69 | while(ros::ok()){
70 | ros::spinOnce();
71 | }
72 |
73 | cv::destroyWindow("view");
74 | cv::destroyWindow("view1");
75 | cv::destroyWindow("view2");
76 | }
77 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Multi-Camera-SLAM
2 |
3 | ROS-Kinetic implementation of Urbstate MultiCol-SLAM
4 |
5 | This is a stable ROS implementation of the MultiCol-SLAM algorithm (original author: Stephan Urban). Please refer to the
6 | "https://github.com/urbste/MultiCol-SLAM" for initial implementation. This enables the user to run MultiCol-SLAM algorithm using live camera feed and perform real-time SLAM.
7 |
8 | Please note that the calibration files are very crucial for efficient tracking. Please refer to https://github.com/urbste/MultiCol-SLAM/issues/9, for concerns on multiple camera calibration setup.
9 |
10 | # Third Party dependencies needed
11 |
12 | 1) Pangolin
13 | For visualization. Get the instructions here: https://github.com/stevenlovegrove/Pangolin. This isn't present in the ./ThirdParty folder, needs to be installed off-the-shelf.
14 |
15 | 2) Eigen3
16 | Required by g2o Version 3.2.9 is included in the ./ThirdParty folder. Other version can be found at http://eigen.tuxfamily.org/index.php?title=Main_Page.
17 |
18 | 3) OpenGV
19 | OpenGV can be found at: https://github.com/laurentkneip/opengv. It is also included in the ./ThirdParty folder. OpenGV is used for re-localization (GP3P) and relative orientation estimation during initialization (Stewenius).
20 |
21 | 4) DBoW2 and g2o
22 | As ORB-SLAM2 modified versions of DBoW2 and g2o are used for place recognition and optimization respectively. Both are included in the ./ThirdParty folder. The original versions can be found here: https://github.com/dorian3d/DBoW2, https://github.com/RainerKuemmerle/g2o.
23 |
24 | 5) OpenCV 3
25 | ROS-Kinetic has its own version of OpenCV-3.3.1-Dev. This version works fine with the MultiCol-SLAM, and I would recommend not to mend with the OpenCV version. In any case OpenCV can be found and installed from: https://github.com/opencv/opencv.
26 |
27 | # Building and running ROS nodes
28 |
29 | Build the package:-
30 | 1) Add the MultiCol-SLAM package path to the ROS_PACKAGE_PATH envirnoment variable as shown below
31 |
32 | export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:/*path_to_directory*/Examples/ROS/MultiCol-SLAM
33 |
34 | 2) Compile the MultiCol-SLAM source codes into a condensed library with *bash build.sh* command.
35 | 3) Compile the ROS executable with the condensed libraries with *bash build_ros.sh* command.
36 |
37 | Run the SLAM algorithm using the ROS toolchain:-
38 | 1) Initiate the ros master (roscore or an existing roslaunch file)
39 | 2) Run the camDriver node (rosrun *your_package_name* camDriver)
40 | 3) Run the SLAM node (rosrun *your_package_name* Multi)
41 |
42 | To change the calibration or setting files, go to Examples/ROS/MultiCol-SLAM/src/ros_multi.cpp, change the file paths appropriately
43 |
--------------------------------------------------------------------------------
/include/cMap.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of MultiCol-SLAM
3 | *
4 | * Copyright (C) 2015-2016 Steffen Urban
5 | * For more information see
6 | *
7 | * MultiCol-SLAM is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * MultiCol-SLAM is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with MultiCol-SLAM . If not, see .
19 | */
20 |
21 | /*
22 | * MultiCol-SLAM is based on ORB-SLAM2 which was also released under GPLv3
23 | * For more information see
24 | * Raúl Mur-Artal (University of Zaragoza)
25 | */
26 |
27 | #ifndef MAP_H
28 | #define MAP_H
29 |
30 | // own includes
31 | #include "cMapPoint.h"
32 | #include "cMultiKeyFrame.h"
33 | // external includes
34 | #include
35 | #include
36 | namespace MultiColSLAM
37 | {
38 |
39 | class cMapPoint;
40 | class cMultiKeyFrame;
41 |
42 | class cMap
43 | {
44 | public:
45 | cMap();
46 |
47 | void AddKeyFrame(cMultiKeyFrame* pKF);
48 | void AddMapPoint(cMapPoint* pMP);
49 | void EraseMapPoint(cMapPoint* pMP);
50 | void EraseKeyFrame(cMultiKeyFrame* pKF);
51 | void SetCurrentCameraPose(cv::Mat Tcw);
52 | void SetReferenceKeyFrames(const std::vector &vpKFs);
53 | void SetReferenceMapPoints(const std::vector &vpMPs);
54 |
55 | std::vector GetAllKeyFrames();
56 | std::vector GetAllMapPoints();
57 |
58 | std::vector GetReferenceKeyFrames();
59 | std::vector GetReferenceMapPoints();
60 |
61 | void GetModelPoints(std::vector& modelPts,
62 | std::vector& modelCompanionPts);
63 | void SetModelPoints(const std::vector& _modelPts,
64 | const std::vector& _modelCompanionPts);
65 |
66 | int MapPointsInMap();
67 | int KeyFramesInMap();
68 |
69 | void SetFlagAfterBA();
70 | bool isMapUpdated();
71 | void ResetUpdated();
72 |
73 | unsigned int GetMaxKFid();
74 |
75 | void clear();
76 |
77 | //std::mutex mMutexMapUpdate;
78 |
79 | protected:
80 | std::set mspMapPoints;
81 | std::set mspKeyFrames;
82 | std::vector mvpReferenceMapPoints;
83 |
84 | unsigned int mnMaxKFid;
85 |
86 | std::mutex mMutexMap;
87 | bool mbMapUpdated;
88 |
89 | };
90 |
91 | }
92 | #endif // MAP_H
93 |
--------------------------------------------------------------------------------
/Examples/ROS/MultiCol-SLAM/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.4.6)
2 | include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
3 | #project(MultiCol-SLAM-ROS)
4 |
5 | rosbuild_init()
6 |
7 | IF(NOT ROS_BUILD_TYPE)
8 | SET(ROS_BUILD_TYPE Release)
9 | ENDIF()
10 |
11 | MESSAGE("Build type: " ${ROS_BUILD_TYPE})
12 |
13 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -march=native ")
14 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O3 -march=native")
15 |
16 | # Check C++11 or C++0x support
17 | include(CheckCXXCompilerFlag)
18 | CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
19 | CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
20 | if(COMPILER_SUPPORTS_CXX11)
21 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
22 | add_definitions(-DCOMPILEDWITHC11)
23 | message(STATUS "Using flag -std=c++11.")
24 | elseif(COMPILER_SUPPORTS_CXX0X)
25 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
26 | add_definitions(-DCOMPILEDWITHC0X)
27 | message(STATUS "Using flag -std=c++0x.")
28 | else()
29 | message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
30 | endif()
31 |
32 | LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../../../cmake_modules)
33 |
34 | find_package(OpenCV 3.0 QUIET)
35 | if(NOT OpenCV_FOUND)
36 | find_package(OpenCV 2.4.3 QUIET)
37 | if(NOT OpenCV_FOUND)
38 | message(FATAL_ERROR "OpenCV > 2.4.3 not found.")
39 | endif()
40 | endif()
41 |
42 | IF(NOT DEFINED EIGEN_INCLUDE_DIR_HINTS)
43 | SET(EIGEN_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/../../../ThirdParty/Eigen)
44 | MESSAGE("Eigen include DIR ${EIGEN_INCLUDE_DIR}")
45 | #SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/ThirdParty/Eigen/cmake)
46 | #FIND_PACKAGE(Eigen3 REQUIRED)
47 | #MESSAGE("-- Eigen version ${EIGEN3_VERSION}: ${EIGEN3_INCLUDE_DIR}")
48 | #INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIR})
49 | SET(MultiCol-SLAM_USE_INTERNAL_EIGEN ON)
50 | INCLUDE_DIRECTORIES(${EIGEN_INCLUDE_DIR})
51 | ENDIF()
52 |
53 | find_package(Pangolin REQUIRED)
54 |
55 | include_directories(
56 | ${PROJECT_SOURCE_DIR}
57 | ${PROJECT_SOURCE_DIR}/include
58 | ${PROJECT_SOURCE_DIR}/../../../
59 | ${PROJECT_SOURCE_DIR}/../../../include
60 | ${PROJECT_SOURCE_DIR}/../../../ThirdParty
61 | ${PROJECT_SOURCE_DIR}/../../../ThirdParty/g2o
62 | ${PROJECT_SOURCE_DIR}/../../../ThirdParty/OpenGV/include
63 | ${PROJECT_SOURCE_DIR}/../../../ThirdParty/DBoW2
64 | ${Pangolin_INCLUDE_DIRS}
65 | )
66 |
67 | SET (G2OLIBS ${PROJECT_SOURCE_DIR}/../../../ThirdParty/g2o/lib/libg2o.so)
68 | SET (DBOW2LIBS ${PROJECT_SOURCE_DIR}/../../../ThirdParty/DBoW2/lib/libDBoW2.so)
69 | SET (OPENGVLIBS ${PROJECT_SOURCE_DIR}/../../../ThirdParty/OpenGV/build/lib/librandom_generators.a
70 | ${PROJECT_SOURCE_DIR}/../../../ThirdParty/OpenGV/build/lib/libopengv.a)
71 |
72 | set(LIBS
73 | ${OpenCV_LIBS}
74 | ${Pangolin_LIBRARIES}
75 | ${G2OLIBS}
76 | ${DBOW2LIBS}
77 | ${OPENGVLIBS}
78 | ${RANDOMGENLIBS}
79 | #-lboost_system
80 | )
81 |
82 | # Node for multi camera
83 | rosbuild_add_executable(Multi
84 | src/ros_multi.cc
85 | )
86 |
87 | #add_dependencies(Multi g2o DBoW2)
88 |
89 | target_link_libraries(Multi
90 | ${LIBS}
91 | /home/varunharis/MultiCol-SLAM/lib/libMultiCol-SLAM.so
92 | )
93 |
--------------------------------------------------------------------------------
/include/cORBextractor.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of ORB-SLAM.
3 | *
4 | * Copyright (C) 2014 Raúl Mur-Artal (University of Zaragoza)
5 | * For more information see
6 | *
7 | * ORB-SLAM is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * ORB-SLAM is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with ORB-SLAM. If not, see .
19 | */
20 |
21 | #ifndef ORBEXTRACTOR_H
22 | #define ORBEXTRACTOR_H
23 |
24 | #include
25 | #include
26 | #include
27 |
28 |
29 | //namespace ORB_SLAM
30 | //{
31 |
32 | class ExtractorNode
33 | {
34 | public:
35 | ExtractorNode() :bNoMore(false){}
36 |
37 | void DivideNode(ExtractorNode &n1,
38 | ExtractorNode &n2,
39 | ExtractorNode &n3,
40 | ExtractorNode &n4);
41 |
42 | std::vector vKeys;
43 | cv::Point2i UL, UR, BL, BR;
44 | std::list::iterator lit;
45 | bool bNoMore;
46 | };
47 |
48 | class ORBextractor
49 | {
50 | public:
51 |
52 | enum {HARRIS_SCORE=0, FAST_SCORE=1 };
53 |
54 | ORBextractor(int nfeatures = 1000,
55 | double scaleFactor = 1.2,
56 | int nlevels = 8,
57 | int scoreType = FAST_SCORE,
58 | int fastTh = 20);
59 |
60 | ~ORBextractor(){}
61 |
62 | // Compute the ORB features and descriptors on an image
63 | void operator()( cv::InputArray image, cv::InputArray mask,
64 | std::vector& keypoints,
65 | cv::OutputArray descriptors);
66 |
67 | int inline GetLevels(){
68 | return nlevels;}
69 |
70 | double inline GetScaleFactor(){
71 | return scaleFactor;}
72 |
73 |
74 | protected:
75 | void ComputePyramid(cv::Mat image, cv::Mat Mask = cv::Mat());
76 | void ComputeKeyPointsOctTree(std::vector >& allKeypoints);
77 | std::vector DistributeOctTree(
78 | const std::vector& vToDistributeKeys,
79 | const int &minX,
80 | const int &maxX,
81 | const int &minY,
82 | const int &maxY,
83 | const int &nFeatures,
84 | const int &level);
85 |
86 | void ComputeKeyPointsOld(std::vector >& allKeypoints);
87 |
88 | //void ComputePyramid(cv::Mat image, cv::Mat Mask=cv::Mat());
89 | //void ComputeKeyPoints(std::vector >& allKeypoints);
90 |
91 | std::vector pattern;
92 |
93 | int nfeatures;
94 | double scaleFactor;
95 | int nlevels;
96 | int scoreType;
97 | int fastTh;
98 |
99 | std::vector mnFeaturesPerLevel;
100 |
101 | std::vector umax;
102 |
103 | std::vector mvScaleFactor;
104 | std::vector mvInvScaleFactor;
105 |
106 | std::vector mvImagePyramid;
107 | std::vector mvMaskPyramid;
108 |
109 | };
110 |
111 | //} //namespace ORB_SLAM
112 |
113 | #endif
114 |
115 |
--------------------------------------------------------------------------------
/src/misc.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of MultiCol-SLAM
3 | * It is based on the file orb.cpp from the OpenCV library (see BSD license below).
4 | *
5 | * Copyright (C) 2015-2016 Steffen Urban
6 | * For more information see
7 | *
8 | * MultiCol-SLAM is free software: you can redistribute it and/or modify
9 | * it under the terms of the GNU General Public License as published by
10 | * the Free Software Foundation, either version 3 of the License, or
11 | * (at your option) any later version.
12 | *
13 | * MultiCol-SLAM is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with MultiCol-SLAM . If not, see .
20 | */
21 | #include "misc.h"
22 |
23 | namespace MultiColSLAM
24 | {
25 | cv::Vec3d triangulate_point(
26 | const cv::Matx31d& relOri_t12,
27 | const cv::Matx33d& relOri_R12,
28 | const cv::Vec3d& v1,
29 | const cv::Vec3d& v2)
30 | {
31 | // this one is adapted to opencv from opengv::triangulate2
32 | cv::Vec3d pt3(0, 0, 0);
33 | cv::Vec3d f2_unrotated = relOri_R12 * v2;
34 | cv::Vec2d b;
35 | b[0] = relOri_t12.dot(v1);
36 | b[1] = relOri_t12.dot(f2_unrotated);
37 | cv::Matx22d A;
38 | A(0, 0) = v1.dot(v1);
39 | A(1, 0) = v1.dot(f2_unrotated);
40 | A(0, 1) = -A(1, 0);
41 | A(1, 1) = -f2_unrotated.dot(f2_unrotated);
42 | cv::Vec2d lambda = A.inv() * b;
43 | cv::Matx31d xm = lambda[0] * v1;
44 | cv::Matx31d xn = relOri_t12 + lambda[1] * f2_unrotated;
45 | cv::Matx31d tmpres = (xm + xn);
46 | pt3(0) = tmpres(0, 0) / 2.0;
47 | pt3(1) = tmpres(1, 0) / 2.0;
48 | pt3(2) = tmpres(2, 0) / 2.0;
49 | return pt3;
50 | }
51 |
52 |
53 | bool CheckDistEpipolarLine(const cv::Vec3d &ray1,
54 | const cv::Vec3d &ray2,
55 | const cv::Matx33d &E12,
56 | const double& thresh)
57 | {
58 | cv::Vec nom = ray2.t()*E12*ray1;
59 | cv::Vec3d Ex1 = E12*ray1;
60 | cv::Vec3d Etx2 = E12.t()*ray2;
61 |
62 | const double den = Ex1(0)*Ex1(0) + Ex1(1)*Ex1(1) + Ex1(2)*Ex1(2) +
63 | Etx2(0)*Etx2(0) + Etx2(1)*Etx2(1) + Etx2(2)*Etx2(2);
64 |
65 | if (den == 0.0)
66 | return false;
67 | const double dsqr = (nom(0)*nom(0)) / den;
68 | return dsqr < thresh;
69 | }
70 |
71 | cv::Matx33d ComputeE(const cv::Matx44d& T1, const cv::Matx44d& T2)
72 | {
73 | cv::Matx33d R1w = T1.get_minor<3, 3>(0, 0);
74 | cv::Matx33d R2w = T2.get_minor<3, 3>(0, 0);
75 |
76 | cv::Vec3d t1w = cv::Vec3d(T1(0, 3), T1(1, 3), T1(2, 3));
77 | cv::Vec3d t2w = cv::Vec3d(T2(0, 3), T2(1, 3), T2(2, 3));
78 |
79 | cv::Matx33d R12 = R1w*R2w.t();
80 | cv::Vec3d t12 = -R1w*R2w.t()*t2w + t1w;
81 | t12 /= cv::norm(t12);
82 | cv::Matx33d t12x = Skew(t12);
83 |
84 | return t12x*R12;
85 | }
86 |
87 | double T_in_ms(HResClk::time_point start,
88 | HResClk::time_point end)
89 | {
90 | return static_cast(
91 | std::chrono::duration_cast(end - start).count());
92 | }
93 |
94 | double T_in_ns(HResClk::time_point start,
95 | HResClk::time_point end)
96 | {
97 | return static_cast(
98 | std::chrono::duration_cast(end - start).count());
99 | }
100 |
101 | }
--------------------------------------------------------------------------------
/include/cOptimizer.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of MultiCol-SLAM
3 | *
4 | * Copyright (C) 2015-2016 Steffen Urban
5 | * For more information see
6 | *
7 | * MultiCol-SLAM is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * MultiCol-SLAM is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with MultiCol-SLAM . If not, see .
19 | */
20 |
21 | /*
22 | * MultiCol-SLAM is based on ORB-SLAM2 which was also released under GPLv3
23 | * For more information see
24 | * Raúl Mur-Artal (University of Zaragoza)
25 | */
26 |
27 | #ifndef OPTIMIZER_H
28 | #define OPTIMIZER_H
29 |
30 | #include "cMap.h"
31 | #include "cMapPoint.h"
32 | #include "cMultiKeyFrame.h"
33 | #include "cLoopClosing.h"
34 | #include "cMultiFrame.h"
35 |
36 | namespace MultiColSLAM
37 | {
38 | const double huberK = 3;
39 | const double huberK2 = huberK*huberK;
40 |
41 |
42 | //namespace ORB_SLAM
43 | //{
44 |
45 | class cLoopClosing;
46 |
47 | class cOptimizer
48 | {
49 | public:
50 | void static BundleAdjustment(const std::vector &vpKF,
51 | const std::vector &vpMP,
52 | bool poseOnly,
53 | int nIterations = 5,
54 | bool *pbStopFlag = NULL);
55 |
56 | void static GlobalBundleAdjustment(cMap* pMap,
57 | bool poseOnly = false,
58 | int nIterations = 5,
59 | bool *pbStopFlag = NULL);
60 |
61 | static std::list LocalBundleAdjustment(cMultiKeyFrame* pKF,
62 | cMap* pMap,
63 | int nrIters = 10,
64 | bool getCovMats = false,
65 | bool *pbStopFlag = NULL);
66 |
67 | int static PoseOptimization(cMultiFrame* pFrame,
68 | double& inliers,
69 | const double& huberMultiplier = 2);
70 |
71 | bool static StructureOnly(cMultiKeyFrame* pKF,
72 | cMapPoint* &vpMP,
73 | vector >& obs,
74 | const double& reprErr);
75 |
76 | void static OptimizeEssentialGraph(cMap* pMap,
77 | cMultiKeyFrame* pLoopMKF, cMultiKeyFrame* pCurMKF,
78 | g2o::Sim3 &Scurw,
79 | const cLoopClosing::KeyFrameAndPose &NonCorrectedSim3,
80 | const cLoopClosing::KeyFrameAndPose &CorrectedSim3,
81 | const std::map > &LoopConnections);
82 |
83 | static int OptimizeSim3(cMultiKeyFrame* pKF1,
84 | cMultiKeyFrame* pKF2,
85 | std::vector &vpMatches1,
86 | g2o::Sim3 &g2oS12);
87 |
88 |
89 | static std::list MotionOnlyBA(cMultiKeyFrame* pKF,
90 | cMap* pMap);
91 |
92 | static int StructureOnlyBA(cMultiKeyFrame* pKF,
93 | cMap* pMap);
94 |
95 | static int AdjustMKF2Model(cMultiKeyFrame* pKF, cMap* pMap);
96 |
97 | static int AdjustFrame2Model(cMultiFrame* frame, cMap* pMap);
98 |
99 | static int CalibrateMKSonModel(cMultiKeyFrame* pKF, cMap* pMap);
100 |
101 | static double stdRecon;
102 | static double stdPose;
103 | static double stdSim;
104 | static double stdModel;
105 | };
106 |
107 | }
108 | #endif // OPTIMIZER_H
109 |
--------------------------------------------------------------------------------
/src/g2o_MultiCol_sim3_expmap.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of MultiCol-SLAM
3 | *
4 | * Copyright (C) 2015-2016 Steffen Urban
5 | * For more information see
6 | *
7 | * MultiCol-SLAM is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * MultiCol-SLAM is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with MultiCol-SLAM . If not, see .
19 | */
20 | #include "g2o_MultiCol_sim3_expmap.h"
21 |
22 | namespace MultiColSLAM
23 | {
24 |
25 | VertexSim3Expmap_Multi::VertexSim3Expmap_Multi(
26 | std::unordered_map& kp_to_cam1,
27 | std::unordered_map& kp_to_cam2)
28 | : g2o::BaseVertex<7, g2o::Sim3>(),
29 | keypoint_to_cam1(kp_to_cam1),
30 | keypoint_to_cam2(kp_to_cam2)
31 | {
32 | _marginalized = false;
33 | _fix_scale = false;
34 | }
35 |
36 | simpleVertexSim3Expmap::simpleVertexSim3Expmap() : BaseVertex<7, g2o::Sim3>()
37 | {
38 | _fix_scale = false;
39 | }
40 |
41 |
42 | edgeSim3::edgeSim3() :
43 | BaseBinaryEdge<7, g2o::Sim3, simpleVertexSim3Expmap, simpleVertexSim3Expmap>()
44 | {
45 | }
46 |
47 | bool simpleVertexSim3Expmap::read(std::istream& is)
48 | {
49 | g2o::Vector7d cam2world;
50 | //for (int i = 0; i<6; i++){
51 | // is >> cam2world[i];
52 | //}
53 | //is >> cam2world[6];
54 | //// if (! is) {
55 | //// // if the scale is not specified we set it to 1;
56 | //// std::cerr << "!s";
57 | //// cam2world[6]=0.;
58 | //// }
59 |
60 | //for (int i = 0; i<2; i++)
61 | //{
62 | // is >> _focal_length1[i];
63 | //}
64 | //for (int i = 0; i<2; i++)
65 | //{
66 | // is >> _principle_point1[i];
67 | //}
68 |
69 | setEstimate(g2o::Sim3(cam2world).inverse());
70 | return true;
71 | }
72 |
73 | bool simpleVertexSim3Expmap::write(std::ostream& os) const
74 | {
75 | g2o::Sim3 cam2world(estimate().inverse());
76 | g2o::Vector7d lv = cam2world.log();
77 | //for (int i = 0; i<7; i++){
78 | // os << lv[i] << " ";
79 | //}
80 | //for (int i = 0; i<2; i++)
81 | //{
82 | // os << _focal_length1[i] << " ";
83 | //}
84 | //for (int i = 0; i<2; i++)
85 | //{
86 | // os << _principle_point1[i] << " ";
87 | //}
88 | return os.good();
89 | }
90 |
91 |
92 | bool edgeSim3::read(std::istream& is)
93 | {
94 | g2o::Vector7d v7;
95 | //for (int i = 0; i<7; i++){
96 | // is >> v7[i];
97 | //}
98 |
99 | g2o::Sim3 cam2world(v7);
100 | setMeasurement(cam2world.inverse());
101 |
102 | //for (int i = 0; i<7; i++)
103 | // for (int j = i; j<7; j++)
104 | // {
105 | // is >> information()(i, j);
106 | // if (i != j)
107 | // information()(j, i) = information()(i, j);
108 | // }
109 | return true;
110 | }
111 |
112 | bool edgeSim3::write(std::ostream& os) const
113 | {
114 | g2o::Sim3 cam2world(measurement().inverse());
115 | g2o::Vector7d v7 = cam2world.log();
116 | //for (int i = 0; i<7; i++)
117 | //{
118 | // os << v7[i] << " ";
119 | //}
120 | //for (int i = 0; i<7; i++)
121 | // for (int j = i; j<7; j++){
122 | // os << " " << information()(i, j);
123 | // }
124 | return os.good();
125 | }
126 | }
--------------------------------------------------------------------------------
/include/cConverter.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of MultiCol-SLAM
3 | *
4 | * Copyright (C) 2015-2016 Steffen Urban
5 | * For more information see
6 | *
7 | * MultiCol-SLAM is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * MultiCol-SLAM is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with MultiCol-SLAM . If not, see .
19 | */
20 |
21 | /*
22 | * MultiCol-SLAM is based on ORB-SLAM2 which was also released under GPLv3
23 | * For more information see
24 | */
25 |
26 | #ifndef CONVERTER_H
27 | #define CONVERTER_H
28 |
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | namespace MultiColSLAM
37 | {
38 |
39 | class cConverter
40 | {
41 | public:
42 | static std::vector toDescriptorVector(const cv::Mat &Descriptors);
43 | static std::vector toDescriptorVector(const std::vector& Descriptors);
44 |
45 | static g2o::SE3Quat toSE3Quat(const cv::Matx44d& homCV);
46 |
47 | static cv::Matx44d toCvMat(const g2o::SE3Quat& SE3);
48 | static cv::Matx44d toCvMat(const g2o::Sim3& Sim3);
49 | static cv::Matx44d toCvMat(const Eigen::Matrix& m);
50 | static cv::Matx33d toCvMat(const Eigen::Matrix3d& m);
51 | static cv::Vec3d toCvVec3d(const Eigen::Matrix& m) {
52 | return cv::Vec3d(m(0), m(1), m(2)); }
53 | static cv::Matx44d toCvSE3(const Eigen::Matrix& R,
54 | const Eigen::Matrix& t);
55 | static cv::Matx ogv2ocv(const Eigen::Matrix& ogv_mat);
56 |
57 | // cv to eigen
58 | static Eigen::Matrix toVector3d(const cv::Vec4d& cvVector);
59 | static Eigen::Matrix toVector3d(const cv::Vec3d& cvVector);
60 | static Eigen::Matrix toVector2d(const cv::Vec2d& cvVector) {
61 | return Eigen::Matrix(cvVector(0), cvVector(1)); }
62 |
63 | static Eigen::Matrix toMatrix3d(const cv::Matx33d& cvMat3);
64 |
65 | static std::vector toQuaternion(const cv::Matx33d& M);
66 | // between mats and vecs
67 | static cv::Matx33d Hom2R(const cv::Matx44d& homCV) {
68 | return cv::Matx33d(homCV(0, 0), homCV(0, 1), homCV(0, 2),
69 | homCV(1, 0), homCV(1, 1), homCV(1, 2),
70 | homCV(2, 0), homCV(2, 1), homCV(2, 2)); }
71 |
72 | static cv::Vec3d Hom2T(const cv::Matx44d& homCV) {
73 | return cv::Vec3d(homCV(0, 3), homCV(1, 3), homCV(2, 3)); }
74 |
75 | static cv::Matx44d Rt2Hom(const cv::Matx33d& R, const cv::Vec3d& t){
76 | return cv::Matx44d(R(0, 0), R(0, 1), R(0, 2), t(0),
77 | R(1, 0), R(1, 1), R(1, 2), t(1),
78 | R(2, 0), R(2, 1), R(2, 2), t(2),
79 | 0.0, 0.0, 0.0, 1.0); }
80 |
81 | // between vecs
82 | static cv::Vec4d toVec4d(const cv::Vec3d& in) {
83 | return cv::Vec4d(in(0), in(1), in(2), 1.0); }
84 | static cv::Vec4d toVec4d(const Eigen::Matrix& in){
85 | return cv::Vec4d(in(0), in(1), in(2), 1.0); }
86 |
87 | // between matx and mat
88 | static cv::Mat toMat(const cv::Matx44d& matx44d);
89 |
90 | // hom
91 | static cv::Matx44d invMat(const cv::Matx44d& M);
92 |
93 | };
94 | }
95 | #endif // cCONVERTER_H
96 |
--------------------------------------------------------------------------------
/src/imuDriver.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | class imuDriver{
12 | public:
13 | ros::NodeHandle nh;
14 | ros::Subscriber sub;
15 | ros::Publisher pub;
16 |
17 | geometry_msgs::Vector3 gyro, acc, gyroInit;
18 | geometry_msgs::Quaternion quat;
19 | sensor_msgs::Imu msg;
20 | float roll, pitch, yaw, tSample;
21 |
22 | imuDriver(){
23 | sub = nh.subscribe("/ecoprt/imu",10,&imuDriver::getIMUData, this);
24 | pub = nh.advertise("/slam/imu", 10);
25 | gyroInit.x = 0;
26 | gyroInit.y = 0;
27 | gyroInit.z = 0;
28 | }
29 |
30 | void getIMUData(const custom_msgs::IMUInfoPtr& msg){
31 | gyro.x = msg->DataGyro[0];
32 | gyro.y = msg->DataGyro[1];
33 | gyro.z = msg->DataGyro[2];
34 |
35 | acc.x = msg->DataAcc[0];
36 | acc.y = msg->DataAcc[1];
37 | acc.z = msg->DataAcc[2];
38 |
39 | tSample = msg->IMUSampFreq;
40 | //std::cout << gyro << "\n" << acc << std::endl;
41 | }
42 |
43 | void getOrientation(){
44 | geometry_msgs::Vector3 unitAcc;
45 | // Unit vector for linear acceleration
46 | unitAcc.x = acc.x/sqrt(pow(acc.x,2) + pow(acc.y,2) + pow(acc.z,2));
47 | unitAcc.y = acc.y/sqrt(pow(acc.x,2) + pow(acc.y,2) + pow(acc.z,2));
48 | unitAcc.z = acc.z/sqrt(pow(acc.x,2) + pow(acc.y,2) + pow(acc.z,2));
49 |
50 | geometry_msgs::Vector3 angAcc;
51 | // Angular acceleration = derivative of angular velocity wrt time
52 | angAcc.x = (gyro.x - gyroInit.x)/tSample;
53 | angAcc.y = (gyro.y - gyroInit.y)/tSample;
54 | angAcc.z = (gyro.z - gyroInit.z)/tSample;
55 |
56 | roll = -atan2(-unitAcc.x,unitAcc.y);
57 | pitch = -atan2(unitAcc.z,sgn(unitAcc.y)*sqrt(pow(unitAcc.x,2)+pow(unitAcc.y,2)));
58 | yaw = angAcc.z*(gyroInit.z + gyro.z*tSample) + (1-angAcc.z)*atan2(acc.x,acc.y);
59 |
60 | gyroInit.x = gyro.x;
61 | gyroInit.y = gyro.y;
62 | gyroInit.z = gyro.z;
63 | //std::cout << "Roll " << roll*180/M_PI << "\n" << "Pitch " << pitch*180/M_PI << "\n" << "Yaw " << yaw*180/M_PI << std::endl;
64 |
65 | euler_to_quaternion(roll, pitch, yaw);
66 | }
67 |
68 | void euler_to_quaternion(float roll, float pitch, float yaw){
69 | float cy = cos(yaw*0.5);
70 | float sy = sin(yaw*0.5);
71 | float cp = cos(pitch*0.5);
72 | float sp = sin(pitch*0.5);
73 | float cr = cos(roll*0.5);
74 | float sr = sin(roll*0.5);
75 |
76 | quat.w = cy * cp * cr + sy * sp * sr;
77 | quat.x = cy * cp * sr - sy * sp * cr;
78 | quat.y = sy * cp * sr + cy * sp * cr;
79 | quat.z = sy * cp * cr - cy * sp * sr;
80 |
81 | publishImuData();
82 | }
83 |
84 | void publishImuData(){
85 | uint32_t seq_id = 0;
86 |
87 | if(seq_id == UINT32_MAX) seq_id = 0;
88 | // We set all zeros for covariance matrices since they're unknown
89 | msg.header.seq = seq_id;
90 | msg.header.stamp = ros::Time::now();
91 | msg.header.frame_id = "IMU";
92 |
93 | msg.orientation.x = quat.x;
94 | msg.orientation.y = quat.y;
95 | msg.orientation.z = quat.z;
96 | msg.orientation.w = quat.w;
97 | msg.orientation_covariance = {0,0,0,0,0,0,0,0,0};
98 |
99 | msg.angular_velocity.x = gyro.x;
100 | msg.angular_velocity.y = gyro.y;
101 | msg.angular_velocity.z = gyro.z;
102 | msg.angular_velocity_covariance = {0,0,0,0,0,0,0,0,0};
103 |
104 | msg.linear_acceleration.x = acc.x;
105 | msg.linear_acceleration.y = acc.x;
106 | msg.linear_acceleration.z = acc.x;
107 | msg.linear_acceleration_covariance = {0,0,0,0,0,0,0,0,0};
108 |
109 | pub.publish(msg);
110 | }
111 |
112 | int sgn(float v) {
113 | if (v < 0) return -1;
114 | if (v > 0) return 1;
115 | return 0;
116 | }
117 | };
118 |
119 | int main(int argc, char** argv){
120 | ros::init(argc, argv, "IMUDriver");
121 | ros::NodeHandle n;
122 |
123 | imuDriver *imu = new imuDriver;
124 | while(ros::ok()){
125 | imu->getOrientation();
126 | ros::spinOnce();
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/Examples/ROS/MultiCol-SLAM/src/ros_multi_backup.cc:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is the ROS implementation of MultiCol SLAM2
3 | */
4 |
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #include
18 |
19 | #include "../../../include/cSystem.h"
20 |
21 | #include "geometry_msgs/TransformStamped.h"
22 | #include "tf/transform_datatypes.h"
23 | #include
24 |
25 | using namespace std;
26 |
27 | class ImageGrabber
28 | {
29 | public:
30 | ImageGrabber(MultiColSLAM::cSystem* pSLAM):mpSLAM(pSLAM){}
31 |
32 | void GrabRGBD(const sensor_msgs::ImageConstPtr& msgRGB,const sensor_msgs::ImageConstPtr& msgD);
33 |
34 | MultiColSLAM::cSystem* mpSLAM;
35 | };
36 |
37 | int main(int argc, char **argv)
38 | {
39 | ros::init(argc, argv, "Multi");
40 | ros::start();
41 |
42 | if(argc != 4)
43 | {
44 | cerr << endl << "Usage: rosrun MultiCol Multi path_to_vocabulary path_to_settings path_to_calibration [1|0](save map?)" << endl;
45 | ros::shutdown();
46 | return 1;
47 | }
48 |
49 | // Create SLAM system. It initializes all system threads and gets ready to process frames.
50 | MultiColSLAM::cSystem SLAM(argv[1],argv[2],argv[3],true);
51 |
52 | ImageGrabber igb(&SLAM);
53 |
54 | ros::NodeHandle nh;
55 |
56 | message_filters::Subscriber rgb_sub(nh, "/camera/rgb/image_raw", 1);
57 | message_filters::Subscriber depth_sub(nh, "camera/depth_registered/image_raw", 1);
58 | typedef message_filters::sync_policies::ApproximateTime sync_pol;
59 | message_filters::Synchronizer sync(sync_pol(10), rgb_sub,depth_sub);
60 | sync.registerCallback(boost::bind(&ImageGrabber::GrabRGBD,&igb,_1,_2));
61 |
62 | ros::spin();
63 |
64 | // Stop all threads
65 | SLAM.Shutdown();
66 |
67 | // Save camera trajectory
68 | SLAM.SaveMKFTrajectoryLAFIDA("KeyFrameTrajectory.txt");
69 | //SLAM.SaveMap("map.bin");
70 |
71 | ros::shutdown();
72 |
73 | return 0;
74 | }
75 |
76 | void ImageGrabber::GrabRGBD(const sensor_msgs::ImageConstPtr& msgRGB,const sensor_msgs::ImageConstPtr& msgD)
77 | {
78 | // Copy the ros image message to cv::Mat.
79 | cv_bridge::CvImageConstPtr cv_ptrRGB;
80 | try
81 | {
82 | cv_ptrRGB = cv_bridge::toCvShare(msgRGB);
83 | }
84 | catch (cv_bridge::Exception& e)
85 | {
86 | ROS_ERROR("cv_bridge exception: %s", e.what());
87 | return;
88 | }
89 |
90 | cv_bridge::CvImageConstPtr cv_ptrD;
91 | try
92 | {
93 | cv_ptrD = cv_bridge::toCvShare(msgD);
94 | }
95 | catch (cv_bridge::Exception& e)
96 | {
97 | ROS_ERROR("cv_bridge exception: %s", e.what());
98 | return;
99 | }
100 |
101 | //mpSLAM->TrackRGBD(cv_ptrRGB->image,cv_ptrD->image,cv_ptrRGB->header.stamp.toSec());
102 | cv::Mat pose = mpSLAM->TrackRGBD(cv_ptrRGB->image,cv_ptrD->image,cv_ptrRGB->header.stamp.toSec());
103 |
104 | if (pose.empty())
105 | return;
106 |
107 | /* global left handed coordinate system */
108 | static cv::Mat pose_prev = cv::Mat::eye(4,4, CV_32F);
109 | static cv::Mat world_lh = cv::Mat::eye(4,4, CV_32F);
110 | // matrix to flip signs of sinus in rotation matrix, not sure why we need to do that
111 | static const cv::Mat flipSign = (cv::Mat_(4,4) << 1,-1,-1, 1,
112 | -1, 1,-1, 1,
113 | -1,-1, 1, 1,
114 | 1, 1, 1, 1);
115 |
116 | //prev_pose * T = pose
117 | cv::Mat translation = (pose * pose_prev.inv()).mul(flipSign);
118 | world_lh = world_lh * translation;
119 | pose_prev = pose.clone();
120 |
121 | tf::Matrix3x3 tf3d;
122 | tf3d.setValue(pose.at(0,0), pose.at(0,1), pose.at(0,2),
123 | pose.at(1,0), pose.at(1,1), pose.at(1,2),
124 | pose.at(2,0), pose.at(2,1), pose.at(2,2));
125 |
126 | tf::Vector3 cameraTranslation_rh( world_lh.at(0,3),world_lh.at(1,3), - world_lh.at(2,3) );
127 |
128 | //rotate 270deg about x and 270deg about x to get ENU: x forward, y left, z up
129 | const tf::Matrix3x3 rotation270degXZ( 0, 1, 0,
130 | 0, 0, 1,
131 | 1, 0, 0);
132 |
133 | static tf::TransformBroadcaster br;
134 |
135 | tf::Matrix3x3 globalRotation_rh = tf3d;
136 | tf::Vector3 globalTranslation_rh = cameraTranslation_rh * rotation270degXZ;
137 |
138 | tf::Quaternion tfqt;
139 | globalRotation_rh.getRotation(tfqt);
140 |
141 | double aux = tfqt[0];
142 | tfqt[0]=-tfqt[2];
143 | tfqt[2]=tfqt[1];
144 | tfqt[1]=aux;
145 |
146 | tf::Transform transform;
147 | transform.setOrigin(globalTranslation_rh);
148 | transform.setRotation(tfqt);
149 |
150 | br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "world", "camera_pose"));
151 | }
152 |
--------------------------------------------------------------------------------
/Examples/ROS/MultiCol-SLAM/src/ros_multi.cc:
--------------------------------------------------------------------------------
1 | // The original version was released under the following license
2 | /**
3 | * Copyright (C) 2014-2016 Raúl Mur-Artal (University of Zaragoza)
4 | * For more information see
5 | *
6 | * ORB-SLAM2 is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * ORB-SLAM2 is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with ORB-SLAM2. If not, see .
18 | */
19 |
20 | // All modifications are released under the following license
21 | /**
22 | * This file is part of MultiCol-SLAM
23 | *
24 | * Copyright (C) 2015-2016 Steffen Urban
25 | * For more information see
26 | *
27 | * MultiCol-SLAM is free software: you can redistribute it and/or modify
28 | * it under the terms of the GNU General Public License as published by
29 | * the Free Software Foundation, either version 3 of the License, or
30 | * (at your option) any later version.
31 | *
32 | * MultiCol-SLAM is distributed in the hope that it will be useful,
33 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
34 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 | * GNU General Public License for more details.
36 | *
37 | * You should have received a copy of the GNU General Public License
38 | * along with MultiCol-SLAM . If not, see .
39 | */
40 |
41 | #include
42 | #include
43 | #include
44 | #include
45 | #include
46 |
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 |
54 | #include "cTracking.h"
55 | #include "cConverter.h"
56 | #include "cam_model_omni.h"
57 | #include "cSystem.h"
58 | #include "camNodelet.h"
59 |
60 | using namespace cv;
61 | using namespace std;
62 |
63 | camSubs::camSubs():it(nh){
64 | sub = it.subscribe("/camera/image/webcam", 1, &camSubs::imageCbWeb, this);
65 | sub1 = it.subscribe("/camera/image/usb1", 1, &camSubs::imageCbUsb1, this);
66 | sub2 = it.subscribe("/camera/image/usb2", 1, &camSubs::imageCbUsb2, this);
67 | ROS_INFO("Subscriber setup!!");
68 | }
69 |
70 | void camSubs::imageCbWeb(const sensor_msgs::ImageConstPtr& msg){
71 | try{
72 | header1 = msg->header;
73 | cv_bridge::CvImagePtr img = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
74 | frame1 = img->image;
75 | }
76 | catch(cv_bridge::Exception& e){
77 | ROS_ERROR("Couldn't get image due to %s",e.what());
78 | }
79 | }
80 |
81 | void camSubs::imageCbUsb1(const sensor_msgs::ImageConstPtr& msg){
82 | try{
83 | header2 = msg->header;
84 | cv_bridge::CvImagePtr img = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
85 | frame2 = img->image;
86 | }
87 | catch(cv_bridge::Exception& e){
88 | ROS_ERROR("Couldn't get image due to %s",e.what());
89 | }
90 | }
91 |
92 | void camSubs::imageCbUsb2(const sensor_msgs::ImageConstPtr& msg){
93 | try{
94 | header3 = msg->header;
95 | cv_bridge::CvImagePtr img = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
96 | frame3 = img->image;
97 | }
98 | catch(cv_bridge::Exception& e){
99 | ROS_ERROR("Couldn't get image due to %s",e.what());
100 | }
101 | }
102 |
103 | int main(int argc, char **argv){
104 | ros::init(argc, argv, "slam");
105 | ros::NodeHandle nh;
106 | image_transport::ImageTransport it(nh);
107 |
108 | const string path2voc = "/home/varunharis/MultiCol-SLAM/Examples/small_orb_omni_voc_9_6.yml";
109 | const string path2settings = "/home/varunharis/MultiCol-SLAM/Examples/Lafida/Slam_Settings_indoor1.yaml";
110 | const string path2calibrations = "/home/varunharis/MultiCol-SLAM/Examples/Lafida";
111 |
112 | camSubs *cam = new camSubs;
113 |
114 | cout << endl << "MultiCol-SLAM Copyright (C) 2016 Steffen Urban" << endl << endl;
115 |
116 | cv::FileStorage frameSettings(path2settings, cv::FileStorage::READ);
117 |
118 | cv::Mat frame1, frame2, frame3;
119 | std::vector images(3);
120 | MultiColSLAM::cSystem MultiSLAM(path2voc, path2settings, path2calibrations, true);
121 |
122 | // Main loop
123 | while(ros::ok()){
124 | ros::spinOnce();
125 | try{
126 | frame1 = cam->frame1;
127 | frame2 = cam->frame2;
128 | frame3 = cam->frame3;
129 |
130 | cvtColor(frame1, frame1, CV_BGR2GRAY);
131 | cvtColor(frame2, frame2, CV_BGR2GRAY);
132 | cvtColor(frame3, frame3, CV_BGR2GRAY);
133 |
134 | images = {frame1, frame2, frame3};
135 | // Pass through the MultiCol-SLAM system
136 | MultiSLAM.TrackMultiColSLAM(images, double(cam->header1.stamp.sec));
137 | }
138 | catch(cv::Exception& e){
139 | cout << "hold on" << endl;
140 | }
141 | }
142 |
143 | // Stop all threads
144 | MultiSLAM.Shutdown();
145 | ros::shutdown();
146 |
147 | // Save camera trajectory
148 | MultiSLAM.SaveMKFTrajectoryLAFIDA("MKFTrajectory.txt");
149 | cv::destroyAllWindows();
150 | return 0;
151 | }
152 |
--------------------------------------------------------------------------------
/include/cMultiFrame.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of MultiCol-SLAM
3 | *
4 | * Copyright (C) 2015-2016 Steffen Urban
5 | * For more information see
6 | *
7 | * MultiCol-SLAM is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * MultiCol-SLAM is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with MultiCol-SLAM . If not, see .
19 | */
20 |
21 | /*
22 | * MultiCol-SLAM is based on ORB-SLAM2 which was also released under GPLv3
23 | * For more information see
24 | * Raúl Mur-Artal (University of Zaragoza)
25 | */
26 |
27 | #ifndef MULTIFRAME_H
28 | #define MULTIFRAME_H
29 |
30 | #include "cMapPoint.h"
31 | #include "DBoW2/DBoW2/BowVector.h"
32 | #include "DBoW2/DBoW2/FeatureVector.h"
33 | #include "cORBVocabulary.h"
34 | #include "cMultiKeyFrame.h"
35 | #include "cORBextractor.h"
36 | #include "mdBRIEFextractorOct.h"
37 | #include "cam_system_omni.h"
38 |
39 | // external
40 | #include
41 | #include
42 | #include
43 |
44 |
45 | namespace MultiColSLAM
46 | {
47 | #define FRAME_GRID_ROWS 48
48 | #define FRAME_GRID_COLS 64
49 |
50 | class cTracking;
51 | class cMapPoint;
52 | class cMultiKeyFrame;
53 | class cMultiKeyFrameDatabase;
54 | class cCamModelGeneral_;
55 |
56 | class cMultiFrame
57 | {
58 | public:
59 | cMultiFrame();
60 | cMultiFrame(const cMultiFrame &frame); // copy constructor
61 |
62 | cMultiFrame(const std::vector& images_,
63 | const double &timeStamp,
64 | std::vector extractor,
65 | ORBVocabulary* voc,
66 | cMultiCamSys_& camSystem_,
67 | int imgCnt);
68 |
69 | ORBVocabulary* mpORBvocabulary;
70 |
71 | std::vector mp_mdBRIEF_extractorOct;
72 |
73 | // images
74 | std::vector images;
75 |
76 | // Frame timestamp
77 | double mTimeStamp;
78 |
79 | // contains all cameras
80 | cMultiCamSys_ camSystem;
81 |
82 | // Number of KeyPoints
83 | std::vector N;
84 | // total number of Keypoints
85 | size_t totalN;
86 |
87 | // Vector of keypoints 2d
88 | // and corresponding bearing vectors 3d
89 | // for each camera
90 | std::vector mvKeys;
91 | std::vector mvKeysRays; // 3D observation rays
92 |
93 | // Bag of Words Vector structures
94 | DBoW2::BowVector mBowVec;
95 | std::vector mBowVecs;
96 | DBoW2::FeatureVector mFeatVec;
97 | std::vector mFeatVecs;
98 | // ORB descriptor, each row associated to a keypoint
99 | // descriptors for each camera
100 | std::vector mDescriptors;
101 | // learned descriptor masks
102 | std::vector mDescriptorMasks;
103 |
104 | // MapPoints associated to keypoints, NULL pointer if not association
105 | std::vector mvpMapPoints;
106 |
107 | // Flag to identify outlier associations
108 | std::vector mvbOutlier;
109 |
110 | // Keypoints are assigned to cells in a grid
111 | // to reduce matching complexity when projecting MapPoints
112 | std::vector mfGridElementWidthInv;
113 | std::vector mfGridElementHeightInv;
114 | // a grid for each camera, thus 3 vectors
115 | std::vector > > > mGrids;
116 |
117 | // Current and Next multi frame id
118 | static long unsigned int nNextId;
119 | long unsigned int mnId;
120 |
121 | cMultiKeyFrame* mpReferenceKF;
122 |
123 | void ComputeBoW();
124 |
125 | void UpdatePoseMatrices();
126 |
127 | // Check if a MapPoint is in the frustum of the camera
128 | // and also fills variables of the MapPoint to be used by the tracking
129 | bool isInFrustum(int cam, cMapPoint* pMP, double viewingCosLimit);
130 |
131 | // Compute the cell of a keypoint (return false if outside the grid)
132 | bool PosInGrid(const int& cam, cv::KeyPoint &kp, int &posX, int &posY);
133 |
134 | std::vector GetFeaturesInArea(const int& cam,
135 | const double &x, const double &y,
136 | const double &r,
137 | const int minLevel = -1, const int maxLevel = -1) const;
138 |
139 | // Scale Pyramid Info
140 | int mnScaleLevels;
141 | double mfScaleFactor;
142 | std::vector mvScaleFactors;
143 | std::vector mvLevelSigma2;
144 | std::vector mvInvLevelSigma2;
145 |
146 | // Undistorted Image Bounds (computed once)
147 | static std::vector mnMinX;
148 | static std::vector mnMaxX;
149 | static std::vector mnMinY;
150 | static std::vector mnMaxY;
151 |
152 | static bool mbInitialComputations;
153 |
154 | // this variable holds the mapping between keypoint ID and camera
155 | // it was observed in
156 | // [key_id : cam_id]
157 | std::unordered_map keypoint_to_cam;
158 | // this variable holds the mapping between the continous indexing of all
159 | // descriptors and keypoints and the image wise indexes
160 | // it was observed in
161 | // [cont_id : local_image_id]
162 | std::unordered_map cont_idx_to_local_cam_idx;
163 |
164 | cv::Matx GetPose() { return camSystem.Get_M_t(); }
165 | cv::Matx GetPoseMin() { return camSystem.Get_M_t_min(); }
166 |
167 | void SetPose(cv::Matx44d& T) { camSystem.Set_M_t(T); }
168 | void SetPoseMin(cv::Matx61d& Tmin) { camSystem.Set_M_t_from_min(Tmin); }
169 |
170 | bool HavingMasks() { return masksLearned; }
171 | int DescDims() { return descDimension; }
172 | int Doing_mdBRIEF() { return mdBRIEF; }
173 | int GetImgCnt() { return imgCnt; }
174 |
175 | private:
176 | bool mdBRIEF;
177 | bool masksLearned;
178 | int descDimension;
179 | int imgCnt;
180 | };
181 | }
182 | #endif // MULTIFRAME_H
183 |
--------------------------------------------------------------------------------
/include/g2o_MultiCol_vertices_edges.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of MultiCol-SLAM
3 | *
4 | * Copyright (C) 2015-2016 Steffen Urban
5 | * For more information see
6 | *
7 | * MultiCol-SLAM is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * MultiCol-SLAM is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with MultiCol-SLAM . If not, see .
19 | */
20 | #ifndef G2O_MULTICOL_VERTICES_EDGES_H
21 | #define G2O_MULTICOL_VERTICES_EDGES_H
22 |
23 | #include
24 | #include
25 |
26 | #include "g2o/types/types_seven_dof_expmap.h"
27 | #include "g2o/core/base_multi_edge.h"
28 | #include
29 |
30 | #include "misc.h"
31 | #include "cam_model_omni.h"
32 |
33 | namespace MultiColSLAM
34 | {
35 | void mcsJacs1(const cv::Vec3d& pt3,
36 | const cv::Matx61d& M_t,
37 | const cv::Matx61d& M_c,
38 | const Eigen::Matrix& camModelData,
39 | cv::Matx& jacs);
40 |
41 | class VertexOmniCameraParameters : public g2o::BaseVertex<5 + 12, Eigen::Matrix>
42 | {
43 | public:
44 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
45 | VertexOmniCameraParameters() {}
46 |
47 | VertexOmniCameraParameters(cCamModelGeneral_ camModel_)
48 | : camModel(camModel_)
49 | {
50 |
51 | }
52 |
53 | virtual void setToOriginImpl()
54 | {
55 | Eigen::Matrix tmpEstimate = camModel.toVector();
56 | _estimate = tmpEstimate;
57 | }
58 | virtual void oplusImpl(const double* update_)
59 | {
60 | Eigen::Map> update(update_);
61 | // update function x + dx, it is overloaded to update the camera parameters
62 | // see cam_model_omni.h
63 | setEstimate(estimate() + update);
64 | camModel.fromVector(_estimate);
65 | }
66 |
67 | bool read(std::istream& is)
68 | {
69 | std::cerr << __PRETTY_FUNCTION__ << " not implemented yet" << std::endl;
70 | return false;
71 | }
72 |
73 | bool write(std::ostream& os) const
74 | {
75 | std::cerr << __PRETTY_FUNCTION__ << " not implemented yet" << std::endl;
76 | return false;
77 | }
78 | cCamModelGeneral_ camModel;
79 | };
80 | /**
81 | * \brief
82 | */
83 | class VertexMt_cayley : public g2o::BaseVertex<6, cv::Matx61d>{
84 | public:
85 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW
86 |
87 | VertexMt_cayley() {}
88 |
89 | virtual void setToOriginImpl()
90 | {
91 | _estimate = cv::Matx61d(0, 0, 0, 0, 0, 0);
92 | }
93 | virtual void oplusImpl(const double* update_)
94 | {
95 | //Eigen::Map update(update_);
96 | cv::Matx61d update(update_);
97 | setEstimate(update + estimate()); // update function x + dx
98 | }
99 |
100 | bool read(std::istream& is)
101 | {
102 | std::cerr << __PRETTY_FUNCTION__ << " not implemented yet" << std::endl;
103 | return false;
104 | }
105 |
106 | bool write(std::ostream& os) const
107 | {
108 | std::cerr << __PRETTY_FUNCTION__ << " not implemented yet" << std::endl;
109 | return false;
110 | }
111 |
112 | };
113 |
114 | /**
115 | * \brief
116 | */
117 | class VertexMc_cayley : public g2o::BaseVertex<6, cv::Matx61d>{
118 | public:
119 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW
120 |
121 | VertexMc_cayley() {}
122 |
123 | virtual void setToOriginImpl()
124 | {
125 | _estimate = cv::Matx61d(0, 0, 0, 0, 0, 0);
126 | }
127 | virtual void oplusImpl(const double* update_)
128 | {
129 | cv::Matx61d update(update_);
130 | setEstimate(update + estimate()); // update function x + dx
131 | }
132 |
133 | bool read(std::istream& is)
134 | {
135 | std::cerr << __PRETTY_FUNCTION__ << " not implemented yet" << std::endl;
136 | return false;
137 | }
138 |
139 | bool write(std::ostream& os) const
140 | {
141 | std::cerr << __PRETTY_FUNCTION__ << " not implemented yet" << std::endl;
142 | return false;
143 | }
144 |
145 | };
146 |
147 | /**
148 | * \brief Point vertex, XYZ
149 | */
150 | class VertexPointXYZ : public g2o::BaseVertex<3, cv::Vec3d>
151 | {
152 | public:
153 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW
154 | VertexPointXYZ() {}
155 |
156 | virtual void setToOriginImpl()
157 | {
158 | _estimate = cv::Vec3d(0, 0, 0);
159 | }
160 |
161 | virtual void oplusImpl(const double* update)
162 | {
163 | cv::Vec3d v(update);
164 | _estimate += v;
165 | }
166 |
167 | virtual bool read(std::istream& /*is*/)
168 | {
169 | std::cerr << __PRETTY_FUNCTION__ << " not implemented yet" << std::endl;
170 | return false;
171 | }
172 |
173 | virtual bool write(std::ostream& /*os*/) const
174 | {
175 | std::cerr << __PRETTY_FUNCTION__ << " not implemented yet" << std::endl;
176 | return false;
177 | }
178 | void SetID(int id) { ptID = id; }
179 | int GetID() { return ptID; }
180 | int ptID; // need this id for the Sim3 optimization
181 | };
182 |
183 |
184 | // edge, that projects a point to a multi camera system
185 | // vertex 0 : t -> Mt, which is the MCS pose
186 | // vertex 1 : i -> 3D point
187 | // vertex 2 : c -> Mc, transformation from MCS to camera
188 | // vertex 3 : c -> interior orientation
189 | class EdgeProjectXYZ2MCS : public g2o::BaseMultiEdge<2, g2o::Vector2D>
190 | {
191 | public:
192 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW
193 |
194 | EdgeProjectXYZ2MCS()
195 | {
196 | information().setIdentity();
197 | resize(4);
198 | }
199 |
200 | virtual bool read(std::istream& /*is*/)
201 | {
202 | std::cerr << __PRETTY_FUNCTION__ << " not implemented yet" << std::endl;
203 | return false;
204 | }
205 |
206 | virtual bool write(std::ostream& /*os*/) const
207 | {
208 | std::cerr << __PRETTY_FUNCTION__ << " not implemented yet" << std::endl;
209 | return false;
210 | }
211 |
212 | void computeError();
213 |
214 | void linearizeOplus();
215 | };
216 |
217 |
218 |
219 | }
220 | #endif
--------------------------------------------------------------------------------
/include/misc.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of MultiCol-SLAM
3 | *
4 | * Copyright (C) 2015-2016 Steffen Urban
5 | * For more information see
6 | *
7 | * MultiCol-SLAM is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * MultiCol-SLAM is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with MultiCol-SLAM . If not, see .
19 | */
20 | #ifndef MISC_H
21 | #define MISC_H
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | namespace MultiColSLAM
30 | {
31 | // some misc defines
32 | #ifndef M_PID
33 | #define M_PID 3.1415926535897932384626433832795028841971693993
34 | #endif
35 |
36 | #ifndef M_PIf
37 | #define M_PIf 3.1415926535897932384626f
38 | #endif
39 |
40 | const double RHOd = 180.0 / M_PID;
41 | const float RHOf = 180.0f / M_PIf;
42 |
43 | typedef std::chrono::high_resolution_clock HResClk;
44 |
45 | const float pi2 = M_PIf;
46 | const float pi32 = 2.0 * M_PIf;
47 | const float deg2radf = M_PIf / 180.0f;
48 | const float rad2degf = 180.0f / M_PIf;
49 | const float pihalf = M_PIf / 2.0f;
50 |
51 | cv::Vec3d triangulate_point(
52 | const cv::Matx31d& relOri_t12,
53 | const cv::Matx33d& relOri_R12,
54 | const cv::Vec3d& v1,
55 | const cv::Vec3d& v2);
56 |
57 |
58 | inline cv::Matx33d Skew(const cv::Vec3d& v)
59 | {
60 | return cv::Matx33d(
61 | 0.0, -v(2), v(1),
62 | v(2), 0.0, -v(0),
63 | -v(1), v(0), 0.0);
64 | }
65 |
66 | /**
67 | * Returns time in milliseconds in double
68 | *
69 | * @param start start time
70 | * @param end end time
71 | *
72 | * @return time in milliseconds
73 | */
74 | double T_in_ms(HResClk::time_point start,
75 | HResClk::time_point end);
76 | /**
77 | * Returns time in nanoseconds in double
78 | *
79 | * @param start start time
80 | * @param end end time
81 | *
82 | * @return time in nanoseconds
83 | */
84 | double T_in_ns(HResClk::time_point start,
85 | HResClk::time_point end);
86 |
87 |
88 | /**
89 | * median
90 | *
91 | * @param data vector of elements
92 | *
93 | * @return median value
94 | */
95 | template
96 | T median(std::vector &v)
97 | {
98 | if (v.size() > 0)
99 | {
100 | std::nth_element(v.begin(), v.begin() + v.size() / 2, v.end());
101 | return v[v.size() / 2];
102 | }
103 | else return T(0);
104 | }
105 |
106 | /**
107 | * evaluate a polynom using Horner
108 | *
109 | * @param coeffs T* of coefficients
110 | * @param s number of polynomial coefficients
111 | * @param x x value to evaluate
112 | *
113 | * @return function value
114 | */
115 | inline double horner(
116 | const double* coeffs, const int& s, const double& x)
117 | {
118 | double res = 0.0;
119 | for (int i = s - 1; i >= 0; i--)
120 | res = res * x + coeffs[i];
121 | return res;
122 | }
123 |
124 |
125 | /**
126 | * Cayley representation to 3x3 rotation matrix
127 | *
128 | * @param cayParamIn Cayley parameter
129 | *
130 | * @return rotation matrix
131 | */
132 | template
133 | cv::Matx cayley2rot(const cv::Matx& cayParamIn)
134 | {
135 | cv::Matx R = cv::Matx::eye();
136 |
137 | T c1 = cayParamIn(0, 0);
138 | T c2 = cayParamIn(1, 0);
139 | T c3 = cayParamIn(2, 0);
140 |
141 | T c1sqr = c1*c1;
142 | T c2sqr = c2*c2;
143 | T c3sqr = c3*c3;
144 |
145 | T scale = T(1) + c1sqr + c2sqr + c3sqr;
146 |
147 | R(0, 0) = 1 + c1sqr - c2sqr - c3sqr;
148 | R(0, 1) = 2 * (c1*c2 - c3);
149 | R(0, 2) = 2 * (c1*c3 + c2);
150 | R(1, 0) = 2 * (c1*c2 + c3);
151 | R(1, 1) = 1 - c1sqr + c2sqr - c3sqr;
152 | R(1, 2) = 2 * (c2*c3 - c1);
153 | R(2, 0) = 2 * (c1*c3 - c2);
154 | R(2, 1) = 2 * (c2*c3 + c1);
155 | R(2, 2) = 1 - c1sqr - c2sqr + c3sqr;
156 |
157 | R = (1 / scale) * R;
158 |
159 | return R;
160 | }
161 |
162 |
163 | /**
164 | * 3x3 rotation matrix to Cayley representation
165 | *
166 | * @param R rotation matrix
167 | *
168 | * @return Cayley parameters
169 | */
170 |
171 | template
172 | cv::Matx rot2cayley(const cv::Matx& R)
173 | {
174 | cv::Matx eyeM = cv::Matx::eye();
175 |
176 | cv::Matx C1 = R - eyeM;
177 | cv::Matx C2 = R + eyeM;
178 | cv::Matx C = C1 * C2.inv();
179 |
180 | cv::Matx cayley(-C(1, 2), C(0, 2), -C(0, 1));
181 |
182 | return cayley;
183 | }
184 |
185 | /**
186 | * 4x4 homogeneous transformation matrix to Cayley + translation representation
187 | *
188 | * @param T 4x4 homogeneous transformation matrix
189 | *
190 | * @return c 6x1 Cayley parameters and translation
191 | */
192 | template
193 | cv::Matx hom2cayley(const cv::Matx& M)
194 | {
195 | cv::Matx R(M(0, 0), M(0, 1), M(0, 2),
196 | M(1, 0), M(1, 1), M(1, 2),
197 | M(2, 0), M(2, 1), M(2, 2));
198 | cv::Matx C = rot2cayley(R);
199 |
200 | return cv::Matx(C(0, 0), C(1, 0), C(2, 0),
201 | M(0, 3), M(1, 3), M(2, 3));
202 | }
203 |
204 | /**
205 | * 6x1 minimal homogeneous transformation vector to homogeneous 4x4 transformation matrix
206 | *
207 | * @param c 6x1 Cayley parameters and translation
208 | *
209 | * @return T 4x4 homogeneous transformation matrix
210 | */
211 | template
212 | cv::Matx cayley2hom(const cv::Matx& cayleyRep)
213 | {
214 | cv::Matx cayleyR(cayleyRep(0, 0), cayleyRep(1, 0), cayleyRep(2, 0));
215 | cv::Matx R = cayley2rot(cayleyR);
216 |
217 | cv::Matx homM(
218 | R(0, 0), R(0, 1), R(0, 2), cayleyRep(3, 0),
219 | R(1, 0), R(1, 1), R(1, 2), cayleyRep(4, 0),
220 | R(2, 0), R(2, 1), R(2, 2), cayleyRep(5, 0),
221 | T(0), T(0), T(0), T(1));
222 |
223 | return homM;
224 | }
225 |
226 | bool CheckDistEpipolarLine(const cv::Vec3d &ray1,
227 | const cv::Vec3d &ray2,
228 | const cv::Matx33d &E12,
229 | const double& thresh);
230 |
231 | cv::Matx33d ComputeE(const cv::Matx44d& T1, const cv::Matx44d& T2);
232 |
233 | inline cv::Matx33d ComputeE(const cv::Matx44d& Trel)
234 | {
235 | cv::Matx33d R = Trel.get_minor<3, 3>(0, 0);
236 | cv::Vec3d t = cv::Vec3d(Trel(0, 3), Trel(1, 3), Trel(2, 3));
237 | t /= cv::norm(t);
238 | cv::Matx33d t12x = Skew(t);
239 |
240 | return t12x*R;
241 | }
242 | }
243 | #endif
--------------------------------------------------------------------------------
/include/cam_system_omni.h:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is part of MultiCol-SLAM
3 | *
4 | * Copyright (C) 2015-2016 Steffen Urban
5 | * For more information see
6 | *
7 | * MultiCol-SLAM is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * MultiCol-SLAM is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with MultiCol-SLAM . If not, see .
19 | */
20 |
21 | /*
22 | multi_cam_system_omni.h
23 |
24 | @brief:
25 | This class represents arbitrary, rigidly coupled multi-(fisheye) camera systems
26 | It holds the calibration matrices M_c and N attached cameras
27 |
28 | See also:
29 | MultiCol Bundle Adjustment:
30 | A Generic Method for Pose Estimation, Simultaneous Self-Calibration
31 | and Reconstruction for Arbitrary Multi-Camera Systems
32 | http://link.springer.com/article/10.1007/s11263-016-0935-0
33 |
34 | ToDo:
35 | Author: Steffen Urban
36 | Date: 23.08.2016
37 | */
38 |
39 | #ifndef MULTI_CAMERA_SYSTEM_H
40 | #define MULTI_CAMERA_SYSTEM_H
41 |
42 | // external includes
43 | #include
44 | #include
45 | #include
46 | #include
47 |
48 | // own includes
49 | #include "misc.h"
50 | #include "cam_model_omni.h"
51 | #include "cConverter.h"
52 | namespace MultiColSLAM
53 | {
54 | class cMultiCamSys_
55 | {
56 | public:
57 | cMultiCamSys_() : nrCams(0), flagMcMt(false),
58 | M_t(cv::Matx44d::eye()), M_t_min(cv::Matx61d::zeros()){}
59 |
60 | // constructor initalizes MCS pose and MCS calibration
61 | cMultiCamSys_(cv::Matx M_t_,
62 | std::vector> M_c_,
63 | std::vector camModels_) :
64 | M_t(M_t_), M_c(M_c_), camModels(camModels_), flagMcMt(true)
65 | {
66 | nrCams = (int)M_c_.size();
67 | M_t_min = hom2cayley(M_t);
68 | //M_t_min = hom2rodrigues(M_t);
69 | M_t_inv = cConverter::invMat(M_t);
70 |
71 | MtMc = std::vector>(nrCams);
72 | MtMc_inv = std::vector>(nrCams);
73 | for (int c = 0; c < nrCams; ++c)
74 | {
75 | MtMc[c] = M_t_ * M_c_[c];
76 | MtMc_inv[c] = cConverter::invMat(MtMc[c]);
77 | M_c_min.push_back(hom2cayley(M_c[c]));
78 | //M_c_min.push_back(hom2rodrigues