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
00036
00037 #include <moveit/dynamics_solver/dynamics_solver.h>
00038
00039
00040 #include <kdl/jntarray.hpp>
00041 #include <kdl_parser/kdl_parser.hpp>
00042 #include <kdl/chainiksolverpos_nr_jl.hpp>
00043 #include <kdl/chainiksolvervel_pinv.hpp>
00044 #include <kdl/chainfksolverpos_recursive.hpp>
00045 #include <kdl/chainjnttojacsolver.hpp>
00046 #include <kdl/tree.hpp>
00047
00048 namespace dynamics_solver
00049 {
00050
00051 namespace
00052 {
00053 inline geometry_msgs::Vector3 transformVector(const Eigen::Affine3d &transform,
00054 const geometry_msgs::Vector3 &vector)
00055 {
00056 Eigen::Vector3d p;
00057 p = Eigen::Vector3d(vector.x, vector.y, vector.z);
00058 p = transform.rotation()*p;
00059
00060 geometry_msgs::Vector3 result;
00061 result.x = p.x();
00062 result.y = p.y();
00063 result.z = p.z();
00064
00065 return result;
00066 }
00067 }
00068
00069 DynamicsSolver::DynamicsSolver(const robot_model::RobotModelConstPtr &kinematic_model,
00070 const std::string &group_name,
00071 const geometry_msgs::Vector3 &gravity_vector)
00072 {
00073 group_name_ = group_name;
00074 kinematic_model_ = kinematic_model;
00075 joint_model_group_ = kinematic_model_->getJointModelGroup(group_name);
00076 if (!joint_model_group_)
00077 return;
00078
00079 if(!joint_model_group_->isChain())
00080 {
00081 logError("Group %s is not a chain. Will not initialize dynamics solver", group_name_.c_str());
00082 joint_model_group_ = NULL;
00083 return;
00084 }
00085
00086 if(joint_model_group_->getMimicJointModels().size() > 0)
00087 {
00088 logError("Group %s has a mimic joint. Will not initialize dynamics solver", group_name_.c_str());
00089 joint_model_group_ = NULL;
00090 return;
00091 }
00092
00093 const robot_model::JointModel* joint = joint_model_group_->getJointRoots()[0];
00094 if(!joint->getParentLinkModel())
00095 {
00096 logError("Group %s does not have a parent link",group_name_.c_str());
00097 joint_model_group_ = NULL;
00098 return;
00099 }
00100
00101 base_name_ = joint->getParentLinkModel()->getName();
00102
00103 tip_name_ = joint_model_group_->getLinkModelNames().back();
00104 logDebug("Base name: %s, Tip name: %s", base_name_.c_str(), tip_name_.c_str());
00105
00106 const boost::shared_ptr<const urdf::ModelInterface> urdf_model = kinematic_model_->getURDF();
00107 const boost::shared_ptr<const srdf::Model> srdf_model = kinematic_model_->getSRDF();
00108 KDL::Tree tree;
00109
00110 if (!kdl_parser::treeFromUrdfModel(*urdf_model, tree))
00111 {
00112 logError("Could not initialize tree object");
00113 joint_model_group_ = NULL;
00114 return;
00115 }
00116 if (!tree.getChain(base_name_, tip_name_, kdl_chain_))
00117 {
00118 logError("Could not initialize chain object");
00119 joint_model_group_ = NULL;
00120 return;
00121 }
00122 num_joints_ = kdl_chain_.getNrOfJoints();
00123 num_segments_ = kdl_chain_.getNrOfSegments();
00124
00125 kinematic_state_.reset(new robot_state::RobotState(kinematic_model_));
00126 joint_state_group_ = kinematic_state_->getJointStateGroup(joint_model_group_->getName());
00127
00128 const std::vector<std::string> joint_model_names = joint_model_group_->getJointModelNames();
00129 for(unsigned int i=0; i < joint_model_names.size(); ++i)
00130 {
00131 const urdf::Joint* ujoint = urdf_model->getJoint(joint_model_names[i]).get();
00132 if (ujoint->limits)
00133 max_torques_.push_back(ujoint->limits->effort);
00134 else
00135 max_torques_.push_back(0.0);
00136 }
00137
00138 KDL::Vector gravity(gravity_vector.x,gravity_vector.y,gravity_vector.z);
00139 gravity_ = gravity.Norm();
00140 logDebug("Gravity norm set to %f", gravity_);
00141
00142 chain_id_solver_.reset(new KDL::ChainIdSolver_RNE(kdl_chain_, gravity));
00143 }
00144
00145 bool DynamicsSolver::getTorques(const std::vector<double> &joint_angles,
00146 const std::vector<double> &joint_velocities,
00147 const std::vector<double> &joint_accelerations,
00148 const std::vector<geometry_msgs::Wrench> &wrenches,
00149 std::vector<double> &torques) const
00150 {
00151 if(!joint_model_group_)
00152 {
00153 logDebug("Did not construct DynamicsSolver object properly. Check error logs.");
00154 return false;
00155 }
00156 if(joint_angles.size() != num_joints_)
00157 {
00158 logError("Joint angles vector should be size %d", num_joints_);
00159 return false;
00160 }
00161 if(joint_velocities.size() != num_joints_)
00162 {
00163 logError("Joint velocities vector should be size %d", num_joints_);
00164 return false;
00165 }
00166 if(joint_accelerations.size() != num_joints_)
00167 {
00168 logError("Joint accelerations vector should be size %d", num_joints_);
00169 return false;
00170 }
00171 if(wrenches.size() != num_segments_)
00172 {
00173 logError("Wrenches vector should be size %d", num_segments_);
00174 return false;
00175 }
00176 if(torques.size() != num_joints_)
00177 {
00178 logError("Torques vector should be size %d", num_joints_);
00179 return false;
00180 }
00181
00182 KDL::JntArray kdl_angles(num_joints_), kdl_velocities(num_joints_), kdl_accelerations(num_joints_), kdl_torques(num_joints_);
00183 KDL::Wrenches kdl_wrenches(num_segments_);
00184
00185 for(unsigned int i=0; i < num_joints_; ++i)
00186 {
00187 kdl_angles(i) = joint_angles[i];
00188 kdl_velocities(i) = joint_velocities[i];
00189 kdl_accelerations(i) = joint_accelerations[i];
00190 }
00191
00192 for(unsigned int i=0; i < num_segments_; ++i)
00193 {
00194 kdl_wrenches[i](0) = wrenches[i].force.x;
00195 kdl_wrenches[i](1) = wrenches[i].force.y;
00196 kdl_wrenches[i](2) = wrenches[i].force.z;
00197
00198 kdl_wrenches[i](3) = wrenches[i].torque.x;
00199 kdl_wrenches[i](4) = wrenches[i].torque.y;
00200 kdl_wrenches[i](5) = wrenches[i].torque.z;
00201 }
00202
00203 if(chain_id_solver_->CartToJnt(kdl_angles, kdl_velocities, kdl_accelerations, kdl_wrenches, kdl_torques) < 0)
00204 {
00205 logError("Something went wrong computing torques");
00206 return false;
00207 }
00208
00209 for(unsigned int i=0; i < num_joints_; ++i)
00210 torques[i] = kdl_torques(i);
00211
00212 return true;
00213 }
00214
00215 bool DynamicsSolver::getMaxPayload(const std::vector<double> &joint_angles,
00216 double &payload,
00217 unsigned int &joint_saturated) const
00218 {
00219 if(!joint_model_group_)
00220 {
00221 logDebug("Did not construct DynamicsSolver object properly. Check error logs.");
00222 return false;
00223 }
00224 if(joint_angles.size() != num_joints_)
00225 {
00226 logError("Joint angles vector should be size %d", num_joints_);
00227 return false;
00228 }
00229 std::vector<double> joint_velocities(num_joints_, 0.0), joint_accelerations(num_joints_, 0.0);
00230 std::vector<double> torques(num_joints_, 0.0), zero_torques(num_joints_, 0.0);
00231
00232 std::vector<geometry_msgs::Wrench> wrenches(num_segments_);
00233 if(!getTorques(joint_angles, joint_velocities, joint_accelerations, wrenches, zero_torques))
00234 return false;
00235
00236 for(unsigned int i=0; i < num_joints_; ++i)
00237 {
00238 if(fabs(zero_torques[i]) >= max_torques_[i])
00239 {
00240 payload = 0.0;
00241 joint_saturated = i;
00242 return true;
00243 }
00244 }
00245
00246 joint_state_group_->setVariableValues(joint_angles);
00247 const Eigen::Affine3d &base_frame = kinematic_state_->getFrameTransform(base_name_);
00248 const Eigen::Affine3d &tip_frame = kinematic_state_->getFrameTransform(tip_name_);
00249 Eigen::Affine3d transform = tip_frame.inverse() * base_frame;
00250 wrenches.back().force.z = 1.0;
00251 wrenches.back().force = transformVector(transform, wrenches.back().force);
00252 wrenches.back().torque = transformVector(transform, wrenches.back().torque);
00253
00254 logDebug("New wrench (local frame): %f %f %f", wrenches.back().force.x, wrenches.back().force.y, wrenches.back().force.z);
00255
00256 if(!getTorques(joint_angles, joint_velocities, joint_accelerations, wrenches, torques))
00257 return false;
00258
00259 double min_payload = std::numeric_limits<double>::max();
00260 for(unsigned int i=0; i < num_joints_; ++i)
00261 {
00262 double payload_joint = std::max<double>((max_torques_[i]-zero_torques[i])/(torques[i]-zero_torques[i]),(-max_torques_[i]-zero_torques[i])/(torques[i]-zero_torques[i]));
00263 logDebug("Joint: %d, Actual Torque: %f, Max Allowed: %f, Gravity: %f", i, torques[i], max_torques_[i], zero_torques[i]);
00264 logDebug("Joint: %d, Payload Allowed (N): %f", i, payload_joint);
00265 if(payload_joint < min_payload)
00266 {
00267 min_payload = payload_joint;
00268 joint_saturated = i;
00269 }
00270 }
00271 payload = min_payload/gravity_;
00272 logDebug("Max payload (kg): %f", payload);
00273 return true;
00274 }
00275
00276 bool DynamicsSolver::getPayloadTorques(const std::vector<double> &joint_angles,
00277 double payload,
00278 std::vector<double> &joint_torques) const
00279 {
00280 if(!joint_model_group_)
00281 {
00282 logDebug("Did not construct DynamicsSolver object properly. Check error logs.");
00283 return false;
00284 }
00285 if(joint_angles.size() != num_joints_)
00286 {
00287 logError("Joint angles vector should be size %d", num_joints_);
00288 return false;
00289 }
00290 if(joint_torques.size() != num_joints_)
00291 {
00292 logError("Joint torques vector should be size %d", num_joints_);
00293 return false;
00294 }
00295 std::vector<double> joint_velocities(num_joints_, 0.0), joint_accelerations(num_joints_, 0.0);
00296 std::vector<geometry_msgs::Wrench> wrenches(num_segments_);
00297
00298 joint_state_group_->setVariableValues(joint_angles);
00299 const Eigen::Affine3d &base_frame = kinematic_state_->getFrameTransform(base_name_);
00300 const Eigen::Affine3d &tip_frame = kinematic_state_->getFrameTransform(tip_name_);
00301 Eigen::Affine3d transform = tip_frame.inverse()* base_frame;
00302 wrenches.back().force.z = payload * gravity_;
00303 wrenches.back().force = transformVector(transform, wrenches.back().force);
00304 wrenches.back().torque = transformVector(transform, wrenches.back().torque);
00305
00306 logDebug("New wrench (local frame): %f %f %f", wrenches.back().force.x, wrenches.back().force.y, wrenches.back().force.z);
00307
00308 if(!getTorques(joint_angles, joint_velocities, joint_accelerations, wrenches, joint_torques))
00309 return false;
00310 return true;
00311 }
00312
00313 const std::vector<double>& DynamicsSolver::getMaxTorques() const
00314 {
00315 return max_torques_;
00316 }
00317
00318 }