|
42 | 42 |
|
43 | 43 | #include <moveit/task_constructor/stages/move_to.h> |
44 | 44 | #include <moveit/task_constructor/cost_terms.h> |
| 45 | +#include <moveit/task_constructor/moveit_compat.h> |
| 46 | + |
45 | 47 | #include <rviz_marker_tools/marker_creation.h> |
46 | 48 |
|
47 | 49 | namespace moveit { |
@@ -142,33 +144,29 @@ bool MoveTo::getJointStateGoal(const boost::any& goal, const moveit::core::Joint |
142 | 144 | } |
143 | 145 |
|
144 | 146 | bool MoveTo::getPoseGoal(const boost::any& goal, const planning_scene::PlanningScenePtr& scene, |
145 | | - Eigen::Isometry3d& target_eigen) { |
| 147 | + Eigen::Isometry3d& target) { |
146 | 148 | try { |
147 | | - const geometry_msgs::PoseStamped& target = boost::any_cast<geometry_msgs::PoseStamped>(goal); |
148 | | - tf2::fromMsg(target.pose, target_eigen); |
149 | | - |
| 149 | + const geometry_msgs::PoseStamped& msg = boost::any_cast<geometry_msgs::PoseStamped>(goal); |
| 150 | + tf2::fromMsg(msg.pose, target); |
150 | 151 | // transform target into global frame |
151 | | - const Eigen::Isometry3d& frame = scene->getFrameTransform(target.header.frame_id); |
152 | | - target_eigen = frame * target_eigen; |
| 152 | + target = scene->getFrameTransform(msg.header.frame_id) * target; |
153 | 153 | } catch (const boost::bad_any_cast&) { |
154 | 154 | return false; |
155 | 155 | } |
156 | 156 | return true; |
157 | 157 | } |
158 | 158 |
|
159 | | -bool MoveTo::getPointGoal(const boost::any& goal, const moveit::core::LinkModel* link, |
| 159 | +bool MoveTo::getPointGoal(const boost::any& goal, const Eigen::Isometry3d& ik_pose, |
160 | 160 | const planning_scene::PlanningScenePtr& scene, Eigen::Isometry3d& target_eigen) { |
161 | 161 | try { |
162 | 162 | const geometry_msgs::PointStamped& target = boost::any_cast<geometry_msgs::PointStamped>(goal); |
163 | 163 | Eigen::Vector3d target_point; |
164 | 164 | tf2::fromMsg(target.point, target_point); |
165 | | - |
166 | 165 | // transform target into global frame |
167 | | - const Eigen::Isometry3d& frame = scene->getFrameTransform(target.header.frame_id); |
168 | | - target_point = frame * target_point; |
| 166 | + target_point = scene->getFrameTransform(target.header.frame_id) * target_point; |
169 | 167 |
|
170 | 168 | // retain link orientation |
171 | | - target_eigen = scene->getCurrentState().getGlobalLinkTransform(link); |
| 169 | + target_eigen = ik_pose; |
172 | 170 | target_eigen.translation() = target_point; |
173 | 171 | } catch (const boost::bad_any_cast&) { |
174 | 172 | return false; |
@@ -204,47 +202,81 @@ bool MoveTo::compute(const InterfaceState& state, planning_scene::PlanningSceneP |
204 | 202 | // plan to joint-space target |
205 | 203 | success = planner_->plan(state.scene(), scene, jmg, timeout, robot_trajectory, path_constraints); |
206 | 204 | } else { // Cartesian goal |
207 | | - const moveit::core::LinkModel* link; |
208 | | - Eigen::Isometry3d target_eigen; |
209 | | - |
210 | | - // Cartesian targets require an IK reference frame |
| 205 | + // Where to go? |
| 206 | + Eigen::Isometry3d target; |
| 207 | + // What frame+offset in the robot should go there? |
211 | 208 | geometry_msgs::PoseStamped ik_pose_msg; |
| 209 | + |
212 | 210 | const boost::any& value = props.get("ik_frame"); |
| 211 | + |
| 212 | + auto get_tip{ [&jmg](std::string& out) { |
| 213 | + // determine IK frame from group |
| 214 | + std::vector<std::string> tips; |
| 215 | + jmg->getEndEffectorTips(tips); |
| 216 | + if (tips.size() != 1) { |
| 217 | + return false; |
| 218 | + } |
| 219 | + out = tips[0]; |
| 220 | + return true; |
| 221 | + } }; |
| 222 | + |
213 | 223 | if (value.empty()) { // property undefined |
214 | | - // determine IK link from group |
215 | | - if (!(link = jmg->getOnlyOneEndEffectorTip())) { |
| 224 | + if (!get_tip(ik_pose_msg.header.frame_id)) { |
216 | 225 | solution.markAsFailure("missing ik_frame"); |
217 | 226 | return false; |
218 | 227 | } |
219 | | - ik_pose_msg.header.frame_id = link->getName(); |
220 | 228 | ik_pose_msg.pose.orientation.w = 1.0; |
221 | 229 | } else { |
222 | 230 | ik_pose_msg = boost::any_cast<geometry_msgs::PoseStamped>(value); |
223 | | - if (!(link = robot_model->getLinkModel(ik_pose_msg.header.frame_id))) { |
224 | | - solution.markAsFailure("unknown link for ik_frame: " + ik_pose_msg.header.frame_id); |
| 231 | + if (ik_pose_msg.header.frame_id.empty() && !get_tip(ik_pose_msg.header.frame_id)) { |
| 232 | + solution.markAsFailure("frame_id of ik_frame is empty and no unique group tip was found"); |
| 233 | + return false; |
| 234 | + } else if (!scene->knowsFrameTransform(ik_pose_msg.header.frame_id)) { |
| 235 | + std::stringstream ss; |
| 236 | + ss << "ik_frame specified in unknown frame '" << ik_pose_msg << "'"; |
| 237 | + solution.markAsFailure(ss.str()); |
225 | 238 | return false; |
226 | 239 | } |
227 | 240 | } |
228 | 241 |
|
229 | | - if (!getPoseGoal(goal, scene, target_eigen) && !getPointGoal(goal, link, scene, target_eigen)) { |
| 242 | + Eigen::Isometry3d ik_pose_world{ [&]() { |
| 243 | + Eigen::Isometry3d t; |
| 244 | + tf2::fromMsg(ik_pose_msg.pose, t); |
| 245 | + t = scene->getFrameTransform(ik_pose_msg.header.frame_id) * t; |
| 246 | + return t; |
| 247 | + }() }; |
| 248 | + |
| 249 | + if (!getPoseGoal(goal, scene, target) && !getPointGoal(goal, ik_pose_world, scene, target)) { |
230 | 250 | solution.markAsFailure(std::string("invalid goal type: ") + goal.type().name()); |
231 | 251 | return false; |
232 | 252 | } |
233 | 253 |
|
| 254 | + auto add_frame{ [&](const Eigen::Isometry3d& pose, const char name[]) { |
| 255 | + geometry_msgs::PoseStamped msg; |
| 256 | + msg.header.frame_id = scene->getPlanningFrame(); |
| 257 | + msg.pose = tf2::toMsg(pose); |
| 258 | + rviz_marker_tools::appendFrame(solution.markers(), msg, 0.1, name); |
| 259 | + } }; |
| 260 | + |
234 | 261 | // visualize plan with frame at target pose and frame at link |
235 | | - geometry_msgs::PoseStamped target; |
236 | | - target.header.frame_id = scene->getPlanningFrame(); |
237 | | - target.pose = tf2::toMsg(target_eigen); |
238 | | - rviz_marker_tools::appendFrame(solution.markers(), target, 0.1, "ik frame"); |
239 | | - rviz_marker_tools::appendFrame(solution.markers(), ik_pose_msg, 0.1, "ik frame"); |
| 262 | + add_frame(target, "target frame"); |
| 263 | + add_frame(ik_pose_world, "ik frame"); |
| 264 | + |
| 265 | + const moveit::core::LinkModel* parent { |
| 266 | +#if MOVEIT_HAS_STATE_RIGID_PARENT_LINK |
| 267 | + scene->getCurrentState().getRigidlyConnectedParentLinkModel(ik_pose_msg.header.frame_id) |
| 268 | +#else |
| 269 | + getRigidlyConnectedParentLinkModel(scene->getCurrentState(), ik_pose_msg.header.frame_id) |
| 270 | +#endif |
| 271 | + }; |
240 | 272 |
|
241 | 273 | // transform target pose such that ik frame will reach there if link does |
242 | 274 | Eigen::Isometry3d ik_pose; |
243 | 275 | tf2::fromMsg(ik_pose_msg.pose, ik_pose); |
244 | | - target_eigen = target_eigen * ik_pose.inverse(); |
| 276 | + target = target * ik_pose_world.inverse() * scene->getFrameTransform(parent->getName()); |
245 | 277 |
|
246 | 278 | // plan to Cartesian target |
247 | | - success = planner_->plan(state.scene(), *link, target_eigen, jmg, timeout, robot_trajectory, path_constraints); |
| 279 | + success = planner_->plan(state.scene(), *parent, target, jmg, timeout, robot_trajectory, path_constraints); |
248 | 280 | } |
249 | 281 |
|
250 | 282 | // store result |
|
0 commit comments