// This file is part of SVO - Semi-direct Visual Odometry. // // Copyright (C) 2014 Christian Forster // (Robotics and Perception Group, University of Zurich, Switzerland). // // SVO is free software: you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the Free Software // Foundation, either version 3 of the License, or any later version. // // SVO is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace svo { using namespace std; using namespace vk; /// SVO Interface class VoNode { public: svo::FrameHandlerMono* vo_; svo::Visualizer visualizer_; bool publish_markers_; //!< publish only the minimal amount of info (choice for embedded devices) bool publish_dense_input_; vk::UserInputThread* user_input_thread_; ros::Subscriber sub_remote_key_; string remote_input_; vk::AbstractCamera* cam_; bool quit_; VoNode(); ~VoNode(); void imgCb(const sensor_msgs::ImageConstPtr& msg); void processUserActions(); void remoteKeyCb(const std_msgs::StringConstPtr& key_input); }; VoNode:: VoNode() : vo_(NULL), publish_markers_(vk::getParam("svo/publish_markers", true)), publish_dense_input_(vk::getParam("svo/publish_dense_input", false)), user_input_thread_(new vk::UserInputThread()), remote_input_(""), cam_(NULL), quit_(false) { // Create Camera if(!vk::camera_loader::loadFromRosNs("svo", cam_)) throw std::runtime_error("Camera model not correctly specified."); // Init camera vo_ = new svo::FrameHandlerMono(cam_); // Set initial position and orientation Sophus::SE3 T_cam_from_world( vk::rpy2dcm(Vector3d(vk::getParam("svo/init_rx", 0.0), vk::getParam("svo/init_ry", 0.0), vk::getParam("svo/init_rz", 0.0))), Eigen::Vector3d(vk::getParam("svo/init_tx", 0.0), vk::getParam("svo/init_ty", 0.0), vk::getParam("svo/init_tz", 0.0))); vo_->setInitialPose(T_cam_from_world); vo_->start(); } VoNode:: ~VoNode() { delete vo_; delete user_input_thread_; delete cam_; } void VoNode:: imgCb(const sensor_msgs::ImageConstPtr& msg) { cv::Mat img; try { img = cv_bridge::toCvShare(msg, "mono8")->image; } catch (cv_bridge::Exception& e) { ROS_ERROR("cv_bridge exception: %s", e.what()); } processUserActions(); vo_->addImage(img, msg->header.stamp.toSec()); visualizer_.publishMinimal(img, vo_->lastFrame(), *vo_, msg->header.stamp.toSec()); if(publish_markers_ && vo_->stage() != FrameHandlerBase::STAGE_PAUSED) visualizer_.visualizeMarkers(vo_->lastFrame(), vo_->coreKeyframes(), vo_->map()); if(publish_dense_input_) visualizer_.exportToDense(vo_->lastFrame()); if(vo_->stage() == FrameHandlerMono::STAGE_PAUSED) usleep(100000); // avoid busy loop when paused } void VoNode::processUserActions() { char input = remote_input_.c_str()[0]; remote_input_ = ""; char console_input = user_input_thread_->getInput(); if(console_input != 0) input = console_input; switch(input) { case 'q': quit_ = true; printf("Svo User Input: QUIT\n"); break; case 'r': vo_->reset(); printf("Svo User Input: RESET\n"); break; case 's': vo_->start(); printf("Svo User Input: START\n"); break; default: ; } } void VoNode::remoteKeyCb(const std_msgs::StringConstPtr& key_input) { remote_input_ = key_input->data; } } // namespace svo int main(int argc, char **argv) { ros::init(argc, argv, "svo"); ros::NodeHandle nh; std::cout << "create vo_node" << std::endl; svo::VoNode vo_node; // subscribe to cam msgs std::string cam_topic(vk::getParam("svo/cam_topic", "camera/image_raw")); image_transport::ImageTransport it(nh); image_transport::Subscriber it_sub = it.subscribe(cam_topic, 5, &svo::VoNode::imgCb, &vo_node); // subscribe to remote input vo_node.sub_remote_key_ = nh.subscribe("svo/remote_key", 5, &svo::VoNode::remoteKeyCb, &vo_node); // start processing callbacks while(ros::ok() && !vo_node.quit_) { ros::spinOnce(); // TODO check when last image was processed. when too long ago. publish warning that no msgs are received! } printf("Svo terminated.\n"); return 0; }