Loading...
Searching...
No Matches
MultiLevelPlanarManipulatorDemo.cpp
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2021,
5 * Max Planck Institute for Intelligent Systems (MPI-IS).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 * * Neither the name of the MPI-IS nor the names
19 * of its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
21 * permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 *********************************************************************/
36
37/* Author: Andreas Orthey */
38
39// This is basically just a simplified version of Ryan Luna's Demo, used for
40// testing purposes of the multilevel planning framework
41
42#include <fstream>
43
44#include "boost/program_options.hpp"
45#include "../PlanarManipulator/PolyWorld.h"
46#include "../PlanarManipulator/PlanarManipulatorPolyWorld.h"
47#include "../PlanarManipulator/PlanarManipulator.h"
48#include "../PlanarManipulator/PlanarManipulatorStateSpace.h"
49#include "../PlanarManipulator/PlanarManipulatorStateValidityChecker.h"
50#include "../PlanarManipulator/PlanarManipulatorIKGoal.h"
51#include "MultiLevelPlanarManipulatorCommon.h"
52
53#include <ompl/geometric/planners/rrt/RRTConnect.h>
54#include <ompl/geometric/planners/rrt/RRT.h>
55#include <ompl/base/spaces/SE2StateSpace.h>
56#include <ompl/base/spaces/RealVectorStateSpace.h>
57#include <ompl/multilevel/planners/qrrt/QRRT.h>
58#include <ompl/multilevel/planners/qmp/QMP.h>
59
60#include <ompl/multilevel/datastructures/Projection.h>
61#include <ompl/multilevel/datastructures/projections/SE2_R2.h>
62#include <boost/math/constants/constants.hpp>
63
64using namespace ompl::geometric;
65
66namespace ompl
67{
68 namespace multilevel
69 {
70 OMPL_CLASS_FORWARD(Projection);
71 }
72} // namespace ompl
73
74class ProjectionJointSpaceToSE2 : public ompl::multilevel::Projection
75{
76public:
77 ProjectionJointSpaceToSE2(StateSpacePtr bundle, StateSpacePtr base, PlanarManipulator *manip)
78 : Projection(bundle, base), manip_(manip)
79 {
81 }
82
83 void project(const State *xBundle, State *xBase) const
84 {
85 std::vector<double> reals;
86 getBundle()->copyToReals(reals, xBundle);
87
88 Eigen::Affine2d eeFrame;
89 manip_->FK(reals, eeFrame);
90
91 double x = eeFrame.translation()(0);
92 double y = eeFrame.translation()(1);
93 double yaw = acos(eeFrame.matrix()(0, 0));
94
95 xBase->as<SE2StateSpace::StateType>()->setXY(x, y);
96 xBase->as<SE2StateSpace::StateType>()->setYaw(yaw);
97
98 getBundle()->printState(xBundle);
99 getBase()->printState(xBase);
100 }
101
102 void lift(const State *xBase, State *xBundle) const
103 {
104 std::vector<double> reals;
105 getBase()->copyToReals(reals, xBase);
106
107 // to Eigen
108 Eigen::Affine2d eeFrame = Eigen::Affine2d::Identity();
109 eeFrame.translation()(0) = reals.at(0);
110 eeFrame.translation()(1) = reals.at(1);
111 eeFrame.rotate(reals.at(2));
112
113 std::vector<double> solution;
114 manip_->FABRIK(solution, eeFrame);
115
116 double *angles = xBundle->as<PlanarManipulatorStateSpace::StateType>()->values;
117 for (uint k = 0; k < solution.size(); k++)
118 {
119 angles[k] = solution.at(k);
120 }
121 }
122
123private:
124 PlanarManipulator *manip_;
125};
126
127int main()
128{
129 Eigen::Affine2d baseFrame;
130 Eigen::Affine2d goalFrame;
131
132 PlanarManipulator manipulator = PlanarManipulator(numLinks, 1.0 / numLinks);
133 PolyWorld world = createCorridorProblem(numLinks, baseFrame, goalFrame);
134
135 // #########################################################################
136 // ## Create robot joint configuration space [TOTAL SPACE]
137 // #########################################################################
138 ompl::base::StateSpacePtr space(new PlanarManipulatorStateSpace(numLinks));
139 ompl::base::RealVectorBounds bounds(numLinks);
140 bounds.setLow(-boost::math::constants::pi<double>());
141 bounds.setHigh(boost::math::constants::pi<double>());
142 space->as<PlanarManipulatorStateSpace>()->setBounds(bounds);
143 manipulator.setBounds(bounds.low, bounds.high);
144
145 SpaceInformationPtr si = std::make_shared<SpaceInformation>(space);
146 si->setStateValidityChecker(std::make_shared<PlanarManipulatorCollisionChecker>(si, manipulator, &world));
147 si->setStateValidityCheckingResolution(0.001);
148
149 // #########################################################################
150 // ## Create task space [SE2 BASE SPACE]
151 // #########################################################################
152 ompl::base::StateSpacePtr spaceSE2(new SE2StateSpace());
153 ompl::base::RealVectorBounds boundsWorkspace(2);
154 boundsWorkspace.setLow(-2);
155 boundsWorkspace.setHigh(+2);
156 spaceSE2->as<SE2StateSpace>()->setBounds(boundsWorkspace);
157
158 SpaceInformationPtr siSE2 = std::make_shared<SpaceInformation>(spaceSE2);
159 siSE2->setStateValidityChecker(std::make_shared<SE2CollisionChecker>(siSE2, &world));
160 siSE2->setStateValidityCheckingResolution(0.001);
161
162 // #########################################################################
163 // ## Create task space [R2 BASE SPACE]
164 // #########################################################################
165 // ompl::base::StateSpacePtr spaceR2(new RealVectorStateSpace(2));
166 // ompl::base::RealVectorBounds boundsR2(2);
167 // boundsR2.setLow(-2);
168 // boundsR2.setHigh(+2);
169 // spaceR2->as<RealVectorStateSpace>()->setBounds(boundsR2);
170
171 // SpaceInformationPtr siR2 = std::make_shared<SpaceInformation>(spaceR2);
172 // // siR2->setStateValidityChecker(std::make_shared<AllValidStateValidityChecker>(siR2));
173 // siR2->setStateValidityChecker(std::make_shared<R2CollisionChecker>(siR2, &world));
174 // siR2->setStateValidityCheckingResolution(0.001);
175
176 // #########################################################################
177 // ## Create mapping total to base space [PROJECTION]
178 // #########################################################################
179 ompl::multilevel::ProjectionPtr projAB = std::make_shared<ProjectionJointSpaceToSE2>(space, spaceSE2, &manipulator);
180
181 // ompl::multilevel::ProjectionPtr projBC = std::make_shared<ompl::multilevel::Projection_SE2_R2>(spaceSE2,
182 // spaceR2);
183
184 // std::static_pointer_cast<ompl::multilevel::FiberedProjection>(projBC)->makeFiberSpace();
185
186 // #########################################################################
187 // ## Put it all together
188 // #########################################################################
189 std::vector<SpaceInformationPtr> siVec;
190 std::vector<ompl::multilevel::ProjectionPtr> projVec;
191
192 // siVec.push_back(siR2); // Base Space R2
193 // projVec.push_back(projBC); // Projection R2 to SE2
194 siVec.push_back(siSE2); // Base Space SE2
195 projVec.push_back(projAB); // Projection SE2 to X
196 siVec.push_back(si); // State Space X
197
198 auto planner = std::make_shared<ompl::multilevel::QRRT>(siVec, projVec);
199
200 // #########################################################################
201 // ## Set start state
202 // #########################################################################
203 ompl::base::State *start = si->allocState();
204 double *start_angles = start->as<PlanarManipulatorStateSpace::StateType>()->values;
205
206 for (int i = 0; i < numLinks; ++i)
207 {
208 start_angles[i] = 1e-1 * (pow(-1, i)) + i * 1e-3;
209 // start_angles[i] = 1e-7;//1e-1*(pow(-1,i)) + i*1e-3;
210 }
211
212 // #########################################################################
213 // ## Set goal state
214 // #########################################################################
215 // 0.346324 0.0828153 2.96842 -2.17559 -0.718962 0.16532 -0.228314 0.172762 0.0471638 0.341137
216 ompl::base::State *goal = si->allocState();
217
218 std::vector<double> goalJoints;
219 manipulator.IK(goalJoints, goalFrame);
220
221 double *goal_angles = goal->as<PlanarManipulatorStateSpace::StateType>()->values;
222 goal_angles[0] = 0.346324;
223 goal_angles[1] = 0.0828153;
224 goal_angles[2] = 2.96842;
225 goal_angles[3] = -2.17559;
226 goal_angles[4] = -0.718962;
227 goal_angles[5] = 0.16532;
228 goal_angles[6] = -0.228314;
229 goal_angles[7] = 0.172762;
230
231 ProblemDefinitionPtr pdef = std::make_shared<ProblemDefinition>(si);
232 pdef->addStartState(start);
233 pdef->setGoalState(goal, 1e-3);
234
235 si->freeState(start);
236 si->freeState(goal);
237
238 // #########################################################################
239 // ## Invoke planner
240 // #########################################################################
241 planner->setProblemDefinition(pdef);
242 planner->setup();
243
244 PlannerStatus status = planner->Planner::solve(timeout);
245
248 {
249 PathPtr path = pdef->getSolutionPath();
250 PathGeometric &pgeo = *static_cast<PathGeometric *>(path.get());
251 OMPL_INFORM("Solution path has %d states", pgeo.getStateCount());
252
253 pgeo.interpolate(250);
254 WriteVisualization(manipulator, &world, pgeo);
255 }
256}
A shared pointer wrapper for ompl::base::Path.
A shared pointer wrapper for ompl::base::ProblemDefinition.
The lower and upper bounds for an Rn space.
A state space representing SE(2).
A shared pointer wrapper for ompl::base::SpaceInformation.
A shared pointer wrapper for ompl::base::StateSpace.
ompl::base::State StateType
Define the type of state allocated by this space.
Definition StateSpace.h:78
Definition of an abstract state.
Definition State.h:50
const T * as() const
Cast this instance to a desired type.
Definition State.h:66
Definition of a geometric path.
std::size_t getStateCount() const
Get the number of states (way-points) that make up this path.
void interpolate(unsigned int count)
Insert a number of states in a path so that the path is made up of exactly count states....
#define OMPL_INFORM(fmt,...)
Log a formatted information string.
Definition Console.h:68
This namespace contains sampling based planning routines shared by both planning under geometric cons...
This namespace contains code that is specific to planning under geometric constraints.
This namespace contains datastructures and planners to exploit multilevel abstractions,...
@ PROJECTION_TASK_SPACE
X \rightarrow T (A mapping from state space X to a task space T).
Main namespace. Contains everything in this library.
A class to store the exit status of Planner::solve().
@ EXACT_SOLUTION
The planner found an exact solution.
@ APPROXIMATE_SOLUTION
The planner found an approximate solution.