00001 #include <vigir_feet_pose_generator/feet_pose_generator.h>
00002
00003 namespace vigir_footstep_planning
00004 {
00005 FeetPoseGenerator::FeetPoseGenerator(ros::NodeHandle& nh)
00006 : has_robot_pose(false)
00007 {
00008 nh.getParam("foot/separation", foot_separation);
00009
00010 nh.getParam("foot/left/frame_id", left_foot_frame_id);
00011 nh.getParam("foot/right/frame_id", right_foot_frame_id);
00012
00013 nh.getParam("foot/left/foot_frame/z", left_foot_shift_z);
00014 nh.getParam("foot/right/foot_frame/z", right_foot_shift_z);
00015
00016
00017 strip(left_foot_frame_id, '/');
00018 strip(right_foot_frame_id, '/');
00019
00020 nh.getParam("pelvis_to_feet_center/x", pelvis_to_feet_center.x);
00021 nh.getParam("pelvis_to_feet_center/y", pelvis_to_feet_center.y);
00022 nh.getParam("pelvis_to_feet_center/z", pelvis_to_feet_center.z);
00023
00024
00025 transform_feet_poses_client = nh.serviceClient<msgs::TransformFeetPosesService>("transform_feet_poses");
00026 }
00027
00028 FeetPoseGenerator::~FeetPoseGenerator()
00029 {
00030 }
00031
00032 void FeetPoseGenerator::setRobotPose(const geometry_msgs::PoseStampedConstPtr &robot_pose)
00033 {
00034 this->robot_pose.header = robot_pose->header;
00035 this->robot_pose = *robot_pose;
00036 has_robot_pose = true;
00037 }
00038
00039 void FeetPoseGenerator::setRobotPoseWithCovariance(const geometry_msgs::PoseWithCovarianceStampedConstPtr &robot_pose)
00040 {
00041 this->robot_pose.header = robot_pose->header;
00042 this->robot_pose.pose = robot_pose->pose.pose;
00043 has_robot_pose = true;
00044 }
00045
00046 void FeetPoseGenerator::setTerrainModel(const vigir_terrain_classifier::TerrainModelMsg::ConstPtr& terrain_model)
00047 {
00048
00049 if (this->terrain_model)
00050 this->terrain_model->fromMsg(*terrain_model);
00051 else
00052 this->terrain_model.reset(new vigir_terrain_classifier::TerrainModel(*terrain_model));
00053 }
00054
00055 msgs::ErrorStatus FeetPoseGenerator::generateFeetPose(const msgs::FeetPoseRequest& request, msgs::Feet& feet)
00056 {
00057 msgs::ErrorStatus status;
00058
00059
00060 std::string request_frame_id = request.header.frame_id;
00061 strip(request_frame_id, '/');
00062
00063 if (request.flags & msgs::FeetPoseRequest::FLAG_CURRENT)
00064 {
00065
00066 if (getCurrentFeetPose(feet, request_frame_id))
00067 {
00068 return status;
00069 }
00070
00071 else if (has_robot_pose)
00072 {
00073 std::string robot_pose_frame_id = strip_const(robot_pose.header.frame_id, '/');
00074 if (request_frame_id != robot_pose_frame_id)
00075 status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FeetPoseGenerator", "generateFeetPose: Frame ID of robot pose ('" + robot_pose_frame_id + "') and request ('" + request_frame_id + "') mismatch, automatic transformation is not implemented yet!");
00076
00077 feet = generateFeetPose(robot_pose);
00078
00079 }
00080 else
00081 {
00082 return status + ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "FeetPoseGenerator", "generateFeetPose: No robot pose available for handling FLAG_CURRENT!");
00083 }
00084 }
00085 else
00086 {
00087 geometry_msgs::PoseStamped pose;
00088 pose.header = request.header;
00089 pose.pose = request.pose;
00090 feet = generateFeetPose(pose);
00091 }
00092
00093 if (request.flags & msgs::FeetPoseRequest::FLAG_PELVIS_FRAME)
00094 {
00095 pelvisToGroundTransform(feet);
00096 }
00097
00098 if (request.flags & msgs::FeetPoseRequest::FLAG_3D)
00099 {
00100 msgs::ErrorStatus temp_status;
00101 msgs::Feet temp_feet = feet;
00102
00103 temp_status = updateFeetPose(temp_feet);
00104 if (hasError(temp_status))
00105 status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FeetPoseGenerator", "generateFeetPose: Couldn't determine either 3D nor height of feet!", false);
00106 else
00107 {
00108 status += temp_status;
00109 feet = temp_feet;
00110 }
00111 }
00112
00113 if (request.flags & msgs::FeetPoseRequest::FLAG_CURRENT_Z)
00114 {
00115 msgs::Feet current_feet;
00116 if (getCurrentFeetPose(current_feet, request_frame_id))
00117 {
00118 feet.left.pose.position.z = current_feet.left.pose.position.z+left_foot_shift_z;
00119 feet.right.pose.position.z = current_feet.right.pose.position.z+right_foot_shift_z;
00120 }
00121 else
00122 status += ErrorStatusError(msgs::ErrorStatus::ERR_UNKNOWN, "FeetPoseGenerator", "generateFeetPose: Couldn't determine height of current feet!");
00123 }
00124
00125 transformToRobotFrame(feet, transform_feet_poses_client);
00126
00127 return status;
00128 }
00129
00130 msgs::ErrorStatus FeetPoseGenerator::updateFeetPose(msgs::Feet& feet) const
00131 {
00132 if (!terrain_model || !terrain_model->hasTerrainModel())
00133 return ErrorStatusError(msgs::ErrorStatus::ERR_INVALID_TERRAIN_MODEL, "FeetPoseGenerator", "updateFeetPose: No terrain model available!", false);
00134
00135 msgs::ErrorStatus status;
00136
00137 if (!terrain_model->update3DData(feet.left.pose) && !terrain_model->getHeight(feet.left.pose.position.x, feet.left.pose.position.y, feet.left.pose.position.z))
00138 status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FeetPoseGenerator", "updateFeetPose: Couldn't determine either 3D nor height of left foot!", false);
00139
00140 if (!terrain_model->update3DData(feet.right.pose) && !terrain_model->getHeight(feet.right.pose.position.x, feet.right.pose.position.y, feet.right.pose.position.z))
00141 status += ErrorStatusWarning(msgs::ErrorStatus::WARN_UNKNOWN, "FeetPoseGenerator", "updateFeetPose: Couldn't determine either 3D nor height of right foot!", false);
00142
00143 return status;
00144 }
00145
00146 bool FeetPoseGenerator::getCurrentFeetPose(msgs::Feet& feet, const std::string& request_frame)
00147 {
00148 if (tf_listener.canTransform(request_frame, left_foot_frame_id, ros::Time(0)) &&
00149 tf_listener.canTransform(request_frame, right_foot_frame_id, ros::Time(0)))
00150 {
00151 tf::StampedTransform t;
00152 tf_listener.lookupTransform(request_frame, left_foot_frame_id, ros::Time(0), t);
00153 tf::poseTFToMsg(t, feet.left.pose);
00154 feet.left.header.stamp = t.stamp_;
00155 feet.left.foot_index = msgs::Foot::LEFT;
00156
00157 tf_listener.lookupTransform(request_frame, right_foot_frame_id, ros::Time(0), t);
00158 tf::poseTFToMsg(t, feet.right.pose);
00159 feet.right.header.stamp = t.stamp_;
00160 feet.right.foot_index = msgs::Foot::RIGHT;
00161
00162 feet.header.stamp = ros::Time::now();
00163 feet.header.frame_id = feet.left.header.frame_id = feet.right.header.frame_id = request_frame;
00164
00165 return true;
00166 }
00167 return false;
00168 }
00169
00170 msgs::Feet FeetPoseGenerator::generateFeetPose(const geometry_msgs::PoseStamped& pose)
00171 {
00172 msgs::Feet feet;
00173 double yaw = tf::getYaw(pose.pose.orientation);
00174 double shift_x = -sin(yaw) * (0.5 * foot_separation);
00175 double shift_y = cos(yaw) * (0.5 * foot_separation);
00176
00177 feet.header = pose.header;
00178
00179 feet.left.header = pose.header;
00180 feet.left.foot_index = msgs::Foot::LEFT;
00181 feet.left.pose.position.x = pose.pose.position.x + shift_x;
00182 feet.left.pose.position.y = pose.pose.position.y + shift_y;
00183 feet.left.pose.position.z = pose.pose.position.z;
00184 feet.left.pose.orientation = tf::createQuaternionMsgFromYaw(yaw);
00185
00186 feet.right.header = pose.header;
00187 feet.right.foot_index = msgs::Foot::RIGHT;
00188 feet.right.pose.position.x = pose.pose.position.x - shift_x;
00189 feet.right.pose.position.y = pose.pose.position.y - shift_y;
00190 feet.right.pose.position.z = pose.pose.position.z;
00191 feet.right.pose.orientation = tf::createQuaternionMsgFromYaw(yaw);
00192
00193 return feet;
00194 }
00195
00196 void FeetPoseGenerator::pelvisToGroundTransform(msgs::Feet& feet) const
00197 {
00199 feet.left.pose.position.x += pelvis_to_feet_center.x;
00200 feet.left.pose.position.y += pelvis_to_feet_center.y;
00201 feet.left.pose.position.z += pelvis_to_feet_center.z;
00202
00203 feet.right.pose.position.x += pelvis_to_feet_center.x;
00204 feet.right.pose.position.y += pelvis_to_feet_center.y;
00205 feet.right.pose.position.z += pelvis_to_feet_center.z;
00206 }
00207 }