trajectory_server.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2014, ATR, Atsushi Watanabe
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the copyright holder nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 /*
00031    * This research was supported by a contract with the Ministry of Internal
00032    Affairs and Communications entitled, 'Novel and innovative R&D making use
00033    of brain structures'
00034 
00035    This software was implemented to accomplish the above research.
00036  */
00037 
00038 #include <ros/ros.h>
00039 #include <math.h>
00040 #include <fstream>
00041 #include <string>
00042 
00043 #include <geometry_msgs/Twist.h>
00044 #include <interactive_markers/interactive_marker_server.h>
00045 #include <nav_msgs/Path.h>
00046 #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
00047 #include <trajectory_tracker_msgs/ChangePath.h>
00048 #include <trajectory_tracker_msgs/TrajectoryServerStatus.h>
00049 #include <visualization_msgs/InteractiveMarkerUpdate.h>
00050 
00051 #include <trajectory_tracker/filter.h>
00052 
00053 #include <neonavigation_common/compatibility.h>
00054 
00055 class ServerNode
00056 {
00057 public:
00058   ServerNode();
00059   ~ServerNode();
00060   void spin();
00061 
00062 private:
00063   ros::NodeHandle nh_;
00064   ros::NodeHandle pnh_;
00065   ros::Publisher pub_path_;
00066   ros::Publisher pub_status_;
00067   ros::ServiceServer srv_change_path_;
00068   interactive_markers::InteractiveMarkerServer srv_im_fb_;
00069 
00070   nav_msgs::Path path_;
00071   std::string topic_path_;
00072   trajectory_tracker_msgs::ChangePath::Request req_path_;
00073   double hz_;
00074   boost::shared_array<uint8_t> buffer_;
00075   int serial_size_;
00076   double filter_step_;
00077   trajectory_tracker::Filter* lpf_[2];
00078 
00079   bool loadFile();
00080   void loadPath();
00081   bool change(trajectory_tracker_msgs::ChangePath::Request& req,
00082               trajectory_tracker_msgs::ChangePath::Response& res);
00083   void processFeedback(
00084       const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback);
00085   void updateIM();
00086   enum
00087   {
00088     MENU_DELETE = 1,
00089     MENU_ADD = 2
00090   };
00091   int update_num_;
00092   int max_markers_;
00093 };
00094 
00095 ServerNode::ServerNode()
00096   : nh_()
00097   , pnh_("~")
00098   , srv_im_fb_("trajectory_server")
00099   , buffer_(new uint8_t[1024])
00100 {
00101   neonavigation_common::compat::checkCompatMode();
00102   neonavigation_common::compat::deprecatedParam(pnh_, "path", topic_path_, std::string("path"));
00103   pnh_.param("file", req_path_.filename, std::string("a.path"));
00104   pnh_.param("hz", hz_, 5.0);
00105   pnh_.param("filter_step", filter_step_, 0.0);
00106 
00107   pub_path_ = neonavigation_common::compat::advertise<nav_msgs::Path>(
00108       nh_, "path",
00109       pnh_, topic_path_, 2, true);
00110   pub_status_ = pnh_.advertise<trajectory_tracker_msgs::TrajectoryServerStatus>("status", 2);
00111   srv_change_path_ = neonavigation_common::compat::advertiseService(
00112       nh_, "change_path",
00113       pnh_, "ChangePath", &ServerNode::change, this);
00114   update_num_ = 0;
00115   max_markers_ = 0;
00116 }
00117 ServerNode::~ServerNode()
00118 {
00119 }
00120 
00121 bool ServerNode::loadFile()
00122 {
00123   std::ifstream ifs(req_path_.filename.c_str());
00124   if (ifs.good())
00125   {
00126     ifs.seekg(0, ifs.end);
00127     serial_size_ = ifs.tellg();
00128     ifs.seekg(0, ifs.beg);
00129     buffer_.reset(new uint8_t[serial_size_]);
00130     ifs.read(reinterpret_cast<char*>(buffer_.get()), serial_size_);
00131 
00132     return true;
00133   }
00134   return false;
00135 }
00136 
00137 void ServerNode::processFeedback(
00138     const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback)
00139 {
00140   int id = std::atoi(feedback->marker_name.c_str());
00141   switch (feedback->event_type)
00142   {
00143     case visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE:
00144       path_.poses[id].pose = feedback->pose;
00145       break;
00146     case visualization_msgs::InteractiveMarkerFeedback::MOUSE_UP:
00147       path_.header.stamp = ros::Time::now();
00148       pub_path_.publish(path_);
00149       break;
00150     case visualization_msgs::InteractiveMarkerFeedback::MENU_SELECT:
00151       switch (feedback->menu_entry_id)
00152       {
00153         case MENU_DELETE:
00154           path_.poses.erase(path_.poses.begin() + id);
00155           break;
00156         case MENU_ADD:
00157           path_.poses.insert(path_.poses.begin() + id, path_.poses[id]);
00158           break;
00159       }
00160       pub_path_.publish(path_);
00161       updateIM();
00162       break;
00163   }
00164 }
00165 
00166 void ServerNode::updateIM()
00167 {
00168   visualization_msgs::InteractiveMarkerUpdate viz;
00169   viz.type = viz.KEEP_ALIVE;
00170   viz.seq_num = update_num_++;
00171   viz.server_id = "Path";
00172   srv_im_fb_.clear();
00173   int i = 0;
00174   for (auto& p : path_.poses)
00175   {
00176     visualization_msgs::InteractiveMarker mark;
00177     visualization_msgs::Marker marker;
00178     visualization_msgs::InteractiveMarkerControl ctl;
00179     visualization_msgs::MenuEntry menu;
00180     mark.header = path_.header;
00181     mark.pose = p.pose;
00182     mark.scale = 1.0;
00183     std::stringstream ss;
00184     ss << i++;
00185     mark.name = ss.str();
00186     marker.ns = "Path";
00187     marker.id = i;
00188     marker.scale.x = 0.2;
00189     marker.scale.y = 0.05;
00190     marker.scale.z = 0.05;
00191     marker.color.r = 1;
00192     marker.color.g = 1;
00193     marker.color.b = 1;
00194     marker.color.a = 1;
00195     marker.type = marker.ARROW;
00196 
00197     ss << " ctl";
00198     ctl.orientation = tf2::toMsg(tf2::Quaternion(tf2::Vector3(0.0, 1.0, 0.0), M_PI / 2.0));
00199     ctl.interaction_mode = ctl.MOVE_ROTATE;
00200     ctl.orientation_mode = ctl.INHERIT;
00201     ctl.always_visible = true;
00202     ctl.markers.push_back(marker);
00203     ctl.name = ss.str();
00204     mark.controls.push_back(ctl);
00205 
00206     ss << " menu";
00207     ctl.interaction_mode = ctl.MENU;
00208     ctl.name = ss.str();
00209     marker.type = marker.SPHERE;
00210     marker.color.g = 0;
00211     marker.color.b = 0;
00212     marker.scale.x = 0.08;
00213     marker.scale.y = 0.08;
00214     marker.scale.z = 0.08;
00215     ctl.markers[0] = marker;
00216     mark.controls.push_back(ctl);
00217 
00218     menu.id = MENU_DELETE;
00219     menu.parent_id = 0;
00220     menu.title = "Delete";
00221     menu.command_type = menu.FEEDBACK;
00222     mark.menu_entries.push_back(menu);
00223     menu.id = MENU_ADD;
00224     menu.parent_id = 0;
00225     menu.title = "Add";
00226 
00227     mark.menu_entries.push_back(menu);
00228     srv_im_fb_.insert(mark, boost::bind(&ServerNode::processFeedback, this, _1));
00229     viz.markers.push_back(mark);
00230   }
00231   srv_im_fb_.applyChanges();
00232 }
00233 
00234 bool ServerNode::change(trajectory_tracker_msgs::ChangePath::Request& req,
00235                         trajectory_tracker_msgs::ChangePath::Response& res)
00236 {
00237   req_path_ = req;
00238   res.success = false;
00239 
00240   if (loadFile())
00241   {
00242     res.success = true;
00243     ros::serialization::IStream stream(buffer_.get(), serial_size_);
00244     ros::serialization::deserialize(stream, path_);
00245     path_.header.stamp = ros::Time::now();
00246     if (filter_step_ > 0)
00247     {
00248       std::cout << filter_step_ << std::endl;
00249       lpf_[0] = new trajectory_tracker::Filter(
00250           trajectory_tracker::Filter::FILTER_LPF, filter_step_, path_.poses[0].pose.position.x);
00251       lpf_[1] = new trajectory_tracker::Filter(
00252           trajectory_tracker::Filter::FILTER_LPF, filter_step_, path_.poses[0].pose.position.y);
00253 
00254       for (size_t i = 0; i < path_.poses.size(); i++)
00255       {
00256         path_.poses[i].pose.position.x = lpf_[0]->in(path_.poses[i].pose.position.x);
00257         path_.poses[i].pose.position.y = lpf_[1]->in(path_.poses[i].pose.position.y);
00258       }
00259 
00260       delete lpf_[0];
00261       delete lpf_[1];
00262     }
00263 
00264     pub_path_.publish(path_);
00265     updateIM();
00266   }
00267   else
00268   {
00269     serial_size_ = 0;
00270     req_path_.filename = "";
00271     path_.poses.clear();
00272     path_.header.frame_id = "map";
00273   }
00274   return true;
00275 }
00276 
00277 void ServerNode::spin()
00278 {
00279   ros::Rate loop_rate(hz_);
00280   trajectory_tracker_msgs::TrajectoryServerStatus status;
00281 
00282   while (ros::ok())
00283   {
00284     status.header = path_.header;
00285     status.filename = req_path_.filename;
00286     status.id = req_path_.id;
00287     pub_status_.publish(status);
00288     ros::spinOnce();
00289     loop_rate.sleep();
00290   }
00291 }
00292 
00293 int main(int argc, char** argv)
00294 {
00295   ros::init(argc, argv, "trajectory_server");
00296 
00297   ServerNode serv;
00298   serv.spin();
00299 
00300   return 0;
00301 }


trajectory_tracker
Author(s): Atsushi Watanabe
autogenerated on Sat Jun 22 2019 20:07:25