Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
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 }