00001 #include <Eigen/Eigen>
00002 #include <boost/format.hpp>
00003 #include <boost/make_shared.hpp>
00004 #include <boost/foreach.hpp>
00005
00006 #include <ros/ros.h>
00007 #include <rosbag/bag.h>
00008 #include <rosbag/view.h>
00009 #include <rosbag/message_instance.h>
00010 #include <interactive_markers/interactive_marker_server.h>
00011 #include <tf/transform_broadcaster.h>
00012 #include <geometry_msgs/Pose.h>
00013 #include <tf_conversions/tf_eigen.h>
00014
00015 #include <hrl_ellipsoidal_control/EllipsoidParams.h>
00016 #include <hrl_ellipsoidal_control/LoadEllipsoidParams.h>
00017
00018
00019 using namespace std;
00020
00021 class InteractiveEllipse
00022 {
00023 private:
00024 interactive_markers::InteractiveMarkerServer im_server_;
00025 tf::TransformBroadcaster tf_broad_;
00026 ros::Publisher params_pub;
00027 ros::Subscriber params_cmd;
00028 std::string parent_frame_, child_frame_;
00029 double rate_;
00030 ros::Timer tf_timer_;
00031 geometry_msgs::Pose marker_pose_;
00032 double z_axis_, y_axis_, old_z_axis_, old_y_axis_;
00033 geometry_msgs::Transform old_marker_tf_;
00034 geometry_msgs::TransformStamped tf_msg_;
00035 hrl_ellipsoidal_control::EllipsoidParams cur_e_params_;
00036 ros::ServiceServer load_param_srv_;
00037 bool is_oblate;
00038 public:
00039 InteractiveEllipse(const std::string& parent_frame, const std::string& child_frame, double rate = 100);
00040 void processTFControl(const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback);
00041 void processEllipseControlY(const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback);
00042 void processEllipseControlZ(const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback);
00043 void addTFMarker(const geometry_msgs::Transform& mkr_tf);
00044 void addEllipseMarker();
00045 void publishTF(const ros::TimerEvent& event);
00046 void loadEllipsoidParams(const hrl_ellipsoidal_control::EllipsoidParams& e_params);
00047 void bagTF(const string& bag_name);
00048 bool loadParamCB(hrl_ellipsoidal_control::LoadEllipsoidParams::Request& req,
00049 hrl_ellipsoidal_control::LoadEllipsoidParams::Response& resp);
00050 };
00051
00052 InteractiveEllipse::InteractiveEllipse(const std::string& parent_frame,
00053 const std::string& child_frame, double rate) :
00054 im_server_("transform_marker"),
00055 parent_frame_(parent_frame),
00056 child_frame_(child_frame),
00057 rate_(rate), z_axis_(0.0), y_axis_(0.0)
00058 {
00059 ros::NodeHandle nh;
00060 marker_pose_.orientation.w = 1;
00061 params_pub = nh.advertise<hrl_ellipsoidal_control::EllipsoidParams>("/ellipsoid_params", 1);
00062 params_cmd = nh.subscribe("/ell_params_cmd", 1, &InteractiveEllipse::loadEllipsoidParams, this);
00063 load_param_srv_ = nh.advertiseService("/load_ellipsoid_params",
00064 &InteractiveEllipse::loadParamCB, this);
00065 }
00066
00067 void InteractiveEllipse::addTFMarker(const geometry_msgs::Transform& mkr_tf)
00068 {
00069 ros::NodeHandle nh;
00070 visualization_msgs::InteractiveMarker tf_marker;
00071 tf_marker.header.frame_id = parent_frame_;
00072 tf_marker.pose.position.x = mkr_tf.translation.x;
00073 tf_marker.pose.position.y = mkr_tf.translation.y;
00074 tf_marker.pose.position.z = mkr_tf.translation.z;
00075 tf_marker.pose.orientation.x = mkr_tf.rotation.x;
00076 tf_marker.pose.orientation.y = mkr_tf.rotation.y;
00077 tf_marker.pose.orientation.z = mkr_tf.rotation.z;
00078 tf_marker.pose.orientation.w = mkr_tf.rotation.w;
00079 tf_marker.name = "tf_marker";
00080 tf_marker.scale = 0.2;
00081 visualization_msgs::InteractiveMarkerControl tf_control;
00082 tf_control.orientation_mode = visualization_msgs::InteractiveMarkerControl::INHERIT;
00083
00084 tf_control.orientation.x = 1; tf_control.orientation.y = 0;
00085 tf_control.orientation.z = 0; tf_control.orientation.w = 1;
00086 tf_control.name = "rotate_x";
00087 tf_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS;
00088 tf_marker.controls.push_back(tf_control);
00089 tf_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
00090 tf_marker.controls.push_back(tf_control);
00091
00092 tf_control.orientation.x = 0; tf_control.orientation.y = 1;
00093 tf_control.orientation.z = 0; tf_control.orientation.w = 1;
00094 tf_control.name = "rotate_y";
00095 tf_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS;
00096 tf_marker.controls.push_back(tf_control);
00097 tf_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
00098 tf_marker.controls.push_back(tf_control);
00099
00100 tf_control.orientation.x = 0; tf_control.orientation.y = 0;
00101 tf_control.orientation.z = 1; tf_control.orientation.w = 1;
00102 tf_control.name = "rotate_z";
00103 tf_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS;
00104 tf_marker.controls.push_back(tf_control);
00105 tf_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
00106 tf_marker.controls.push_back(tf_control);
00107 im_server_.insert(tf_marker, boost::bind(&InteractiveEllipse::processTFControl, this, _1));
00108 im_server_.applyChanges();
00109 tf_timer_ = nh.createTimer(ros::Duration(1.0 / rate_), &InteractiveEllipse::publishTF, this);
00110 }
00111
00112 void InteractiveEllipse::processTFControl(
00113 const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback)
00114 {
00115 ROS_INFO_STREAM(tf_msg_.transform.translation.x << " " <<
00116 tf_msg_.transform.translation.y << " " <<
00117 tf_msg_.transform.translation.z << " " <<
00118 tf_msg_.transform.rotation.x << " " <<
00119 tf_msg_.transform.rotation.y << " " <<
00120 tf_msg_.transform.rotation.z << " " <<
00121 tf_msg_.transform.rotation.w);
00122 marker_pose_ = feedback->pose;
00123 }
00124
00125 void InteractiveEllipse::addEllipseMarker()
00126 {
00127 visualization_msgs::InteractiveMarker tf_marker;
00128 tf_marker.header.frame_id = child_frame_;
00129 tf_marker.name = "ellipse_marker_y";
00130 tf_marker.scale = 0.4;
00131 visualization_msgs::InteractiveMarkerControl tf_control;
00132 tf_control.orientation_mode = visualization_msgs::InteractiveMarkerControl::INHERIT;
00133
00134 tf_control.orientation.x = 0; tf_control.orientation.y = 1;
00135 tf_control.orientation.z = 0; tf_control.orientation.w = 1;
00136 tf_control.name = "shift_y";
00137 tf_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
00138 tf_marker.controls.push_back(tf_control);
00139 im_server_.insert(tf_marker, boost::bind(&InteractiveEllipse::processEllipseControlY, this, _1));
00140 tf_marker.controls.clear();
00141
00142 tf_marker.name = "ellipse_marker_z";
00143 tf_control.orientation.x = 0; tf_control.orientation.y = 0;
00144 tf_control.orientation.z = 1; tf_control.orientation.w = 1;
00145 tf_control.name = "shift_z";
00146 tf_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::MOVE_AXIS;
00147 tf_marker.controls.push_back(tf_control);
00148 im_server_.insert(tf_marker, boost::bind(&InteractiveEllipse::processEllipseControlZ, this, _1));
00149 im_server_.applyChanges();
00150 }
00151
00152 void InteractiveEllipse::processEllipseControlY(
00153 const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback)
00154 {
00155 z_axis_ = feedback->pose.position.z;
00156 }
00157
00158 void InteractiveEllipse::processEllipseControlZ(
00159 const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback)
00160 {
00161 y_axis_ = feedback->pose.position.y;
00162 }
00163
00164 void InteractiveEllipse::publishTF(const ros::TimerEvent& event)
00165 {
00166 tf_msg_.header.stamp = ros::Time::now();
00167 tf_msg_.header.frame_id = parent_frame_;
00168 tf_msg_.child_frame_id = child_frame_;
00169 tf_msg_.transform.translation.x = marker_pose_.position.x;
00170 tf_msg_.transform.translation.y = marker_pose_.position.y;
00171 tf_msg_.transform.translation.z = marker_pose_.position.z;
00172 tf_msg_.transform.rotation.x = marker_pose_.orientation.x;
00173 tf_msg_.transform.rotation.y = marker_pose_.orientation.y;
00174 tf_msg_.transform.rotation.z = marker_pose_.orientation.z;
00175 tf_msg_.transform.rotation.w = marker_pose_.orientation.w;
00176 tf::Transform cur_tf, old_tf;
00177 tf::transformMsgToTF(tf_msg_.transform, cur_tf);
00178 tf::transformMsgToTF(old_marker_tf_, old_tf);
00179 Eigen::Affine3d cur_tf_eig, old_tf_eig;
00180 tf::TransformTFToEigen(cur_tf, cur_tf_eig);
00181 tf::TransformTFToEigen(old_tf, old_tf_eig);
00182 cur_tf_eig = cur_tf_eig;
00183 tf::TransformEigenToTF(cur_tf_eig, cur_tf);
00184 tf::transformTFToMsg(cur_tf, tf_msg_.transform);
00185 tf_broad_.sendTransform(tf_msg_);
00186 hrl_ellipsoidal_control::EllipsoidParams e_params;
00187 e_params.e_frame = tf_msg_;
00188 e_params.height = y_axis_ + old_y_axis_;
00189 e_params.E = z_axis_ + old_z_axis_;
00190 e_params.is_oblate = is_oblate;
00191 params_pub.publish(e_params);
00192 cur_e_params_ = e_params;
00193 }
00194
00195 void InteractiveEllipse::loadEllipsoidParams(const hrl_ellipsoidal_control::EllipsoidParams& e_params)
00196 {
00197 geometry_msgs::Pose pose, empty_pose;
00198 pose.position.x = e_params.e_frame.transform.translation.x;
00199 pose.position.y = e_params.e_frame.transform.translation.y;
00200 pose.position.z = e_params.e_frame.transform.translation.z;
00201 pose.orientation.x = e_params.e_frame.transform.rotation.x;
00202 pose.orientation.y = e_params.e_frame.transform.rotation.y;
00203 pose.orientation.z = e_params.e_frame.transform.rotation.z;
00204 pose.orientation.w = e_params.e_frame.transform.rotation.w;
00205 marker_pose_ = pose;
00206 empty_pose.orientation.w = 1;
00207 im_server_.setPose("tf_marker", pose);
00208 im_server_.setPose("ellipse_marker_y", empty_pose);
00209 im_server_.setPose("ellipse_marker_z", empty_pose);
00210 im_server_.applyChanges();
00211
00212 old_y_axis_ = e_params.height;
00213 old_z_axis_ = e_params.E;
00214 is_oblate = e_params.is_oblate;
00215 }
00216
00217 void InteractiveEllipse::bagTF(const string& bag_name)
00218 {
00219 rosbag::Bag bag;
00220 bag.open(bag_name, rosbag::bagmode::Write);
00221 bag.write("/ellipsoid_params", ros::Time::now(), cur_e_params_);
00222 bag.close();
00223 }
00224
00225 bool InteractiveEllipse::loadParamCB(hrl_ellipsoidal_control::LoadEllipsoidParams::Request& req,
00226 hrl_ellipsoidal_control::LoadEllipsoidParams::Response& resp)
00227 {
00228 loadEllipsoidParams(req.params);
00229 return true;
00230 }
00231
00232 int main(int argc, char **argv)
00233 {
00234 ros::init(argc, argv, "interative_ellipse");
00235 if(argc < 3 || argc > 7) {
00236 printf("Usage: interative_ellipse parent_frame child_frame rate [inital_params] [save_params] [use_ellipsoid_markers]\n");
00237 return 1;
00238 }
00239 if(argc >= 4) {
00240 InteractiveEllipse itf(argv[1], argv[2], atof(argv[3]));
00241 geometry_msgs::Transform mkr_tf;
00242 mkr_tf.rotation.w = 1;
00243 itf.addTFMarker(mkr_tf);
00244 if(!(argc >= 7 && atoi(argv[6])))
00245 itf.addEllipseMarker();
00246 if(argc >= 5) {
00247
00248 hrl_ellipsoidal_control::EllipsoidParams::Ptr e_params;
00249 rosbag::Bag bag;
00250 bag.open(argv[4], rosbag::bagmode::Read);
00251 rosbag::View view(bag, rosbag::TopicQuery("/ellipsoid_params"));
00252 BOOST_FOREACH(rosbag::MessageInstance const msg, view) {
00253 e_params = msg.instantiate< hrl_ellipsoidal_control::EllipsoidParams >();
00254 break;
00255 }
00256 bag.close();
00257 itf.loadEllipsoidParams(*e_params);
00258 }
00259 ros::spin();
00260 if(argc >= 6)
00261 itf.bagTF(argv[5]);
00262 }
00263
00264 return 0;
00265 }