@@ -28,12 +28,14 @@ TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
28
28
#include < console_bridge/console.h>
29
29
#include < tesseract_environment/core/utils.h>
30
30
#include < boost/date_time/posix_time/posix_time.hpp>
31
+ #include < trajopt_sqp/trust_region_sqp_solver.h>
32
+ #include < trajopt_sqp/osqp_eigen_solver.h>
31
33
TESSERACT_COMMON_IGNORE_WARNINGS_POP
32
34
33
35
#include < tesseract_motion_planners/trajopt_ifopt/trajopt_ifopt_motion_planner.h>
34
36
#include < tesseract_command_language/command_language.h>
35
37
#include < tesseract_command_language/utils/utils.h>
36
- // #include <tesseract_motion_planners/core/utils.h>
38
+ #include < tesseract_motion_planners/core/utils.h>
37
39
38
40
using namespace trajopt ;
39
41
@@ -83,102 +85,109 @@ bool TrajOptIfoptMotionPlanner::terminate()
83
85
void TrajOptIfoptMotionPlanner::clear ()
84
86
{
85
87
// params = sco::BasicTrustRegionSQPParameters();
86
- // callbacks.clear();
88
+ callbacks.clear ();
87
89
}
88
90
89
91
tesseract_common::StatusCode TrajOptIfoptMotionPlanner::solve (const PlannerRequest& request,
90
92
PlannerResponse& response,
91
93
bool verbose) const
92
94
{
93
- // if (!checkUserInput(request))
94
- // {
95
- // response.status =
96
- // tesseract_common::StatusCode(TrajOptIfoptMotionPlannerStatusCategory::ErrorInvalidInput, status_category_);
97
- // return response.status;
98
- // }
99
- // std::shared_ptr<ifopt::Problem> problem;
100
- // if (request.data)
101
- // {
102
- // problem = std::static_pointer_cast<trajopt::TrajOptProb>(request.data);
103
- // }
104
- // else
105
- // {
106
- // if (!problem_generator)
107
- // {
108
- // CONSOLE_BRIDGE_logError("TrajOptPlanner does not have a problem generator specified.");
109
- // response.status =
110
- // tesseract_common::StatusCode(TrajOptIfoptMotionPlannerStatusCategory::ErrorInvalidInput,
111
- // status_category_);
112
- // return response.status;
113
- // }
114
- // problem = problem_generator(name_, request, plan_profiles, composite_profiles);
115
- // response.data = problem;
116
- // }
117
-
118
- // // Set Log Level
119
- // if (verbose)
120
- // util::gLogLevel = util::LevelInfo;
121
- // else
122
- // util::gLogLevel = util::LevelWarn;
123
-
124
- // // Create optimizer
125
- // sco::BasicTrustRegionSQP opt(problem);
126
- // opt.setParameters(params);
127
- // opt.initialize(trajToDblVec(problem->GetInitTraj()));
128
-
129
- // // Add all callbacks
130
- // for (const sco::Optimizer::Callback& callback : callbacks)
131
- // {
132
- // opt.addCallback(callback);
133
- // }
134
-
135
- // // Optimize
136
- // auto tStart = boost::posix_time::second_clock::local_time();
137
- // opt.optimize();
138
- // CONSOLE_BRIDGE_logInform("planning time: %.3f", (boost::posix_time::second_clock::local_time() -
139
- // tStart).seconds()); if (opt.results().status != sco::OptStatus::OPT_CONVERGED)
140
- // {
141
- // response.status =
142
- // tesseract_common::StatusCode(TrajOptIfoptMotionPlannerStatusCategory::FailedToFindValidSolution,
143
- // status_category_);
144
- // return response.status;
145
- // }
146
-
147
- // // Get the results
148
- // tesseract_common::TrajArray trajectory = getTraj(opt.x(), problem->GetVars());
149
-
150
- // // Flatten the results to make them easier to process
151
- // response.results = request.seed;
152
- // auto results_flattened = flattenProgramToPattern(response.results, request.instructions);
153
- // auto instructions_flattened = flattenProgram(request.instructions);
154
-
155
- // // Loop over the flattened results and add them to response if the input was a plan instruction
156
- // Eigen::Index result_index = 0;
157
- // for (std::size_t idx = 0; idx < instructions_flattened.size(); idx++)
158
- // {
159
- // // If idx is zero then this should be the start instruction
160
- // assert((idx == 0) ? isPlanInstruction(instructions_flattened.at(idx).get()) : true);
161
- // assert((idx == 0) ? isMoveInstruction(results_flattened[idx].get()) : true);
162
- // if (isPlanInstruction(instructions_flattened.at(idx).get()))
163
- // {
164
- // // This instruction corresponds to a composite. Set all results in that composite to the results
165
- // const auto* plan_instruction = instructions_flattened.at(idx).get().cast_const<PlanInstruction>();
166
- // if (plan_instruction->isStart())
167
- // {
168
- // assert(idx == 0);
169
- // assert(isMoveInstruction(results_flattened[idx].get()));
170
- // auto* move_instruction = results_flattened[idx].get().cast<MoveInstruction>();
171
- // move_instruction->getWaypoint().cast<StateWaypoint>()->position = trajectory.row(result_index++);
172
- // }
173
- // else
174
- // {
175
- // auto* move_instructions = results_flattened[idx].get().cast<CompositeInstruction>();
176
- // for (auto& instruction : *move_instructions)
177
- // instruction.cast<MoveInstruction>()->getWaypoint().cast<StateWaypoint>()->position =
178
- // trajectory.row(result_index++);
179
- // }
180
- // }
181
- // }
95
+ if (!checkUserInput (request))
96
+ {
97
+ response.status =
98
+ tesseract_common::StatusCode (TrajOptIfoptMotionPlannerStatusCategory::ErrorInvalidInput, status_category_);
99
+ return response.status ;
100
+ }
101
+ std::shared_ptr<TrajOptIfoptProblem> problem;
102
+ if (request.data )
103
+ {
104
+ problem = std::static_pointer_cast<TrajOptIfoptProblem>(request.data );
105
+ }
106
+ else
107
+ {
108
+ if (!problem_generator)
109
+ {
110
+ CONSOLE_BRIDGE_logError (" TrajOptIfoptPlanner does not have a problem generator specified." );
111
+ response.status =
112
+ tesseract_common::StatusCode (TrajOptIfoptMotionPlannerStatusCategory::ErrorInvalidInput, status_category_);
113
+ return response.status ;
114
+ }
115
+ problem = problem_generator (name_, request, plan_profiles, composite_profiles);
116
+ response.data = problem;
117
+ }
118
+
119
+ // Create optimizer
120
+ /* * @todo Enable solver selection (e.g. IPOPT) */
121
+ auto qp_solver = std::make_shared<trajopt_sqp::OSQPEigenSolver>();
122
+ trajopt_sqp::TrustRegionSQPSolver solver (qp_solver);
123
+ /* * @todo Set these as the defaults in trajopt and allow setting */
124
+ qp_solver->solver_ .settings ()->setVerbosity (verbose);
125
+ qp_solver->solver_ .settings ()->setWarmStart (true );
126
+ qp_solver->solver_ .settings ()->setPolish (true );
127
+ qp_solver->solver_ .settings ()->setAdaptiveRho (false );
128
+ qp_solver->solver_ .settings ()->setMaxIteraction (8192 );
129
+ qp_solver->solver_ .settings ()->setAbsoluteTolerance (1e-4 );
130
+ qp_solver->solver_ .settings ()->setRelativeTolerance (1e-6 );
131
+
132
+ // Add all callbacks
133
+ for (const trajopt_sqp::SQPCallback::Ptr & callback : callbacks)
134
+ {
135
+ solver.registerCallback (callback);
136
+ }
137
+
138
+ // solve
139
+ solver.verbose = verbose;
140
+
141
+ auto tStart = boost::posix_time::second_clock::local_time ();
142
+ solver.Solve (*(problem->nlp ));
143
+ CONSOLE_BRIDGE_logInform (" planning time: %.3f" , (boost::posix_time::second_clock::local_time () - tStart).seconds ());
144
+
145
+ // Check success
146
+ if (solver.getStatus () != trajopt_sqp::SQPStatus::NLP_CONVERGED)
147
+ {
148
+ response.status = tesseract_common::StatusCode (TrajOptIfoptMotionPlannerStatusCategory::FailedToFindValidSolution,
149
+ status_category_);
150
+ return response.status ;
151
+ }
152
+
153
+ // Get the results - This can likely be simplified if we get rid of the traj array
154
+ Eigen::VectorXd x = problem->nlp ->GetOptVariables ()->GetValues ();
155
+ Eigen::Map<trajopt::TrajArray> trajectory (x.data (),
156
+ static_cast <Eigen::Index>(problem->vars .size ()),
157
+ static_cast <Eigen::Index>(problem->vars [0 ]->GetValues ().size ()));
158
+
159
+ // Flatten the results to make them easier to process
160
+ response.results = request.seed ;
161
+ auto results_flattened = flattenProgramToPattern (response.results , request.instructions );
162
+ auto instructions_flattened = flattenProgram (request.instructions );
163
+
164
+ // Loop over the flattened results and add them to response if the input was a plan instruction
165
+ Eigen::Index result_index = 0 ;
166
+ for (std::size_t idx = 0 ; idx < instructions_flattened.size (); idx++)
167
+ {
168
+ // If idx is zero then this should be the start instruction
169
+ assert ((idx == 0 ) ? isPlanInstruction (instructions_flattened.at (idx).get ()) : true );
170
+ assert ((idx == 0 ) ? isMoveInstruction (results_flattened[idx].get ()) : true );
171
+ if (isPlanInstruction (instructions_flattened.at (idx).get ()))
172
+ {
173
+ // This instruction corresponds to a composite. Set all results in that composite to the results
174
+ const auto * plan_instruction = instructions_flattened.at (idx).get ().cast_const <PlanInstruction>();
175
+ if (plan_instruction->isStart ())
176
+ {
177
+ assert (idx == 0 );
178
+ assert (isMoveInstruction (results_flattened[idx].get ()));
179
+ auto * move_instruction = results_flattened[idx].get ().cast <MoveInstruction>();
180
+ move_instruction->getWaypoint ().cast <StateWaypoint>()->position = trajectory.row (result_index++);
181
+ }
182
+ else
183
+ {
184
+ auto * move_instructions = results_flattened[idx].get ().cast <CompositeInstruction>();
185
+ for (auto & instruction : *move_instructions)
186
+ instruction.cast <MoveInstruction>()->getWaypoint ().cast <StateWaypoint>()->position =
187
+ trajectory.row (result_index++);
188
+ }
189
+ }
190
+ }
182
191
183
192
response.status =
184
193
tesseract_common::StatusCode (TrajOptIfoptMotionPlannerStatusCategory::SolutionFound, status_category_);
0 commit comments