00001 /* 00002 * avoid_joint_limits.cpp 00003 * 00004 * Created on: Sep 23, 2013 00005 * Author: dsolomon 00006 */ 00007 /* 00008 * Software License Agreement (Apache License) 00009 * 00010 * Copyright (c) 2013, Southwest Research Institute 00011 * 00012 * Licensed under the Apache License, Version 2.0 (the "License"); 00013 * you may not use this file except in compliance with the License. 00014 * You may obtain a copy of the License at 00015 * 00016 * http://www.apache.org/licenses/LICENSE-2.0 00017 * 00018 * Unless required by applicable law or agreed to in writing, software 00019 * distributed under the License is distributed on an "AS IS" BASIS, 00020 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00021 * See the License for the specific language governing permissions and 00022 * limitations under the License. 00023 */ 00024 00025 #include "constrained_ik/constraints/joint_vel_limits.h" 00026 #include "constrained_ik/constrained_ik.h" 00027 #include <ros/ros.h> 00028 00029 namespace constrained_ik 00030 { 00031 namespace constraints 00032 { 00033 00034 using namespace Eigen; 00035 using namespace std; 00036 00037 JointVelLimits::JointVelLimits(): Constraint(), weight_(1.0), timestep_(.1) 00038 { 00039 debug_ = true; 00040 } 00041 00042 Eigen::VectorXd JointVelLimits::calcError() 00043 { 00044 size_t nRows = limited_joints_.size(); 00045 VectorXd error(nRows); 00046 VectorXd vel_error = jvel_.cwiseAbs() - vel_limits_; 00047 for (int ii=0; ii<nRows; ++ii) 00048 { 00049 size_t jntIdx = limited_joints_[ii]; 00050 int velSign = jvel_(jntIdx)<0 ? 1 : -1; // negative jvel requires positive velocity correction, and vice versa 00051 00052 error(ii) = velSign * weight_ * vel_error(jntIdx) * 1.25; 00053 } 00054 00055 if (debug_ && nRows) 00056 { 00057 ROS_ERROR_STREAM("iteration " << state_.iter); 00058 ROS_ERROR_STREAM("Joint velocity: " << jvel_.transpose()); 00059 ROS_ERROR_STREAM("velocity error: " << error.transpose()); 00060 } 00061 00062 return error; 00063 } 00064 00065 Eigen::MatrixXd JointVelLimits::calcJacobian() 00066 { 00067 size_t nRows = limited_joints_.size(); 00068 MatrixXd jacobian(nRows, numJoints()); 00069 00070 for (int ii=0; ii<nRows; ++ii) 00071 { 00072 size_t jntIdx = limited_joints_[ii]; 00073 00074 VectorXd tmpRow = VectorXd::Zero(numJoints()); 00075 tmpRow(jntIdx) = 1.0; 00076 00077 jacobian.row(ii) = tmpRow * weight_; 00078 } 00079 00080 return jacobian; 00081 } 00082 00083 void JointVelLimits::init(const Constrained_IK *ik) 00084 { 00085 Constraint::init(ik); 00086 00087 timestep_ = .08; //TODO this should come from somewhere 00088 // initialize velocity limits 00089 vel_limits_.resize(numJoints()); 00090 for (size_t ii=0; ii<numJoints(); ++ii) 00091 vel_limits_(ii) = 2*M_PI; //TODO this should come from somewhere 00092 } 00093 00094 void JointVelLimits::reset() 00095 { 00096 limited_joints_.clear(); 00097 } 00098 00099 // TODO: Move this to a common "utils" file 00100 template<class T> 00101 std::ostream& operator<< (std::ostream& os, const std::vector<T>& v) 00102 { 00103 if (!v.empty()) 00104 { 00105 copy(v.begin(), v.end()-1, std::ostream_iterator<T>(os, ", ")); 00106 os << v.back(); // no comma after last element 00107 } 00108 return os; 00109 } 00110 00111 void JointVelLimits::update(const SolverState &state) 00112 { 00113 if (!initialized_) return; 00114 Constraint::update(state); 00115 limited_joints_.clear(); 00116 00117 jvel_ = (state_.joints - state_.joint_seed)/timestep_; 00118 // check for limited joints 00119 for (size_t ii=0; ii<numJoints(); ++ii) 00120 if ( std::abs(jvel_(ii)) > vel_limits_(ii) ) 00121 limited_joints_.push_back(ii); 00122 00123 // print debug message, if enabled 00124 if (debug_ && !limited_joints_.empty()) 00125 ROS_ERROR_STREAM(limited_joints_.size() << " joint vel limits active: " << limited_joints_); 00126 } 00127 00128 } /* namespace constraints */ 00129 } /* namespace constrained_ik */