TestStability.cpp
Go to the documentation of this file.
00001 /*
00002  * hrl_kinematics - a kinematics library for humanoid robots based on KDL
00003  *
00004  * Copyright 2011-2012 Armin Hornung, University of Freiburg
00005  * License: BSD
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  *
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the University of Freiburg nor the names of its
00016  *       contributors may be used to endorse or promote products derived from
00017  *       this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00023  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00024  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00025  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00026  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00027  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00028  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029  * POSSIBILITY OF SUCH DAMAGE.
00030  */
00031 
00032 #include "hrl_kinematics/TestStability.h"
00033 #include <pcl/surface/convex_hull.h>
00034 #include <pcl/point_types.h>
00035 
00036 using robot_state_publisher::SegmentPair;
00037 using boost::shared_ptr;
00038 
00039 namespace hrl_kinematics {
00040 
00041 TestStability::TestStability(std::string rfoot_mesh_link_name, 
00042                              std::string root_link_name, std::string rfoot_link_name, std::string lfoot_link_name, 
00043                              const boost::shared_ptr<const urdf::ModelInterface>& urdf_model,
00044                              double foot_polygon_scale)
00045   : Kinematics(root_link_name, rfoot_link_name, lfoot_link_name, urdf_model)
00046   , rfoot_mesh_link_name_(rfoot_mesh_link_name)
00047 {
00048   //Build support polygon
00049   initFootPolygon(foot_polygon_scale);
00050 }
00051 
00052 TestStability::~TestStability() {
00053 
00054 }
00055 
00056 bool TestStability::isPoseStable(const std::map<std::string, double>& joint_positions, FootSupport support_mode){
00057   tf::Vector3 normal(0.0, 0.0, 1.0);
00058   return isPoseStable(joint_positions, support_mode, normal);
00059 }
00060 
00061 bool TestStability::isPoseStable(const std::map<std::string, double>& joint_positions,
00062                                  FootSupport support_mode, const tf::Vector3& normal_vector)
00063 {
00064 
00065   tf::Vector3 upright_vector(0.0, 0.0, 1.0);
00066   double angle = acos(upright_vector.dot(normal_vector.normalized()));
00067 
00068   tf::Quaternion q;
00069   if (std::abs(angle) < FLT_EPSILON)
00070     q=tf::createIdentityQuaternion();
00071   else{
00072     tf::Vector3 axis = upright_vector.cross(normal_vector).normalized();
00073     q = tf::Quaternion(axis, angle);
00074   }
00075   tf::Transform rotate_plane(q, tf::Vector3(0,0,0));
00076 
00077   tf::Point com; // center of mass in root frame
00078   double m;
00079 
00080   // transforms from root to left and right foot:
00081   tf::Transform tf_right_foot, tf_left_foot;
00082   computeCOM(joint_positions, com, m, tf_right_foot, tf_left_foot);
00083 
00084   tf::Transform tf_to_support;
00085 
00086   if (support_mode == SUPPORT_SINGLE_LEFT){
00087     support_polygon_ = foot_support_polygon_left_;
00088     tf_to_support_ = tf_left_foot;
00089   } else { // RIGHT or DOUBLE
00090     support_polygon_ = foot_support_polygon_right_;
00091     tf_to_support_ = tf_right_foot;
00092 
00093   }
00094 
00095   // rotate and project down
00096   for (unsigned i = 0; i < support_polygon_.size(); ++i){
00097     support_polygon_[i] = rotate_plane * support_polygon_[i];
00098   }
00099 
00100   // append left if double support:
00101   if (support_mode == SUPPORT_DOUBLE){
00102     tf::Transform tf_right_to_left = tf_right_foot.inverseTimes(tf_left_foot);
00103     for (unsigned i = 0; i < foot_support_polygon_left_.size(); ++i){
00104       support_polygon_.push_back(rotate_plane * tf_right_to_left * foot_support_polygon_left_[i]);
00105     }
00106     support_polygon_ = convexHull(support_polygon_);
00107   }
00108   if (support_polygon_.size() <= 2)
00109     return false;
00110 
00111   // projected com in support frame, rotated around support plane:
00112   p_com_ = rotate_plane * tf_to_support_.inverse() * com;
00113   p_com_.setZ(0.0);
00114 
00115   return pointInConvexHull(p_com_, support_polygon_);
00116 }
00117 
00118 geometry_msgs::PolygonStamped TestStability::getSupportPolygon() const{
00119   geometry_msgs::PolygonStamped footprint_poly;
00120   footprint_poly.header.frame_id = root_link_name_;
00121   footprint_poly.header.stamp = ros::Time::now();
00122   for (unsigned i=0; i < support_polygon_.size(); ++i){
00123     geometry_msgs::Point32 p;
00124     tf::Point tfP = tf_to_support_ * support_polygon_[i];
00125     p.x = tfP.x();
00126     p.y = tfP.y();
00127     p.z = tfP.z();
00128     footprint_poly.polygon.points.push_back(p);
00129   }
00130 
00131   return footprint_poly;
00132 }
00133 
00134 visualization_msgs::Marker TestStability::getCOMMarker() const{
00135 
00136   visualization_msgs::Marker com_marker;
00137   com_marker.header.stamp = ros::Time::now();
00138   com_marker.header.frame_id = root_link_name_;
00139   com_marker.action = visualization_msgs::Marker::ADD;
00140   com_marker.type = visualization_msgs::Marker::SPHERE;
00141   tf::pointTFToMsg(tf_to_support_ * p_com_, com_marker.pose.position);
00142   tf::quaternionTFToMsg(tf_to_support_.getRotation(), com_marker.pose.orientation);
00143   com_marker.scale.x = 0.03;
00144   com_marker.scale.y = 0.03;
00145   com_marker.scale.z = 0.005;
00146   com_marker.color.a = 1.0;
00147   com_marker.color.g = 1.0;
00148   com_marker.color.r = 0.0;
00149 
00150 
00151   return com_marker;
00152 }
00153 
00154 std::vector<tf::Point> TestStability::convexHull(const std::vector<tf::Point>& points) const{
00155   std::vector<tf::Point> hull;
00156 
00157   pcl::PointCloud<pcl::PointXYZ>::Ptr pcl_points(new pcl::PointCloud<pcl::PointXYZ>);
00158   pcl::PointCloud<pcl::PointXYZ> chull_points;
00159   pcl::ConvexHull<pcl::PointXYZ> chull;
00160 
00161   if (points.empty()){
00162     ROS_ERROR("convexHull on empty set of points!");
00163     return hull;
00164   }
00165 
00166   for (unsigned i = 0; i < points.size(); ++i){
00167     pcl_points->points.push_back(pcl::PointXYZ(points[i].x(), points[i].y(), 0.0));
00168   }
00169 
00170   chull.setDimension(2);
00171   chull.setInputCloud(pcl_points);
00172   std::vector<pcl::Vertices> polygons;
00173   chull.reconstruct(chull_points, polygons);
00174 
00175   if (polygons.size() == 0){
00176     ROS_ERROR("Convex hull polygons are empty");
00177     return hull;
00178   } else if (polygons.size() > 1){
00179     ROS_WARN("Convex hull polygons are larger than 1");
00180   }
00181 
00182   for (unsigned i = 0; i < polygons[0].vertices.size(); ++i){
00183     int idx = polygons[0].vertices[i];
00184     tf::Point p(chull_points.points[idx].x,
00185                 chull_points.points[idx].y,
00186                 chull_points.points[idx].z);
00187     hull.push_back(p);
00188   }
00189 
00190   return hull;
00191 }
00192 
00193 bool TestStability::pointInConvexHull(const tf::Point& point, const std::vector<tf::Point>& polygon) const{
00194   assert(polygon.size() >=3);
00195   int positive_direction = 0;
00196   for (unsigned i = 0; i < polygon.size(); ++i){
00197     int i2 = (i+1)% (polygon.size());
00198     double dx = polygon[i2].getX() - polygon[i].getX();
00199     double dy = polygon[i2].getY() - polygon[i].getY();
00200     if (dx == 0.0 && dy == 0.0){
00201       ROS_DEBUG("Skipping polygon connection [%d-%d] (identical points)", i, i2);
00202       continue;
00203     }
00204     double line_test = (point.y() - polygon[i].getY())*dx - (point.x() - polygon[i].getX())*dy;
00205     if (i == 0)
00206       positive_direction = (line_test > 0.0);
00207     ROS_DEBUG("Line test [%d-%d] from (%f,%f) to (%f,%f): %f", i, i2, polygon[i].getX(), polygon[i].getY(),
00208               polygon[i2].getX(), polygon[i2].getY(), line_test);
00209     if ((line_test > 0.0) != positive_direction)
00210       return false;
00211 
00212   }
00213 
00214   return true;
00215 }
00216 
00217 void TestStability::initFootPolygon(double foot_polygon_scale){
00218   
00219   //Init convex hull scaling factor
00220   foot_polygon_scale_ = foot_polygon_scale;
00221 
00222   // TODO: param?
00223   if (!loadFootPolygon()){
00224     ROS_WARN("Could not load foot mesh, using default points");
00225 
00226     foot_support_polygon_right_.push_back(tf::Point(0.07f, 0.023f, 0.0));
00227     foot_support_polygon_right_.push_back(tf::Point(0.07f, -0.03f, 0.0));
00228     foot_support_polygon_right_.push_back(tf::Point(-0.03f, -0.03f, 0.0));
00229     foot_support_polygon_right_.push_back(tf::Point(-0.03f, 0.02, 0.0));
00230   }
00231 
00232   // mirror for left:
00233   foot_support_polygon_left_ = foot_support_polygon_right_;
00234   for (unsigned i=0; i < foot_support_polygon_left_.size(); ++i){
00235     foot_support_polygon_left_[i] *= tf::Point(1.0, -1.0, 1.0);
00236   }
00237 
00238   // restore order of polygon
00239   foot_support_polygon_left_ = convexHull(foot_support_polygon_left_);
00240 }
00241 
00242 
00243 bool TestStability::loadFootPolygon(){
00244   boost::shared_ptr<const urdf::Link> foot_link =  urdf_model_->getLink(rfoot_mesh_link_name_);
00245   assert(foot_link);
00246   boost::shared_ptr<const urdf::Geometry> geom;
00247   urdf::Pose geom_pose;
00248   if (foot_link->collision && foot_link->collision->geometry){
00249     geom = foot_link->collision->geometry;
00250     geom_pose = foot_link->collision->origin;
00251   } else if (foot_link->visual && foot_link->visual->geometry){
00252     geom = foot_link->visual->geometry;
00253     geom_pose = foot_link->visual->origin;
00254   } else{
00255     ROS_ERROR_STREAM("No geometry for link "<< rfoot_mesh_link_name_ << " available");
00256     return false;
00257   }
00258 
00259   tf::Pose geom_origin = tf::Pose(tf::Transform(tf::Quaternion(geom_pose.rotation.x, geom_pose.rotation.y, geom_pose.rotation.z, geom_pose.rotation.w),
00260                                               tf::Vector3(geom_pose.position.x, geom_pose.position.y, geom_pose.position.z)));
00261 
00262   if (geom->type != urdf::Geometry::MESH){
00263     ROS_ERROR_STREAM("Geometry for link "<< rfoot_mesh_link_name_ << " is not a mesh");
00264     return false;
00265   } else {
00266     shared_ptr<const urdf::Mesh> mesh = boost::dynamic_pointer_cast<const urdf::Mesh>(geom);
00267 
00268     const Eigen::Vector3d scale(mesh->scale.x, mesh->scale.y, mesh->scale.z);
00269     shapes::Mesh* shape_mesh = shapes::createMeshFromResource(mesh->filename, scale);
00270     size_t vertex_count = shape_mesh->vertex_count;
00271 
00272     //Vector storing the original foot points
00273     std::vector<tf::Point> foot_SP_right;
00274     for (unsigned int i = 0 ; i < vertex_count ; ++i)
00275     {
00276       unsigned int i3 = i * 3;
00277 
00278       tf::Point p(shape_mesh->vertices[i3], shape_mesh->vertices[i3 + 1], shape_mesh->vertices[i3 + 2]); // proj down (z=0)
00279       tf::Point projectedP = geom_origin*p;
00280       projectedP.setZ(0.0);
00281       // transform into local foot frame:
00282       //foot_support_polygon_right_.push_back(projectedP);
00283       foot_SP_right.push_back(projectedP);
00284     }
00285 
00286     //Compute foot center point w.r.t local frame
00287     float sum_x_coord = 0.0;
00288     float sum_y_coord = 0.0;
00289     tf::Point r_foot_center;
00290     for (unsigned int i = 0 ; i < foot_SP_right.size(); ++i)
00291     {
00292         sum_x_coord = sum_x_coord + foot_SP_right[i].x();
00293         sum_y_coord = sum_y_coord + foot_SP_right[i].y();
00294     }
00295     //X and Y of right foot center
00296     r_foot_center.setX(sum_x_coord/foot_SP_right.size());
00297     r_foot_center.setY(sum_y_coord/foot_SP_right.size());
00298 
00299     //Vector storing foot points w.r.t foot center
00300     std::vector<tf::Point> foot_SP_right_center;
00301     tf::Point foot_point;
00302     for (unsigned int i = 0 ; i < foot_SP_right.size(); ++i){
00303       //Express point w.r.t foot center and directly apply scaling
00304       foot_point.setX( (foot_SP_right[i].x() - r_foot_center.x()) * foot_polygon_scale_ );
00305       foot_point.setY( (foot_SP_right[i].y() - r_foot_center.y()) * foot_polygon_scale_ );
00306       foot_SP_right_center.push_back(foot_point);
00307     }
00308 
00309     //Express new(scaled) coordinates in local frame
00310     std::vector<tf::Point> scaled_SP_right;
00311     for (unsigned int i = 0 ; i < foot_SP_right_center.size() ; ++i){
00312       //Express point w.r.t foot center and directly apply scaling
00313       foot_point.setX( foot_SP_right_center[i].x() + r_foot_center.x() ) ;
00314       foot_point.setY( foot_SP_right_center[i].y() + r_foot_center.y() ) ;
00315       scaled_SP_right.push_back(foot_point);
00316     }
00317 
00318 
00319     //std::cout<<"Num points"<<scaled_SP_right.size()<<std::endl;
00320 
00321     //Without scaling
00322     //foot_support_polygon_right_ = convexHull(foot_support_polygon_right_);
00323     //foot_support_polygon_right_ = convexHull(foot_SP_right);
00324 
00325     //With scaling
00326     foot_support_polygon_right_ = convexHull(scaled_SP_right);
00327 
00328   }
00329 
00330   ROS_DEBUG("Foot polygon loaded with %zu points", foot_support_polygon_right_.size());
00331 
00332   return true;
00333 
00334 }
00335 
00336 
00337 //Function to guarantee correct double support
00338 void TestStability::scaleConvexHull(double scaling_factor)
00339 {
00340         //Reinit convex hull with new scaling factor
00341         initFootPolygon(scaling_factor);
00342 }
00343 
00344 
00345 
00346 } /* namespace hrl_kinematics */


hrl_kinematics
Author(s): Armin Hornung
autogenerated on Wed Aug 26 2015 11:51:09