chomp_optimizer.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2009, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Mrinal Kalakrishnan */
36 
38 #include <ros/ros.h>
39 #include <visualization_msgs/MarkerArray.h>
44 #include <eigen3/Eigen/LU>
45 #include <eigen3/Eigen/Core>
46 
47 namespace chomp
48 {
50 {
51  return ((double)random() / (double)RAND_MAX);
52 }
53 
54 ChompOptimizer::ChompOptimizer(ChompTrajectory* trajectory, const planning_scene::PlanningSceneConstPtr& planning_scene,
55  const std::string& planning_group, const ChompParameters* parameters,
56  const moveit::core::RobotState& start_state)
57  : full_trajectory_(trajectory)
58  , kmodel_(planning_scene->getRobotModel())
59  , planning_group_(planning_group)
60  , parameters_(parameters)
61  , group_trajectory_(*full_trajectory_, planning_group_, DIFF_RULE_LENGTH)
62  , planning_scene_(planning_scene)
63  , state_(start_state)
64  , start_state_(start_state)
65  , initialized_(false)
66 {
67  std::vector<std::string> cd_names;
68  planning_scene->getCollisionDetectorNames(cd_names);
69 
70  ROS_INFO_STREAM("The following collision detectors are active in the planning scene.");
71  for (std::size_t i = 0; i < cd_names.size(); i++)
72  {
73  ROS_INFO_STREAM(cd_names[i]);
74  }
75 
76  ROS_INFO_STREAM("Active collision detector is: " + planning_scene->getActiveCollisionDetectorName());
77 
79  planning_scene->getCollisionWorld(planning_scene->getActiveCollisionDetectorName()).get());
80  if (!hy_world_)
81  {
82  ROS_WARN_STREAM("Could not initialize hybrid collision world from planning scene");
83  return;
84  }
85 
87  planning_scene->getCollisionRobot(planning_scene->getActiveCollisionDetectorName()).get());
88  if (!hy_robot_)
89  {
90  ROS_WARN_STREAM("Could not initialize hybrid collision robot from planning scene");
91  return;
92  }
93  initialize();
94 }
95 
97 {
98  // init some variables:
102 
105 
111  &planning_scene_->getAllowedCollisionMatrix(), gsr_);
112  ROS_INFO_STREAM("First coll check took " << (ros::WallTime::now() - wt));
114  for (size_t i = 0; i < gsr_->gradients_.size(); i++)
115  {
116  num_collision_points_ += gsr_->gradients_[i].gradients.size();
117  }
118 
119  // set up the joint costs:
120  joint_costs_.reserve(num_joints_);
121 
122  double max_cost_scale = 0.0;
123 
124  joint_model_group_ = planning_scene_->getRobotModel()->getJointModelGroup(planning_group_);
125 
126  const std::vector<const moveit::core::JointModel*> joint_models = joint_model_group_->getActiveJointModels();
127  for (size_t i = 0; i < joint_models.size(); i++)
128  {
129  const moveit::core::JointModel* model = joint_models[i];
130  double joint_cost = 1.0;
131  std::string joint_name = model->getName();
132  // nh.param("joint_costs/" + joint_name, joint_cost, 1.0);
133  std::vector<double> derivative_costs(3);
134  derivative_costs[0] = joint_cost * parameters_->smoothness_cost_velocity_;
135  derivative_costs[1] = joint_cost * parameters_->smoothness_cost_acceleration_;
136  derivative_costs[2] = joint_cost * parameters_->smoothness_cost_jerk_;
137  joint_costs_.push_back(ChompCost(group_trajectory_, i, derivative_costs, parameters_->ridge_factor_));
138  double cost_scale = joint_costs_[i].getMaxQuadCostInvValue();
139  if (max_cost_scale < cost_scale)
140  max_cost_scale = cost_scale;
141  }
142 
143  // scale the smoothness costs
144  for (int i = 0; i < num_joints_; i++)
145  {
146  joint_costs_[i].scale(max_cost_scale);
147  }
148 
149  // allocate memory for matrices:
150  smoothness_increments_ = Eigen::MatrixXd::Zero(num_vars_free_, num_joints_);
151  collision_increments_ = Eigen::MatrixXd::Zero(num_vars_free_, num_joints_);
152  final_increments_ = Eigen::MatrixXd::Zero(num_vars_free_, num_joints_);
153  smoothness_derivative_ = Eigen::VectorXd::Zero(num_vars_all_);
154  jacobian_ = Eigen::MatrixXd::Zero(3, num_joints_);
155  jacobian_pseudo_inverse_ = Eigen::MatrixXd::Zero(num_joints_, 3);
156  jacobian_jacobian_tranpose_ = Eigen::MatrixXd::Zero(3, 3);
157  random_state_ = Eigen::VectorXd::Zero(num_joints_);
158  joint_state_velocities_ = Eigen::VectorXd::Zero(num_joints_);
159 
162 
163  collision_point_joint_names_.resize(num_vars_all_, std::vector<std::string>(num_collision_points_));
169 
170  collision_point_potential_.resize(num_vars_all_, std::vector<double>(num_collision_points_));
171  collision_point_vel_mag_.resize(num_vars_all_, std::vector<double>(num_collision_points_));
173 
175  is_collision_free_ = false;
178 
180 
183 
184  // HMC initialization:
185  // momentum_ = Eigen::MatrixXd::Zero(num_vars_free_, num_joints_);
186  // random_momentum_ = Eigen::MatrixXd::Zero(num_vars_free_, num_joints_);
187  // random_joint_momentum_ = Eigen::VectorXd::Zero(num_vars_free_);
188  multivariate_gaussian_.clear();
189  stochasticity_factor_ = 1.0;
190  for (int i = 0; i < num_joints_; i++)
191  {
192  multivariate_gaussian_.push_back(
193  MultivariateGaussian(Eigen::VectorXd::Zero(num_vars_free_), joint_costs_[i].getQuadraticCostInverse()));
194  }
195 
196  std::map<std::string, std::string> fixed_link_resolution_map;
197  for (int i = 0; i < num_joints_; i++)
198  {
199  joint_names_.push_back(joint_model_group_->getActiveJointModels()[i]->getName());
200  // ROS_INFO("Got joint %s", joint_names_[i].c_str());
202  fixed_link_resolution_map[joint_names_[i]] = joint_names_[i];
203  }
204 
206  {
207  if (!jm->getParentLinkModel()) // root joint doesn't have a parent
208  continue;
209 
210  fixed_link_resolution_map[jm->getName()] = jm->getParentLinkModel()->getParentJointModel()->getName();
211  }
212 
213  // TODO - is this just the joint_roots_?
214  for (size_t i = 0; i < joint_model_group_->getUpdatedLinkModels().size(); i++)
215  {
216  if (fixed_link_resolution_map.find(
217  joint_model_group_->getUpdatedLinkModels()[i]->getParentJointModel()->getName()) ==
218  fixed_link_resolution_map.end())
219  {
220  const moveit::core::JointModel* parent_model = NULL;
221  bool found_root = false;
222 
223  while (!found_root)
224  {
225  if (parent_model == NULL)
226  {
227  parent_model = joint_model_group_->getUpdatedLinkModels()[i]->getParentJointModel();
228  }
229  else
230  {
231  parent_model = parent_model->getParentLinkModel()->getParentJointModel();
232  for (size_t j = 0; j < joint_names_.size(); j++)
233  {
234  if (parent_model->getName() == joint_names_[j])
235  {
236  found_root = true;
237  }
238  }
239  }
240  }
241  fixed_link_resolution_map[joint_model_group_->getUpdatedLinkModels()[i]->getParentJointModel()->getName()] =
242  parent_model->getName();
243  }
244  }
245 
246  int start = free_vars_start_;
247  int end = free_vars_end_;
248  for (int i = start; i <= end; ++i)
249  {
250  size_t j = 0;
251  for (size_t g = 0; g < gsr_->gradients_.size(); g++)
252  {
253  collision_detection::GradientInfo& info = gsr_->gradients_[g];
254 
255  for (size_t k = 0; k < info.sphere_locations.size(); k++)
256  {
257  if (fixed_link_resolution_map.find(info.joint_name) != fixed_link_resolution_map.end())
258  {
259  collision_point_joint_names_[i][j] = fixed_link_resolution_map[info.joint_name];
260  }
261  else
262  {
263  ROS_ERROR("Couldn't find joint %s!", info.joint_name.c_str());
264  }
265  j++;
266  }
267  }
268  }
269  initialized_ = true;
270 }
271 
273 {
274  destroy();
275 }
276 
278 {
279  const moveit::core::JointModel* parent_model = NULL;
280  bool found_root = false;
281 
282  if (model == kmodel_->getRootJoint())
283  return;
284 
285  while (!found_root)
286  {
287  if (parent_model == NULL)
288  {
289  if (model->getParentLinkModel() == NULL)
290  {
291  ROS_ERROR_STREAM("Model " << model->getName() << " not root but has NULL link model parent");
292  return;
293  }
294  else if (model->getParentLinkModel()->getParentJointModel() == NULL)
295  {
296  ROS_ERROR_STREAM("Model " << model->getName() << " not root but has NULL joint model parent");
297  return;
298  }
299  parent_model = model->getParentLinkModel()->getParentJointModel();
300  }
301  else
302  {
303  if (parent_model == kmodel_->getRootJoint())
304  {
305  found_root = true;
306  }
307  else
308  {
309  parent_model = parent_model->getParentLinkModel()->getParentJointModel();
310  }
311  }
312  joint_parent_map_[model->getName()][parent_model->getName()] = true;
313  }
314 }
315 
317 {
318  bool optimization_result = 0;
319  ros::WallTime start_time = ros::WallTime::now();
320  // double averageCostVelocity = 0.0;
321  // int currentCostIter = 0;
322  int costWindow = 10;
323  std::vector<double> costs(costWindow, 0.0);
324  // double minimaThreshold = 0.05;
325  bool should_break_out = false;
326 
327  // iterate
329  {
330  ros::WallTime for_time = ros::WallTime::now();
332  ROS_INFO_STREAM("Forward kinematics took " << (ros::WallTime::now() - for_time));
333  double cCost = getCollisionCost();
334  double sCost = getSmoothnessCost();
335  double cost = cCost + sCost;
336 
337  // ROS_INFO_STREAM("Collision cost " << cCost << " smoothness cost " << sCost);
338 
341 
342  // if(parameters_->getAddRandomness() && currentCostIter != -1)
343  // {
344  // costs[currentCostIter] = cCost;
345  // currentCostIter++;
346 
347  // if(currentCostIter >= costWindow)
348  // {
349  // for(int i = 1; i < costWindow; i++)
350  // {
351  // averageCostVelocity += (costs.at(i) - costs.at(i - 1));
352  // }
353 
354  // averageCostVelocity /= (double)(costWindow);
355  // currentCostIter = -1;
356  // }
357  // }
358 
359  if (iteration_ == 0)
360  {
363  }
364  else
365  {
366  if (cost < best_group_trajectory_cost_)
367  {
371  }
372  }
376 
379 
380  // if(!parameters_->getUseHamiltonianMonteCarlo())
381  // {
382  // // non-stochastic version:
384  // }
385  // else
386  // {
387  // // hamiltonian monte carlo updates:
388  // getRandomMomentum();
389  // updateMomentum();
390  // updatePositionFromMomentum();
391  // stochasticity_factor_ *= parameters_->getHmcAnnealingFactor();
392  // }
393 
396 
397  if (iteration_ % 10 == 0)
398  {
399  ROS_INFO("iteration: %d", iteration_);
401  {
403  ROS_INFO("Chomp Got mesh to mesh safety at iter %d. Breaking out early.", iteration_);
404  is_collision_free_ = true;
405  iteration_++;
406  should_break_out = true;
407  }
408  // } else if(safety == CollisionProximitySpace::InCollisionSafe) {
409 
412 
413  // ROS_DEBUG("Trajectory cost: %f (s=%f, c=%f)", getTrajectoryCost(), getSmoothnessCost(), getCollisionCost());
414  // CollisionProximitySpace::TrajectorySafety safety = checkCurrentIterValidity();
415  // if(safety == CollisionProximitySpace::MeshToMeshSafe)
416  // {
417  // num_collision_free_iterations_ = 0;
418  // ROS_INFO("Chomp Got mesh to mesh safety at iter %d. Breaking out early.", iteration_);
419  // is_collision_free_ = true;
420  // iteration_++;
421  // should_break_out = true;
422  // } else if(safety == CollisionProximitySpace::InCollisionSafe) {
423  // num_collision_free_iterations_ = parameters_->getMaxIterationsAfterCollisionFree();
424  // ROS_INFO("Chomp Got in collision safety at iter %d. Breaking out soon.", iteration_);
425  // is_collision_free_ = true;
426  // iteration_++;
427  // should_break_out = true;
428  // }
429  // else
430  // {
431  // is_collision_free_ = false;
432  // }
433  }
434 
436  {
437  if (cCost < parameters_->collision_threshold_)
438  {
440  is_collision_free_ = true;
441  iteration_++;
442  should_break_out = true;
443  }
444  else
445  {
446  // ROS_INFO_STREAM("cCost " << cCost << " over threshold " << parameters_->getCollisionThreshold());
447  }
448  }
449 
450  if ((ros::WallTime::now() - start_time).toSec() > parameters_->planning_time_limit_)
451  {
452  ROS_WARN("Breaking out early due to time limit constraints.");
453  break;
454  }
455 
458 
459  // if(fabs(averageCostVelocity) < minimaThreshold && currentCostIter == -1 && !is_collision_free_ &&
460  // parameters_->getAddRandomness())
461  // {
462  // ROS_INFO("Detected local minima. Attempting to break out!");
463  // int iter = 0;
464  // bool success = false;
465  // while(iter < 20 && !success)
466  // {
467  // performForwardKinematics();
468  // double original_cost = getTrajectoryCost();
469  // group_trajectory_backup_ = group_trajectory_.getTrajectory();
470  // perturbTrajectory();
471  // handleJointLimits();
472  // updateFullTrajectory();
473  // performForwardKinematics();
474  // double new_cost = getTrajectoryCost();
475  // iter ++;
476  // if(new_cost < original_cost)
477  // {
478  // ROS_INFO("Got out of minimum in %d iters!", iter);
479  // averageCostVelocity = 0.0;
480  // currentCostIter = 0;
481  // success = true;
482  // }
483  // else
484  // {
485  // group_trajectory_.getTrajectory() = group_trajectory_backup_;
486  // updateFullTrajectory();
487  // currentCostIter = 0;
488  // averageCostVelocity = 0.0;
489  // success = false;
490  // }
491 
492  // }
493 
494  // if(!success)
495  // {
496  // ROS_INFO("Failed to exit minimum!");
497  // }
498  //}
499  // else if (currentCostIter == -1)
500  //{
501  // currentCostIter = 0;
502  // averageCostVelocity = 0.0;
503  //}
504 
505  if (should_break_out)
506  {
509  {
510  break;
511  }
513  {
514  // CollisionProximitySpace::TrajectorySafety safety = checkCurrentIterValidity();
515  // if(safety != CollisionProximitySpace::MeshToMeshSafe &&
516  // safety != CollisionProximitySpace::InCollisionSafe) {
517  // ROS_WARN_STREAM("Apparently regressed");
518  // }
519  break;
520  }
521  }
522  }
523 
524  if (is_collision_free_)
525  {
526  optimization_result = true;
527  ROS_INFO("Chomp path is collision free");
528  }
529  else
530  {
531  optimization_result = false;
532  ROS_ERROR("Chomp path is not collision free!");
533  }
534 
537 
538  ROS_INFO("Terminated after %d iterations, using path from iteration %d", iteration_, last_improvement_iteration_);
539  ROS_INFO("Optimization core finished in %f sec", (ros::WallTime::now() - start_time).toSec());
540  ROS_INFO_STREAM("Time per iteration " << (ros::WallTime::now() - start_time).toSec() / (iteration_ * 1.0));
541 
542  return optimization_result;
543 }
544 
546 {
547  moveit_msgs::RobotTrajectory traj;
548  traj.joint_trajectory.joint_names = joint_names_;
549 
550  for (int i = 0; i < group_trajectory_.getNumPoints(); i++)
551  {
552  trajectory_msgs::JointTrajectoryPoint point;
553  for (int j = 0; j < group_trajectory_.getNumJoints(); j++)
554  {
555  point.positions.push_back(best_group_trajectory_(i, j));
556  }
557  traj.joint_trajectory.points.push_back(point);
558  }
559  moveit_msgs::RobotState start_state_msg;
561  return planning_scene_->isPathValid(start_state_msg, traj, planning_group_);
562 }
563 
566 
567 // CollisionProximitySpace::TrajectorySafety ChompOptimizer::checkCurrentIterValidity()
568 // {
569 // JointTrajectory jointTrajectory;
570 // jointTrajectory.joint_names = joint_names_;
571 // jointTrajectory.header.frame_id = collision_space_->getCollisionModelsInterface()->getRobotFrameId();
572 // jointTrajectory.header.stamp = ros::Time::now();
573 // Constraints goalConstraints;
574 // Constraints pathConstraints;
575 // ArmNavigationErrorCodes errorCode;
576 // vector<ArmNavigationErrorCodes> trajectoryErrorCodes;
577 // for(int i = 0; i < group_trajectory_.getNumPoints(); i++)
578 // {
579 // JointTrajectoryPoint point;
580 // for(int j = 0; j < group_trajectory_.getNumJoints(); j++)
581 // {
582 // point.positions.push_back(best_group_trajectory_(i, j));
583 // }
584 // jointTrajectory.points.push_back(point);
585 // }
586 
587 // return collision_space_->isTrajectorySafe(jointTrajectory, goalConstraints, pathConstraints, planning_group_);
588 // /*
589 // bool valid = collision_space_->getCollisionModelsInterface()->isJointTrajectoryValid(*state_,
590 // jointTrajectory,
591 // goalConstraints,
592 // pathConstraints, errorCode,
593 // trajectoryErrorCodes, false);
594 // */
595 
596 // }
597 
599 {
600  for (int i = 0; i < num_joints_; i++)
601  {
604  }
605 }
606 
608 {
609  double potential;
610  double vel_mag_sq;
611  double vel_mag;
612  Eigen::Vector3d potential_gradient;
613  Eigen::Vector3d normalized_velocity;
614  Eigen::Matrix3d orthogonal_projector;
615  Eigen::Vector3d curvature_vector;
616  Eigen::Vector3d cartesian_gradient;
617 
619 
620  int startPoint = 0;
621  int endPoint = free_vars_end_;
622 
623  // In stochastic descent, simply use a random point in the trajectory, rather than all the trajectory points.
624  // This is faster and guaranteed to converge, but it may take more iterations in the worst case.
626  {
627  startPoint = (int)(((double)random() / (double)RAND_MAX) * (free_vars_end_ - free_vars_start_) + free_vars_start_);
628  if (startPoint < free_vars_start_)
629  startPoint = free_vars_start_;
630  if (startPoint > free_vars_end_)
631  startPoint = free_vars_end_;
632  endPoint = startPoint;
633  }
634  else
635  {
636  startPoint = free_vars_start_;
637  }
638 
639  for (int i = startPoint; i <= endPoint; i++)
640  {
641  for (int j = 0; j < num_collision_points_; j++)
642  {
643  potential = collision_point_potential_[i][j];
644 
645  if (potential < 0.0001)
646  continue;
647 
648  potential_gradient = -collision_point_potential_gradient_[i][j];
649 
650  vel_mag = collision_point_vel_mag_[i][j];
651  vel_mag_sq = vel_mag * vel_mag;
652 
653  // all math from the CHOMP paper:
654 
655  normalized_velocity = collision_point_vel_eigen_[i][j] / vel_mag;
656  orthogonal_projector = Eigen::Matrix3d::Identity() - (normalized_velocity * normalized_velocity.transpose());
657  curvature_vector = (orthogonal_projector * collision_point_acc_eigen_[i][j]) / vel_mag_sq;
658  cartesian_gradient = vel_mag * (orthogonal_projector * potential_gradient - potential * curvature_vector);
659 
660  // pass it through the jacobian transpose to get the increments
662 
664  {
666  collision_increments_.row(i - free_vars_start_).transpose() -= jacobian_pseudo_inverse_ * cartesian_gradient;
667  }
668  else
669  {
670  collision_increments_.row(i - free_vars_start_).transpose() -= jacobian_.transpose() * cartesian_gradient;
671  }
672 
673  /*
674  if(point_is_in_collision_[i][j])
675  {
676  break;
677  }
678  */
679  }
680  }
681  // cout << collision_increments_ << endl;
682 }
683 
685 {
687  jacobian_ * jacobian_.transpose() + Eigen::MatrixXd::Identity(3, 3) * parameters_->pseudo_inverse_ridge_factor_;
689 }
690 
692 {
693  for (int i = 0; i < num_joints_; i++)
694  {
695  final_increments_.col(i) =
696  parameters_->learning_rate_ * (joint_costs_[i].getQuadraticCostInverse() *
699  }
700 }
701 
703 {
704  const std::vector<const moveit::core::JointModel*>& joint_models = joint_model_group_->getActiveJointModels();
705  for (size_t i = 0; i < joint_models.size(); i++)
706  {
707  double scale = 1.0;
708  double max = final_increments_.col(i).maxCoeff();
709  double min = final_increments_.col(i).minCoeff();
710  double max_scale = parameters_->joint_update_limit_ / fabs(max);
711  double min_scale = parameters_->joint_update_limit_ / fabs(min);
712  if (max_scale < scale)
713  scale = max_scale;
714  if (min_scale < scale)
715  scale = min_scale;
717  }
718  // ROS_DEBUG("Scale: %f",scale);
719  // group_trajectory_.getFreeTrajectoryBlock() += scale * final_increments_;
720 }
721 
723 {
725 }
726 
728 {
729  double cost = 0.0;
730  for (int i = 0; i < num_joints_; i++)
731  cost += joint_costs_[i].getCost(group_trajectory_.getJointTrajectory(i));
732  std::cout << "Cost = " << cost << std::endl;
733 }
734 
736 {
737  return getSmoothnessCost() + getCollisionCost();
738 }
739 
741 {
742  double smoothness_cost = 0.0;
743  // joint costs:
744  for (int i = 0; i < num_joints_; i++)
745  smoothness_cost += joint_costs_[i].getCost(group_trajectory_.getJointTrajectory(i));
746 
747  return parameters_->smoothness_cost_weight_ * smoothness_cost;
748 }
749 
751 {
752  double collision_cost = 0.0;
753 
754  double worst_collision_cost = 0.0;
756 
757  // collision costs:
758  for (int i = free_vars_start_; i <= free_vars_end_; i++)
759  {
760  double state_collision_cost = 0.0;
761  for (int j = 0; j < num_collision_points_; j++)
762  {
763  state_collision_cost += collision_point_potential_[i][j] * collision_point_vel_mag_[i][j];
764  }
765  collision_cost += state_collision_cost;
766  if (state_collision_cost > worst_collision_cost)
767  {
768  worst_collision_cost = state_collision_cost;
770  }
771  }
772 
773  return parameters_->obstacle_cost_weight_ * collision_cost;
774 }
775 
776 void ChompOptimizer::computeJointProperties(int trajectory_point)
777 {
778  // tf::Transform inverseWorldTransform = collision_space_->getInverseWorldTransform(*state_);
779  for (int j = 0; j < num_joints_; j++)
780  {
782  const moveit::core::RevoluteJointModel* revolute_joint =
783  dynamic_cast<const moveit::core::RevoluteJointModel*>(joint_model);
784  const moveit::core::PrismaticJointModel* prismatic_joint =
785  dynamic_cast<const moveit::core::PrismaticJointModel*>(joint_model);
786 
787  std::string parent_link_name = joint_model->getParentLinkModel()->getName();
788  std::string child_link_name = joint_model->getChildLinkModel()->getName();
789  Eigen::Affine3d joint_transform =
790  state_.getGlobalLinkTransform(parent_link_name) *
791  (kmodel_->getLinkModel(child_link_name)->getJointOriginTransform() * (state_.getJointTransform(joint_model)));
792 
793  // joint_transform = inverseWorldTransform * jointTransform;
794  Eigen::Vector3d axis;
795 
796  if (revolute_joint != NULL)
797  {
798  axis = revolute_joint->getAxis();
799  }
800  else if (prismatic_joint != NULL)
801  {
802  axis = prismatic_joint->getAxis();
803  }
804  else
805  {
806  axis = Eigen::Vector3d::Identity();
807  }
808 
809  axis = joint_transform * axis;
810 
811  joint_axes_[trajectory_point][j] = axis;
812  joint_positions_[trajectory_point][j] = joint_transform.translation();
813  }
814 }
815 
816 template <typename Derived>
817 void ChompOptimizer::getJacobian(int trajectory_point, Eigen::Vector3d& collision_point_pos, std::string& joint_name,
818  Eigen::MatrixBase<Derived>& jacobian) const
819 {
820  for (int j = 0; j < num_joints_; j++)
821  {
822  if (isParent(joint_name, joint_names_[j]))
823  {
824  Eigen::Vector3d column = joint_axes_[trajectory_point][j].cross(
825  Eigen::Vector3d(collision_point_pos(0), collision_point_pos(1), collision_point_pos(2)) -
826  joint_positions_[trajectory_point][j]);
827 
828  jacobian.col(j)[0] = column.x();
829  jacobian.col(j)[1] = column.y();
830  jacobian.col(j)[2] = column.z();
831  }
832  else
833  {
834  jacobian.col(j)[0] = 0.0;
835  jacobian.col(j)[1] = 0.0;
836  jacobian.col(j)[2] = 0.0;
837  }
838  }
839 }
840 
842 {
843  const std::vector<const moveit::core::JointModel*> joint_models = joint_model_group_->getActiveJointModels();
844  for (size_t joint_i = 0; joint_i < joint_models.size(); joint_i++)
845  {
846  const moveit::core::JointModel* joint_model = joint_models[joint_i];
847 
848  if (joint_model->getType() == moveit::core::JointModel::REVOLUTE)
849  {
850  const moveit::core::RevoluteJointModel* revolute_joint =
851  dynamic_cast<const moveit::core::RevoluteJointModel*>(joint_model);
852  if (revolute_joint->isContinuous())
853  {
854  continue;
855  }
856  }
857 
858  const moveit::core::JointModel::Bounds& bounds = joint_model->getVariableBounds();
859 
860  double joint_max = -DBL_MAX;
861  double joint_min = DBL_MAX;
862 
863  for (moveit::core::JointModel::Bounds::const_iterator it = bounds.begin(); it != bounds.end(); it++)
864  {
865  if (it->min_position_ < joint_min)
866  {
867  joint_min = it->min_position_;
868  }
869 
870  if (it->max_position_ > joint_max)
871  {
872  joint_max = it->max_position_;
873  }
874  }
875 
876  int count = 0;
877 
878  bool violation = false;
879  do
880  {
881  double max_abs_violation = 1e-6;
882  double max_violation = 0.0;
883  int max_violation_index = 0;
884  violation = false;
885  for (int i = free_vars_start_; i <= free_vars_end_; i++)
886  {
887  double amount = 0.0;
888  double absolute_amount = 0.0;
889  if (group_trajectory_(i, joint_i) > joint_max)
890  {
891  amount = joint_max - group_trajectory_(i, joint_i);
892  absolute_amount = fabs(amount);
893  }
894  else if (group_trajectory_(i, joint_i) < joint_min)
895  {
896  amount = joint_min - group_trajectory_(i, joint_i);
897  absolute_amount = fabs(amount);
898  }
899  if (absolute_amount > max_abs_violation)
900  {
901  max_abs_violation = absolute_amount;
902  max_violation = amount;
903  max_violation_index = i;
904  violation = true;
905  }
906  }
907 
908  if (violation)
909  {
910  int free_var_index = max_violation_index - free_vars_start_;
911  double multiplier =
912  max_violation / joint_costs_[joint_i].getQuadraticCostInverse()(free_var_index, free_var_index);
914  multiplier * joint_costs_[joint_i].getQuadraticCostInverse().col(free_var_index);
915  }
916  if (++count > 10)
917  break;
918  } while (violation);
919  }
920 }
921 
923 {
924  double inv_time = 1.0 / group_trajectory_.getDiscretization();
925  double inv_time_sq = inv_time * inv_time;
926 
927  // calculate the forward kinematics for the fixed states only in the first iteration:
928  int start = free_vars_start_;
929  int end = free_vars_end_;
930  if (iteration_ == 0)
931  {
932  start = 0;
933  end = num_vars_all_ - 1;
934  }
935 
936  is_collision_free_ = true;
937 
938  ros::WallDuration total_dur(0.0);
939 
940  // for each point in the trajectory
941  for (int i = start; i <= end; ++i)
942  {
943  // Set Robot state from trajectory point...
949 
951  total_dur += (ros::WallTime::now() - grad);
953  state_is_in_collision_[i] = false;
954 
955  // Keep vars in scope
956  {
957  size_t j = 0;
958  for (size_t g = 0; g < gsr_->gradients_.size(); g++)
959  {
960  collision_detection::GradientInfo& info = gsr_->gradients_[g];
961 
962  for (size_t k = 0; k < info.sphere_locations.size(); k++)
963  {
964  collision_point_pos_eigen_[i][j][0] = info.sphere_locations[k].x();
965  collision_point_pos_eigen_[i][j][1] = info.sphere_locations[k].y();
966  collision_point_pos_eigen_[i][j][2] = info.sphere_locations[k].z();
967 
970  collision_point_potential_gradient_[i][j][0] = info.gradients[k].x();
971  collision_point_potential_gradient_[i][j][1] = info.gradients[k].y();
972  collision_point_potential_gradient_[i][j][2] = info.gradients[k].z();
973 
974  point_is_in_collision_[i][j] = (info.distances[k] - info.sphere_radii[k] < info.sphere_radii[k]);
975 
976  if (point_is_in_collision_[i][j])
977  {
978  state_is_in_collision_[i] = true;
979  // if(is_collision_free_ == true) {
980  // ROS_INFO_STREAM("We know it's not collision free " << g);
981  // ROS_INFO_STREAM("Sphere location " << info.sphere_locations[k].x() << " " <<
982  // info.sphere_locations[k].y() << " " << info.sphere_locations[k].z());
983  // ROS_INFO_STREAM("Gradient " << info.gradients[k].x() << " " << info.gradients[k].y() << " " <<
984  // info.gradients[k].z() << " distance " << info.distances[k] << " radii " << info.sphere_radii[k]);
985  // ROS_INFO_STREAM("Radius " << info.sphere_radii[k] << " potential " <<
986  // collision_point_potential_[i][j]);
987  // }
988 
989  is_collision_free_ = false;
990  }
991  j++;
992  }
993  }
994  }
995  }
996 
997  // ROS_INFO_STREAM("Total dur " << total_dur << " total checks " << end-start+1);
998 
999  // now, get the vel and acc for each collision point (using finite differencing)
1000  for (int i = free_vars_start_; i <= free_vars_end_; i++)
1001  {
1002  for (int j = 0; j < num_collision_points_; j++)
1003  {
1004  collision_point_vel_eigen_[i][j] = Eigen::Vector3d(0, 0, 0);
1005  collision_point_acc_eigen_[i][j] = Eigen::Vector3d(0, 0, 0);
1006  for (int k = -DIFF_RULE_LENGTH / 2; k <= DIFF_RULE_LENGTH / 2; k++)
1007  {
1009  (inv_time * DIFF_RULES[0][k + DIFF_RULE_LENGTH / 2]) * collision_point_pos_eigen_[i + k][j];
1011  (inv_time_sq * DIFF_RULES[1][k + DIFF_RULE_LENGTH / 2]) * collision_point_pos_eigen_[i + k][j];
1012  }
1013 
1014  // get the norm of the velocity:
1016  }
1017  }
1018 }
1019 
1021 {
1022  const Eigen::MatrixXd::RowXpr& point = group_trajectory.getTrajectoryPoint(i);
1023 
1024  std::vector<double> joint_states;
1025  for (int j = 0; j < group_trajectory.getNumJoints(); j++)
1026  {
1027  joint_states.push_back(point(0, j));
1028  }
1029 
1031  state_.update();
1032 }
1033 
1035 {
1036  // int mid_point = (free_vars_start_ + free_vars_end_) / 2;
1038  return;
1039  int mid_point = worst_collision_cost_state_;
1040  moveit::core::RobotState random_state = state_;
1042  random_state.setToRandomPositions(planning_group);
1043  std::vector<double> vals;
1044  random_state.copyJointGroupPositions(planning_group_, vals);
1045  double* ptr = &vals[0];
1046  Eigen::Map<Eigen::VectorXd> random_matrix(ptr, vals.size());
1047  // Eigen::VectorXd random_matrix = vals;
1048 
1049  // convert the state into an increment
1050  random_matrix -= group_trajectory_.getTrajectoryPoint(mid_point).transpose();
1051 
1052  // project the increment orthogonal to joint velocities
1054  joint_state_velocities_.normalize();
1055  random_matrix = (Eigen::MatrixXd::Identity(num_joints_, num_joints_) -
1057  random_matrix;
1058 
1059  int mp_free_vars_index = mid_point - free_vars_start_;
1060  for (int i = 0; i < num_joints_; i++)
1061  {
1063  joint_costs_[i].getQuadraticCostInverse().col(mp_free_vars_index) * random_state_(i);
1064  }
1065 }
1066 
1069 // void ChompOptimizer::getRandomState(const RobotState currentState, const string& groupName, Eigen::VectorXd&
1070 // state_vec)
1071 // {
1072 // const vector<RobotState *::JointState*>& jointStates =
1073 // currentState->getJointStateGroup(groupName)->getJointStateVector();
1074 // for(size_t i = 0; i < jointStates.size(); i++)
1075 // {
1076 
1077 // bool continuous = false;
1078 
1079 // RobotState *::JointState* jointState = jointStates[i];
1080 // const RevoluteJointModel* revolute_joint
1081 // = dynamic_cast<const RevoluteJointModel*>(jointState->getJointModel());
1082 // if(revolute_joint && revolute_joint->continuous_) {
1083 // continuous = true;
1084 // }
1085 
1086 // map<string, pair<double, double> > bounds = jointState->getJointModel()->getAllVariableBounds();
1087 // int j = 0;
1088 // for(map<string, pair<double, double> >::iterator it = bounds.begin(); it != bounds.end(); it++)
1089 // {
1090 // double randVal = jointState->getJointStateValues()[j] + (getRandomDouble()
1091 // * (parameters_->getRandomJumpAmount()) -
1092 // getRandomDouble() *
1093 // (parameters_->getRandomJumpAmount()));
1094 
1095 // if(!continuous)
1096 // {
1097 // if(randVal > it->second.second)
1098 // {
1099 // randVal = it->second.second;
1100 // }
1101 // else if(randVal < it->second.first)
1102 // {
1103 // randVal = it->second.first;
1104 // }
1105 // }
1106 
1107 // ROS_DEBUG_STREAM("Joint " << it->first << " old value " << jointState->getJointStateValues()[j] << " new value
1108 // " << randVal);
1109 // state_vec(i) = randVal;
1110 
1111 // j++;
1112 // }
1113 // }
1114 // }
1115 
1116 /*
1117 void ChompOptimizer::getRandomMomentum()
1118 {
1119  if (is_collision_free_)
1120  random_momentum_.setZero(num_vars_free_, num_joints_);
1121  else
1122  for (int i = 0; i < num_joints_; ++i)
1123  {
1124  multivariate_gaussian_[i].sample(random_joint_momentum_);
1125  random_momentum_.col(i) = stochasticity_factor_ * random_joint_momentum_;
1126  }
1127 }
1128 
1129 void ChompOptimizer::updateMomentum()
1130 {
1131  // double alpha = 1.0 - parameters_->getHmcStochasticity();
1132  double eps = parameters_->getHmcDiscretization();
1133  if (iteration_ > 0)
1134  momentum_ = (momentum_ + eps * final_increments_);
1135  else
1136  momentum_ = random_momentum_;
1137  // momentum_ = alpha * (momentum_ + eps*final_increments_) + sqrt(1.0-alpha*alpha)*random_momentum_;
1138 }
1139 
1140 void ChompOptimizer::updatePositionFromMomentum()
1141 {
1142  double eps = parameters_->getHmcDiscretization();
1143  group_trajectory_.getFreeTrajectoryBlock() += eps * momentum_;
1144 }
1145 */
1146 
1147 } // namespace chomp
bool use_pseudo_inverse_
the noise added to the diagnal of the total quadratic cost matrix in the objective function ...
const ChompParameters * parameters_
const std::string & getName() const
const CollisionRobotDistanceFieldConstPtr getCollisionRobotDistanceField() const
const std::string & getName() const
Eigen::MatrixXd::RowXpr getTrajectoryPoint(int traj_point)
const std::vector< const LinkModel * > & getUpdatedLinkModels() const
void getJacobian(int trajectoryPoint, Eigen::Vector3d &collision_point_pos, std::string &jointName, Eigen::MatrixBase< Derived > &jacobian) const
std::map< std::string, std::map< std::string, bool > > joint_parent_map_
unsigned int num_collision_free_iterations_
void getCollisionGradients(const CollisionRequest &req, CollisionResult &res, const CollisionRobot &robot, const robot_state::RobotState &state, const AllowedCollisionMatrix *acm, GroupStateRepresentationPtr &gsr) const
Eigen::MatrixXd jacobian_pseudo_inverse_
std::vector< EigenSTL::vector_Vector3d > collision_point_potential_gradient_
ROSCPP_DECL void start()
ChompTrajectory group_trajectory_
std::vector< std::string > joint_names_
Generates samples from a multivariate gaussian distribution.
std::vector< MultivariateGaussian > multivariate_gaussian_
const collision_detection::CollisionWorldHybrid * hy_world_
Eigen::MatrixXd smoothness_increments_
std::vector< Eigen::Vector3d, Eigen::aligned_allocator< Eigen::Vector3d > > vector_Vector3d
unsigned int collision_free_iteration_
collision_detection::GroupStateRepresentationPtr gsr_
const moveit::core::JointModelGroup * joint_model_group_
std::vector< EigenSTL::vector_Vector3d > collision_point_acc_eigen_
const Eigen::Affine3d & getGlobalLinkTransform(const std::string &link_name)
std::vector< std::vector< double > > collision_point_vel_mag_
ChompOptimizer(ChompTrajectory *trajectory, const planning_scene::PlanningSceneConstPtr &planning_scene, const std::string &planning_group, const ChompParameters *parameters, const moveit::core::RobotState &start_state)
const moveit::core::RobotModelConstPtr & kmodel_
const JointModelGroup * getJointModelGroup(const std::string &group) const
std::vector< EigenSTL::vector_Vector3d > joint_axes_
planning_scene::PlanningSceneConstPtr planning_scene_
double pseudo_inverse_ridge_factor_
enable pseudo inverse calculations or not.
void getJointVelocities(int traj_point, Eigen::MatrixBase< Derived > &velocities)
Gets the joint velocities at the given trajectory point.
double getPotential(double field_distance, double radius, double clearence)
void setRobotStateFromPoint(ChompTrajectory &group_trajectory, int i)
ChompTrajectory * full_trajectory_
std::vector< std::vector< std::string > > collision_point_joint_names_
static const int DIFF_RULE_LENGTH
Definition: chomp_utils.h:46
Eigen::MatrixXd jacobian_jacobian_tranpose_
bool isCurrentTrajectoryMeshToMeshCollisionFree() const
Eigen::MatrixXd best_group_trajectory_
double min_clearence_
set the update limit for the robot joints
int getStartIndex() const
Gets the start index.
const collision_detection::CollisionRobotHybrid * hy_robot_
EigenSTL::vector_Vector3d gradients
double smoothness_cost_acceleration_
variables associated with the cost in velocity
double joint_update_limit_
set the ridge factor if pseudo inverse is enabled
EigenSTL::vector_Vector3d sphere_locations
#define ROS_WARN(...)
void copyJointGroupPositions(const std::string &joint_group_name, std::vector< double > &gstate) const
std::vector< EigenSTL::vector_Vector3d > collision_point_vel_eigen_
bool isParent(const std::string &childLink, const std::string &parentLink) const
std::vector< EigenSTL::vector_Vector3d > collision_point_pos_eigen_
const JointModel * getParentJointModel() const
std::vector< int > state_is_in_collision_
const std::vector< const JointModel * > & getFixedJointModels() const
Eigen::Block< Eigen::MatrixXd, Eigen::Dynamic, Eigen::Dynamic > getFreeJointTrajectoryBlock(int joint)
Gets the block of free (optimizable) trajectory for a single joint.
void update(bool force=false)
int getNumPoints() const
Gets the number of points in the trajectory.
double smoothness_cost_jerk_
variables associated with the cost in acceleration
double getRandomDouble()
#define ROS_INFO(...)
Eigen::MatrixXd group_trajectory_backup_
std::vector< double > sphere_radii
Eigen::MatrixXd::ColXpr getJointTrajectory(int joint)
int getEndIndex() const
Gets the end index.
std::vector< double > distances
Eigen::MatrixXd & getTrajectory()
Gets the entire trajectory matrix.
Represents the smoothness cost for CHOMP, for a single joint.
Definition: chomp_cost.h:49
Eigen::MatrixXd collision_increments_
moveit::core::RobotState state_
std::vector< std::vector< double > > collision_point_potential_
double min(double a, double b)
void updateFromGroupTrajectory(const ChompTrajectory &group_trajectory)
Updates the full trajectory (*this) from the group trajectory.
Eigen::MatrixXd jacobian_
#define ROS_WARN_STREAM(args)
static const double DIFF_RULES[3][DIFF_RULE_LENGTH]
Definition: chomp_utils.h:49
bool filter_mode_
the collision threshold cost that needs to be mainted to avoid collisions
int max_iterations_
maximum time the optimizer can take to find a solution before terminating
Represents a discretized joint-space trajectory for CHOMP.
moveit::core::RobotState start_state_
std::vector< std::vector< int > > point_is_in_collision_
int getNumFreePoints() const
Gets the number of points (that are free to be optimized) in the trajectory.
bool use_stochastic_descent_
variables associated with the cost in jerk
const JointModel * getJointModel(const std::string &joint) const
std::vector< EigenSTL::vector_Vector3d > joint_positions_
void robotStateToRobotStateMsg(const RobotState &state, moveit_msgs::RobotState &robot_state, bool copy_attached_bodies=true)
#define ROS_INFO_STREAM(args)
static WallTime now()
const LinkModel * getChildLinkModel() const
void setJointGroupPositions(const std::string &joint_group_name, const double *gstate)
double getDiscretization() const
Gets the discretization time interval of the trajectory.
const LinkModel * getParentLinkModel() const
const Eigen::Affine3d & getJointTransform(const std::string &joint_name)
const std::vector< const JointModel * > & getActiveJointModels() const
std::vector< ChompCost > joint_costs_
#define ROS_ERROR_STREAM(args)
void computeJointProperties(int trajectoryPoint)
void registerParents(const moveit::core::JointModel *model)
int getNumJoints() const
Gets the number of joints in each trajectory point.
Eigen::VectorXd smoothness_derivative_
Eigen::Block< Eigen::MatrixXd, Eigen::Dynamic, Eigen::Dynamic > getFreeTrajectoryBlock()
Gets the block of the trajectory which can be optimized.
const VariableBounds & getVariableBounds(const std::string &variable) const
double max(double a, double b)
std::vector< VariableBounds > Bounds
#define ROS_ERROR(...)
IMETHOD void random(Vector &a)
JointType getType() const
Eigen::MatrixXd final_increments_
Eigen::VectorXd joint_state_velocities_
const Eigen::Vector3d & getAxis() const
const Eigen::Vector3d & getAxis() const
Eigen::VectorXd random_state_


chomp_motion_planner
Author(s): Gil Jones , Mrinal Kalakrishnan
autogenerated on Sun Oct 18 2020 13:17:08