Skip to content

Commit 46a0f12

Browse files
committed
Merge remote-tracking branch 'upstream/master' into ros2
# Conflicts: # capabilities/src/execute_task_solution_capability.cpp # core/src/stages/move_relative.cpp
2 parents 5519162 + 4f69a22 commit 46a0f12

File tree

9 files changed

+80
-10
lines changed

9 files changed

+80
-10
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
url = https://github.com/pybind/pybind11
44
branch = smart_holder
55
shallow = true
6+
[submodule "core/src/scope_guard"]
7+
path = core/src/scope_guard
8+
url = https://github.com/ricab/scope_guard

capabilities/src/execute_task_solution_capability.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,12 @@ bool ExecuteTaskSolutionCapability::constructMotionPlan(const moveit_task_constr
183183

184184
/* TODO add action feedback and markers */
185185
exec_traj.effect_on_success = [this,
186-
&scene_diff = const_cast<::moveit_msgs::msg::PlanningScene&>(sub_traj.scene_diff),
187-
description](const plan_execution::ExecutableMotionPlan* /*plan*/) {
188-
scene_diff.robot_state.joint_state = sensor_msgs::msg::JointState();
189-
scene_diff.robot_state.multi_dof_joint_state = sensor_msgs::msg::MultiDOFJointState();
186+
&scene_diff = const_cast<::moveit_msgs::PlanningScene&>(sub_traj.scene_diff),
187+
description](const plan_execution::ExecutableMotionPlan* /*plan*/) {
188+
// Never modify joint state directly (only via robot trajectories)
189+
scene_diff.robot_state.joint_state = sensor_msgs::JointState();
190+
scene_diff.robot_state.multi_dof_joint_state = sensor_msgs::MultiDOFJointState();
191+
scene_diff.robot_state.is_diff = true; // silent empty JointState msg error
190192

191193
if (!moveit::core::isEmpty(scene_diff)) {
192194
RCLCPP_DEBUG_STREAM(LOGGER, "apply effect of " << description);

core/include/moveit/task_constructor/task.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,9 @@ class Task : protected WrapperBase
129129

130130
/// reset, init scene (if not yet done), and init all stages, then start planning
131131
moveit::core::MoveItErrorCode plan(size_t max_solutions = 0);
132-
/// interrupt current planning (or execution)
132+
/// interrupt current planning
133133
void preempt();
134+
void resetPreemptRequest();
134135
/// execute solution, return the result
135136
moveit::core::MoveItErrorCode execute(const SolutionBase& s);
136137

core/include/moveit/task_constructor/task_p.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class TaskPrivate : public WrapperBasePrivate
6363
std::string ns_;
6464
robot_model_loader::RobotModelLoaderPtr robot_model_loader_;
6565
moveit::core::RobotModelConstPtr robot_model_;
66-
bool preempt_requested_;
66+
std::atomic<bool> preempt_requested_;
6767

6868
// introspection and monitoring
6969
std::unique_ptr<Introspection> introspection_;

core/src/scope_guard

Submodule scope_guard added at 71a0452

core/src/stages/move_relative.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,11 @@ bool MoveRelative::compute(const InterfaceState& state, planning_scene::Planning
191191

192192
double max_distance = props.get<double>("max_distance");
193193
double min_distance = props.get<double>("min_distance");
194+
195+
// if min_distance == max_distance, resort to moving full distance (negative min_distance)
196+
if (max_distance > 0.0 && std::fabs(max_distance - min_distance) < std::numeric_limits<double>::epsilon())
197+
min_distance = -1.0;
198+
194199
const auto& path_constraints = props.get<moveit_msgs::msg::Constraints>("path_constraints");
195200

196201
robot_trajectory::RobotTrajectoryPtr robot_trajectory;
@@ -300,7 +305,8 @@ bool MoveRelative::compute(const InterfaceState& state, planning_scene::Planning
300305
comment = result.message;
301306
solution.setPlannerId(planner_->getPlannerId());
302307

303-
if (robot_trajectory) { // the following requires a robot_trajectory returned from planning
308+
if (robot_trajectory && robot_trajectory->getWayPointCount() > 0) { // the following requires a robot_trajectory
309+
// returned from planning
304310
moveit::core::RobotStatePtr& reached_state = robot_trajectory->getLastWayPointPtr();
305311
reached_state->updateLinkTransforms();
306312
const Eigen::Isometry3d& reached_pose = reached_state->getGlobalLinkTransform(link) * offset;
@@ -335,7 +341,7 @@ bool MoveRelative::compute(const InterfaceState& state, planning_scene::Planning
335341
}
336342

337343
// store result
338-
if (robot_trajectory) {
344+
if (robot_trajectory && robot_trajectory->getWayPointCount() > 0) {
339345
scene->setCurrentState(robot_trajectory->getLastWayPoint());
340346
if (dir == Interface::BACKWARD)
341347
robot_trajectory->reverse();

core/src/task.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
#include <moveit/robot_model_loader/robot_model_loader.h>
4747
#include <moveit/planning_pipeline/planning_pipeline.h>
4848

49+
#include <scope_guard/scope_guard.hpp>
50+
4951
#include <functional>
5052

5153
using namespace std::chrono_literals;
@@ -237,6 +239,9 @@ void Task::compute() {
237239
}
238240

239241
moveit::core::MoveItErrorCode Task::plan(size_t max_solutions) {
242+
// ensure the preempt request is resetted once this method exits
243+
auto guard = sg::make_scope_guard([this]() noexcept { this->resetPreemptRequest(); });
244+
240245
auto impl = pimpl();
241246
init();
242247

@@ -248,7 +253,6 @@ moveit::core::MoveItErrorCode Task::plan(size_t max_solutions) {
248253
explainFailure();
249254
return error_code;
250255
};
251-
impl->preempt_requested_ = false;
252256
const double available_time = timeout();
253257
const auto start_time = std::chrono::steady_clock::now();
254258
while (canCompute() && (max_solutions == 0 || numSolutions() < max_solutions)) {
@@ -269,6 +273,10 @@ void Task::preempt() {
269273
pimpl()->preempt_requested_ = true;
270274
}
271275

276+
void Task::resetPreemptRequest() {
277+
pimpl()->preempt_requested_ = false;
278+
}
279+
272280
moveit::core::MoveItErrorCode Task::execute(const SolutionBase& s) {
273281
// Add random ID to prevent warnings about multiple publishers within the same node
274282
auto node = rclcpp::Node::make_shared("moveit_task_constructor_executor_" +

core/test/test_container.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -672,3 +672,31 @@ TEST(Task, timeout) {
672672
EXPECT_TRUE(t.plan());
673673
EXPECT_EQ(t.solutions().size(), 2u);
674674
}
675+
676+
// https://github.com/moveit/moveit_task_constructor/pull/597
677+
// start planning in another thread, then preempt it in this thread
678+
TEST(Task, preempt) {
679+
moveit::core::MoveItErrorCode ec;
680+
resetMockupIds();
681+
682+
Task t;
683+
t.setRobotModel(getModel());
684+
685+
auto timeout = std::chrono::milliseconds(10);
686+
t.add(std::make_unique<GeneratorMockup>(PredefinedCosts::constant(0.0)));
687+
t.add(std::make_unique<TimedForwardMockup>(timeout));
688+
689+
// preempt before preempt_request_ is reset in plan()
690+
{
691+
std::thread thread{ [&ec, &t, timeout] {
692+
std::this_thread::sleep_for(timeout);
693+
ec = t.plan(1);
694+
} };
695+
t.preempt();
696+
thread.join();
697+
}
698+
699+
EXPECT_EQ(ec, moveit::core::MoveItErrorCode::PREEMPTED);
700+
EXPECT_EQ(t.solutions().size(), 0u);
701+
EXPECT_TRUE(t.plan(1)); // make sure the preempt request has been resetted on the previous call to plan()
702+
}

core/test/test_fallback.cpp

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#include <moveit/task_constructor/container_p.h>
22
#include <moveit/task_constructor/stage_p.h>
33
#include <moveit/task_constructor/task_p.h>
4-
#include <moveit/task_constructor/stages/fixed_state.h>
4+
#include <moveit/task_constructor/stages/predicate_filter.h>
5+
#include <moveit/task_constructor/stages/noop.h>
56
#include <moveit/planning_scene/planning_scene.h>
67

78
#include "stage_mockups.h"
@@ -160,6 +161,26 @@ TEST_F(FallbacksFixturePropagate, activeChildReset) {
160161
EXPECT_COSTS(fwd2->solutions(), testing::IsEmpty());
161162
}
162163

164+
// https://github.com/moveit/moveit_task_constructor/issues/581#issuecomment-2147985474
165+
TEST_F(FallbacksFixturePropagate, filterPropagatesFailures) {
166+
t.add(std::make_unique<GeneratorMockup>(PredefinedCosts::single(0.0)));
167+
168+
auto fallbacks = std::make_unique<Fallbacks>("Fallbacks");
169+
auto add_filtered_fwd = [&fallbacks](double cost, bool accept) {
170+
auto fwd = std::make_unique<ForwardMockup>(PredefinedCosts::constant(cost));
171+
auto filter = std::make_unique<stages::PredicateFilter>("filter", std::move(fwd));
172+
filter->setPredicate([accept](const SolutionBase& /*solution*/, std::string& /*comment*/) { return accept; });
173+
fallbacks->add(std::move(filter));
174+
};
175+
add_filtered_fwd(INF, false); // Propagate fails, filter rejects
176+
add_filtered_fwd(2.0, true); // Propagate succeeds, filter accepts
177+
fallbacks->add(std::make_unique<stages::NoOp>());
178+
t.add(std::move(fallbacks));
179+
180+
EXPECT_TRUE(t.plan());
181+
EXPECT_COSTS(t.solutions(), testing::ElementsAre(2.));
182+
}
183+
163184
using FallbacksFixtureConnect = TaskTestBase;
164185

165186
TEST_F(FallbacksFixtureConnect, connectStageInsideFallbacks) {

0 commit comments

Comments
 (0)