00001 /* 00002 * Software License Agreement (Apache License) 00003 * 00004 * Copyright (c) 2013, Southwest Research Institute 00005 * 00006 * Licensed under the Apache License, Version 2.0 (the "License"); 00007 * you may not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 00019 #include "constrained_ik/constrained_ik.h" 00020 #include "constrained_ik/constraints/goal_orientation.h" 00021 #include <ros/ros.h> 00022 00023 namespace constrained_ik 00024 { 00025 namespace constraints 00026 { 00027 00028 using namespace Eigen; 00029 00030 // initialize limits/tolerances to default values 00031 GoalOrientation::GoalOrientation() : Constraint(), rot_err_tol_(0.009), rot_err_(0.0), weight_(Vector3d::Ones()) 00032 { 00033 } 00034 00035 double GoalOrientation::calcAngle(const Eigen::Affine3d &p1, const Eigen::Affine3d &p2) 00036 { 00037 Quaterniond q1(p1.rotation()), q2(p2.rotation()); 00038 return q1.angularDistance(q2); 00039 } 00040 00041 Eigen::Vector3d GoalOrientation::calcAngleError(const Eigen::Affine3d &p1, const Eigen::Affine3d &p2) 00042 { 00043 Eigen::AngleAxisd r12(p1.rotation().transpose()*p2.rotation()); // rotation from p1 -> p2 00044 double theta = Constrained_IK::rangedAngle(r12.angle()); // TODO: move rangedAngle to utils class 00045 return p1.rotation() * r12.axis() * theta; // axis k * theta expressed in frame0 00046 } 00047 00048 Eigen::VectorXd GoalOrientation::calcError() 00049 { 00050 Vector3d err = calcAngleError(state_.pose_estimate, state_.goal); 00051 err = err.cwiseProduct(weight_); 00052 ROS_ASSERT(err.rows() == 3); 00053 return err; 00054 } 00055 00056 // translate cartesian errors into joint-space errors 00057 Eigen::MatrixXd GoalOrientation::calcJacobian() 00058 { 00059 MatrixXd tmpJ; 00060 if (!ik_->getKin().calcJacobian(state_.joints, tmpJ)) 00061 throw std::runtime_error("Failed to calculate Jacobian"); 00062 MatrixXd J = tmpJ.bottomRows(3); 00063 00064 // weight each row of J 00065 for (size_t ii=0; ii<3; ++ii) 00066 J.row(ii) *= weight_(ii); 00067 00068 ROS_ASSERT(J.rows() == 3); 00069 return J; 00070 } 00071 00072 bool GoalOrientation::checkStatus() const 00073 { 00074 // check to see if we've reached the goal orientation 00075 if (rot_err_ < rot_err_tol_) 00076 return true; 00077 00078 return Constraint::checkStatus(); 00079 } 00080 00081 void GoalOrientation::reset() 00082 { 00083 Constraint::reset(); 00084 rot_err_ = 0; 00085 } 00086 00087 void GoalOrientation::update(const SolverState &state) 00088 { 00089 Constraint::update(state); 00090 00091 rot_err_ = calcAngle(state.goal, state.pose_estimate); 00092 } 00093 00094 } // namespace constraints 00095 } // namespace constrained_ik 00096