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
00037 #include <chomp_motion_planner/chomp_optimizer.h>
00038 #include <ros/ros.h>
00039 #include <visualization_msgs/MarkerArray.h>
00040 #include <chomp_motion_planner/chomp_utils.h>
00041 #include <planning_models/kinematic_model.h>
00042 #include <eigen3/Eigen/LU>
00043 #include <eigen3/Eigen/Core>
00044 #include <ros/console.h>
00045 using namespace std;
00046 using namespace Eigen;
00047 using namespace planning_models;
00048 using namespace collision_proximity;
00049 using namespace arm_navigation_msgs;
00050 using namespace trajectory_msgs;
00051
00052 namespace chomp
00053 {
00054 double getRandomDouble()
00055 {
00056 return ((double)random() / (double)RAND_MAX);
00057 }
00058
00059 ChompOptimizer::ChompOptimizer(ChompTrajectory *trajectory, KinematicModel *robot_model,
00060 const string& planning_group,const ChompParameters *parameters, const ros::Publisher& vis_marker_array_publisher,
00061 const ros::Publisher& vis_marker_publisher, CollisionProximitySpace *collision_space) :
00062 full_trajectory_(trajectory), robot_model_(robot_model), planning_group_(planning_group), parameters_(parameters),
00063 collision_space_(collision_space), group_trajectory_(*full_trajectory_, planning_group_, DIFF_RULE_LENGTH),
00064 vis_marker_array_pub_(vis_marker_array_publisher), vis_marker_pub_(vis_marker_publisher)
00065 {
00066 initialize();
00067 }
00068
00069 void ChompOptimizer::initialize()
00070 {
00071 robot_state_ = collision_space_->getCollisionModelsInterface()->getPlanningSceneState();
00072
00073 num_vars_free_ = group_trajectory_.getNumFreePoints();
00074 num_vars_all_ = group_trajectory_.getNumPoints();
00075 num_joints_ = group_trajectory_.getNumJoints();
00076
00077 free_vars_start_ = group_trajectory_.getStartIndex();
00078 free_vars_end_ = group_trajectory_.getEndIndex();
00079
00080 vector<GradientInfo> infos;
00081 collision_space_->getStateGradients(infos);
00082
00083 num_collision_points_ = 0;
00084 for(size_t i = 0; i < infos.size(); i++)
00085 {
00086 GradientInfo& info = infos[i];
00087 num_collision_points_ += info.sphere_locations.size();
00088
00089 }
00090
00091
00092 joint_costs_.reserve(num_joints_);
00093
00094 double max_cost_scale = 0.0;
00095 ros::NodeHandle nh("~");
00096
00097 map<string, KinematicModel::JointModelGroup*> jointMap = robot_model_->getJointModelGroupMap();
00098 KinematicModel::JointModelGroup* jointModelGroup = jointMap[planning_group_];
00099 vector<const KinematicModel::JointModel*> jointModels = jointModelGroup->getJointModels();
00100 for(size_t i = 0; i < jointModels.size(); i++)
00101 {
00102 const KinematicModel::JointModel* model = jointModels[i];
00103 double joint_cost = 1.0;
00104 string joint_name = model->getName();
00105 nh.param("joint_costs/" + joint_name, joint_cost, 1.0);
00106 vector<double> derivative_costs(3);
00107 derivative_costs[0] = joint_cost * parameters_->getSmoothnessCostVelocity();
00108 derivative_costs[1] = joint_cost * parameters_->getSmoothnessCostAcceleration();
00109 derivative_costs[2] = joint_cost * parameters_->getSmoothnessCostJerk();
00110
00111 joint_costs_.push_back(ChompCost(group_trajectory_, i, derivative_costs, parameters_->getRidgeFactor()));
00112 double cost_scale = joint_costs_[i].getMaxQuadCostInvValue();
00113 if(max_cost_scale < cost_scale)
00114 max_cost_scale = cost_scale;
00115 }
00116
00117
00118 for(int i = 0; i < num_joints_; i++)
00119 {
00120 joint_costs_[i].scale(max_cost_scale);
00121 }
00122
00123
00124 smoothness_increments_ = MatrixXd::Zero(num_vars_free_, num_joints_);
00125 collision_increments_ = MatrixXd::Zero(num_vars_free_, num_joints_);
00126 final_increments_ = MatrixXd::Zero(num_vars_free_, num_joints_);
00127 smoothness_derivative_ = VectorXd::Zero(num_vars_all_);
00128 jacobian_ = MatrixXd::Zero(3, num_joints_);
00129 jacobian_pseudo_inverse_ = MatrixXd::Zero(num_joints_, 3);
00130 jacobian_jacobian_tranpose_ = MatrixXd::Zero(3, 3);
00131 random_state_ = VectorXd::Zero(num_joints_);
00132 joint_state_velocities_ = VectorXd::Zero(num_joints_);
00133
00134 group_trajectory_backup_ = group_trajectory_.getTrajectory();
00135 best_group_trajectory_ = group_trajectory_.getTrajectory();
00136
00137 collision_point_joint_names_.resize(num_vars_all_, vector<string>(num_collision_points_));
00138 collision_point_pos_eigen_.resize(num_vars_all_, vector<Vector3d>(num_collision_points_));
00139 collision_point_vel_eigen_.resize(num_vars_all_, vector<Vector3d>(num_collision_points_));
00140 collision_point_acc_eigen_.resize(num_vars_all_, vector<Vector3d>(num_collision_points_));
00141 joint_axes_.resize(num_vars_all_, vector<tf::Vector3>(num_joints_));
00142 joint_positions_.resize(num_vars_all_, vector<tf::Vector3>(num_joints_));
00143
00144 collision_point_potential_.resize(num_vars_all_, vector<double>(num_collision_points_));
00145 collision_point_vel_mag_.resize(num_vars_all_, vector<double>(num_collision_points_));
00146 collision_point_potential_gradient_.resize(num_vars_all_, vector<Vector3d>(num_collision_points_));
00147
00148 collision_free_iteration_ = 0;
00149 is_collision_free_ = false;
00150 state_is_in_collision_.resize(num_vars_all_);
00151 point_is_in_collision_.resize(num_vars_all_, vector<int>(num_collision_points_));
00152
00153 last_improvement_iteration_ = -1;
00154
00155
00156 momentum_ = MatrixXd::Zero(num_vars_free_, num_joints_);
00157 random_momentum_ = MatrixXd::Zero(num_vars_free_, num_joints_);
00158 random_joint_momentum_ = VectorXd::Zero(num_vars_free_);
00159 multivariate_gaussian_.clear();
00160 stochasticity_factor_ = 1.0;
00161 for(int i = 0; i < num_joints_; i++)
00162 {
00163 multivariate_gaussian_.push_back(
00164 MultivariateGaussian(VectorXd::Zero(num_vars_free_),
00165 joint_costs_[i].getQuadraticCostInverse()));
00166 }
00167
00168 map<string, KinematicModel::JointModelGroup*> groupMap = robot_model_->getJointModelGroupMap();
00169 KinematicModel::JointModelGroup* modelGroup = groupMap[planning_group_];
00170 map<string, string> fixedLinkResolutionMap;
00171 for(int i = 0; i < num_joints_; i++)
00172 {
00173 joint_names_.push_back(modelGroup->getJointModels()[i]->getName());
00174 ROS_INFO("Got joint %s", joint_names_[i].c_str());
00175 registerParents(modelGroup->getJointModels()[i]);
00176 fixedLinkResolutionMap[joint_names_[i]] = joint_names_[i];
00177 }
00178
00179 for(size_t i = 0; i < modelGroup->getFixedJointModels().size(); i ++)
00180 {
00181 const KinematicModel::JointModel* model = modelGroup->getFixedJointModels()[i];
00182 fixedLinkResolutionMap[model->getName()] = model->getParentLinkModel()->getParentJointModel()->getName();
00183 }
00184
00185 for(size_t i = 0; i < modelGroup->getUpdatedLinkModels().size(); i ++)
00186 {
00187 if(fixedLinkResolutionMap.find(modelGroup->getUpdatedLinkModels()[i]->getParentJointModel()->getName()) == fixedLinkResolutionMap.end())
00188 {
00189 const KinematicModel::JointModel* parentModel = NULL;
00190 bool foundRoot = false;
00191
00192 while(!foundRoot)
00193 {
00194 if(parentModel == NULL)
00195 {
00196 parentModel = modelGroup->getUpdatedLinkModels()[i]->getParentJointModel();
00197 }
00198 else
00199 {
00200 parentModel = parentModel->getParentLinkModel()->getParentJointModel();
00201 for(size_t j = 0; j < joint_names_.size(); j++)
00202 {
00203 if(parentModel->getName() == joint_names_[j])
00204 {
00205 foundRoot = true;
00206 }
00207 }
00208 }
00209 }
00210 fixedLinkResolutionMap[modelGroup->getUpdatedLinkModels()[i]->getParentJointModel()->getName()] = parentModel->getName();
00211 }
00212 }
00213
00214 for(map<string, map<string, bool> >::iterator it = joint_parent_map_.begin(); it != joint_parent_map_.end(); it++)
00215 {
00216 stringstream ss;
00217 ss << it->first << " Parents : {";
00218
00219 for(map<string, bool>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++)
00220 {
00221 ss << it2->first << ",";
00222 }
00223 ss << "}";
00224 ROS_INFO("%s",ss.str().c_str());
00225 }
00226
00227 int start = free_vars_start_;
00228 int end = free_vars_end_;
00229 vector<GradientInfo> gradients;
00230 collision_space_->getStateGradients(gradients);
00231 for(int i = start; i <= end; ++i)
00232 {
00233 size_t j = 0;
00234 for(size_t g = 0; g < gradients.size(); g++)
00235 {
00236 GradientInfo& info = gradients[g];
00237
00238 for(size_t k = 0; k < info.sphere_locations.size(); k++)
00239 {
00240 if(fixedLinkResolutionMap.find(info.joint_name) != fixedLinkResolutionMap.end())
00241 {
00242 collision_point_joint_names_[i][j] = fixedLinkResolutionMap[info.joint_name];
00243 }
00244 else
00245 {
00246 ROS_ERROR("Couldn't find joint %s!", info.joint_name.c_str());
00247 }
00248 j++;
00249 }
00250 }
00251 }
00252 }
00253
00254 ChompOptimizer::~ChompOptimizer()
00255 {
00256 destroy();
00257 }
00258
00259 void ChompOptimizer::registerParents(const KinematicModel::JointModel* model)
00260 {
00261 const KinematicModel::JointModel* parentModel = NULL;
00262 bool foundRoot = false;
00263
00264 if(model == robot_model_->getRoot()) return;
00265
00266 while(!foundRoot)
00267 {
00268 if(parentModel == NULL)
00269 {
00270 if(model->getParentLinkModel() == NULL) {
00271 ROS_ERROR_STREAM("Model " << model->getName() << " not root but has NULL link model parent");
00272 return;
00273 } else if(model->getParentLinkModel()->getParentJointModel() == NULL) {
00274 ROS_ERROR_STREAM("Model " << model->getName() << " not root but has NULL joint model parent");
00275 return;
00276 }
00277 parentModel = model->getParentLinkModel()->getParentJointModel();
00278 } else
00279 {
00280 if(parentModel == robot_model_->getRoot())
00281 {
00282 foundRoot = true;
00283 } else {
00284 parentModel = parentModel->getParentLinkModel()->getParentJointModel();
00285 }
00286 }
00287 joint_parent_map_[model->getName()][parentModel->getName()] = true;
00288 }
00289 }
00290
00291 void ChompOptimizer::optimize()
00292 {
00293 ros::WallTime start_time = ros::WallTime::now();
00294 double averageCostVelocity = 0.0;
00295 int currentCostIter = 0;
00296 int costWindow = 10;
00297 vector<double>costs(costWindow, 0.0);
00298 double minimaThreshold = 0.05;
00299 bool shouldBreakOut = false;
00300
00301 if(parameters_->getAnimatePath())
00302 {
00303 animatePath();
00304 }
00305
00306
00307 for(iteration_ = 0; iteration_ < parameters_->getMaxIterations(); iteration_++)
00308 {
00309 ros::WallTime for_time = ros::WallTime::now();
00310 performForwardKinematics();
00311 ROS_DEBUG_STREAM("Forward kinematics took " << (ros::WallTime::now()-for_time));
00312 double cCost = getCollisionCost();
00313 double sCost = getSmoothnessCost();
00314 double cost = cCost + sCost;
00315
00316 if(parameters_->getAddRandomness() && currentCostIter != -1)
00317 {
00318 costs[currentCostIter] = cCost;
00319 currentCostIter++;
00320
00321 if(currentCostIter >= costWindow)
00322 {
00323 for(int i = 1; i < costWindow; i++)
00324 {
00325 averageCostVelocity += (costs.at(i) - costs.at(i - 1));
00326 }
00327
00328 averageCostVelocity /= (double)(costWindow);
00329 currentCostIter = -1;
00330 }
00331 }
00332 if(iteration_ == 0)
00333 {
00334 best_group_trajectory_ = group_trajectory_.getTrajectory();
00335 best_group_trajectory_cost_ = cost;
00336 }
00337 else
00338 {
00339 if(cost < best_group_trajectory_cost_)
00340 {
00341 best_group_trajectory_ = group_trajectory_.getTrajectory();
00342 best_group_trajectory_cost_ = cost;
00343 last_improvement_iteration_ = iteration_;
00344 }
00345 }
00346 calculateSmoothnessIncrements();
00347 ros::WallTime coll_time = ros::WallTime::now();
00348 calculateCollisionIncrements();
00349 ROS_DEBUG_STREAM("Collision increments took " << (ros::WallTime::now()-coll_time));
00350 calculateTotalIncrements();
00351
00352 if(!parameters_->getUseHamiltonianMonteCarlo())
00353 {
00354
00355 addIncrementsToTrajectory();
00356 }
00357 else
00358 {
00359
00360 getRandomMomentum();
00361 updateMomentum();
00362 updatePositionFromMomentum();
00363 stochasticity_factor_ *= parameters_->getHmcAnnealingFactor();
00364 }
00365 handleJointLimits();
00366 updateFullTrajectory();
00367
00368 if(iteration_ % 10 == 0)
00369 {
00370 ROS_DEBUG("Trajectory cost: %f (s=%f, c=%f)", getTrajectoryCost(), getSmoothnessCost(), getCollisionCost());
00371 CollisionProximitySpace::TrajectorySafety safety = checkCurrentIterValidity();
00372 if(safety == CollisionProximitySpace::MeshToMeshSafe)
00373 {
00374 num_collision_free_iterations_ = 0;
00375 ROS_INFO("Chomp Got mesh to mesh safety at iter %d. Breaking out early.", iteration_);
00376 is_collision_free_ = true;
00377 iteration_++;
00378 shouldBreakOut = true;
00379 } else if(safety == CollisionProximitySpace::InCollisionSafe) {
00380 num_collision_free_iterations_ = parameters_->getMaxIterationsAfterCollisionFree();
00381 ROS_INFO("Chomp Got in collision safety at iter %d. Breaking out soon.", iteration_);
00382 is_collision_free_ = true;
00383 iteration_++;
00384 shouldBreakOut = true;
00385 }
00386 else
00387 {
00388 is_collision_free_ = false;
00389 }
00390 }
00391
00392 if(!parameters_->getFilterMode())
00393 {
00394 if(cCost < parameters_->getCollisionThreshold())
00395 {
00396 is_collision_free_ = true;
00397 iteration_++;
00398 shouldBreakOut = true;
00399 }
00400 }
00401
00402
00403 if((ros::WallTime::now() - start_time).toSec() > parameters_->getPlanningTimeLimit() && !parameters_->getAnimatePath() && !parameters_->getAnimateEndeffector())
00404 {
00405 ROS_WARN("Breaking out early due to time limit constraints.");
00406 break;
00407 }
00408
00409 if(fabs(averageCostVelocity) < minimaThreshold && currentCostIter == -1 && !is_collision_free_ && parameters_->getAddRandomness())
00410 {
00411 ROS_INFO("Detected local minima. Attempting to break out!");
00412 int iter = 0;
00413 bool success = false;
00414 while(iter < 20 && !success)
00415 {
00416 performForwardKinematics();
00417 double original_cost = getTrajectoryCost();
00418 group_trajectory_backup_ = group_trajectory_.getTrajectory();
00419 perturbTrajectory();
00420 handleJointLimits();
00421 updateFullTrajectory();
00422 performForwardKinematics();
00423 double new_cost = getTrajectoryCost();
00424 iter ++;
00425 if(new_cost < original_cost)
00426 {
00427 ROS_INFO("Got out of minimum in %d iters!", iter);
00428 averageCostVelocity = 0.0;
00429 currentCostIter = 0;
00430 success = true;
00431 }
00432 else
00433 {
00434 group_trajectory_.getTrajectory() = group_trajectory_backup_;
00435 updateFullTrajectory();
00436 currentCostIter = 0;
00437 averageCostVelocity = 0.0;
00438 success = false;
00439 }
00440
00441 }
00442
00443 if(!success)
00444 {
00445 ROS_INFO("Failed to exit minimum!");
00446 }
00447 }
00448 else if(currentCostIter == -1)
00449 {
00450 currentCostIter = 0;
00451 averageCostVelocity = 0.0;
00452 }
00453
00454 if(parameters_->getAnimateEndeffector())
00455 {
00456 animateEndeffector();
00457 }
00458
00459 if(parameters_->getAnimatePath() && iteration_ % 25 == 0)
00460 {
00461 animatePath();
00462 }
00463
00464 if(shouldBreakOut)
00465 {
00466 collision_free_iteration_++;
00467 if(num_collision_free_iterations_ == 0) {
00468 break;
00469 } else if(collision_free_iteration_ > num_collision_free_iterations_)
00470 {
00471 CollisionProximitySpace::TrajectorySafety safety = checkCurrentIterValidity();
00472 if(safety != CollisionProximitySpace::MeshToMeshSafe &&
00473 safety != CollisionProximitySpace::InCollisionSafe) {
00474 ROS_WARN_STREAM("Apparently regressed");
00475 }
00476 break;
00477 }
00478 }
00479 }
00480
00481 if(is_collision_free_)
00482 {
00483 ROS_INFO("Chomp path is collision free");
00484 }
00485 else
00486 {
00487 ROS_ERROR("Chomp path is not collision free!");
00488 }
00489
00490 if(parameters_->getAnimatePath())
00491 {
00492 animatePath();
00493 }
00494
00495 group_trajectory_.getTrajectory() = best_group_trajectory_;
00496 updateFullTrajectory();
00497
00498 if(parameters_->getAnimatePath())
00499 animatePath();
00500
00501 ROS_INFO("Terminated after %d iterations, using path from iteration %d", iteration_, last_improvement_iteration_);
00502 ROS_INFO("Optimization core finished in %f sec", (ros::WallTime::now() - start_time).toSec() );
00503 ROS_INFO_STREAM("Time per iteration " << (ros::WallTime::now() - start_time).toSec()/(iteration_*1.0));
00504 }
00505
00506 CollisionProximitySpace::TrajectorySafety ChompOptimizer::checkCurrentIterValidity()
00507 {
00508 JointTrajectory jointTrajectory;
00509 jointTrajectory.joint_names = joint_names_;
00510 jointTrajectory.header.frame_id = collision_space_->getCollisionModelsInterface()->getRobotFrameId();
00511 jointTrajectory.header.stamp = ros::Time::now();
00512 Constraints goalConstraints;
00513 Constraints pathConstraints;
00514 ArmNavigationErrorCodes errorCode;
00515 vector<ArmNavigationErrorCodes> trajectoryErrorCodes;
00516 for(int i = 0; i < group_trajectory_.getNumPoints(); i++)
00517 {
00518 JointTrajectoryPoint point;
00519 for(int j = 0; j < group_trajectory_.getNumJoints(); j++)
00520 {
00521 point.positions.push_back(best_group_trajectory_(i, j));
00522 }
00523 jointTrajectory.points.push_back(point);
00524 }
00525
00526 return collision_space_->isTrajectorySafe(jointTrajectory, goalConstraints, pathConstraints, planning_group_);
00527
00528
00529
00530
00531
00532
00533
00534
00535 }
00536
00537 void ChompOptimizer::calculateSmoothnessIncrements()
00538 {
00539 for(int i = 0; i < num_joints_; i++)
00540 {
00541 joint_costs_[i].getDerivative(group_trajectory_.getJointTrajectory(i), smoothness_derivative_);
00542 smoothness_increments_.col(i)
00543 = -smoothness_derivative_.segment(group_trajectory_.getStartIndex(), num_vars_free_);
00544 }
00545 }
00546
00547 void ChompOptimizer::calculateCollisionIncrements()
00548 {
00549 double potential;
00550 double vel_mag_sq;
00551 double vel_mag;
00552 Vector3d potential_gradient;
00553 Vector3d normalized_velocity;
00554 Matrix3d orthogonal_projector;
00555 Vector3d curvature_vector;
00556 Vector3d cartesian_gradient;
00557
00558
00559 collision_increments_.setZero(num_vars_free_, num_joints_);
00560
00561 int startPoint = 0;
00562 int endPoint = free_vars_end_;
00563
00564
00565
00566 if(parameters_->getUseStochasticDescent())
00567 {
00568 startPoint = (int)(((double)random() / (double)RAND_MAX)*(free_vars_end_ - free_vars_start_) + free_vars_start_);
00569 if(startPoint < free_vars_start_) startPoint = free_vars_start_;
00570 if(startPoint > free_vars_end_) startPoint = free_vars_end_;
00571 endPoint = startPoint;
00572 }
00573 else
00574 {
00575 startPoint = free_vars_start_;
00576 }
00577
00578 for(int i = startPoint; i <= endPoint; i++)
00579 {
00580 for(int j = 0; j < num_collision_points_; j++)
00581 {
00582 potential = collision_point_potential_[i][j];
00583
00584 if(potential < 0.0001)
00585 continue;
00586
00587 potential_gradient = -collision_point_potential_gradient_[i][j];
00588
00589 vel_mag = collision_point_vel_mag_[i][j];
00590 vel_mag_sq = vel_mag * vel_mag;
00591
00592
00593
00594 normalized_velocity = collision_point_vel_eigen_[i][j] / vel_mag;
00595 orthogonal_projector = Matrix3d::Identity() - (normalized_velocity * normalized_velocity.transpose());
00596 curvature_vector = (orthogonal_projector * collision_point_acc_eigen_[i][j]) / vel_mag_sq;
00597 cartesian_gradient = vel_mag * (orthogonal_projector * potential_gradient - potential * curvature_vector);
00598
00599
00600 getJacobian(i, collision_point_pos_eigen_[i][j], collision_point_joint_names_[i][j] ,jacobian_);
00601
00602 if(parameters_->getUsePseudoInverse())
00603 {
00604 calculatePseudoInverse();
00605 collision_increments_.row(i - free_vars_start_).transpose() -= jacobian_pseudo_inverse_ * cartesian_gradient;
00606 }
00607 else
00608 {
00609 collision_increments_.row(i - free_vars_start_).transpose() -= jacobian_.transpose() * cartesian_gradient;
00610 }
00611
00612
00613
00614
00615
00616
00617
00618 }
00619 }
00620
00621 }
00622
00623 void ChompOptimizer::calculatePseudoInverse()
00624 {
00625 jacobian_jacobian_tranpose_ = jacobian_ * jacobian_.transpose() + MatrixXd::Identity(3, 3)
00626 * parameters_->getPseudoInverseRidgeFactor();
00627 jacobian_pseudo_inverse_ = jacobian_.transpose() * jacobian_jacobian_tranpose_.inverse();
00628 }
00629
00630 void ChompOptimizer::calculateTotalIncrements()
00631 {
00632 for(int i = 0; i < num_joints_; i++)
00633 {
00634 final_increments_.col(i) = parameters_->getLearningRate() * (joint_costs_[i].getQuadraticCostInverse()
00635 * (parameters_->getSmoothnessCostWeight() * smoothness_increments_.col(i)
00636 + parameters_->getObstacleCostWeight() * collision_increments_.col(i)));
00637 }
00638
00639 }
00640
00641 void ChompOptimizer::addIncrementsToTrajectory()
00642 {
00643 map<string, KinematicModel::JointModelGroup*> modelGroups = robot_model_->getJointModelGroupMap();
00644 string group = planning_group_;
00645 const KinematicModel::JointModelGroup* modelGroup = modelGroups[group];
00646 const vector<const KinematicModel::JointModel*>& jointModels = modelGroup->getJointModels();
00647
00648 for(size_t i = 0; i < jointModels.size(); i++)
00649 {
00650 double scale = 1.0;
00651 double max = final_increments_.col(i).maxCoeff();
00652 double min = final_increments_.col(i).minCoeff();
00653 double max_scale = parameters_->getJointUpdateLimit() / fabs(max);
00654 double min_scale = parameters_->getJointUpdateLimit() / fabs(min);
00655 if(max_scale < scale)
00656 scale = max_scale;
00657 if(min_scale < scale)
00658 scale = min_scale;
00659 group_trajectory_.getFreeTrajectoryBlock().col(i) += scale * final_increments_.col(i);
00660 }
00661
00662
00663 }
00664
00665 void ChompOptimizer::updateFullTrajectory()
00666 {
00667 full_trajectory_->updateFromGroupTrajectory(group_trajectory_);
00668 }
00669
00670 void ChompOptimizer::debugCost()
00671 {
00672 double cost = 0.0;
00673 for(int i = 0; i < num_joints_; i++)
00674 cost += joint_costs_[i].getCost(group_trajectory_.getJointTrajectory(i));
00675 cout << "Cost = " << cost << endl;
00676 }
00677
00678 double ChompOptimizer::getTrajectoryCost()
00679 {
00680 return getSmoothnessCost() + getCollisionCost();
00681 }
00682
00683 double ChompOptimizer::getSmoothnessCost()
00684 {
00685 double smoothness_cost = 0.0;
00686
00687 for(int i = 0; i < num_joints_; i++)
00688 smoothness_cost += joint_costs_[i].getCost(group_trajectory_.getJointTrajectory(i));
00689
00690 return parameters_->getSmoothnessCostWeight() * smoothness_cost;
00691 }
00692
00693 double ChompOptimizer::getCollisionCost()
00694 {
00695 double collision_cost = 0.0;
00696
00697 double worst_collision_cost = 0.0;
00698 worst_collision_cost_state_ = -1;
00699
00700
00701 for(int i = free_vars_start_; i <= free_vars_end_; i++)
00702 {
00703 double state_collision_cost = 0.0;
00704 for(int j = 0; j < num_collision_points_; j++)
00705 {
00706 state_collision_cost += collision_point_potential_[i][j] * collision_point_vel_mag_[i][j];
00707 }
00708 collision_cost += state_collision_cost;
00709 if(state_collision_cost > worst_collision_cost)
00710 {
00711 worst_collision_cost = state_collision_cost;
00712 worst_collision_cost_state_ = i;
00713 }
00714 }
00715
00716 return parameters_->getObstacleCostWeight() * collision_cost;
00717 }
00718
00719 void ChompOptimizer::computeJointProperties(int trajectoryPoint)
00720 {
00721 tf::Transform inverseWorldTransform = collision_space_->getInverseWorldTransform(*robot_state_);
00722 for(int j = 0; j < num_joints_; j++)
00723 {
00724 string jointName = joint_names_[j];
00725 const KinematicState::JointState* jointState = robot_state_->getJointState(jointName);
00726 const KinematicModel::JointModel* jointModel = jointState->getJointModel();
00727 const KinematicModel::RevoluteJointModel* revoluteJoint = dynamic_cast<const KinematicModel::RevoluteJointModel*>(jointModel);
00728 const KinematicModel::PrismaticJointModel* prismaticJoint = dynamic_cast<const KinematicModel::PrismaticJointModel*>(jointModel);
00729
00730 string parentLinkName = jointModel->getParentLinkModel()->getName();
00731 string childLinkName = jointModel->getChildLinkModel()->getName();
00732 tf::Transform jointTransform =
00733 robot_state_->getLinkState(parentLinkName)->getGlobalLinkTransform()
00734 * (robot_model_->getLinkModel(childLinkName)->getJointOriginTransform()
00735 * (robot_state_->getJointState(jointModel->getName())->getVariableTransform()));
00736
00737
00738 jointTransform = inverseWorldTransform * jointTransform;
00739 tf::Vector3 axis;
00740
00741
00742 if(revoluteJoint != NULL)
00743 {
00744 axis = revoluteJoint->axis_;
00745 }
00746 else if(prismaticJoint != NULL)
00747 {
00748 axis = prismaticJoint->axis_;
00749 }
00750
00751 axis = jointTransform * axis;
00752
00753 joint_axes_[trajectoryPoint][j] = axis;
00754 joint_positions_[trajectoryPoint][j] = jointTransform.getOrigin();
00755 }
00756 }
00757
00758 template<typename Derived>
00759 void ChompOptimizer::getJacobian(int trajectoryPoint, Vector3d& collision_point_pos, string& jointName,
00760 MatrixBase<Derived>& jacobian) const
00761 {
00762 for(int j = 0; j < num_joints_; j++)
00763 {
00764 if(isParent(jointName, joint_names_[j]))
00765 {
00766 tf::Vector3 column = joint_axes_[trajectoryPoint][j].cross(tf::Vector3(collision_point_pos(0),
00767 collision_point_pos(1),
00768 collision_point_pos(2))
00769 - joint_positions_[trajectoryPoint][j]);
00770
00771 jacobian.col(j)[0] = column.x();
00772 jacobian.col(j)[1] = column.y();
00773 jacobian.col(j)[2] = column.z();
00774 }
00775 else
00776 {
00777 jacobian.col(j)[0] = 0.0;
00778 jacobian.col(j)[1] = 0.0;
00779 jacobian.col(j)[2] = 0.0;
00780 }
00781 }
00782 }
00783
00784 void ChompOptimizer::handleJointLimits()
00785 {
00786 map<string, KinematicModel::JointModelGroup*> modelGroups = robot_model_->getJointModelGroupMap();
00787 string group = planning_group_;
00788 KinematicModel::JointModelGroup* modelGroup = modelGroups[group];
00789
00790 for(int joint = 0; joint < num_joints_; joint++)
00791 {
00792 const string& jointName = joint_names_[joint];
00793 const KinematicModel::JointModel* jointModel = modelGroup->getJointModel(jointName);
00794 const KinematicModel::RevoluteJointModel* revoluteJoint = dynamic_cast<const KinematicModel::RevoluteJointModel*>(jointModel);
00795
00796 if(revoluteJoint->continuous_)
00797 {
00798 continue;
00799 }
00800 map<string, pair<double,double> > bounds = jointModel->getAllVariableBounds();
00801
00802 double joint_max = -10000;
00803 double joint_min = 10000;
00804
00805 for(map<string,pair<double,double> >::iterator it = bounds.begin(); it != bounds.end(); it ++)
00806 {
00807 if(it->second.first < joint_min)
00808 {
00809 joint_min = it->second.first;
00810 }
00811
00812 if(it->second.second > joint_max)
00813 {
00814 joint_max = it->second.second;
00815 }
00816 }
00817
00818
00819 int count = 0;
00820
00821 bool violation = false;
00822 do
00823 {
00824 double max_abs_violation = 1e-6;
00825 double max_violation = 0.0;
00826 int max_violation_index = 0;
00827 violation = false;
00828 for(int i = free_vars_start_; i <= free_vars_end_; i++)
00829 {
00830 double amount = 0.0;
00831 double absolute_amount = 0.0;
00832 if(group_trajectory_(i, joint) > joint_max)
00833 {
00834 amount = joint_max - group_trajectory_(i, joint);
00835 absolute_amount = fabs(amount);
00836 }
00837 else if(group_trajectory_(i, joint) < joint_min)
00838 {
00839 amount = joint_min - group_trajectory_(i, joint);
00840 absolute_amount = fabs(amount);
00841 }
00842 if(absolute_amount > max_abs_violation)
00843 {
00844 max_abs_violation = absolute_amount;
00845 max_violation = amount;
00846 max_violation_index = i;
00847 violation = true;
00848 }
00849 }
00850
00851 if(violation)
00852 {
00853 int free_var_index = max_violation_index - free_vars_start_;
00854 double multiplier = max_violation / joint_costs_[joint].getQuadraticCostInverse()(free_var_index,
00855 free_var_index);
00856 group_trajectory_.getFreeJointTrajectoryBlock(joint) += multiplier
00857 * joint_costs_[joint].getQuadraticCostInverse().col(free_var_index);
00858 }
00859 if(++count > 10)
00860 break;
00861 }
00862 while(violation);
00863 }
00864 }
00865
00866 void ChompOptimizer::performForwardKinematics()
00867 {
00868 double invTime = 1.0 / group_trajectory_.getDiscretization();
00869 double invTimeSq = invTime * invTime;
00870
00871
00872 int start = free_vars_start_;
00873 int end = free_vars_end_;
00874 if(iteration_ == 0)
00875 {
00876 start = 0;
00877 end = num_vars_all_ - 1;
00878 }
00879
00880 is_collision_free_ = true;
00881
00882
00883 for(int i = start; i <= end; ++i)
00884 {
00885
00886 setRobotStateFromPoint(group_trajectory_, i);
00887 computeJointProperties(i);
00888 state_is_in_collision_[i] = false;
00889
00890 vector<GradientInfo> gradients;
00891 collision_space_->getStateGradients(gradients);
00892
00893 {
00894 size_t j = 0;
00895 for(size_t g = 0; g < gradients.size(); g++)
00896 {
00897 GradientInfo& info = gradients[g];
00898
00899 for(size_t k = 0; k < info.sphere_locations.size(); k++)
00900 {
00901 collision_point_pos_eigen_[i][j][0] = info.sphere_locations[k].x();
00902 collision_point_pos_eigen_[i][j][1] = info.sphere_locations[k].y();
00903 collision_point_pos_eigen_[i][j][2] = info.sphere_locations[k].z();
00904
00905 collision_point_potential_[i][j] = getPotential(info.distances[k], info.sphere_radii[k], parameters_->getMinClearence());
00906 collision_point_potential_gradient_[i][j][0] = info.gradients[k].x();
00907 collision_point_potential_gradient_[i][j][1] = info.gradients[k].y();
00908 collision_point_potential_gradient_[i][j][2] = info.gradients[k].z();
00909
00910 point_is_in_collision_[i][j] = (info.distances[k] - info.sphere_radii[k] < info.sphere_radii[k]);
00911
00912 if(point_is_in_collision_[i][j])
00913 {
00914 state_is_in_collision_[i] = true;
00915 is_collision_free_ = false;
00916 }
00917 j ++;
00918 }
00919 }
00920 }
00921 }
00922
00923
00924 for(int i = free_vars_start_; i <= free_vars_end_; i++)
00925 {
00926 for(int j = 0; j < num_collision_points_; j++)
00927 {
00928 collision_point_vel_eigen_[i][j] = Vector3d(0,0,0);
00929 collision_point_acc_eigen_[i][j] = Vector3d(0,0,0);
00930 for(int k = -DIFF_RULE_LENGTH / 2; k <= DIFF_RULE_LENGTH / 2; k++)
00931 {
00932 collision_point_vel_eigen_[i][j] += (invTime * DIFF_RULES[0][k + DIFF_RULE_LENGTH / 2]) * collision_point_pos_eigen_[i
00933 + k][j];
00934 collision_point_acc_eigen_[i][j] += (invTimeSq * DIFF_RULES[1][k + DIFF_RULE_LENGTH / 2]) * collision_point_pos_eigen_[i
00935 + k][j];
00936 }
00937
00938
00939 collision_point_vel_mag_[i][j] = collision_point_vel_eigen_[i][j].norm();
00940 }
00941 }
00942 }
00943
00944 void ChompOptimizer::setRobotStateFromPoint(ChompTrajectory& group_trajectory, int i)
00945 {
00946 const MatrixXd::RowXpr& point = group_trajectory.getTrajectoryPoint(i);
00947
00948 vector<double> jointStates;
00949 for(int j = 0; j < group_trajectory.getNumJoints(); j ++)
00950 {
00951 jointStates.push_back(point(0,j));
00952 }
00953
00954 ros::WallTime timer = ros::WallTime::now();
00955 KinematicState::JointStateGroup* group = (KinematicState::JointStateGroup*)(robot_state_->getJointStateGroup(planning_group_));
00956 group->setKinematicState(jointStates);
00957 timer = ros::WallTime::now();
00958 collision_space_->setCurrentGroupState(*robot_state_);
00959 }
00960
00961 void ChompOptimizer::perturbTrajectory()
00962 {
00963
00964 if(worst_collision_cost_state_ < 0)
00965 return;
00966 int mid_point = worst_collision_cost_state_;
00967 getRandomState(robot_state_, planning_group_, random_state_);
00968
00969
00970 random_state_ -= group_trajectory_.getTrajectoryPoint(mid_point).transpose();
00971
00972
00973 group_trajectory_.getJointVelocities(mid_point, joint_state_velocities_);
00974 joint_state_velocities_.normalize();
00975 random_state_ = (MatrixXd::Identity(num_joints_, num_joints_) - joint_state_velocities_
00976 * joint_state_velocities_.transpose()) * random_state_;
00977
00978 int mp_free_vars_index = mid_point - free_vars_start_;
00979 for(int i = 0; i < num_joints_; i++)
00980 {
00981 group_trajectory_.getFreeJointTrajectoryBlock(i)
00982 += joint_costs_[i].getQuadraticCostInverse().col(mp_free_vars_index) * random_state_(i);
00983 }
00984 }
00985
00986 void ChompOptimizer::getRandomState(const KinematicState* currentState, const string& groupName, VectorXd& state_vec)
00987 {
00988 const vector<KinematicState::JointState*>& jointStates =
00989 currentState->getJointStateGroup(groupName)->getJointStateVector();
00990 for(size_t i = 0; i < jointStates.size(); i++)
00991 {
00992
00993 bool continuous = false;
00994
00995 KinematicState::JointState* jointState = jointStates[i];
00996 const KinematicModel::RevoluteJointModel* revolute_joint
00997 = dynamic_cast<const KinematicModel::RevoluteJointModel*>(jointState->getJointModel());
00998 if(revolute_joint && revolute_joint->continuous_) {
00999 continuous = true;
01000 }
01001
01002 map<string, pair<double, double> > bounds = jointState->getJointModel()->getAllVariableBounds();
01003 int j = 0;
01004 for(map<string, pair<double, double> >::iterator it = bounds.begin(); it != bounds.end(); it++)
01005 {
01006 double randVal = jointState->getJointStateValues()[j] + (getRandomDouble()
01007 * (parameters_->getRandomJumpAmount()) - getRandomDouble() * (parameters_->getRandomJumpAmount()));
01008
01009 if(!continuous)
01010 {
01011 if(randVal > it->second.second)
01012 {
01013 randVal = it->second.second;
01014 }
01015 else if(randVal < it->second.first)
01016 {
01017 randVal = it->second.first;
01018 }
01019 }
01020
01021 ROS_DEBUG_STREAM("Joint " << it->first << " old value " << jointState->getJointStateValues()[j] << " new value " << randVal);
01022 state_vec(i) = randVal;
01023
01024 j++;
01025 }
01026 }
01027 }
01028
01029 void ChompOptimizer::getRandomMomentum()
01030 {
01031 if(is_collision_free_)
01032 random_momentum_.setZero(num_vars_free_, num_joints_);
01033 else
01034 for(int i = 0; i < num_joints_; ++i)
01035 {
01036 multivariate_gaussian_[i].sample(random_joint_momentum_);
01037 random_momentum_.col(i) = stochasticity_factor_ * random_joint_momentum_;
01038 }
01039 }
01040
01041 void ChompOptimizer::updateMomentum()
01042 {
01043
01044 double eps = parameters_->getHmcDiscretization();
01045 if(iteration_ > 0)
01046 momentum_ = (momentum_ + eps * final_increments_);
01047 else
01048 momentum_ = random_momentum_;
01049
01050 }
01051
01052 void ChompOptimizer::updatePositionFromMomentum()
01053 {
01054 double eps = parameters_->getHmcDiscretization();
01055 group_trajectory_.getFreeTrajectoryBlock() += eps * momentum_;
01056 }
01057
01058 void ChompOptimizer::animatePath()
01059 {
01060 for(int i = free_vars_start_; i <= free_vars_end_; i++)
01061 {
01062 visualizeState(i);
01063
01064 ros::WallDuration(.05).sleep();
01065 }
01066 }
01067
01068 void ChompOptimizer::animateEndeffector()
01069 {
01070 visualization_msgs::Marker msg;
01071 msg.points.resize(num_vars_free_);
01072
01073 int sn = (int)(num_collision_points_ - 1);
01074 for(int i = 0; i < num_vars_free_; ++i)
01075 {
01076 int j = i + free_vars_start_;
01077 msg.points[i].x = collision_point_pos_eigen_[j][sn][0];
01078 msg.points[i].y = collision_point_pos_eigen_[j][sn][1];
01079 msg.points[i].z = collision_point_pos_eigen_[j][sn][2];
01080 }
01081 msg.header.frame_id = collision_space_->getCollisionModelsInterface()->getRobotFrameId();
01082 msg.header.stamp = ros::Time();
01083 msg.ns = "chomp_endeffector";
01084 msg.id = 0;
01085 msg.type = visualization_msgs::Marker::SPHERE_LIST;
01086 msg.action = visualization_msgs::Marker::ADD;
01087 double scale = 0.05;
01088 msg.scale.x = scale;
01089 msg.scale.y = scale;
01090 msg.scale.z = scale;
01091 msg.color.a = 0.6;
01092 msg.color.r = 0.5;
01093 msg.color.g = 1.0;
01094 msg.color.b = 0.3;
01095 vis_marker_pub_.publish(msg);
01096 ros::WallDuration(0.1).sleep();
01097
01098 }
01099
01100 void ChompOptimizer::visualizeState(int index)
01101 {
01102
01103 visualization_msgs::MarkerArray msg;
01104 msg.markers.resize(num_collision_points_ + num_joints_);
01105 int num_arrows = 0;
01106 double potential_threshold = 1e-10;
01107 for(int i = 0; i < num_collision_points_; i++)
01108 {
01109 msg.markers[i].header.frame_id = collision_space_->getCollisionModelsInterface()->getRobotFrameId();
01110 msg.markers[i].header.stamp = ros::Time();
01111 msg.markers[i].ns = "chomp_collisions";
01112 msg.markers[i].id = i;
01113 msg.markers[i].type = visualization_msgs::Marker::SPHERE;
01114 msg.markers[i].action = visualization_msgs::Marker::ADD;
01115 msg.markers[i].pose.position.x = collision_point_pos_eigen_[index][i][0];
01116 msg.markers[i].pose.position.y = collision_point_pos_eigen_[index][i][1];
01117 msg.markers[i].pose.position.z = collision_point_pos_eigen_[index][i][2];
01118 msg.markers[i].pose.orientation.x = 0.0;
01119 msg.markers[i].pose.orientation.y = 0.0;
01120 msg.markers[i].pose.orientation.z = 0.0;
01121 msg.markers[i].pose.orientation.w = 1.0;
01122 double scale = 0.1;
01123 msg.markers[i].scale.x = scale;
01124 msg.markers[i].scale.y = scale;
01125 msg.markers[i].scale.z = scale;
01126 msg.markers[i].color.a = 0.6;
01127 msg.markers[i].color.r = 0.5;
01128 msg.markers[i].color.g = 1.0;
01129 msg.markers[i].color.b = 0.3;
01130 if(collision_point_potential_[index][i] > potential_threshold)
01131 num_arrows++;
01132 }
01133
01134 vis_marker_array_pub_.publish(msg);
01135
01136
01137 msg.markers.resize(0);
01138 msg.markers.resize(num_collision_points_);
01139 for(int i = 0; i < num_collision_points_; i++)
01140 {
01141 msg.markers[i].header.frame_id = collision_space_->getCollisionModelsInterface()->getRobotFrameId();
01142 msg.markers[i].header.stamp = ros::Time();
01143 msg.markers[i].ns = "chomp_arrows";
01144 msg.markers[i].id = i;
01145 msg.markers[i].type = visualization_msgs::Marker::ARROW;
01146 msg.markers[i].action = visualization_msgs::Marker::ADD;
01147 msg.markers[i].points.resize(2);
01148 msg.markers[i].points[0].x = collision_point_pos_eigen_[index][i](0);
01149 msg.markers[i].points[0].y = collision_point_pos_eigen_[index][i](1);
01150 msg.markers[i].points[0].z = collision_point_pos_eigen_[index][i](2);
01151 msg.markers[i].points[1] = msg.markers[i].points[0];
01152 double scale = 0.25f;
01153 if(collision_point_potential_[index][i] <= potential_threshold)
01154 scale = 0.0;
01155 msg.markers[i].points[1].x += scale * collision_point_potential_gradient_[index][i](0);
01156 msg.markers[i].points[1].y += scale * collision_point_potential_gradient_[index][i](1);
01157 msg.markers[i].points[1].z += scale * collision_point_potential_gradient_[index][i](2);
01158 msg.markers[i].scale.x = 0.01;
01159 msg.markers[i].scale.y = 0.03;
01160 msg.markers[i].color.a = 0.5;
01161 msg.markers[i].color.r = 0.5;
01162 msg.markers[i].color.g = 0.5;
01163 msg.markers[i].color.b = 1.0;
01164 }
01165 vis_marker_array_pub_.publish(msg);
01166
01167 }
01168
01169 }