Files
vio/svo_ros/src/vo_node.cpp
T

182 lines
5.2 KiB
C++

// This file is part of SVO - Semi-direct Visual Odometry.
//
// Copyright (C) 2014 Christian Forster <forster at ifi dot uzh dot ch>
// (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 <http://www.gnu.org/licenses/>.
#include <ros/package.h>
#include <string>
#include <svo/frame_handler_mono.h>
#include <svo/map.h>
#include <svo/config.h>
#include <svo_ros/visualizer.h>
#include <vikit/params_helper.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/Imu.h>
#include <std_msgs/String.h>
#include <message_filters/subscriber.h>
#include <message_filters/synchronizer.h>
#include <message_filters/sync_policies/approximate_time.h>
#include <image_transport/image_transport.h>
#include <boost/thread.hpp>
#include <cv_bridge/cv_bridge.h>
#include <Eigen/Core>
#include <vikit/abstract_camera.h>
#include <vikit/camera_loader.h>
#include <vikit/user_input_thread.h>
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<bool>("svo/publish_markers", true)),
publish_dense_input_(vk::getParam<bool>("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<double>("svo/init_rx", 0.0),
vk::getParam<double>("svo/init_ry", 0.0),
vk::getParam<double>("svo/init_rz", 0.0))),
Eigen::Vector3d(vk::getParam<double>("svo/init_tx", 0.0),
vk::getParam<double>("svo/init_ty", 0.0),
vk::getParam<double>("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<std::string>("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;
}