fluid-hierarchical-task-network: Domain.FindPlan(...) rejects valid new plan
Describe the bug
Domain.FindPlan(...) rejects valid new plan, because the MethodTraversalRecord equals the LastMTR, even though the found plan differs from the last found plan.
To Reproduce
Define a domain like this (where OperatorA and OperatorB are both operators that do NOT finish instantly):
.Select("Test Select")
.Action("Test Action A")
.Condition("Can choose A", ctx => ctx.HasState(TestWorldState.CanChooseA))
.SetOperator(new OperatorA())
.End()
.Action("Test Action B")
.Condition("Can not choose A", ctx => !ctx.HasState(TestWorldState.CanChooseA))
.SetOperator(new OperatorB())
.End()
.End()
Then set TestWorldState.CanChooseA to true and Tick() the planer. Observe (as expected) that a plan containing only “Test Action A” is found.
Then (while the existing plan is not yet finished) set TestWorldState.CanChooseA to false and Tick() the planer again. Observe that the plan containing only “Test Action B” is initially found during the decomposition but is then discarded by this part of the code:
// If this MTR equals the last MTR, then we need to double check whether we ended up
// just finding the exact same plan. During decomposition each compound task can't check
// for equality, only for less than, so this case needs to be treated after the fact.
var isMTRsEqual = ctx.MethodTraversalRecord.Count == ctx.LastMTR.Count;
if (isMTRsEqual)
{
for (var i = 0; i < ctx.MethodTraversalRecord.Count; i++)
if (ctx.MethodTraversalRecord[i] < ctx.LastMTR[i])
{
isMTRsEqual = false;
break;
}
if (isMTRsEqual)
{
plan = null;
status = DecompositionStatus.Rejected;
}
}
because both the MethodTraversalRecord and the LastMTR are equal and contain only the single entry 0, even though the new plan (containing only “Test Action B”) is different from the old plan (containing only “Test Action A”).
Expected behavior The new plan should not have been rejected for being equal to the old plan because it is clearly different.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 40 (21 by maintainers)
Ah, I found the conceptual difference: In my test it is the other way around:
Initially the WorldState is set in a way that the “better”/first Action is chosen, then the WorldState changes so that the first Action is no longer allowed and the “worse”/second Action should be chosen instead.
If you change your test like this, you can see it for yourself:
Hmm. Your test passes but my test still fails… I will investigate what the remaining difference is.
I will have a look.
Here, I modified your test to be able to reproduce the problem without needing my extensions: