Skip to content

Commit 79869b8

Browse files
authored
Merge pull request #304 from v4hn/pr-move-to-tests
Add MoveTo tests & make them pass
2 parents d6f68f9 + 3b83598 commit 79869b8

File tree

17 files changed

+438
-108
lines changed

17 files changed

+438
-108
lines changed

core/include/moveit/task_constructor/moveit_compat.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,5 @@
5555

5656
// use object shape poses relative to a single object pose
5757
#define MOVEIT_HAS_OBJECT_POSE MOVEIT_VERSION_GE(1, 1, 6)
58+
59+
#define MOVEIT_HAS_STATE_RIGID_PARENT_LINK MOVEIT_VERSION_GE(1, 1, 6)

core/include/moveit/task_constructor/stage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ enum InterfaceFlag
8484
GENERATE = WRITES_PREV_END | WRITES_NEXT_START,
8585
};
8686

87-
using InterfaceFlags = Flags<InterfaceFlag>;
87+
using InterfaceFlags = utils::Flags<InterfaceFlag>;
8888

8989
/** invert interface such that
9090
* - new end can connect to old start

core/include/moveit/task_constructor/stages/fixed_state.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ namespace stages {
4848
class FixedState : public Generator
4949
{
5050
public:
51-
FixedState(const std::string& name = "initial state");
51+
FixedState(const std::string& name = "initial state", planning_scene::PlanningScenePtr = nullptr);
5252
void setState(const planning_scene::PlanningScenePtr& scene);
5353

5454
void reset() override;

core/include/moveit/task_constructor/stages/move_to.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class MoveTo : public PropagatingEitherWay
9999
bool getJointStateGoal(const boost::any& goal, const core::JointModelGroup* jmg, moveit::core::RobotState& state);
100100
bool getPoseGoal(const boost::any& goal, const planning_scene::PlanningScenePtr& scene,
101101
Eigen::Isometry3d& target_eigen);
102-
bool getPointGoal(const boost::any& goal, const moveit::core::LinkModel* link,
102+
bool getPointGoal(const boost::any& goal, const Eigen::Isometry3d& ik_pose,
103103
const planning_scene::PlanningScenePtr& scene, Eigen::Isometry3d& target_eigen);
104104

105105
protected:

core/include/moveit/task_constructor/utils.h

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,38 @@
3232
* POSSIBILITY OF SUCH DAMAGE.
3333
*********************************************************************/
3434

35-
/* Authors: Robert Haschke
36-
Desc: Project-agnostic utility classes
35+
/* Authors: Robert Haschke, Michael 'v4hn' Goerner
36+
Desc: Miscellaneous utilities
3737
*/
3838

3939
#pragma once
4040

41+
#include <string>
4142
#include <type_traits>
4243
#include <initializer_list>
4344

45+
#include <Eigen/Geometry>
46+
47+
#include <moveit/macros/class_forward.h>
48+
49+
namespace planning_scene {
50+
MOVEIT_CLASS_FORWARD(PlanningScene);
51+
}
52+
53+
namespace moveit {
54+
55+
namespace core {
56+
MOVEIT_CLASS_FORWARD(LinkModel);
57+
MOVEIT_CLASS_FORWARD(JointModelGroup);
58+
MOVEIT_CLASS_FORWARD(RobotState);
59+
} // namespace core
60+
61+
namespace task_constructor {
62+
MOVEIT_CLASS_FORWARD(Property);
63+
MOVEIT_CLASS_FORWARD(SolutionBase);
64+
65+
namespace utils {
66+
4467
/** template class to compose flags from enums in a type-safe fashion */
4568
template <typename Enum>
4669
class Flags
@@ -118,3 +141,13 @@ class Flags
118141
};
119142

120143
#define DECLARE_FLAGS(Flags, Enum) using Flags = QFlags<Enum>;
144+
145+
const moveit::core::LinkModel* getRigidlyConnectedParentLinkModel(const moveit::core::RobotState& state,
146+
std::string frame);
147+
148+
bool getRobotTipForFrame(const Property& property, const planning_scene::PlanningScene& scene,
149+
const moveit::core::JointModelGroup* jmg, SolutionBase& solution,
150+
const moveit::core::LinkModel*& robot_link, Eigen::Isometry3d& tip_in_global_frame);
151+
} // namespace utils
152+
} // namespace task_constructor
153+
} // namespace moveit

