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