├── README.md ├── vi_sensor_interface ├── CMakeLists.txt ├── README.md ├── cmake │ ├── FindEigen3.cmake │ └── FindVISensor.cmake ├── include │ ├── ConcurrentQueue.hpp │ └── vi_sensor_interface.hpp └── src │ ├── main.cpp │ └── vi_sensor_interface.cpp └── vi_sensor_stereo_block_matcher ├── CMakeLists.txt ├── README.md ├── cmake ├── FindEigen3.cmake └── FindVISensor.cmake ├── include └── vi_sensor_interface.hpp └── src ├── main.cpp └── vi_sensor_interface.cpp /README.md: -------------------------------------------------------------------------------- 1 | visensor_sample_applications 2 | =================== 3 | 4 | This repo contains a few sample standalone applications for the VI-Sensor 5 | 6 | * **vi_sensor_interface**: A very basic interface to the VI-Sensor. Receives images and IMU messages and displays it using openCV. 7 | * **vi_sensor_stereo_block_matcher**: Applies rectification to Vi-Sensor images and subsequently computes the disparity image using standard openCV block matcher. Intrinsic & extrinsic calibration parameters for rectification are downloaded from VI-Sensor. 8 | -------------------------------------------------------------------------------- /vi_sensor_interface/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #Sammy Omari, Skybotix AG, 28/3/2014 2 | cmake_minimum_required(VERSION 2.8.0) 3 | 4 | ############ 5 | # SETTINGS 6 | ############ 7 | set(PKGNAME vi_sensor_interface) 8 | 9 | set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) 10 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin) 11 | set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib) 12 | set(Boost_USE_MULTITHREADED ON) 13 | 14 | find_package(Boost COMPONENTS system filesystem thread REQUIRED) 15 | find_package(Threads REQUIRED) 16 | find_package(Eigen3 REQUIRED) 17 | find_package(OpenCV REQUIRED ) 18 | find_package(VISensor REQUIRED ) 19 | 20 | set(CMAKE_BUILD_TYPE Release) 21 | ADD_DEFINITIONS (-march=native -O2 -fmessage-length=0 -MMD -MP -Wall -pedantic -std=c++0x ) #Release 22 | #ADD_DEFINITIONS (-march=native -O0 -g3 -fmessage-length=0 -MMD -MP -Wall -pedantic -std=c++0x ) #Debug 23 | 24 | FILE( 25 | GLOB SRCS 26 | src/*.cpp 27 | ) 28 | 29 | include_directories( ${EIGEN3_INCLUDE_DIR} ) 30 | include_directories( ${Boost_INCLUDE_DIRS} ) 31 | include_directories( ${VISensorDriver_INCLUDE_DIR} ) 32 | include_directories(include) 33 | 34 | add_executable(${PKGNAME} ${SRCS}) 35 | target_link_libraries(${PKGNAME} ${OpenCV_LIBS} ${VISensorDriver_LIBRARY} visensor ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) 36 | -------------------------------------------------------------------------------- /vi_sensor_interface/README.md: -------------------------------------------------------------------------------- 1 | vi_sensor_interface 2 | =================== 3 | 4 | Simple example on how to interface the VI-Sensor and display the images using openCV 5 | 6 | Build instructions 7 | ================== 8 | Download libvisensor and install it if you have not done that before 9 | 10 |

11 | git clone https://github.com/ethz-asl/libvisensor.git
12 | cd libvisensor
13 | ./install_libvisensor.sh
14 | 
15 | 16 | Now, were building the interface 17 | 18 |

