-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TrajOpt failed to find a collision-free path in the following example #147
Comments
solution is found when ifopt is enabled. but it takes about 23s. |
What hash are you using for tesseract repos? |
Are there waypoints that intersect with the collision column? If so, the current default profiles for the TrajOpt and TrajOpt-IFOPT planner add Cartesian waypoints as constraints (rather than costs). From what I understand, this means that the robot must visit each waypoint exactly (since you are specifying a |
tesseract: commit 1241d51a953ff655082c77878ec82b33d12b9070 Sat Dec 4 00:53:36 2021 -0600 ubuntu 18.04, ros melodic BTW: does the method with ompl profile use the solution found by ompl as initial seed of trajopt? I got output like this: |
there is no such waypoint. Defined waypoints are: |
I was able to recreate the issue. There is a fundamental difference between TrajOpt and TrajOptIfopt when it comes to how collision are added to the SQP problem. In the case of TrajOpt it adds every contact as a single equation which results in a large number of equations added. In the case of TrajOptIfopt the number of equation cannot be dynamic so we had to change things. If you set the num_eq to three it will find the three pairs of links which have the worst contact distance and generate a weighted average for gradient for a given link pair and use the worst contact distance as the constant when it creates the convex approximation. This appears to make TrajOptIfopt more stable when dealing with octomaps because for a given link pair that includes octomap you get a single equation that represents all of the contacts. This may mean it is better to update TrajOpt to do the same thing as TrajOptIfopt. I was able to get it to plan if you replace the function Command::Ptr TestExample::addPointCloud()
{
// Create octomap and add it to the local environment
pcl::PointCloud<pcl::PointXYZ> full_cloud;
double delta = 0.01;
double height = cylinder_h_;
double radius = 0.1;
auto n_h = static_cast<int>(height / delta);
auto n_r = static_cast<int>(radius / delta);
auto n_th = static_cast<int>(2*3.1415926 / delta);
for (int h = 0; h < n_h; ++h)
for (int r = 0; r < n_r; ++r)
for (int th = 0; th < n_th; ++th)
full_cloud.push_back(pcl::PointXYZ( static_cast<float>(r * delta * cos(th*delta)),
static_cast<float>(r * delta * sin(th*delta)),
static_cast<float>(h * delta)) );
sensor_msgs::PointCloud2 pointcloud_msg;
pcl::toROSMsg(full_cloud, pointcloud_msg);
// Add octomap to environment
Link link_octomap("octomap_attached");
Visual::Ptr visual = std::make_shared<Visual>();
visual->origin = Eigen::Isometry3d::Identity();
visual->origin.translation() = Eigen::Vector3d(0.8, 0, 0);
visual->geometry = std::make_shared<tesseract_geometry::Octree>(full_cloud, 0.025, tesseract_geometry::Octree::SPHERE_INSIDE, true);
link_octomap.visual.push_back(visual);
Collision::Ptr collision = std::make_shared<Collision>();
collision->origin = visual->origin;
collision->geometry = visual->geometry;
link_octomap.collision.push_back(collision);
Joint joint_octomap("joint_octomap_attached");
joint_octomap.parent_link_name = "base_link";
joint_octomap.child_link_name = link_octomap.getName();
joint_octomap.type = JointType::FIXED;
return std::make_shared<tesseract_environment::AddLinkCommand>(link_octomap, joint_octomap);
} |
Also, It is always good to set the collision buffer to a value greater than zero which makes things more stable and converge faster. Below I have set it to 2cm which will allow it to still include equation in the SQP problem near the collision margin. auto composite_profile = std::make_shared<TrajOptIfoptDefaultCompositeProfile>();
composite_profile->collision_cost_config->type = tesseract_collision::CollisionEvaluatorType::LVS_DISCRETE;
composite_profile->collision_cost_config->collision_margin_buffer = 0.02;
composite_profile->collision_constraint_config->type = tesseract_collision::CollisionEvaluatorType::LVS_DISCRETE;
composite_profile->collision_constraint_config->collision_margin_buffer = 0.02; auto composite_profile = std::make_shared<TrajOptDefaultCompositeProfile>();
composite_profile->collision_cost_config.enabled = true;
composite_profile->collision_cost_config.safety_margin_buffer = 0.02;
composite_profile->collision_constraint_config.enabled = true;
composite_profile->collision_constraint_config.safety_margin_buffer = 0.02; |
Oh, forgot one thing. Also had to set the coeff for TrajOpt to auto composite_profile = std::make_shared<TrajOptDefaultCompositeProfile>();
composite_profile->collision_cost_config.enabled = true;
composite_profile->collision_cost_config.safety_margin_buffer = 0.02;
composite_profile->collision_cost_config.coeff = 1;
composite_profile->collision_constraint_config.enabled = true;
composite_profile->collision_constraint_config.safety_margin_buffer = 0.02;
composite_profile->collision_constraint_config.coeff = 1; |
Also motion planning is much faster if you sphere instead of boxes and recommend building in release because the default is debug. |
@Levi-Armstrong Thanks very much for your detailed answer. Trajopt and TrajoptIfopt now can find valid solutions within 2s now after implementing your suggestion. maybe not so important: TrajoptIfopt has the following error output while it did find a valid path :
|
Is the option for using a single weighted sum of all collision vectors still an option in both the TrajOpt and TrajOptIfopt planners? It seems like that would be a good alternative to specifying an arbitrary number of collision vectors to consider |
This will usually happen near a convergence. It should be changed to a warning. If you were to add your constraint/cost then and you were seeing this on the first few iteration then you would want to look into it. |
The legacy trajopt has an option to enable weighted average, but I know for a fact how it is implemented is incorrect. I correctly implemented it in the IFOPT version but did not with trajopt because the goal is that it will be deprecated once we are confident that IFOPT version is ready. I do not believe it would be a lot of work to update trajopt to do the same. |
I might look into back-porting this for the legacy planner since we're using this option for one of my current projects |
When the robot is closer to the collision cylinder (say 0.7), both trajopt and trajopt_ifopt failed to find a collision-free path, while ompl X trajopt succeeded.
|
Here is an example in the ros planning server on how to check if it was successful.
Is this the base of the robot? If so, one thing to remember is that trajopt is a local optimizer, so the initial condition(trajectory) will affect its ability to find a solution. This is why ompl + trajopt succeeds because ompl gave trajopt a better seed to start with allowing it to find a different local optimum solution. If you are using the default trajopt process planner it is using joint interpolated as the initial seed which get created by the Simple planner. In this case it may be better to change the simple planner the fixed state assign simple planner and tell it to assign all states in the trajectory as the start state. This will allow trajopt to evolve organically from the start to the goal. I image why it fails when you move it closer is that joint 6 link gets a gradient to move way from the base of the robot and the other links get a gradient to move closer to the base creating opposing constraints at the optimizer.
|
Gotcha. Thanks very much! |
Other question: has the weighted average been fixed in legacy trajopt? |
It has not, but I have a PR which should completely fix it for TrajOptIfopt where each shape pair has an equation instead of a link pair because a link can have multiple shapes. I think the best solution would be to copy the code from IFOPT into trajopt_utils that does the averaging and use it in both trajopt and trajopt_ifopt. |
Hi,
I am testing with a simple example modified from basic_cartesian_example: move the manipulator from one side of a cylinder to the other side in joint space:
But trajOpt failed to find a valid path. I'm not sure which paramter should be tuned.
The ros package "test_example" is attached. It needs xacro and srdf files from tesseract_ros_example.
Usage: (method_id: 1: trajopt_ifopt profile; 2: trajopt profile; 3: ompl profile)
roslaunch test_example test_example.launch method_id:=3
method_id 1&3 can find solution in about 20~30s. method_id 2 fails to find a solution.
test_example.zip
Thanks!
The text was updated successfully, but these errors were encountered: