5
5
#include < drake/geometry/geometry_instance.h>
6
6
#include < drake/geometry/geometry_roles.h>
7
7
#include < drake/geometry/proximity_properties.h>
8
+ #include < drake/multibody/inverse_kinematics/minimum_distance_lower_bound_constraint.h>
9
+ #include < drake/multibody/inverse_kinematics/orientation_constraint.h>
10
+ #include < drake/multibody/inverse_kinematics/position_constraint.h>
11
+ #include < drake/math/rigid_transform.h>
12
+ #include < drake/math/rotation_matrix.h>
8
13
#include < drake/solvers/solve.h>
9
14
#include < drake/visualization/visualization_config.h>
10
15
#include < drake/visualization/visualization_config_functions.h>
@@ -78,7 +83,7 @@ void KTOptPlanningContext::solve(planning_interface::MotionPlanResponse& res)
78
83
moveit::drake::getJerkBounds (joint_model_group, plant, lower_jerk_bounds, upper_jerk_bounds);
79
84
80
85
// q represents the complete state (joint positions and velocities)
81
- auto q = Eigen::VectorXd::Zero (plant.num_positions () + plant.num_velocities ());
86
+ Eigen::VectorXd q = Eigen::VectorXd::Zero (plant.num_positions () + plant.num_velocities ());
82
87
q << moveit::drake::getJointPositionVector (start_state, getGroupName (), plant);
83
88
q << moveit::drake::getJointVelocityVector (start_state, getGroupName (), plant);
84
89
@@ -137,6 +142,7 @@ void KTOptPlanningContext::solve(planning_interface::MotionPlanResponse& res)
137
142
138
143
// process path_constraints
139
144
addPathPositionConstraints (trajopt, plant, plant_context, params_.position_constraint_padding );
145
+ addPathOrientationConstraints (trajopt, plant, plant_context, params_.orientation_constraint_padding );
140
146
141
147
// solve the program
142
148
auto result = drake::solvers::Solve (prog);
@@ -155,7 +161,7 @@ void KTOptPlanningContext::solve(planning_interface::MotionPlanResponse& res)
155
161
// add collision constraints
156
162
for (int s = 0 ; s < params_.num_collision_check_points ; ++s)
157
163
{
158
- trajopt.AddPathPositionConstraint (std::make_shared<MinimumDistanceLowerBoundConstraint>(
164
+ trajopt.AddPathPositionConstraint (std::make_shared<drake::multibody:: MinimumDistanceLowerBoundConstraint>(
159
165
&plant, params_.collision_check_lower_distance_bound , &plant_context),
160
166
static_cast <double >(s) / (params_.num_collision_check_points - 1 ));
161
167
}
@@ -204,66 +210,145 @@ void KTOptPlanningContext::addPathPositionConstraints(KinematicTrajectoryOptimiz
204
210
const auto & req = getMotionPlanRequest ();
205
211
206
212
// check for path position constraints
207
- if (! req.path_constraints .position_constraints . empty () )
213
+ for ( const auto & position_constraint : req.path_constraints .position_constraints )
208
214
{
209
- for (const auto & position_constraint : req.path_constraints .position_constraints )
215
+ // Extract the bounding box's center (primitive pose)
216
+ const auto & primitive_pose = position_constraint.constraint_region .primitive_poses [0 ];
217
+ Eigen::Vector3d box_center (primitive_pose.position .x , primitive_pose.position .y , primitive_pose.position .z );
218
+ Eigen::Quaterniond box_orientation (primitive_pose.orientation .w , primitive_pose.orientation .x ,
219
+ primitive_pose.orientation .y , primitive_pose.orientation .z );
220
+ drake::math::RigidTransformd X_AbarA (box_orientation, box_center);
221
+
222
+ // Extract dimensions of the bounding box from
223
+ // constraint_region.primitives Assuming it is a box
224
+ // (shape_msgs::SolidPrimitive::BOX) and has dimensions in [x, y, z]
225
+ const auto link_ee_name = position_constraint.link_name ;
226
+ if (!plant.HasBodyNamed (link_ee_name))
210
227
{
211
- // Extract the bounding box's center (primitive pose)
212
- const auto & primitive_pose = position_constraint.constraint_region .primitive_poses [0 ];
213
- Eigen::Vector3d box_center (primitive_pose.position .x , primitive_pose.position .y , primitive_pose.position .z );
214
-
215
- // Extract dimensions of the bounding box from
216
- // constraint_region.primitives Assuming it is a box
217
- // (shape_msgs::SolidPrimitive::BOX) and has dimensions in [x, y, z]
218
- const auto link_ee_name = position_constraint.link_name ;
219
- if (!plant.HasBodyNamed (link_ee_name))
220
- {
221
- RCLCPP_ERROR (getLogger (),
222
- " The link specified in the PositionConstraint message, %s, does not exist in the Drake "
223
- " plant." ,
224
- link_ee_name.c_str ());
225
- continue ;
226
- }
227
- const auto & link_ee_frame = plant.GetFrameByName (link_ee_name);
228
+ RCLCPP_ERROR (getLogger (),
229
+ " The link specified in the PositionConstraint message, %s, does not exist in the Drake "
230
+ " plant." ,
231
+ link_ee_name.c_str ());
232
+ continue ;
233
+ }
234
+ // frameB
235
+ const auto & link_ee_frame = plant.GetFrameByName (link_ee_name);
228
236
229
- const auto base_frame_name = position_constraint.header .frame_id ;
230
- if (!plant.HasBodyNamed (base_frame_name))
231
- {
232
- RCLCPP_ERROR (getLogger (),
233
- " The link specified in the PositionConstraint message, %s, does not exist in the Drake "
234
- " plant." ,
235
- base_frame_name.c_str ());
236
- continue ;
237
- }
238
- const auto & base_frame = plant.GetFrameByName (base_frame_name);
237
+ const auto base_frame_name = position_constraint.header .frame_id ;
238
+ if (!plant.HasBodyNamed (base_frame_name))
239
+ {
240
+ RCLCPP_ERROR (getLogger (),
241
+ " The link specified in the PositionConstraint message, %s, does not exist in the Drake "
242
+ " plant." ,
243
+ base_frame_name.c_str ());
244
+ continue ;
245
+ }
246
+ // frameA
247
+ const auto & base_frame = plant.GetFrameByName (base_frame_name);
239
248
240
- const auto & primitive = position_constraint.constraint_region .primitives [0 ];
241
- if (primitive.type != shape_msgs::msg::SolidPrimitive::BOX)
242
- {
243
- RCLCPP_WARN (getLogger (), " Expects a bounding box constraint as a SolidPrimitive::BOX" );
244
- continue ;
245
- }
249
+ const auto & primitive = position_constraint.constraint_region .primitives [0 ];
250
+ if (primitive.type != shape_msgs::msg::SolidPrimitive::BOX)
251
+ {
252
+ RCLCPP_WARN (getLogger (), " Expects a bounding box constraint as a SolidPrimitive::BOX" );
253
+ continue ;
254
+ }
246
255
247
- // Calculate the lower and upper bounds based on the box dimensions
248
- // around the center
249
- const auto offset_vec = Eigen::Vector3d (std::max (0.0 , primitive.dimensions [0 ] / 2.0 - padding),
250
- std::max (0.0 , primitive.dimensions [1 ] / 2.0 - padding),
251
- std::max (0.0 , primitive.dimensions [2 ] / 2.0 - padding));
252
- const auto lower_bound = box_center - offset_vec;
253
- const auto upper_bound = box_center + offset_vec;
256
+ // Calculate the lower and upper bounds based on the box dimensions
257
+ // around the center
258
+ const auto offset_vec = Eigen::Vector3d (std::max (padding, primitive.dimensions [0 ] / 2.0 - padding),
259
+ std::max (padding, primitive.dimensions [1 ] / 2.0 - padding),
260
+ std::max (padding, primitive.dimensions [2 ] / 2.0 - padding));
254
261
262
+ // Check if equality constraint
263
+ if (req.path_constraints .name == " use_equality_constraints" )
264
+ {
265
+ // Add position constraint to each knot point of the trajectory
266
+ for (int i = 0 ; i < params_.num_position_equality_points ; ++i)
267
+ {
268
+ trajopt.AddPathPositionConstraint (std::make_shared<drake::multibody::PositionConstraint>(
269
+ &plant, base_frame, X_AbarA, -offset_vec, offset_vec, link_ee_frame,
270
+ Eigen::Vector3d (0.0 , 0.0 , 0.0 ), &plant_context),
271
+ static_cast <double >(i) / (params_.num_position_equality_points - 1 ));
272
+ }
273
+ }
274
+ else
275
+ {
255
276
// Add position constraint to each knot point of the trajectory
256
- for (int i = 0 ; i < params_.num_position_constraint_points ; ++i)
277
+ for (int i = 0 ; i < params_.num_position_inequality_points ; ++i)
257
278
{
258
- trajopt.AddPathPositionConstraint (
259
- std::make_shared<PositionConstraint>( &plant, base_frame, lower_bound, upper_bound , link_ee_frame,
260
- Eigen::Vector3d (0.0 , 0.0 , 0.0 ), &plant_context),
261
- static_cast <double >(i) / (params_.num_position_constraint_points - 1 ));
279
+ trajopt.AddPathPositionConstraint (std::make_shared<drake::multibody::PositionConstraint>(
280
+ &plant, base_frame, X_AbarA, -offset_vec, offset_vec , link_ee_frame,
281
+ Eigen::Vector3d (0.0 , 0.0 , 0.0 ), &plant_context),
282
+ static_cast <double >(i) / (params_.num_position_inequality_points - 1 ));
262
283
}
263
284
}
264
285
}
265
286
}
266
287
288
+ void KTOptPlanningContext::addPathOrientationConstraints (KinematicTrajectoryOptimization& trajopt,
289
+ const MultibodyPlant<double >& plant,
290
+ Context<double >& plant_context, const double padding)
291
+ {
292
+ // retrieve the motion planning request
293
+ const auto & req = getMotionPlanRequest ();
294
+
295
+ // check for path position constraints
296
+ for (const auto & orientation_constraint : req.path_constraints .orientation_constraints )
297
+ {
298
+ // NOTE: Current thesis, when you apply a Drake Orientation Constraint it
299
+ // expects the following
300
+ // Frame A: The frame in which the orientation constraint is defined
301
+ // Frame B: The frame to which the orientation constraint is enforced
302
+ // theta_bound: The angle difference between frame A's orientation and
303
+ // frame B's orientation
304
+
305
+ // Extract FrameA and FrameB for orientation constraint
306
+ // frame B
307
+ const auto link_ee_name = orientation_constraint.link_name ;
308
+ if (!plant.HasBodyNamed (link_ee_name))
309
+ {
310
+ RCLCPP_ERROR (getLogger (),
311
+ " The link specified in the Orientation Constraint message, %s, does not exist in the Drake "
312
+ " plant." ,
313
+ link_ee_name.c_str ());
314
+ continue ;
315
+ }
316
+ const auto & link_ee_frame = plant.GetFrameByName (link_ee_name);
317
+
318
+ // frame A
319
+ const auto base_frame_name = orientation_constraint.header .frame_id ;
320
+ if (!plant.HasBodyNamed (base_frame_name))
321
+ {
322
+ RCLCPP_ERROR (getLogger (),
323
+ " The link specified in the Orientation Constraint message, %s, does not exist in the Drake "
324
+ " plant." ,
325
+ base_frame_name.c_str ());
326
+ continue ;
327
+ }
328
+ const auto & base_frame = plant.GetFrameByName (base_frame_name);
329
+
330
+ // Extract the orientation of that Frame B needs to be constrained to w.r.t Frame A
331
+ const auto & constrained_orientation = orientation_constraint.orientation ;
332
+ // convert to drake's RotationMatrix
333
+ const auto R_BbarB = drake::math::RotationMatrixd (Eigen::Quaterniond (
334
+ constrained_orientation.w , constrained_orientation.x , constrained_orientation.y , constrained_orientation.z ));
335
+
336
+ // NOTE: There are 3 tolerances given for the orientation constraint in moveit
337
+ // message, Drake only takes in a single theta bound. For now, we take any
338
+ // of the tolerances as the theta bound
339
+ const double theta_bound = orientation_constraint.absolute_x_axis_tolerance - padding;
340
+
341
+ // Add orientation constraint to each knot point of the trajectory
342
+ for (int i = 0 ; i < params_.num_orientation_constraint_points ; ++i)
343
+ {
344
+ trajopt.AddPathPositionConstraint (std::make_shared<drake::multibody::OrientationConstraint>(
345
+ &plant, link_ee_frame, drake::math::RotationMatrixd::Identity (), base_frame,
346
+ R_BbarB, theta_bound, &plant_context),
347
+ static_cast <double >(i) / (params_.num_orientation_constraint_points - 1 ));
348
+ }
349
+ }
350
+ }
351
+
267
352
bool KTOptPlanningContext::terminate ()
268
353
{
269
354
RCLCPP_ERROR (getLogger (), " KTOptPlanningContext::terminate() is not implemented!" );
0 commit comments