19 | cd vi_sensor_interface
20 | mkdir build
21 | cd build
22 | cmake ..
23 | make
24 | cd ../bin
25 | ./vi_sensor_interface
26 | 
27 | 28 | -------------------------------------------------------------------------------- /vi_sensor_interface/cmake/FindEigen3.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find Eigen3 lib 2 | # Once done this will define 3 | # 4 | # EIGEN3_FOUND - system has eigen lib 5 | # EIGEN3_INCLUDE_DIR - the eigen include directory 6 | 7 | # Copyright (c) 2006, 2007 Montel Laurent, 8 | # Redistribution and use is allowed according to the terms of the BSD license. 9 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 10 | 11 | if( EIGEN3_INCLUDE_DIR ) 12 | # in cache already 13 | set( EIGEN3_FOUND TRUE ) 14 | else (EIGEN3_INCLUDE_DIR) 15 | find_path( EIGEN3_INCLUDE_DIR NAMES Eigen/Core 16 | PATH_SUFFIXES eigen3/ 17 | HINTS 18 | ${INCLUDE_INSTALL_DIR} 19 | /usr/local/include 20 | ${KDE4_INCLUDE_DIR} 21 | ) 22 | include( FindPackageHandleStandardArgs ) 23 | find_package_handle_standard_args( Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR ) 24 | mark_as_advanced( EIGEN3_INCLUDE_DIR ) 25 | endif(EIGEN3_INCLUDE_DIR) 26 | 27 | -------------------------------------------------------------------------------- /vi_sensor_interface/cmake/FindVISensor.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(PC_VISENSOR visensor) 3 | message("pkg: ${PC_VISENSOR_INCLUDEDIRS}") 4 | set(VISENSOR_DEFINITIONS ${PC_VISENSOR_CFLAGS_OTHER}) 5 | 6 | find_path(VISensorDriver_INCLUDE_DIR visensor.hpp 7 | HINTS ${PC_VISENSOR_INCLUDEDIR} ${PC_VISENSOR_INCLUDE_DIRS} 8 | PATH_SUFFIXES visensor ) 9 | 10 | find_library(VISensorDriver_LIBRARY NAMES libvisensor.so 11 | HINTS ${PC_VISENSOR_LIBDIR} ${PC_VISENSOR_LIBRARY_DIRS} /usr/local/lib) 12 | 13 | set(VISENSOR_LIBRARIES ${VISENSOR_LIBRARY} ) 14 | set(VISENSOR_INCLUDE_DIRS ${VISENSOR_INCLUDE_DIR} ) 15 | 16 | include(FindPackageHandleStandardArgs) 17 | # handle the QUIETLY and REQUIRED arguments and set LIBXML2_FOUND to TRUE 18 | # if all listed variables are TRUE 19 | find_package_handle_standard_args(VISensorDriver DEFAULT_MSG 20 | VISensorDriver_LIBRARY VISensorDriver_INCLUDE_DIR) 21 | 22 | mark_as_advanced(VISensorDriver_INCLUDE_DIR VISensorDriver_LIBRARY ) 23 | -------------------------------------------------------------------------------- /vi_sensor_interface/include/ConcurrentQueue.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Skybotix AG, Switzerland (info@skybotix.com) 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and non-commercial use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * Redistributions of source code must retain the above copyright notice, this 10 | * list of conditions and the following disclaimer. 11 | * 12 | * Redistributions in binary form must reproduce the above copyright notice, this 13 | * list of conditions and the following disclaimer in the documentation and/or 14 | * other materials provided with the distribution. 15 | * 16 | * Neither the name of the {organization} nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 24 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | 33 | #ifndef CONCURRENTQUEUE_HPP_ 34 | #define CONCURRENTQUEUE_HPP_ 35 | 36 | #include 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | template 44 | class ConcurrentQueue { 45 | private: 46 | std::queue q_; 47 | boost::mutex m_; 48 | boost::condition_variable c_; 49 | unsigned int cntr; 50 | 51 | public: 52 | ConcurrentQueue() { 53 | cntr = 0; 54 | }; 55 | 56 | void push(const T& data) { 57 | boost::lock_guard l(m_); 58 | q_.push(data); 59 | c_.notify_one(); 60 | } 61 | 62 | //if the queue is empty and we pop, we just wait for data!! 63 | T pop() { 64 | boost::mutex::scoped_lock l(m_); 65 | 66 | if (q_.size() == 0) { 67 | c_.wait(l); 68 | } 69 | 70 | T res = q_.front(); 71 | q_.pop(); 72 | return res; 73 | } 74 | 75 | //checks queue is empty 76 | bool empty() { 77 | boost::mutex::scoped_lock l(m_); 78 | return q_.size() == 0; 79 | } 80 | 81 | //return size of queue 82 | size_t size() { 83 | boost::mutex::scoped_lock l(m_); 84 | return q_.size(); 85 | } 86 | 87 | void clear() { 88 | std::queue empty; 89 | std::swap(q_, empty); 90 | } 91 | 92 | //returns current queue and clear it 93 | std::queue pop_all() { 94 | boost::mutex::scoped_lock l(m_); 95 | 96 | std::queue queue; //empty here 97 | std::swap(queue, q_); 98 | 99 | return queue; 100 | } 101 | 102 | //returns current queue and clear it 103 | std::queue clone() { 104 | boost::mutex::scoped_lock l(m_); 105 | 106 | std::queue queue = q_; 107 | return queue; 108 | } 109 | 110 | }; 111 | 112 | #endif /* CONCURRENTQUEUE_HPP_ */ 113 | -------------------------------------------------------------------------------- /vi_sensor_interface/include/vi_sensor_interface.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Skybotix AG, Switzerland (info@skybotix.com) 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and non-commercial use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * Redistributions of source code must retain the above copyright notice, this 10 | * list of conditions and the following disclaimer. 11 | * 12 | * Redistributions in binary form must reproduce the above copyright notice, this 13 | * list of conditions and the following disclaimer in the documentation and/or 14 | * other materials provided with the distribution. 15 | * 16 | * Neither the name of the {organization} nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 24 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include 46 | #include 47 | 48 | #include 49 | 50 | #include 51 | #include "ConcurrentQueue.hpp" 52 | 53 | class ViSensorInterface { 54 | public: 55 | ViSensorInterface(); 56 | ViSensorInterface(uint32_t image_rate, uint32_t imu_rate); 57 | ~ViSensorInterface(); 58 | 59 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 60 | private: 61 | visensor::ViSensorDriver drv_; 62 | typedef ConcurrentQueue ViFrameQueue; 63 | 64 | ViFrameQueue frameQueue[4]; 65 | 66 | bool vi_sensor_connected_; 67 | boost::mutex io_mutex_; 68 | 69 | void StartIntegratedSensor(uint32_t image_rate, uint32_t imu_rate); 70 | void ImageCallback(visensor::ViFrame::Ptr frame_ptr); 71 | void ImuCallback(boost::shared_ptr imu_ptr); 72 | void worker(unsigned int cam_id); 73 | }; 74 | -------------------------------------------------------------------------------- /vi_sensor_interface/src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Skybotix AG, Switzerland (info@skybotix.com) 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and non-commercial use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * Redistributions of source code must retain the above copyright notice, this 10 | * list of conditions and the following disclaimer. 11 | * 12 | * Redistributions in binary form must reproduce the above copyright notice, this 13 | * list of conditions and the following disclaimer in the documentation and/or 14 | * other materials provided with the distribution. 15 | * 16 | * Neither the name of the {organization} nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 24 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | 33 | #include 34 | 35 | int main(int argc, char** argv) { 36 | 37 | ViSensorInterface viSensor; 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /vi_sensor_interface/src/vi_sensor_interface.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Skybotix AG, Switzerland (info@skybotix.com) 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and non-commercial use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * Redistributions of source code must retain the above copyright notice, this 10 | * list of conditions and the following disclaimer. 11 | * 12 | * Redistributions in binary form must reproduce the above copyright notice, this 13 | * list of conditions and the following disclaimer in the documentation and/or 14 | * other materials provided with the distribution. 15 | * 16 | * Neither the name of the {organization} nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 24 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #include 33 | 34 | ViSensorInterface::ViSensorInterface(uint32_t image_rate, uint32_t imu_rate) 35 | : vi_sensor_connected_(false) { 36 | StartIntegratedSensor(image_rate, imu_rate); 37 | } 38 | 39 | ViSensorInterface::ViSensorInterface() 40 | : vi_sensor_connected_(false) { 41 | StartIntegratedSensor(20, 200); 42 | } 43 | 44 | ViSensorInterface::~ViSensorInterface() { 45 | 46 | } 47 | 48 | void ViSensorInterface::StartIntegratedSensor(uint32_t image_rate, uint32_t imu_rate) { 49 | 50 | if (image_rate > 30) { 51 | image_rate = 30; 52 | std::cout << "Desired image rate is too hight, setting it to 30 Hz." << std::endl; 53 | } 54 | if (imu_rate > 800) { 55 | imu_rate = 800; 56 | std::cout << "Desired imu rate is too hight, setting it to 800 Hz." << std::endl; 57 | } 58 | 59 | try { 60 | drv_.init(); 61 | } catch (visensor::exceptions::ConnectionException const &ex) { 62 | std::cout << ex.what() << "\n"; 63 | return; 64 | } 65 | 66 | std::cout << "Libvisensor version is " << visensor::LIBRARY_VERSION_MAJOR << "." 67 | << visensor::LIBRARY_VERSION_MINOR << "." << visensor::LIBRARY_VERSION_PATCH << std::endl; 68 | 69 | // load available calibration and configure sensors corresponding to it 70 | drv_.selectCameraCalibration(); 71 | 72 | // set callback for image messages 73 | drv_.setCameraCallback(boost::bind(&ViSensorInterface::ImageCallback, this, _1)); 74 | 75 | // set callback for IMU messages 76 | drv_.setImuCallback(boost::bind(&ViSensorInterface::ImuCallback, this, _1)); 77 | 78 | drv_.startAllCameras(image_rate); 79 | drv_.startAllImus(imu_rate); 80 | vi_sensor_connected_ = true; 81 | 82 | boost::thread drawWorker_0(boost::bind(&ViSensorInterface::worker, this, 0)); 83 | boost::thread drawWorker_1(boost::bind(&ViSensorInterface::worker, this, 1)); 84 | boost::thread drawWorker_2(boost::bind(&ViSensorInterface::worker, this, 2)); 85 | boost::thread drawWorker_3(boost::bind(&ViSensorInterface::worker, this, 3)); 86 | 87 | drawWorker_0.join(); 88 | drawWorker_1.join(); 89 | drawWorker_2.join(); 90 | drawWorker_3.join(); 91 | } 92 | 93 | void ViSensorInterface::ImageCallback(visensor::ViFrame::Ptr frame_ptr) { 94 | uint32_t camera_id = frame_ptr->camera_id; 95 | //push image on queue 96 | frameQueue[camera_id].push(frame_ptr); 97 | } 98 | 99 | void ViSensorInterface::ImuCallback(boost::shared_ptr imu_ptr) { 100 | if (imu_ptr->imu_id != visensor::SensorId::IMU0) 101 | return; 102 | uint32_t timeNSec = imu_ptr->timestamp; 103 | Eigen::Vector3d gyro(imu_ptr->gyro[0], imu_ptr->gyro[1], imu_ptr->gyro[2]); 104 | Eigen::Vector3d acc(imu_ptr->acc[0], imu_ptr->acc[1], imu_ptr->acc[2]); 105 | std::cout << "IMU Accelerometer data: " << acc[0] << "\t "<< acc[1] << "\t"<< acc[2] << "\t" << std::endl; 106 | //Do stuff with IMU... 107 | } 108 | 109 | void ViSensorInterface::worker(unsigned int cam_id) { 110 | while (1) { 111 | //Popping image from queue. If no image available, we perform a blocking wait 112 | visensor::ViFrame::Ptr frame = frameQueue[cam_id].pop(); 113 | uint32_t camera_id = frame->camera_id; 114 | cv::Mat image; 115 | image.create(frame->height, frame->width, CV_8UC1); 116 | memcpy(image.data, frame->getImageRawPtr(), frame->height * frame->width); 117 | //update window with image 118 | char winName[255]; 119 | boost::mutex::scoped_lock lock(io_mutex_); //lock thread as opencv does seem to have problems with multithreading 120 | sprintf(winName, "Camera %u", camera_id); 121 | cv::namedWindow(winName, CV_WINDOW_AUTOSIZE); 122 | cv::imshow(winName, image); 123 | cv::waitKey(1); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /vi_sensor_stereo_block_matcher/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #Sammy Omari, Skybotix AG, 28/3/2014 2 | cmake_minimum_required(VERSION 2.8.0) 3 | 4 | ############ 5 | # SETTINGS 6 | ############ 7 | set(PKGNAME vi_sensor_stereo_block_matcher) 8 | 9 | set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) 10 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin) 11 | set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib) 12 | set(Boost_USE_MULTITHREADED ON) 13 | 14 | find_package(Boost COMPONENTS system filesystem thread REQUIRED) 15 | find_package(Threads REQUIRED) 16 | find_package(Eigen3 REQUIRED) 17 | find_package( OpenCV REQUIRED ) 18 | find_package(VISensor REQUIRED ) 19 | 20 | set(CMAKE_BUILD_TYPE Release) 21 | ADD_DEFINITIONS (-march=native -O2 -fmessage-length=0 -MMD -MP -Wall -pedantic -std=c++0x ) #Release 22 | #ADD_DEFINITIONS (-march=native -O0 -g3 -fmessage-length=0 -MMD -MP -Wall -pedantic -std=c++0x ) #Debug 23 | 24 | FILE( 25 | GLOB SRCS 26 | src/*.cpp 27 | ) 28 | 29 | include_directories( ${EIGEN3_INCLUDE_DIR} ) 30 | include_directories( ${Boost_INCLUDE_DIRS} ) 31 | include_directories( ${VISensorDriver_INCLUDE_DIR} ) 32 | include_directories(include) 33 | 34 | add_executable(${PKGNAME} ${SRCS}) 35 | target_link_libraries(${PKGNAME} ${OpenCV_LIBS} ${VISensorDriver_LIBRARY} visensor ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) 36 | -------------------------------------------------------------------------------- /vi_sensor_stereo_block_matcher/README.md: -------------------------------------------------------------------------------- 1 | vi_sensor_stereo_block_matcher 2 | =================== 3 | 4 | Simple example on how to compute a stereo disparity image using the VI-Sensor 5 | 6 | Build instructions 7 | ================== 8 | Download libvisensor and install it if you have not done that before 9 | 10 |

