|
| 1 | +# Pre-conditions and Post-conditions |
| 2 | + |
| 3 | +This document describes the pre-condition and post-condition attributes that can be attached to any node in XML. |
| 4 | + |
| 5 | +## Pre-conditions |
| 6 | + |
| 7 | +Pre-conditions are evaluated **before** a node's `tick()` method is called. They can short-circuit the node execution by returning a status immediately. |
| 8 | + |
| 9 | +### Available Pre-conditions |
| 10 | + |
| 11 | +| Attribute | When Evaluated | Behavior | |
| 12 | +|-----------|----------------|----------| |
| 13 | +| `_failureIf` | IDLE only | If true, return FAILURE without calling tick() | |
| 14 | +| `_successIf` | IDLE only | If true, return SUCCESS without calling tick() | |
| 15 | +| `_skipIf` | IDLE only | If true, return SKIPPED without calling tick() | |
| 16 | +| `_while` | IDLE and RUNNING | If false when IDLE, return SKIPPED. If false when RUNNING, halt node and return SKIPPED | |
| 17 | + |
| 18 | +### Evaluation Order |
| 19 | + |
| 20 | +When a node has multiple pre-conditions, they are evaluated in this order: |
| 21 | +1. `_failureIf` |
| 22 | +2. `_successIf` |
| 23 | +3. `_skipIf` |
| 24 | +4. `_while` |
| 25 | + |
| 26 | +The first condition that triggers will determine the result. |
| 27 | + |
| 28 | +### Important: One-time Evaluation |
| 29 | + |
| 30 | +**`_failureIf`, `_successIf`, and `_skipIf` are evaluated only once** when the node transitions from IDLE (or SKIPPED) to another state. They are **NOT re-evaluated** while the node is RUNNING. |
| 31 | + |
| 32 | +This means if you have: |
| 33 | +```xml |
| 34 | +<MyAction _successIf="condition"/> |
| 35 | +``` |
| 36 | + |
| 37 | +The `condition` is checked only when `MyAction` starts. If `MyAction` returns RUNNING, subsequent ticks will continue executing `MyAction` without re-checking the condition. |
| 38 | + |
| 39 | +### The `_while` Exception |
| 40 | + |
| 41 | +`_while` is the only pre-condition that is re-evaluated on every tick, even while the node is RUNNING. If the condition becomes false while the node is running, the node is halted and returns SKIPPED. |
| 42 | + |
| 43 | +```xml |
| 44 | +<MyAction _while="battery_ok"/> |
| 45 | +``` |
| 46 | + |
| 47 | +If `battery_ok` becomes false while `MyAction` is running, the action is interrupted. |
| 48 | + |
| 49 | +### When to Use Each Pre-condition |
| 50 | + |
| 51 | +- **`_skipIf`**: Skip a node without failing the parent (useful in Sequences) |
| 52 | +- **`_failureIf`**: Fail early based on a condition (useful in Fallbacks) |
| 53 | +- **`_successIf`**: Succeed early based on a condition |
| 54 | +- **`_while`**: Guard that must remain true for the entire execution |
| 55 | + |
| 56 | +### Re-evaluating Conditions Every Tick |
| 57 | + |
| 58 | +If you need a condition to be checked on every tick (not just when transitioning from IDLE), use the `<Precondition>` decorator node instead of inline attributes: |
| 59 | + |
| 60 | +```xml |
| 61 | +<!-- This checks the condition on every tick while child is RUNNING --> |
| 62 | +<Precondition if="my_condition" else="RUNNING"> |
| 63 | + <MyAction/> |
| 64 | +</Precondition> |
| 65 | +``` |
| 66 | + |
| 67 | +With `else="RUNNING"`, if the condition is false, the decorator returns RUNNING (keeping the tree alive) rather than SUCCESS/FAILURE/SKIPPED. |
| 68 | + |
| 69 | +## Post-conditions |
| 70 | + |
| 71 | +Post-conditions are scripts executed **after** a node completes (or is halted). |
| 72 | + |
| 73 | +### Available Post-conditions |
| 74 | + |
| 75 | +| Attribute | When Executed | |
| 76 | +|-----------|---------------| |
| 77 | +| `_onSuccess` | After node returns SUCCESS | |
| 78 | +| `_onFailure` | After node returns FAILURE | |
| 79 | +| `_onHalted` | After node is halted (including by `_while`) | |
| 80 | +| `_post` | After any completion (SUCCESS, FAILURE, or HALTED) | |
| 81 | + |
| 82 | +### Example |
| 83 | + |
| 84 | +```xml |
| 85 | +<MyAction |
| 86 | + _onSuccess="result := 'ok'" |
| 87 | + _onFailure="result := 'failed'" |
| 88 | + _onHalted="result := 'interrupted'"/> |
| 89 | +``` |
| 90 | + |
| 91 | +## Common Patterns |
| 92 | + |
| 93 | +### Conditional Execution in Sequence |
| 94 | + |
| 95 | +```xml |
| 96 | +<Sequence> |
| 97 | + <CheckBattery/> |
| 98 | + <MoveToGoal _skipIf="already_at_goal"/> |
| 99 | + <PickObject/> |
| 100 | +</Sequence> |
| 101 | +``` |
| 102 | + |
| 103 | +If `already_at_goal` is true, `MoveToGoal` is skipped and the sequence continues with `PickObject`. |
| 104 | + |
| 105 | +### Early Exit in Fallback |
| 106 | + |
| 107 | +```xml |
| 108 | +<Fallback> |
| 109 | + <CachedResult _successIf="cache_valid"/> |
| 110 | + <ComputeResult/> |
| 111 | +</Fallback> |
| 112 | +``` |
| 113 | + |
| 114 | +If `cache_valid` is true, `CachedResult` succeeds immediately without executing. |
| 115 | + |
| 116 | +### Guarded Action |
| 117 | + |
| 118 | +```xml |
| 119 | +<MoveToGoal _while="battery_level > 20"/> |
| 120 | +``` |
| 121 | + |
| 122 | +The movement continues only while battery is sufficient. If battery drops, the action is halted. |
| 123 | + |
| 124 | +## Related |
| 125 | + |
| 126 | +- [Port Connection Rules](PORT_CONNECTION_RULES.md) - How ports connect between nodes |
| 127 | +- [Name Validation Rules](name_validation_rules.md) - Valid names for ports and nodes |
0 commit comments