articulated_door_model.cpp
Go to the documentation of this file.
00001 
00017 #include <ros/ros.h>
00018 
00019 #include "tf/message_filter.h"
00020 #include "message_filters/subscriber.h"
00021 #include "tf/transform_listener.h"
00022 #include <tf/transform_broadcaster.h>
00023 
00024 #include "articulation_models/models/factory.h"
00025 
00026 #include "articulation_msgs/ModelMsg.h"
00027 #include "articulation_msgs/TrackMsg.h"
00028 #include "articulation_msgs/ParamMsg.h"
00029 #include "geometry_msgs/PoseStamped.h"
00030 
00031 #include <sstream>
00032 #include <cmath> //abs
00033 
00034 #include <visualization_msgs/Marker.h>
00035 
00036 using namespace articulation_models;
00037 using namespace articulation_msgs;
00038 
00039 //Global storage
00040 ModelMsg global_model_msg;
00041 
00042 //FUNCTIONS
00043 visualization_msgs::Marker visualize_door_model(GenericModelPtr model);
00044 void print(tf::Matrix3x3 m);
00045 void print(tf::Quaternion q);
00046 void print(tf::Vector3 v);
00047 std::string stream(tf::Vector3 v);
00048 std::string stream(tf::Quaternion v);
00049 std::string stream(tf::StampedTransform tf);
00050 void publish_door_coordinate_frame(GenericModelPtr generic_model);
00051 tf::Transform compute_aligned_door_frame(GenericModelPtr generic_model);
00052 
00053 void poseCallback(const tf::TransformListener* listener, 
00054                   std::string target_frame, 
00055                   geometry_msgs::PoseStamped::ConstPtr pose_stamped);
00056 
00057 int main(int argc, char** argv) 
00058 {
00059   ros::init(argc, argv, "articulated_door_model_fitting");
00060   ros::NodeHandle n;
00061   ros::Publisher model_pub = n.advertise<ModelMsg> ("door_model", 5);
00062   ros::Publisher model_visualization_pub = n.advertise<visualization_msgs::Marker> ("door_trajectory", 5);
00063 
00064   message_filters::Subscriber<geometry_msgs::PoseStamped> pose_sub;
00065   pose_sub.subscribe(n, "pose0", 10);
00066   std::string fixed_frame;
00067   ros::NodeHandle nh("~");
00068   nh.param<std::string>("fixed_frame", fixed_frame, "/odom_combined");
00069   ROS_DEBUG("Using %s as fixed frame", fixed_frame.c_str());
00070   tf::TransformListener tf_listener;
00071   tf::MessageFilter<geometry_msgs::PoseStamped> tf_filter(pose_sub, tf_listener, fixed_frame, 10);
00072   tf_filter.registerCallback(boost::bind(&poseCallback, &tf_listener, fixed_frame, _1));
00073 
00074   tf::TransformBroadcaster br;
00075   ros::Rate loop_rate(10);
00076 
00077   MultiModelFactory factory;
00078   global_model_msg.name = "rotational";
00079   ParamMsg sigma_param;
00080   sigma_param.name = "sigma_position";
00081   sigma_param.value = 0.02;
00082   sigma_param.type = ParamMsg::PRIOR;
00083   global_model_msg.params.push_back(sigma_param);
00084   unsigned long int prev_size = 0;
00085   GenericModelPtr model_instance;
00086   while (ros::ok()) {
00087     if(global_model_msg.track.pose.size() < 4)
00088       ROS_INFO_THROTTLE(2, "Not enough samples: %lu", global_model_msg.track.pose.size());
00089     else {
00090       //New observation? Refit model
00091       if(prev_size < global_model_msg.track.pose.size()) 
00092       {
00093         model_instance = factory.restoreModel(global_model_msg);
00094         model_instance->fitModel();
00095         model_instance->evaluateModel();
00096         ROS_INFO_STREAM_THROTTLE(5,"log LH of rotational model: " << model_instance->getLogLikelihood(false));
00097       }
00098 
00099       //Send model to the world
00100       ROS_FATAL_COND(model_instance.get() == NULL, "Used model_instance before restoring the model?"); //since prev_size is initialized with 0
00101       ModelMsg fitted_model_msg = model_instance->getModel();
00102       tf::Transform aligned_door_tf = compute_aligned_door_frame(model_instance);
00103       tf::StampedTransform door_stamped(aligned_door_tf, ros::Time::now(), fitted_model_msg.track.header.frame_id, "/door");
00104       br.sendTransform(door_stamped);
00105       ROS_INFO_STREAM_THROTTLE(1, "<node pkg=\"tf\" type=\"static_transform_publisher\" name=\"door_broadcaster\" args=\"" << stream(door_stamped)<<" 100\" />");
00106 
00107       if(model_pub.getNumSubscribers() > 0)
00108         model_pub.publish(fitted_model_msg);
00109       if(model_visualization_pub.getNumSubscribers() > 0)
00110         model_visualization_pub.publish(visualize_door_model(model_instance));
00111 
00112     }
00113     ros::spinOnce();
00114     loop_rate.sleep();
00115   }
00116 }
00117 
00118 void poseCallback(const tf::TransformListener* listener, 
00119                   std::string target_frame, 
00120                   geometry_msgs::PoseStamped::ConstPtr pose_stamped)
00121 {
00122     try 
00123     {
00124       geometry_msgs::PoseStamped pose_in_fixed_frame;
00125       listener->transformPose(target_frame, *pose_stamped, pose_in_fixed_frame);
00126       
00127       //ROS_INFO_STREAM_ONCE("Storing the first pose:\n " << pose_in_fixed_frame);
00128       global_model_msg.track.pose.push_back(pose_in_fixed_frame.pose);
00129       global_model_msg.track.header = pose_in_fixed_frame.header; //update header, it's used elsewhere
00130       //ROS_INFO_STREAM(pose_in_fixed_frame);
00131       ROS_INFO("Recorded %lu. pose", global_model_msg.track.pose.size());
00132     }
00133     catch (tf::TransformException &ex) 
00134     {
00135       ROS_ERROR("Failure %s\n", ex.what()); //Print exception which was caught
00136     }
00137 }
00138 
00139 
00140 visualization_msgs::Marker visualize_door_model(GenericModelPtr generic_model)
00141 {
00142   ModelMsg model = generic_model->getModel();
00143   visualization_msgs::Marker trajectory;
00144   trajectory.header = model.track.header;
00145   trajectory.id = 1;
00146   trajectory.type = visualization_msgs::Marker::POINTS;
00147   trajectory.action = visualization_msgs::Marker::ADD;
00148   trajectory.pose.orientation.w = 1.0;
00149   trajectory.scale.x = 0.02;
00150   trajectory.scale.y = 0.02;
00151   trajectory.scale.z = 0.02;
00152   trajectory.color.a = 0.5;
00153   trajectory.color.r = 0.5;
00154   trajectory.color.g = 0.5;
00155 
00156   for(unsigned int i = 0; i < model.track.pose.size(); i++){
00157     trajectory.points.push_back(model.track.pose[i].position);
00158   }
00159   geometry_msgs::Point center;
00160   center.x = generic_model->getParam("rot_center.x");
00161   center.y = generic_model->getParam("rot_center.y");
00162   center.z = generic_model->getParam("rot_center.z");
00163   trajectory.points.push_back(center);
00164   return trajectory;
00165 }
00166 
00167 
00168 tf::Transform compute_aligned_door_frame(GenericModelPtr generic_model) 
00169 {
00170   //static tf::TransformBroadcaster br;
00171   TrackMsg tm = global_model_msg.track;
00172   //GET DOOR MODEL PARAMETER
00173   double q_min = generic_model->getParam("q_min[0]");
00174   double q_max = generic_model->getParam("q_max[0]");
00175   double rot_radius = generic_model->getParam("rot_radius");
00176   tf::Vector3 rot_center(generic_model->getParam("rot_center.x"),
00177                          generic_model->getParam("rot_center.y"),
00178                          generic_model->getParam("rot_center.z"));
00179         
00180   tf::Quaternion rot_axis(generic_model->getParam("rot_axis.x"),
00181                           generic_model->getParam("rot_axis.y"),
00182                           generic_model->getParam("rot_axis.z"),
00183                           generic_model->getParam("rot_axis.w"));
00184   
00185   tf::Quaternion rot_orientation(generic_model->getParam("rot_orientation.x"),
00186                                  generic_model->getParam("rot_orientation.y"),
00187                                  generic_model->getParam("rot_orientation.z"),
00188                                  generic_model->getParam("rot_orientation.w"));
00189 
00190   //COMPUTE POSES FOR AXIS FRAME, Q_MIN, Q_MAX
00191   tf::Transform center(rot_axis,rot_center);
00192   tf::Transform rotZ_min(tf::Quaternion(tf::Vector3(0, 0, 1), -q_min), tf::Vector3(0, 0, 0));
00193   tf::Transform rotZ_max(tf::Quaternion(tf::Vector3(0, 0, 1), -q_max), tf::Vector3(0, 0, 0));
00194   tf::Transform r(tf::Quaternion(0,0,0,1), tf::Vector3(rot_radius, 0, 0));
00195   tf::Transform offset(rot_orientation, tf::Vector3(0, 0, 0));
00196   tf::Transform qmin_pose = rotZ_min * r * offset;
00197   tf::Transform qmax_pose = rotZ_max * r * offset;
00198 
00199 /*
00200   br.sendTransform(tf::StampedTransform(center, tm.header.stamp, tm.header.frame_id, "a_door"));
00201   br.sendTransform(tf::StampedTransform(qmin_pose, tm.header.stamp, "a_door", "qmin"));
00202   br.sendTransform(tf::StampedTransform(qmax_pose, tm.header.stamp, "a_door", "qmax"));
00203 
00204   tf::Transform closed_door_cb(tf::Quaternion(0,0,0,1), tf::Vector3(1,0,0));
00205   br.sendTransform(tf::StampedTransform(closed_door_cb, 
00206                                         tm.header.stamp, 
00207                                         "aligned_door", 
00208                                         "closed"));
00209 
00210   tf::Transform open_door_cb(tf::Quaternion(0,0,0,1), tf::Vector3(0,1,0));
00211   br.sendTransform(tf::StampedTransform(open_door_cb, 
00212                                         tm.header.stamp, 
00213                                         "aligned_door", 
00214                                         "open"));
00215                                         */
00216 
00217   //COMPUTE POSE FOR FIRST POSE RECORDED
00218   tf::Pose q1st_pose_in_fixed_frame;
00219   tf::poseMsgToTF(tm.pose[0], q1st_pose_in_fixed_frame);
00220   tf::Transform q1st_pose = center.inverse() * q1st_pose_in_fixed_frame;
00221   //br.sendTransform(tf::StampedTransform(q1st_pose, tm.header.stamp, "door", "q1st"));
00222 
00223   tf::Vector3 q1st_position = q1st_pose.getOrigin();
00224   tf::Vector3 qmin_position = qmin_pose.getOrigin();
00225   tf::Vector3 qmax_position = qmax_pose.getOrigin();
00226   tf::Vector3 closed_door_handle_in_ff, open_door_handle_in_ff;
00227   //FIND OUT WHETHER Q_MIN OR Q_MAX ARE NEARER TO Q_START
00228   //Assuming qmax_ and qmin_position are of same (radius) length
00229   ROS_ERROR_COND((abs(qmin_position.length2() - qmax_position.length2()) > 0.001), "Reprojected poses should have same length");
00230   if(q1st_position.dot(qmax_position) > q1st_position.dot(qmin_position))
00231   {
00232     //First pose recorded is more similar to the pose at q_max
00233     closed_door_handle_in_ff = center*qmax_position;
00234     open_door_handle_in_ff   = center*qmin_position;
00235   } else {
00236     closed_door_handle_in_ff = center*qmin_position;
00237     open_door_handle_in_ff   = center*qmax_position;
00238   }
00239   /*DEBUG
00240   tf::Transform cdhiff(tf::Quaternion(0,0,0,1), closed_door_handle_in_ff);
00241   br.sendTransform(tf::StampedTransform(cdhiff, tm.header.stamp, tm.header.frame_id, "a_closed_door_handle"));
00242   tf::Transform odhiff(tf::Quaternion(0,0,0,1), open_door_handle_in_ff);
00243   br.sendTransform(tf::StampedTransform(odhiff, tm.header.stamp, tm.header.frame_id, "a_open_door_handle"));
00244   //END DEBUG*/
00245 
00246   tf::Vector3 closed_axis = closed_door_handle_in_ff - center.getOrigin();
00247   tf::Vector3 open_axis = open_door_handle_in_ff - center.getOrigin();
00248   /*DEBUG
00249   tf::Transform a(tf::Quaternion(0,0,0,1), open_axis);
00250   br.sendTransform(tf::StampedTransform(a, tm.header.stamp, tm.header.frame_id, "a_open_axis_in_ff"));
00251   tf::Transform b(tf::Quaternion(0,0,0,1), closed_axis);
00252   br.sendTransform(tf::StampedTransform(b, tm.header.stamp, tm.header.frame_id, "a_closed_axis_in_ff"));
00253   ROS_WARN("Line: %d", __LINE__);
00254   //END DEBUG*/
00255 
00256   tf::Vector3 rotation_axis = closed_axis.cross(open_axis);
00257   open_axis = rotation_axis.cross(closed_axis);
00258   closed_axis = closed_axis.normalize();
00259   print(closed_axis);
00260   open_axis = open_axis.normalize();
00261   print(open_axis);
00262   rotation_axis = rotation_axis.normalize();
00263   print(rotation_axis);
00264 
00265   tf::Matrix3x3 basis(closed_axis.x(), open_axis.x(), rotation_axis.x(),
00266                       closed_axis.y(), open_axis.y(), rotation_axis.y(),
00267                       closed_axis.z(), open_axis.z(), rotation_axis.z());
00268   print(basis);
00269   tf::Quaternion qbasis; basis.getRotation(qbasis);
00270   print(qbasis);
00271   return tf::Transform(basis, center.getOrigin());
00272   /*DEBUG
00273   tf::Transform aligned_cdhiff(tf::Quaternion(0,0,0,1), tf::Vector3(1,0,0));
00274   br.sendTransform(tf::StampedTransform(aligned_cdhiff, tm.header.stamp, "aligned_door", "aligned_closed_door_handle"));
00275   ROS_WARN("Line: %d", __LINE__);
00276   tf::Transform aligned_odhiff(tf::Quaternion(0,0,0,1), tf::Vector3(0,1,0));
00277   br.sendTransform(tf::StampedTransform(aligned_odhiff, tm.header.stamp, "aligned_door", "aligned_open_door_handle"));
00278   ROS_WARN("Line: %d", __LINE__);
00279   //END DEBUG*/
00280 }
00281 
00282 void print(tf::Matrix3x3 m){
00283   ROS_DEBUG("RotM:\n%.5f, %.5f, %.5f\n%.5f, %.5f, %.5f\n%.5f, %.5f, %.5f\n", 
00284             m[0][0], m[0][1], m[0][2], 
00285             m[1][0], m[1][1], m[1][2], 
00286             m[2][0], m[2][1], m[2][2]);
00287 }
00288 void print(tf::Quaternion q){
00289   ROS_DEBUG("Quat: %.4f, %.4f, %.4f, %.4f", q.getX(), q.getY(), q.getZ(), q.w());
00290 }
00291 void print(tf::Vector3 v){
00292   ROS_DEBUG("Vec: %.4f, %.4f, %.4f, %.4f", v.getX(), v.getY(), v.getZ(), v.w());
00293 }
00294 std::string stream(tf::Vector3 v){
00295   std::stringstream ss;
00296   ss << v.x() << " "  << v.y() << " "  << v.z(); 
00297   return ss.str();
00298 }
00299 std::string stream(tf::Quaternion v){
00300   std::stringstream ss;
00301   ss << v.x() << " "  << v.y() << " "  << v.z()<< " "  << v.w();
00302   return ss.str();
00303 }
00304 std::string stream(tf::StampedTransform tf){
00305   std::stringstream ss;
00306   ss << stream(tf.getOrigin()) << " " <<  stream(tf.getRotation()) << " " << tf.frame_id_ << " " << tf.child_frame_id_;
00307   return ss.str();
00308 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


door_perception
Author(s): Felix Endres
autogenerated on Wed Dec 26 2012 16:03:53