11 | git clone https://github.com/ethz-asl/libvisensor.git
12 | cd libvisensor
13 | ./install_libvisensor.sh
14 | 
15 | 16 | Now, were building the stereo block matcher 17 | 18 |

19 | cd vi_sensor_stereo_block_matcher
20 | mkdir build
21 | cd build
22 | cmake ..
23 | make
24 | cd ../bin
25 | ./vi_sensor_stereo_block_matcher
26 | 
27 | -------------------------------------------------------------------------------- /vi_sensor_stereo_block_matcher/cmake/FindEigen3.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find Eigen3 lib 2 | # Once done this will define 3 | # 4 | # EIGEN3_FOUND - system has eigen lib 5 | # EIGEN3_INCLUDE_DIR - the eigen include directory 6 | 7 | # Copyright (c) 2006, 2007 Montel Laurent, 8 | # Redistribution and use is allowed according to the terms of the BSD license. 9 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 10 | 11 | if( EIGEN3_INCLUDE_DIR ) 12 | # in cache already 13 | set( EIGEN3_FOUND TRUE ) 14 | else (EIGEN3_INCLUDE_DIR) 15 | find_path( EIGEN3_INCLUDE_DIR NAMES Eigen/Core 16 | PATH_SUFFIXES eigen3/ 17 | HINTS 18 | ${INCLUDE_INSTALL_DIR} 19 | /usr/local/include 20 | ${KDE4_INCLUDE_DIR} 21 | ) 22 | include( FindPackageHandleStandardArgs ) 23 | find_package_handle_standard_args( Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR ) 24 | mark_as_advanced( EIGEN3_INCLUDE_DIR ) 25 | endif(EIGEN3_INCLUDE_DIR) 26 | 27 | -------------------------------------------------------------------------------- /vi_sensor_stereo_block_matcher/cmake/FindVISensor.cmake: -------------------------------------------------------------------------------- 1 | find_package(PkgConfig) 2 | pkg_check_modules(PC_VISENSOR visensor) 3 | message("pkg: ${PC_VISENSOR_INCLUDEDIRS}") 4 | set(VISENSOR_DEFINITIONS ${PC_VISENSOR_CFLAGS_OTHER}) 5 | 6 | find_path(VISensorDriver_INCLUDE_DIR visensor.hpp 7 | HINTS ${PC_VISENSOR_INCLUDEDIR} ${PC_VISENSOR_INCLUDE_DIRS} 8 | PATH_SUFFIXES visensor ) 9 | 10 | find_library(VISensorDriver_LIBRARY NAMES libvisensor.so 11 | HINTS ${PC_VISENSOR_LIBDIR} ${PC_VISENSOR_LIBRARY_DIRS} /usr/local/lib) 12 | 13 | set(VISENSOR_LIBRARIES ${VISENSOR_LIBRARY} ) 14 | set(VISENSOR_INCLUDE_DIRS ${VISENSOR_INCLUDE_DIR} ) 15 | 16 | include(FindPackageHandleStandardArgs) 17 | # handle the QUIETLY and REQUIRED arguments and set LIBXML2_FOUND to TRUE 18 | # if all listed variables are TRUE 19 | find_package_handle_standard_args(VISensorDriver DEFAULT_MSG 20 | VISensorDriver_LIBRARY VISensorDriver_INCLUDE_DIR) 21 | 22 | mark_as_advanced(VISensorDriver_INCLUDE_DIR VISensorDriver_LIBRARY ) 23 | -------------------------------------------------------------------------------- /vi_sensor_stereo_block_matcher/include/vi_sensor_interface.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Skybotix AG, Switzerland (info@skybotix.com) 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and non-commercial use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * Redistributions of source code must retain the above copyright notice, this 10 | * list of conditions and the following disclaimer. 11 | * 12 | * Redistributions in binary form must reproduce the above copyright notice, this 13 | * list of conditions and the following disclaimer in the documentation and/or 14 | * other materials provided with the distribution. 15 | * 16 | * Neither the name of the {organization} nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 24 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include 47 | #include 48 | 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | #include 55 | 56 | class ViSensorInterface { 57 | public: 58 | ViSensorInterface(); 59 | ViSensorInterface(uint32_t image_rate, uint32_t imu_rate); 60 | ~ViSensorInterface(); 61 | void run(void); 62 | 63 | EIGEN_MAKE_ALIGNED_OPERATOR_NEW 64 | private: 65 | void StartIntegratedSensor(uint32_t image_rate, uint32_t imu_rate); 66 | void ImageCallback(visensor::ViFrame::Ptr frame_ptr); 67 | void ImuCallback(boost::shared_ptr imu_ptr); 68 | void process_data(); 69 | bool computeRectificationMaps(void); 70 | 71 | visensor::ViSensorDriver drv_; 72 | typedef std::deque ViFrameQueue; 73 | visensor::SensorId::SensorId idxCam0_; 74 | visensor::SensorId::SensorId idxCam1_; 75 | 76 | ViFrameQueue frameQueue[4]; 77 | 78 | boost::mutex io_mutex_; 79 | bool computed_rectification_map_; 80 | cv::Mat map00_, map01_, map10_, map11_; 81 | cv::StereoBM bm_; 82 | }; 83 | -------------------------------------------------------------------------------- /vi_sensor_stereo_block_matcher/src/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Skybotix AG, Switzerland (info@skybotix.com) 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and non-commercial use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * Redistributions of source code must retain the above copyright notice, this 10 | * list of conditions and the following disclaimer. 11 | * 12 | * Redistributions in binary form must reproduce the above copyright notice, this 13 | * list of conditions and the following disclaimer in the documentation and/or 14 | * other materials provided with the distribution. 15 | * 16 | * Neither the name of the {organization} nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 24 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #include 33 | 34 | int main(int argc, char** argv) { 35 | 36 | ViSensorInterface visensor; 37 | visensor.run(); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /vi_sensor_stereo_block_matcher/src/vi_sensor_interface.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014, Skybotix AG, Switzerland (info@skybotix.com) 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and non-commercial use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * Redistributions of source code must retain the above copyright notice, this 10 | * list of conditions and the following disclaimer. 11 | * 12 | * Redistributions in binary form must reproduce the above copyright notice, this 13 | * list of conditions and the following disclaimer in the documentation and/or 14 | * other materials provided with the distribution. 15 | * 16 | * Neither the name of the {organization} nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 24 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | */ 32 | #include 33 | 34 | ViSensorInterface::ViSensorInterface(uint32_t image_rate, uint32_t imu_rate) 35 | : computed_rectification_map_(false) { 36 | StartIntegratedSensor(image_rate, imu_rate); 37 | } 38 | 39 | ViSensorInterface::ViSensorInterface() 40 | : computed_rectification_map_(false) { 41 | 42 | StartIntegratedSensor(20, 200); 43 | } 44 | 45 | ViSensorInterface::~ViSensorInterface() { 46 | 47 | } 48 | 49 | void ViSensorInterface::run(void) { 50 | // set callback for completed frames 51 | drv_.setCameraCallback(boost::bind(&ViSensorInterface::ImageCallback, this, _1)); 52 | 53 | // set callback for completed IMU messages 54 | drv_.setImuCallback(boost::bind(&ViSensorInterface::ImuCallback, this, _1)); 55 | 56 | //Lets wait for the user to end program. 57 | //This is ok as program is callback-driven anyways 58 | boost::mutex m; 59 | boost::mutex::scoped_lock l(m); 60 | boost::condition_variable c; 61 | c.wait(l); 62 | } 63 | 64 | void ViSensorInterface::StartIntegratedSensor(uint32_t image_rate, uint32_t imu_rate) { 65 | 66 | if (image_rate > 30) { 67 | image_rate = 30; 68 | std::cout << "Desired image rate is too high, setting it to 30 Hz." << std::endl; 69 | } 70 | if (imu_rate > 800) { 71 | imu_rate = 800; 72 | std::cout << "Desired imu rate is too high, setting it to 800 Hz." << std::endl; 73 | } 74 | 75 | try { 76 | drv_.init(); 77 | } catch (visensor::exceptions::ConnectionException const &ex) { 78 | std::cout << ex.what() << "\n"; 79 | return; 80 | } 81 | 82 | std::cout << "Libvisensor version is " << visensor::LIBRARY_VERSION_MAJOR << "." 83 | << visensor::LIBRARY_VERSION_MINOR << "." << visensor::LIBRARY_VERSION_PATCH << std::endl; 84 | 85 | // load available calibration and configure sensors corresponding to it 86 | drv_.selectCameraCalibration(); 87 | 88 | //determine which camera is left and which is right (required for opencv block matcher) 89 | if (!drv_.isStereoCameraFlipped()){ 90 | idxCam0_ = visensor::SensorId::CAM0; 91 | idxCam1_ = visensor::SensorId::CAM1; 92 | }else{ 93 | idxCam0_ = visensor::SensorId::CAM1; 94 | idxCam1_ = visensor::SensorId::CAM0; 95 | } 96 | 97 | drv_.startAllCameras(image_rate); 98 | drv_.startAllImus(imu_rate); 99 | } 100 | 101 | void ViSensorInterface::ImageCallback(visensor::ViFrame::Ptr frame_ptr) { 102 | boost::mutex::scoped_lock lock(io_mutex_); //lock thread as opencv does seem to have problems with multithreading 103 | uint32_t camera_id = frame_ptr->camera_id; 104 | frameQueue[camera_id].emplace_back(frame_ptr); 105 | process_data(); 106 | } 107 | 108 | void ViSensorInterface::ImuCallback(boost::shared_ptr imu_ptr) { 109 | Eigen::Vector3d gyro(imu_ptr->gyro[0], imu_ptr->gyro[1], imu_ptr->gyro[2]); 110 | Eigen::Vector3d acc(imu_ptr->acc[0], imu_ptr->acc[1], imu_ptr->acc[2]); 111 | } 112 | 113 | void ViSensorInterface::process_data() { 114 | 115 | //Lets sync image streams from cam0 & cam1 116 | if (frameQueue[idxCam0_].empty() || frameQueue[idxCam1_].empty()) 117 | return; 118 | while (frameQueue[idxCam0_].front()->timestamp > frameQueue[idxCam1_].front()->timestamp) { 119 | frameQueue[idxCam1_].pop_front(); 120 | if (frameQueue[idxCam0_].empty() || frameQueue[idxCam1_].empty()) 121 | return; 122 | } 123 | while (frameQueue[idxCam0_].front()->timestamp < frameQueue[idxCam1_].front()->timestamp) { 124 | frameQueue[idxCam0_].pop_front(); 125 | if (frameQueue[idxCam0_].empty() || frameQueue[idxCam1_].empty()) 126 | return; 127 | } 128 | 129 | //If we arrive here, both queues have synced timestamps 130 | visensor::ViFrame::Ptr frame0 = frameQueue[idxCam0_].front(); 131 | visensor::ViFrame::Ptr frame1 = frameQueue[idxCam1_].front(); 132 | 133 | if (!computed_rectification_map_) 134 | computeRectificationMaps(); 135 | 136 | cv::Mat img0, img1; 137 | img0.create(frame0->height, frame0->width, CV_8UC1); 138 | img0.data = frame0->getImageRawPtr(); 139 | 140 | img1.create(frame1->height, frame1->width, CV_8UC1); 141 | img1.data = frame1->getImageRawPtr(); 142 | 143 | cv::Mat img0rect, img1rect; 144 | cv::remap(img0, img0rect, map00_, map01_, cv::INTER_LINEAR); 145 | cv::remap(img1, img1rect, map10_, map11_, cv::INTER_LINEAR); 146 | 147 | cv::namedWindow("img_rect_cam0", CV_WINDOW_AUTOSIZE); 148 | cv::imshow("img_rect_cam0", img0rect); 149 | 150 | cv::Mat disp, disp8; 151 | bm_(img0rect, img1rect, disp); 152 | disp.convertTo(disp8, CV_8U); 153 | cv::namedWindow("disparity", CV_WINDOW_AUTOSIZE); 154 | cv::imshow("disparity", disp8); 155 | cv::waitKey(1); 156 | 157 | //We dont need the frames anymore, lets drop them 158 | frameQueue[idxCam0_].pop_front(); 159 | frameQueue[idxCam1_].pop_front(); 160 | } 161 | 162 | bool ViSensorInterface::computeRectificationMaps(void) { 163 | visensor::ViCameraCalibration camera_calibration_0, camera_calibration_1; 164 | try { 165 | visensor::ViCameraCalibration tmp; 166 | std::vector calibrations; 167 | drv_.getSelectedCameraCalibration(&tmp, idxCam0_); 168 | if (tmp.lens_model_->type_ != visensor::ViCameraLensModel::LensModelTypes::RADTAN || 169 | tmp.projection_model_->type_ != visensor::ViCameraProjectionModel::ProjectionModelTypes::PINHOLE) { 170 | std::cerr << "No radtan and pinhole calibration specified. Therefore the factory " 171 | "calibration is choosen for the ROS sensor message." << std::endl; 172 | calibrations = drv_.getCameraCalibrations( 173 | idxCam0_, 0, tmp.is_flipped_, 174 | visensor::ViCameraLensModel::LensModelTypes::RADTAN, 175 | visensor::ViCameraProjectionModel::ProjectionModelTypes::PINHOLE); 176 | if (calibrations.size() == 0) { 177 | std::cerr << "No corresponding Factory Calibration for cam left found" << std::endl; 178 | return false; 179 | } 180 | camera_calibration_0 = calibrations.front(); 181 | } 182 | else { 183 | camera_calibration_0 = tmp; 184 | } 185 | drv_.getSelectedCameraCalibration(&tmp, idxCam1_); 186 | if (tmp.lens_model_->type_ != visensor::ViCameraLensModel::LensModelTypes::RADTAN || 187 | tmp.projection_model_->type_ != visensor::ViCameraProjectionModel::ProjectionModelTypes::PINHOLE) { 188 | std::cerr << "No radtan and pinhole calibration specified. " 189 | "Therefore the factory calibration is choosen for the ROS sensor message." << std::endl; 190 | calibrations = drv_.getCameraCalibrations( 191 | idxCam1_, 0, tmp.is_flipped_, 192 | visensor::ViCameraLensModel::LensModelTypes::RADTAN, 193 | visensor::ViCameraProjectionModel::ProjectionModelTypes::PINHOLE); 194 | if (calibrations.size() == 0) { 195 | std::cerr << "No corresponding Factory Calibration for cam right found" << std::endl; 196 | return false; 197 | } 198 | camera_calibration_1 = calibrations.front(); 199 | } 200 | else { 201 | camera_calibration_1 = tmp; 202 | } 203 | } 204 | catch (visensor::exceptions const &ex) { 205 | std::cerr << "Could not read the camera configuration of cameras "<< idxCam0_ << " and " 206 | << idxCam1_ << ". Exception: " << ex.what() << std::endl; 207 | return false; 208 | } 209 | 210 | int image_width = camera_calibration_0.resolution_[0]; 211 | int image_height = camera_calibration_0.resolution_[1];; 212 | 213 | double c0[9]; 214 | double d0[5]; 215 | double r0[9]; 216 | double p0[12]; 217 | double rot0[9]; 218 | double t0[3]; 219 | 220 | double c1[9]; 221 | double d1[5]; 222 | double r1[9]; 223 | double p1[12]; 224 | double rot1[9]; 225 | double t1[3]; 226 | 227 | double r[9]; 228 | double t[3]; 229 | 230 | std::vector lens_coefficients = camera_calibration_0.lens_model_->getCoefficients(); 231 | std::fill(d0, d0 + 5, 0); 232 | for ( unsigned int i = 0; i < lens_coefficients.size(); ++i ) { 233 | d0[i] = lens_coefficients.at(i); 234 | } 235 | visensor::ViCameraProjectionModelPinhole::Ptr cam0_projection_model = 236 | camera_calibration_0.getProjectionModel(); 237 | c0[0] = cam0_projection_model->focal_length_u_; 238 | c0[1] = 0.0; 239 | c0[2] = cam0_projection_model->principal_point_u_; 240 | c0[3] = 0.0; 241 | c0[4] = cam0_projection_model->focal_length_v_; 242 | c0[5] = cam0_projection_model->principal_point_v_; 243 | c0[6] = 0.0; 244 | c0[7] = 0.0; 245 | c0[8] = 1.0; 246 | 247 | lens_coefficients = camera_calibration_1.lens_model_->getCoefficients(); 248 | std::fill(d1, d1 + 5, 0); 249 | for ( unsigned int i = 0; i < lens_coefficients.size(); ++i ) { 250 | d1[i] = lens_coefficients.at(i); 251 | } 252 | visensor::ViCameraProjectionModelPinhole::Ptr cam1_projection_model = 253 | camera_calibration_1.getProjectionModel(); 254 | c1[0] = cam1_projection_model->focal_length_u_; 255 | c1[1] = 0.0; 256 | c1[2] = cam1_projection_model->principal_point_u_; 257 | c1[3] = 0.0; 258 | c1[4] = cam1_projection_model->focal_length_v_; 259 | c1[5] = cam1_projection_model->principal_point_v_; 260 | c1[6] = 0.0; 261 | c1[7] = 0.0; 262 | c1[8] = 1.0; 263 | 264 | for (int i = 0; i < 9; ++i) { 265 | rot0[i] = camera_calibration_0.R_[i]; 266 | rot1[i] = camera_calibration_1.R_[i]; 267 | } 268 | for (int i = 0; i < 3; ++i) { 269 | t0[i] = camera_calibration_0.t_[i]; 270 | t1[i] = camera_calibration_1.t_[i]; 271 | } 272 | 273 | Eigen::Map < Eigen::Matrix3d > RR0(rot0); 274 | Eigen::Map < Eigen::Vector3d > tt0(t0); 275 | Eigen::Map < Eigen::Matrix3d > RR1(rot1); 276 | Eigen::Map < Eigen::Vector3d > tt1(t1); 277 | 278 | Eigen::Matrix4d T0 = Eigen::Matrix4d::Zero(); 279 | Eigen::Matrix4d T1 = Eigen::Matrix4d::Zero(); 280 | 281 | T0.block<3, 3>(0, 0) = RR0; 282 | T0.block<3, 1>(0, 3) = tt0; 283 | T0(3, 3) = 1.0; 284 | T1.block<3, 3>(0, 0) = RR1; 285 | T1.block<3, 1>(0, 3) = tt1; 286 | T1(3, 3) = 1.0; 287 | 288 | Eigen::Matrix4d T_rel = Eigen::Matrix4d::Zero(); 289 | T_rel = T1 * T0.inverse(); 290 | 291 | Eigen::Map < Eigen::Matrix3d > R_rel(r); 292 | Eigen::Map < Eigen::Vector3d > t_rel(t); 293 | 294 | R_rel = T_rel.block<3, 3>(0, 0); 295 | t_rel << T_rel(0, 3), T_rel(1, 3), T_rel(2, 3); 296 | 297 | double r_temp[9]; 298 | r_temp[0] = R_rel(0, 0); 299 | r_temp[1] = R_rel(0, 1); 300 | r_temp[2] = R_rel(0, 2); 301 | r_temp[3] = R_rel(1, 0); 302 | r_temp[4] = R_rel(1, 1); 303 | r_temp[5] = R_rel(1, 2); 304 | r_temp[6] = R_rel(2, 0); 305 | r_temp[7] = R_rel(2, 1); 306 | r_temp[8] = R_rel(2, 2); 307 | 308 | //cv::Mat wrapped(rows, cols, CV_32FC1, external_mem, CV_AUTOSTEP); 309 | cv::Mat C0(3, 3, CV_64FC1, c0, 3 * sizeof(double)); 310 | cv::Mat D0(5, 1, CV_64FC1, d0, 1 * sizeof(double)); 311 | cv::Mat R0(3, 3, CV_64FC1, r0, 3 * sizeof(double)); 312 | cv::Mat P0(3, 4, CV_64FC1, p0, 4 * sizeof(double)); 313 | 314 | cv::Mat C1(3, 3, CV_64FC1, c1, 3 * sizeof(double)); 315 | cv::Mat D1(5, 1, CV_64FC1, d1, 1 * sizeof(double)); 316 | cv::Mat R1(3, 3, CV_64FC1, r1, 3 * sizeof(double)); 317 | cv::Mat P1(3, 4, CV_64FC1, p1, 4 * sizeof(double)); 318 | 319 | cv::Mat R(3, 3, CV_64FC1, r_temp, 3 * sizeof(double)); 320 | 321 | cv::Mat T(3, 1, CV_64FC1, t, 1 * sizeof(double)); 322 | 323 | cv::Size img_size(image_width, image_height); 324 | 325 | cv::Rect roi1, roi2; 326 | cv::Mat Q; 327 | 328 | cv::stereoRectify(C0, D0, C1, D1, img_size, R, T, R0, R1, P0, P1, Q, cv::CALIB_ZERO_DISPARITY, 0, 329 | img_size, &roi1, &roi2); 330 | 331 | cv::initUndistortRectifyMap(C0, D0, R0, P0, img_size, CV_16SC2, map00_, map01_); 332 | cv::initUndistortRectifyMap(C1, D1, R1, P1, img_size, CV_16SC2, map10_, map11_); 333 | 334 | computed_rectification_map_ = true; 335 | return true; 336 | } 337 | --------------------------------------------------------------------------------