00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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 }