uos_rotunit_snapshotter.cpp
Go to the documentation of this file.
00001 /*
00002  * UOS-ROS packages - Robot Operating System code by the University of Osnabrück
00003  * Copyright (C) 2015 University of Osnabrück
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  *
00019  * uos_rotunit_snapshotter.cpp
00020  *
00021  * Created on: 26.02.2015
00022  *      Authors: Sebastian Puetz <spuetz@uni-osnabrueck.de>
00023  */
00024 #include "uos_rotunit_snapshotter.h"
00025 
00026 RotunitSnapshotter::RotunitSnapshotter(ros::NodeHandle& nh, std::string action_name)
00027   : nh_(nh),
00028     action_name_(action_name),
00029     started_(false),
00030     server_(nh_, action_name_, boost::bind(&RotunitSnapshotter::makeSnapshot, this, _1), false)
00031 {
00032   ros::NodeHandle nh_private("~");
00033   nh_private.param("rotation_angle", rotation_angle , 2*M_PI);
00034   nh_private.param("continuous", continuous, true);
00035 
00036   ROS_INFO("rotation angle is %f and continuous is %s", rotation_angle, continuous ? "true" : "false");
00037 
00038   client_ = nh_.serviceClient<laser_assembler::AssembleScans2>("assemble_scans2");
00039   cloud_pub_ = nh_.advertise<sensor_msgs::PointCloud2> ("assembled_cloud", 1);
00040   snapshot_pub_ = nh_.advertise<uos_rotunit_snapshotter::RotunitSnapshot> ("snapshot", 1);
00041   server_.start();
00042   if(continuous)
00043     state_sub_ = nh_.subscribe("joint_states", 1000, &RotunitSnapshotter::rotCallback, this);
00044   ROS_INFO("%s action server is running...", action_name_.c_str());
00045 }
00046 
00047 double RotunitSnapshotter::norm2PI(double angle){
00048   while(angle < 0)
00049     angle += 2 * M_PI;
00050   while(angle > 2 * M_PI)
00051     angle -= 2 * M_PI;
00052   return angle;
00053 }
00054 
00055 int RotunitSnapshotter::getIndex(const sensor_msgs::JointState::ConstPtr &jointState){
00056   for (size_t i = 0; i < jointState->name.size(); ++i)
00057   {
00058     if (jointState->name[i] == "laser_rot_joint")
00059       return i;
00060   }
00061   return -1;
00062 }
00063 
00064 bool RotunitSnapshotter::checkIfFinished(double current_rot, ros::Time stamp){
00065   if(!started_){
00066     begin_angle = current_rot;
00067     begin_stamp = stamp;
00068     previous_rot = current_rot;
00069     residual_rot = rotation_angle;
00070     destination_rot = norm2PI(current_rot + rotation_angle);
00071     started_ = true;
00072     ROS_INFO("Start snapshot at %f degree, the destination angle is %f, angle aim is %f",
00073       current_rot * 180.0 / M_PI, rotation_angle * 180.0 / M_PI, destination_rot * 180.0 / M_PI);
00074   }
00075   double diff = norm2PI(current_rot - previous_rot);
00076   if(diff > M_PI / 180.0 && diff <= MAX_STEP_SIZE)
00077     residual_rot -= diff;
00078 
00079   // TODO cehck rotational direction
00080 
00081   if(residual_rot <= 0)
00082   {
00083     end_angle = current_rot;
00084     end_stamp = stamp;
00085     started_ = false;
00086     ROS_INFO("Finished snapshot at %f degree!", current_rot * 180.0 / M_PI);
00087     return true;
00088   }
00089   previous_rot = current_rot;
00090   return false;
00091 }
00092 
00093 void RotunitSnapshotter::makeSnapshot(const uos_rotunit_snapshotter::RotunitSnapshotGoalConstPtr &goal){
00094   finished_ = false;
00095   if(!continuous)
00096     state_sub_ = nh_.subscribe("joint_states", 1000, &RotunitSnapshotter::rotCallback, this);
00097   boost::mutex::scoped_lock lock(mutex_);
00098   while (!finished_)
00099     condition_.wait(lock);
00100 
00101   server_.setSucceeded(result_);
00102 }
00103 
00104 void RotunitSnapshotter::rotCallback(const sensor_msgs::JointState::ConstPtr &jointState){
00105   boost::mutex::scoped_lock lock(mutex_);
00106   
00107   if(server_.isPreemptRequested() || !ros::ok()){
00108     ROS_INFO("%s: Preempted", action_name_.c_str());
00109     // set the action state to preempted
00110     finished_ = true;
00111     server_.setPreempted();
00112     condition_.notify_one();
00113     return;
00114   }
00115   int index = getIndex(jointState);
00116   if(index == -1)
00117     return;
00118 
00119   double rot = jointState->position[index];
00120   ROS_DEBUG("Current angle: %f", rot * 180 /M_PI);
00121 
00122   if(checkIfFinished(rot, jointState->header.stamp)){
00123     laser_assembler::AssembleScans2 srv;
00124     srv.request.begin = begin_stamp;
00125     srv.request.end = end_stamp;
00126 
00127     ROS_INFO("Call assembler with a duration of %fsec",
00128     end_stamp.toSec()-begin_stamp.toSec());
00129 
00130     if (client_.call(srv)){
00131       cloud_pub_.publish(srv.response.cloud);
00132       ROS_INFO("Published scan with %d points", srv.response.cloud.height * srv.response.cloud.width);
00133       uos_rotunit_snapshotter::RotunitSnapshot snapshot;
00134       snapshot.header.stamp = end_stamp;
00135       snapshot.cloud = srv.response.cloud;
00136       snapshot.begin_angle = begin_angle;
00137       snapshot.end_angle = end_angle;
00138       snapshot.scan_time = end_stamp - begin_stamp;
00139       result_.snapshot = snapshot;
00140       
00141       snapshot_pub_.publish(snapshot);
00142 
00143       finished_ = true;
00144       if(!continuous)
00145         state_sub_.shutdown();
00146       condition_.notify_one();
00147     }
00148     else
00149       ROS_ERROR("Error making service call\n") ;
00150   }
00151 }
00152 
00153 int main(int argc, char** argv){
00154 
00155   ros::init(argc, argv, "RotunitSnapshotter");
00156   ros::NodeHandle nh;
00157   
00158   ROS_INFO("Waiting for [assemble_scans2] to be advertised");
00159   ros::service::waitForService("assemble_scans2");
00160   ROS_INFO("Found [assemble_scans2]! Starting the snapshotter");
00161   
00162   RotunitSnapshotter snapshotter(nh, std::string("rotunit_snapshotter"));
00163   ros::spin();
00164   return EXIT_SUCCESS;
00165 }


uos_rotunit_snapshotter
Author(s):
autogenerated on Fri Aug 28 2015 13:31:06