Skip to content

Commit a31e52d

Browse files
committed
Propagate status across Connecting gap
Not only propagate updates along solution paths, but also bridge the gap of a `Connecting` stage. - If a state becomes enabled, re-enable opposite `ARMED` states as well. - If a state becomes pruned, also prune opposite states if they don't have alternatives. - Make sure that we don't run into a recursive update loop by disabling notify() callbacks.
1 parent 3648db4 commit a31e52d

File tree

3 files changed

+49
-3
lines changed

3 files changed

+49
-3
lines changed

core/include/moveit/task_constructor/storage.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,18 @@ class Interface : public ordered<InterfaceState*>
200200
BACKWARD,
201201
};
202202
using NotifyFunction = std::function<void(iterator, bool)>;
203+
204+
class DisableNotify
205+
{
206+
Interface& if_;
207+
Interface::NotifyFunction old_;
208+
209+
public:
210+
DisableNotify(Interface& i) : if_(i) { old_.swap(if_.notify_); }
211+
~DisableNotify() { old_.swap(if_.notify_); }
212+
};
213+
friend class DisableNotify;
214+
203215
Interface(const NotifyFunction& notify = NotifyFunction());
204216

205217
/// add a new InterfaceState
@@ -210,9 +222,10 @@ class Interface : public ordered<InterfaceState*>
210222

211223
/// update state's priority (and call notify_ if it really has changed)
212224
void updatePriority(InterfaceState* state, const InterfaceState::Priority& priority);
225+
inline bool notifyEnabled() const { return static_cast<bool>(notify_); }
213226

214227
private:
215-
const NotifyFunction notify_;
228+
NotifyFunction notify_;
216229

217230
// restrict access to some functions to ensure consistency
218231
// (we need to set/unset InterfaceState::owner_)

core/src/stage.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -709,13 +709,44 @@ ConnectingPrivate::StatePair ConnectingPrivate::make_pair<Interface::FORWARD>(In
709709
return StatePair(second, first);
710710
}
711711

712+
// TODO: bool updated -> uint_8 updated (bitfield of PRIORITY | STATUS)
712713
template <Interface::Direction dir>
713714
void ConnectingPrivate::newState(Interface::iterator it, bool updated) {
714-
if (updated) { // many pairs might be affected: resort
715+
auto parent_pimpl = parent()->pimpl();
716+
Interface::DisableNotify disable_source_interface(*pullInterface(dir));
717+
if (updated) {
718+
if (pullInterface(opposite<dir>())->notifyEnabled()) // suppress recursive loop
719+
{
720+
// If status has changed, propagate the update to the opposite side
721+
auto status = it->priority().status();
722+
if (status == InterfaceState::Status::PRUNED) // PRUNED becomes ARMED on opposite side
723+
status = InterfaceState::Status::ARMED; // (only for pending state pairs)
724+
725+
for (const auto& candidate : this->pending) {
726+
if (std::get<opposite<dir>()>(candidate) != it) // only consider pairs with source state == state
727+
continue;
728+
auto oit = std::get<dir>(candidate); // opposite target state
729+
auto ostatus = oit->priority().status();
730+
if (ostatus != status) {
731+
if (status != InterfaceState::Status::ENABLED) {
732+
// quicker check for hasPendingOpposites(): search in it->owner() for an enabled alternative
733+
bool cancel = false; // if found, cancel propagation of new status
734+
for (const auto alternative : *it->owner())
735+
if ((cancel = alternative->priority().enabled()))
736+
break;
737+
if (cancel)
738+
continue;
739+
}
740+
// pass creator=nullptr to skip hasPendingOpposites() check
741+
parent_pimpl->setStatus<opposite<dir>()>(nullptr, nullptr, &*oit, status);
742+
}
743+
}
744+
}
745+
746+
// many pairs will have changed priorities: resort pending list
715747
pending.sort();
716748
} else { // new state: insert all pairs with other interface
717749
assert(it->priority().enabled()); // new solutions are feasible, aren't they?
718-
auto parent_pimpl = parent()->pimpl();
719750
InterfacePtr other_interface = pullInterface(dir);
720751
bool have_enabled_opposites = false;
721752
for (Interface::iterator oit = other_interface->begin(), oend = other_interface->end(); oit != oend; ++oit) {

core/test/test_pruning.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ TYPED_TEST(PruningContainerTests, ConnectReactivatesPrunedPaths) {
9191
}
9292

9393
TEST_F(Pruning, ConnectConnectForward) {
94+
add(t, new BackwardMockup());
9495
add(t, new GeneratorMockup());
9596
auto c1 = add(t, new ConnectMockup({ INF, 0, 0 })); // 1st attempt is a failue
9697
add(t, new GeneratorMockup({ 0, 10, 20 }));
@@ -112,6 +113,7 @@ TEST_F(Pruning, ConnectConnectForward) {
112113
}
113114

114115
TEST_F(Pruning, ConnectConnectBackward) {
116+
add(t, new BackwardMockup());
115117
add(t, new GeneratorMockup({ 1, 2, 3 }));
116118
auto c1 = add(t, new ConnectMockup());
117119
add(t, new BackwardMockup());

0 commit comments

Comments
 (0)