core/src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ add_library(${PROJECT_NAME}
55
${PROJECT_INCLUDE}/introspection.h
66
${PROJECT_INCLUDE}/marker_tools.h
77
${PROJECT_INCLUDE}/merge.h
8+
${PROJECT_INCLUDE}/moveit_compat.h
89
${PROJECT_INCLUDE}/properties.h
910
${PROJECT_INCLUDE}/stage.h
1011
${PROJECT_INCLUDE}/stage_p.h
@@ -27,6 +28,7 @@ add_library(${PROJECT_NAME}
2728
stage.cpp
2829
storage.cpp
2930
task.cpp
31+
utils.cpp
3032

3133
solvers/planner_interface.cpp
3234
solvers/cartesian_path.cpp

core/src/solvers/joint_interpolation.cpp

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
#include <moveit/planning_scene/planning_scene.h>
4141
#include <moveit/trajectory_processing/iterative_time_parameterization.h>
4242

43+
#include <chrono>
44+
4345
namespace moveit {
4446
namespace task_constructor {
4547
namespace solvers {
@@ -53,9 +55,9 @@ void JointInterpolationPlanner::init(const core::RobotModelConstPtr& /*robot_mod
5355

5456
bool JointInterpolationPlanner::plan(const planning_scene::PlanningSceneConstPtr& from,
5557
const planning_scene::PlanningSceneConstPtr& to,
56-
const moveit::core::JointModelGroup* jmg, double timeout,
58+
const moveit::core::JointModelGroup* jmg, double /*timeout*/,
5759
robot_trajectory::RobotTrajectoryPtr& result,
58-
const moveit_msgs::Constraints& path_constraints) {
60+
const moveit_msgs::Constraints& /*path_constraints*/) {
5961
const auto& props = properties();
6062

6163
// Get maximum joint distance
@@ -95,12 +97,38 @@ bool JointInterpolationPlanner::plan(const planning_scene::PlanningSceneConstPtr
9597
return true;
9698
}
9799

98-
bool JointInterpolationPlanner::plan(const planning_scene::PlanningSceneConstPtr& /*from*/,
99-
const moveit::core::LinkModel& /*link*/, const Eigen::Isometry3d& /*target_eigen*/,
100-
const moveit::core::JointModelGroup* /*jmg*/, double /*timeout*/,
101-
robot_trajectory::RobotTrajectoryPtr& /*result*/,
102-
const moveit_msgs::Constraints& /*path_constraints*/) {
103-
throw std::runtime_error("Not yet implemented");
100+
bool JointInterpolationPlanner::plan(const planning_scene::PlanningSceneConstPtr& from,
101+
const moveit::core::LinkModel& link, const Eigen::Isometry3d& target_eigen,
102+
const moveit::core::JointModelGroup* jmg, double timeout,
103+
robot_trajectory::RobotTrajectoryPtr& result,
104+
const moveit_msgs::Constraints& path_constraints) {
105+
const auto start_time = std::chrono::steady_clock::now();
106+
107+
auto to{ from->diff() };
108+
109+
kinematic_constraints::KinematicConstraintSet constraints{ to->getRobotModel() };
110+
constraints.add(path_constraints, from->getTransforms());
111+
112+
auto is_valid{ [&constraints, &to](moveit::core::RobotState* robot_state, const moveit::core::JointModelGroup* jmg,
113+
const double* joint_values) -> bool {
114+
robot_state->setJointGroupPositions(jmg, joint_values);
115+
robot_state->update();
116+
return to->isStateValid(*robot_state, constraints, jmg->getName());
117+
} };
118+
119+
if (!to->getCurrentStateNonConst().setFromIK(jmg, target_eigen, link.getName(), timeout, is_valid)) {
120+
// TODO(v4hn): planners need a way to add feedback to failing plans
121+
// in case of an invalid solution feedback should include unwanted collisions or violated constraints
122+
ROS_WARN_NAMED("JointInterpolationPlanner", "IK failed for pose target");
123+
return false;
124+
}
125+
to->getCurrentStateNonConst().update();
126+
127+
timeout = std::chrono::duration<double>(std::chrono::steady_clock::now() - start_time).count();
128+
if (timeout <= 0.0)
129+
return false;
130+
131+
return plan(from, to, jmg, timeout, result, path_constraints);
104132
}
105133
} // namespace solvers
106134
} // namespace task_constructor

core/src/stages/compute_ik.cpp

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -287,31 +287,17 @@ void ComputeIK::compute() {
287287
ik_pose_msg = boost::any_cast<geometry_msgs::PoseStamped>(value);
288288
Eigen::Isometry3d ik_pose;
289289
tf2::fromMsg(ik_pose_msg.pose, ik_pose);
290-
if (robot_model->hasLinkModel(ik_pose_msg.header.frame_id)) {
291-
link = robot_model->getLinkModel(ik_pose_msg.header.frame_id);
292-
} else {
293-
const robot_state::AttachedBody* attached =
294-
scene->getCurrentState().getAttachedBody(ik_pose_msg.header.frame_id);
295-
if (!attached) {
296-
ROS_WARN_STREAM_NAMED("ComputeIK", "Unknown frame: " << ik_pose_msg.header.frame_id);
297-
return;
298-
}
299-
const EigenSTL::vector_Isometry3d& tf =
300-
#if MOVEIT_HAS_OBJECT_POSE
301-
attached->getShapePosesInLinkFrame();
302-
#else
303-
attached->getFixedTransforms();
304-
#endif
305-
if (tf.empty()) {
306-
ROS_WARN_STREAM_NAMED("ComputeIK", "Attached body doesn't have shapes.");
307-
return;
308-
}
309-
// prepend link
310-
link = attached->getAttachedLink();
311-
ik_pose = tf[0] * ik_pose;
290+
291+
if (!scene->getCurrentState().knowsFrameTransform(ik_pose_msg.header.frame_id)) {
292+
ROS_WARN_STREAM_NAMED("ComputeIK", "ik frame unknown in robot: '" << ik_pose_msg.header.frame_id << "'");
293+
return;
312294
}
295+
ik_pose = scene->getCurrentState().getFrameTransform(ik_pose_msg.header.frame_id) * ik_pose;
296+
297+
link = utils::getRigidlyConnectedParentLinkModel(scene->getCurrentState(), ik_pose_msg.header.frame_id);
298+
313299
// transform target pose such that ik frame will reach there if link does
314-
target_pose = target_pose * ik_pose.inverse();
300+
target_pose = target_pose * ik_pose.inverse() * scene->getCurrentState().getFrameTransform(link->getName());
315301
}
316302

317303
// validate placed link for collisions
@@ -323,7 +309,7 @@ void ComputeIK::compute() {
323309
// markers used for failures
324310
std::deque<visualization_msgs::Marker> failure_markers;
325311
// frames at target pose and ik frame
326-
rviz_marker_tools::appendFrame(failure_markers, target_pose_msg, 0.1, "ik frame");
312+
rviz_marker_tools::appendFrame(failure_markers, target_pose_msg, 0.1, "target frame");
327313
rviz_marker_tools::appendFrame(failure_markers, ik_pose_msg, 0.1, "ik frame");
328314
// visualize placed end-effector
329315
auto appender = [&failure_markers](visualization_msgs::Marker& marker, const std::string& /*name*/) {

core/src/stages/fixed_state.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ namespace moveit {
4343
namespace task_constructor {
4444
namespace stages {
4545

46-
FixedState::FixedState(const std::string& name) : Generator(name) {
46+
FixedState::FixedState(const std::string& name, planning_scene::PlanningScenePtr scene)
47+
: Generator(name), scene_(scene) {
4748
setCostTerm(std::make_unique<cost::Constant>(0.0));
4849
}
4950

core/src/stages/move_relative.cpp

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -193,24 +193,11 @@ bool MoveRelative::compute(const InterfaceState& state, planning_scene::Planning
193193
success = planner_->plan(state.scene(), scene, jmg, timeout, robot_trajectory, path_constraints);
194194
} else {
195195
// Cartesian targets require an IK reference frame
196-
geometry_msgs::PoseStamped ik_pose_msg;
197196
const moveit::core::LinkModel* link;
198-
const boost::any& value = props.get("ik_frame");
199-
if (value.empty()) { // property undefined
200-
// determine IK link from group
201-
if (!(link = jmg->getOnlyOneEndEffectorTip())) {
202-
solution.markAsFailure("missing ik_frame");
203-
return false;
204-
}
205-
ik_pose_msg.header.frame_id = link->getName();
206-
ik_pose_msg.pose.orientation.w = 1.0;
207-
} else {
208-
ik_pose_msg = boost::any_cast<geometry_msgs::PoseStamped>(value);
209-
if (!(link = robot_model->getLinkModel(ik_pose_msg.header.frame_id))) {
210-
solution.markAsFailure("unknown link for ik_frame: " + ik_pose_msg.header.frame_id);
211-
return false;
212-
}
213-
}
197+
Eigen::Isometry3d ik_pose_world;
198+
199+
if (!utils::getRobotTipForFrame(props.property("ik_frame"), *scene, jmg, solution, link, ik_pose_world))
200+
return false;
214201

215202
bool use_rotation_distance = false; // measure achieved distance as rotation?
216203
Eigen::Vector3d linear; // linear translation
@@ -291,9 +278,7 @@ bool MoveRelative::compute(const InterfaceState& state, planning_scene::Planning
291278

292279
COMPUTE:
293280
// transform target pose such that ik frame will reach there if link does
294-
Eigen::Isometry3d ik_pose;
295-
tf2::fromMsg(ik_pose_msg.pose, ik_pose);
296-
target_eigen = target_eigen * ik_pose.inverse();
281+
target_eigen = target_eigen * scene->getCurrentState().getGlobalLinkTransform(link).inverse() * ik_pose_world;
297282

298283
success = planner_->plan(state.scene(), *link, target_eigen, jmg, timeout, robot_trajectory, path_constraints);
299284

0 commit comments

Comments
 (0)