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 #include "pr2_doors_common/door_functions.h"
00036 #include <kdl/frames.hpp>
00037
00038 using namespace ros;
00039 using namespace std;
00040 using namespace KDL;
00041
00042
00043 namespace pr2_doors_common
00044 {
00045 static const double eps_angle = 5.0*M_PI/180.0;
00046 static const double gripper_height = 0.8;
00047
00048 tf::Stamped<tf::Pose> getRobotPose(const door_msgs::Door& door, double dist)
00049 {
00050 Vector x_axis(1,0,0);
00051
00052
00053 Vector frame_1(door.frame_p1.x, door.frame_p1.y, door.frame_p1.z);
00054 Vector frame_2(door.frame_p2.x, door.frame_p2.y, door.frame_p2.z);
00055 Vector frame_center = (frame_2 + frame_1)/2.0;
00056
00057
00058 Vector frame_normal = getFrameNormal(door);
00059 Vector robot_pos = frame_center + (frame_normal * dist);
00060 tf::Stamped<tf::Pose> robot_pose;
00061 robot_pose.frame_id_ = door.header.frame_id;
00062 robot_pose.stamp_ = door.header.stamp;
00063 robot_pose.setOrigin( tf::Vector3(robot_pos(0), robot_pos(1), robot_pos(2)));
00064 robot_pose.setRotation( tf::createQuaternionFromRPY(getVectorAngle(x_axis, frame_normal), 0, 0) );
00065
00066 return robot_pose;
00067 }
00068
00069 double getNearestDoorAngle(const tf::Pose& robot_pose, const door_msgs::Door& door, double robot_dist, double touch_dist)
00070 {
00071 double angle = 0, step = 0;
00072 if (door.rot_dir == door.ROT_DIR_CLOCKWISE)
00073 step = -0.01;
00074 else if (door.rot_dir == door.ROT_DIR_COUNTERCLOCKWISE)
00075 step = 0.01;
00076 else{
00077 ROS_ERROR("Door rot dir is not specified");
00078 return 0.0;
00079 }
00080
00081 while ((robot_pose.getOrigin() - getGripperPose(door, angle, touch_dist).getOrigin()).length() < robot_dist &&
00082 fabs(angle) < M_PI_2)
00083 angle += step;
00084
00085 return angle;
00086 }
00087
00088 tf::Stamped<tf::Pose> getGripperPose(const door_msgs::Door& door, double angle, double dist)
00089 {
00090 Vector x_axis(1,0,0);
00091
00092
00093 Vector hinge, frame_vec;
00094 if (door.hinge == door_msgs::Door::HINGE_P1){
00095 hinge = Vector(door.door_p1.x, door.door_p1.y, door.door_p1.z);
00096 frame_vec = Vector(door.frame_p2.x - door.frame_p1.x, door.frame_p2.y - door.frame_p1.y, door.frame_p2.z - door.frame_p1.z);
00097 }
00098 else if (door.hinge == door_msgs::Door::HINGE_P2){
00099 hinge = Vector(door.door_p2.x, door.door_p2.y, door.door_p2.z);
00100 frame_vec = Vector(door.frame_p1.x - door.frame_p2.x, door.frame_p1.y - door.frame_p2.y, door.frame_p1.z - door.frame_p2.z);
00101 }
00102
00103
00104 frame_vec.Normalize();
00105 frame_vec = frame_vec * dist;
00106 Rotation rot_angle = Rotation::RotZ(angle);
00107 Vector gripper_pos = hinge + (rot_angle * frame_vec);
00108
00109 tf::Stamped<tf::Pose> gripper_pose;
00110 Vector normal_frame = getFrameNormal(door);
00111 gripper_pose.frame_id_ = door.header.frame_id;
00112 gripper_pose.stamp_ = door.header.stamp;
00113 gripper_pose.setOrigin( tf::Vector3(gripper_pos(0), gripper_pos(1), gripper_height));
00114 gripper_pose.setRotation( tf::createQuaternionFromRPY(getVectorAngle(x_axis, normal_frame)+angle, 0, 0) );
00115
00116 return gripper_pose;
00117 }
00118
00119 tf::Stamped<tf::Pose> getGripperPose(const door_msgs::Door& door, double angle, double dist, int side)
00120 {
00121 Vector x_axis(1,0,0);
00122
00123
00124 Vector hinge, frame_vec;
00125 if (door.hinge == door_msgs::Door::HINGE_P1){
00126 hinge = Vector(door.door_p1.x, door.door_p1.y, door.door_p1.z);
00127 frame_vec = Vector(door.frame_p2.x - door.frame_p1.x, door.frame_p2.y - door.frame_p1.y, door.frame_p2.z - door.frame_p1.z);
00128 }
00129 else if (door.hinge == door_msgs::Door::HINGE_P2){
00130 hinge = Vector(door.door_p2.x, door.door_p2.y, door.door_p2.z);
00131 frame_vec = Vector(door.frame_p1.x - door.frame_p2.x, door.frame_p1.y - door.frame_p2.y, door.frame_p1.z - door.frame_p2.z);
00132 }
00133
00134
00135 frame_vec.Normalize();
00136 frame_vec = frame_vec * dist;
00137 Rotation rot_angle = Rotation::RotZ(angle);
00138 Vector gripper_pos = hinge + (rot_angle * frame_vec);
00139
00140 tf::Stamped<tf::Pose> gripper_pose;
00141 Vector normal_frame = getFrameNormal(door);
00142 gripper_pose.frame_id_ = door.header.frame_id;
00143 gripper_pose.stamp_ = door.header.stamp;
00144 gripper_pose.setOrigin( tf::Vector3(gripper_pos(0), gripper_pos(1), gripper_height));
00145 if(side == door_msgs::DoorCmd::PULL)
00146 {
00147 gripper_pose.setRotation( tf::createQuaternionFromRPY(getVectorAngle(-x_axis, normal_frame)+angle, 0, 0) );
00148 }
00149 else
00150 {
00151 gripper_pose.setRotation( tf::createQuaternionFromRPY(getVectorAngle(x_axis, normal_frame)+angle, 0, 0) );
00152 }
00153 return gripper_pose;
00154 }
00155
00156
00157 geometry_msgs::Point32 getHingeAxisPoint(const door_msgs::Door& door)
00158 {
00159 geometry_msgs::Point32 hinge;
00160 if (door.hinge == door_msgs::Door::HINGE_P1){
00161 hinge = door.door_p1;
00162 }
00163 else if (door.hinge == door_msgs::Door::HINGE_P2){
00164 hinge = door.door_p2;
00165 }
00166 return hinge;
00167 }
00168
00169 geometry_msgs::Point32 getEdgePoint(const door_msgs::Door& door)
00170 {
00171 geometry_msgs::Point32 edge;
00172 if (door.hinge == door_msgs::Door::HINGE_P1){
00173 edge = door.door_p2;
00174 }
00175 else if (door.hinge == door_msgs::Door::HINGE_P2){
00176 edge = door.door_p1;
00177 }
00178 return edge;
00179 }
00180
00181 tf::Stamped<tf::Pose> getHandlePose(const door_msgs::Door& door, int side)
00182 {
00183 Vector x_axis(1,0,0);
00184
00185 double dist = sqrt(pow(door.frame_p1.x - door.handle.x,2)+pow(door.frame_p1.y - door.handle.y,2));
00186 if(door.hinge == door_msgs::Door::HINGE_P2)
00187 {
00188 dist = sqrt(pow(door.frame_p2.x - door.handle.x,2)+pow(door.frame_p2.y - door.handle.y,2));
00189 }
00190 double angle = getDoorAngle(door);
00191
00192
00193 Vector hinge, frame_vec;
00194 if (door.hinge == door_msgs::Door::HINGE_P1){
00195 hinge = Vector(door.door_p1.x, door.door_p1.y, door.door_p1.z);
00196 frame_vec = Vector(door.frame_p2.x - door.frame_p1.x, door.frame_p2.y - door.frame_p1.y, door.frame_p2.z - door.frame_p1.z);
00197 }
00198 else if (door.hinge == door_msgs::Door::HINGE_P2){
00199 hinge = Vector(door.door_p2.x, door.door_p2.y, door.door_p2.z);
00200 frame_vec = Vector(door.frame_p1.x - door.frame_p2.x, door.frame_p1.y - door.frame_p2.y, door.frame_p1.z - door.frame_p2.z);
00201 }
00202
00203
00204 frame_vec.Normalize();
00205 frame_vec = frame_vec * dist;
00206 Rotation rot_angle = Rotation::RotZ(angle);
00207 Vector handle_pos = hinge + (rot_angle * frame_vec);
00208
00209 tf::Stamped<tf::Pose> handle_pose;
00210 Vector normal_frame = getFrameNormal(door);
00211 if(side == -1)
00212 {
00213 normal_frame = -normal_frame;
00214 }
00215 handle_pose.frame_id_ = door.header.frame_id;
00216 handle_pose.stamp_ = door.header.stamp;
00217 handle_pose.setOrigin( tf::Vector3(handle_pos(0), handle_pos(1), gripper_height));
00218 handle_pose.setRotation( tf::createQuaternionFromRPY(getVectorAngle(x_axis, normal_frame)+angle, 0, 0) );
00219
00220 tf::Pose gripper_rotate(tf::createQuaternionFromRPY(0.0,0.0,M_PI/2.0),tf::Vector3(0.0,0.0,0.0));
00221 handle_pose.mult(handle_pose,gripper_rotate);
00222 return handle_pose;
00223 }
00224
00225 double getDoorAngle(const door_msgs::Door& door)
00226 {
00227 Vector frame_vec(door.frame_p1.x-door.frame_p2.x, door.frame_p1.y-door.frame_p2.y, door.frame_p1.z-door.frame_p2.z);
00228 Vector door_vec(door.door_p1.x-door.door_p2.x, door.door_p1.y-door.door_p2.y, door.door_p1.z-door.door_p2.z);
00229 double angle = getVectorAngle(frame_vec, door_vec);
00230
00231
00232 if (door.rot_dir == door_msgs::Door::ROT_DIR_CLOCKWISE && angle > eps_angle)
00233 ROS_DEBUG("Door angle is positive, but door message specifies it turns clockwise");
00234
00235 if (door.rot_dir == door_msgs::Door::ROT_DIR_COUNTERCLOCKWISE && angle < -eps_angle)
00236 ROS_DEBUG("Door angle is negative, but door message specifies it turns counter-clockwise");
00237
00238 return angle;
00239 }
00240
00241 double getVectorAngle(const Vector& v1, const Vector& v2)
00242 {
00243 Vector vec1 = v1; vec1.Normalize();
00244 Vector vec2 = v2; vec2.Normalize();
00245 double dot = vec2(0) * vec1(0) + vec2(1) * vec1(1);
00246 double perp_dot = vec2(1) * vec1(0) - vec2(0) * vec1(1);
00247 return atan2(perp_dot, dot);
00248 }
00249
00250 Vector getDoorNormal(const door_msgs::Door& door)
00251 {
00252 Vector frame_normal = getFrameNormal(door);
00253 Rotation rot_frame_door = Rotation::RotZ(getDoorAngle(door));
00254 return rot_frame_door * frame_normal;
00255 }
00256
00257 Vector getFrameNormal(const door_msgs::Door& door)
00258 {
00259
00260 Vector p12(door.frame_p1.x-door.frame_p2.x, door.frame_p1.y-door.frame_p2.y, door.frame_p1.z-door.frame_p2.z);
00261 p12.Normalize();
00262 Vector z_axis(0,0,1);
00263 Vector normal = p12 * z_axis;
00264
00265
00266 Vector dir(door.travel_dir.x, door.travel_dir.y, door.travel_dir.z);
00267 if (dot(dir, normal) < 0)
00268 normal = normal * -1.0;
00269
00270 return normal;
00271 }
00272
00273 bool transformTo(const tf::Transformer& tf, const string& goal_frame, const door_msgs::Door& door_in, door_msgs::Door& door_out, const std::string& fixed_frame)
00274 {
00275 door_out = door_in;
00276 ros::Time time_now = ros::Time::now();
00277 if (!transformPointTo(tf, door_in.header.frame_id, goal_frame, door_in.header.stamp, door_in.frame_p1, door_out.frame_p1, fixed_frame, time_now)) return false;
00278 if (!transformPointTo(tf, door_in.header.frame_id, goal_frame, door_in.header.stamp, door_in.frame_p2, door_out.frame_p2, fixed_frame, time_now)) return false;
00279 if (!transformPointTo(tf, door_in.header.frame_id, goal_frame, door_in.header.stamp, door_in.door_p1, door_out.door_p1, fixed_frame, time_now)) return false;
00280 if (!transformPointTo(tf, door_in.header.frame_id, goal_frame, door_in.header.stamp, door_in.door_p2, door_out.door_p2, fixed_frame, time_now)) return false;
00281 if (!transformPointTo(tf, door_in.header.frame_id, goal_frame, door_in.header.stamp, door_in.handle, door_out.handle, fixed_frame, time_now)) return false;
00282 if (!transformVectorTo(tf, door_in.header.frame_id, goal_frame, door_in.header.stamp, door_in.travel_dir, door_out.travel_dir, fixed_frame, time_now)) return false;
00283 door_out.header.frame_id = goal_frame;
00284 door_out.header.stamp = time_now;
00285 return true;
00286 }
00287
00288 bool transformPointTo(const tf::Transformer& tf, const string& source_frame, const string& goal_frame, const Time& time_source,
00289 const geometry_msgs::Point32& point_in, geometry_msgs::Point32& point_out, const std::string& fixed_frame, const Time& time_goal)
00290 {
00291 ros::Duration timeout = Duration().fromSec(5.0);
00292 if (!tf.waitForTransform(source_frame, time_source, goal_frame, time_goal, fixed_frame, timeout)) return false;
00293 tf::Stamped<tf::Point> pnt(tf::Vector3(point_in.x, point_in.y, point_in.z), time_source, source_frame);
00294 tf.transformPoint(goal_frame, time_goal, pnt, fixed_frame, pnt);
00295 point_out.x = pnt[0];
00296 point_out.y = pnt[1];
00297 point_out.z = pnt[2];
00298
00299 return true;
00300 }
00301
00302 bool transformVectorTo(const tf::Transformer& tf, const string& source_frame, const string& goal_frame, const Time& time_source,
00303 const geometry_msgs::Vector3& point_in, geometry_msgs::Vector3& point_out, const std::string& fixed_frame, const Time& time_goal)
00304 {
00305 ros::Duration timeout = Duration().fromSec(2.0);
00306 if (!tf.waitForTransform(source_frame, time_source, goal_frame, time_goal, fixed_frame, timeout)) return false;
00307 tf::Stamped<tf::Point> pnt(tf::Vector3(point_in.x, point_in.y, point_in.z), time_source, source_frame);
00308 tf.transformVector(goal_frame, time_goal, pnt, fixed_frame, pnt);
00309 point_out.x = pnt[0];
00310 point_out.y = pnt[1];
00311 point_out.z = pnt[2];
00312
00313 return true;
00314 }
00315
00316 std::vector<geometry_msgs::Point> getPolygon(const door_msgs::Door& door, const double &door_thickness)
00317 {
00318 std::vector<geometry_msgs::Point> door_polygon;
00319 geometry_msgs::Point tmp;
00320 Vector door_normal = getDoorNormal(door);
00321 tmp.x = door.frame_p1.x + door_normal(0) * door_thickness/2.0;
00322 tmp.y = door.frame_p1.y + door_normal(1) * door_thickness/2.0;
00323 door_polygon.push_back(tmp);
00324
00325 tmp.x = door.frame_p1.x - door_normal(0) * door_thickness/2.0;
00326 tmp.y = door.frame_p1.y - door_normal(1) * door_thickness/2.0;
00327 door_polygon.push_back(tmp);
00328
00329 tmp.x = door.frame_p2.x - door_normal(0) * door_thickness/2.0;
00330 tmp.y = door.frame_p2.y - door_normal(1) * door_thickness/2.0;
00331 door_polygon.push_back(tmp);
00332
00333 tmp.x = door.frame_p2.x + door_normal(0) * door_thickness/2.0;
00334 tmp.y = door.frame_p2.y + door_normal(1) * door_thickness/2.0;
00335 door_polygon.push_back(tmp);
00336 return door_polygon;
00337 }
00338
00339 door_msgs::Door rotateDoor(const door_msgs::Door& door, const double &angle)
00340 {
00341 door_msgs::Door result = door;
00342 geometry_msgs::Point32 hinge = door.frame_p1;
00343 geometry_msgs::Point32 edge = door.frame_p2;
00344 if(door.hinge == door.HINGE_P2)
00345 {
00346 hinge = door.frame_p2;
00347 edge = door.frame_p1;
00348 }
00349 double handle_distance = sqrt(pow(door.handle.y-hinge.y,2) + pow(door.handle.x-hinge.x,2));
00350 double door_frame_global_yaw = atan2(edge.y-hinge.y,edge.x-hinge.x);
00351 double door_length = sqrt(pow(edge.y-hinge.y,2) + pow(edge.x-hinge.x,2));
00352
00353 double sth = sin(door_frame_global_yaw+angle);
00354 double cth = cos(door_frame_global_yaw+angle);
00355
00356 geometry_msgs::Point32 new_edge;
00357 new_edge.x = hinge.x + cth *door_length;
00358 new_edge.y = hinge.y + sth *door_length;
00359 geometry_msgs::Point32 new_handle = door.handle;
00360 new_handle.x = hinge.x + cth*handle_distance;
00361 new_handle.y = hinge.y + sth*handle_distance;
00362
00363 result.door_p1 = hinge;
00364 result.door_p2 = new_edge;
00365 if(door.hinge == door.HINGE_P2)
00366 {
00367 result.door_p2 = hinge;
00368 result.door_p1 = new_edge;
00369 }
00370 result.handle = new_handle;
00371 return result;
00372 }
00373
00374 double getFrameAngle(const door_msgs::Door& door)
00375 {
00376 double result;
00377 if(door.hinge == door.HINGE_P1)
00378 {
00379 result = atan2(door.frame_p2.y - door.frame_p1.y, door.frame_p2.x - door.frame_p1.x);
00380 }
00381 else
00382 {
00383 result = atan2(door.frame_p1.y - door.frame_p2.y, door.frame_p1.x - door.frame_p2.x);
00384 }
00385 return result;
00386 }
00387
00388 double getHandleDir(const door_msgs::Door& d)
00389 {
00390 Vector normal = getFrameNormal(d);
00391 Vector frame_vec;
00392 if (d.hinge == door_msgs::Door::HINGE_P1)
00393 frame_vec = Vector(d.frame_p2.x - d.frame_p1.x, d.frame_p2.y - d.frame_p1.y, d.frame_p2.z - d.frame_p1.z);
00394 else if (d.hinge == door_msgs::Door::HINGE_P2)
00395 frame_vec = Vector(d.frame_p1.x - d.frame_p2.x, d.frame_p1.y - d.frame_p2.y, d.frame_p1.z - d.frame_p2.z);
00396 else
00397 ROS_ERROR("Hinge side is not defined");
00398
00399 Vector rot_vec = frame_vec * normal;
00400 if (rot_vec(2) > 0)
00401 return -1.0;
00402 else
00403 return 1.0;
00404 }
00405
00406 double getDoorDir(const door_msgs::Door& d)
00407 {
00408
00409 Vector frame_vec;
00410 if (d.hinge == door_msgs::Door::HINGE_P1)
00411 frame_vec = Vector(d.frame_p2.x - d.frame_p1.x, d.frame_p2.y - d.frame_p1.y, d.frame_p2.z - d.frame_p1.z);
00412 else if (d.hinge == door_msgs::Door::HINGE_P2)
00413 frame_vec = Vector(d.frame_p1.x - d.frame_p2.x, d.frame_p1.y - d.frame_p2.y, d.frame_p1.z - d.frame_p2.z);
00414 else
00415 ROS_ERROR("Hinge side is not defined");
00416
00417
00418 if (d.rot_dir == door_msgs::Door::ROT_DIR_CLOCKWISE)
00419 frame_vec = Rotation::RotZ(-M_PI_2) * frame_vec;
00420 else if (d.rot_dir == door_msgs::Door::ROT_DIR_COUNTERCLOCKWISE)
00421 frame_vec = Rotation::RotZ(M_PI_2) * frame_vec;
00422 else
00423 ROS_ERROR("Rot dir is not defined");
00424
00425 if (dot(frame_vec, getFrameNormal(d)) < 0)
00426 return -1.0;
00427 else
00428 return 1.0;
00429 }
00430
00431 std::ostream& operator<< (std::ostream& os, const door_msgs::Door& d)
00432 {
00433 os << "Door message in " << d.header.frame_id << " at time " << d.header.stamp.toSec() << endl;
00434 os << " - frame ("
00435 << d.frame_p1.x << " " << d.frame_p1.y << " "<< d.frame_p1.z << ") -- ("
00436 << d.frame_p2.x << " " << d.frame_p2.y << " "<< d.frame_p2.z << ")" << endl;
00437
00438 os << " - door ("
00439 << d.door_p1.x << " " << d.door_p1.y << " "<< d.door_p1.z << ") -- ("
00440 << d.door_p2.x << " " << d.door_p2.y << " "<< d.door_p2.z << ")" << endl;
00441
00442 os << " - handle ("
00443 << d.handle.x << " " << d.handle.y << " "<< d.handle.z << ")" << endl;
00444
00445 os << " - travel_dir ("
00446 << d.travel_dir.x << " " << d.travel_dir.y << " "<< d.travel_dir.z << ")" << endl;
00447
00448 os << " - latch_state " << d.latch_state << endl;
00449 os << " - hinge side " << d.hinge << endl;
00450 os << " - rot_dir " << d.rot_dir << endl;
00451 os << " - angle [deg] " << getDoorAngle(d)*180.0/M_PI << endl;
00452 return os;
00453 }
00454
00455
00456 }