diff --git a/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/plan/DeletedAnchorStrategy.kt b/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/plan/DeletedAnchorStrategy.kt index a385ef88ce..173ed876dd 100644 --- a/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/plan/DeletedAnchorStrategy.kt +++ b/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/plan/DeletedAnchorStrategy.kt @@ -1,7 +1,27 @@ package gov.nasa.ammos.aerie.procedural.scheduling.plan +/** + * How to handle directives anchored to a deleted activity. + * + * If you intend to delete an activity that you believe has nothing anchored to it, + * using [Error] is recommended. This is the default. + */ enum class DeletedAnchorStrategy { - Error, - Cascade, + /** Throw an error. */ Error, + /** Recursively delete everything in the anchor chain. */ Cascade, + + /** + * Attempt to delete the activity in-place without changing the start times + * of any activities anchored to it. + * + * Consider the anchor chain `A <- B <- C`, where `A` starts at an absolute time and + * `B` and `C` are anchored. + * - If `A` is deleted with [ReAnchor], `B` will be set to start at the absolute time `A.startTime + B.offset`. + * `C` will be unchanged. + * - If `B` is deleted with [ReAnchor], `C` will be anchored to `A` with a new offset equal to `B.offset + C.offset`. + * + * If an activity is anchored to the end of the deleted activity, the delete activity's duration is assumed to be 0, + * which may change the ultimate start time of the anchored activity. + */ ReAnchor, } diff --git a/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/plan/Edit.kt b/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/plan/Edit.kt index 1b2e324b27..9e1fac6fdf 100644 --- a/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/plan/Edit.kt +++ b/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/plan/Edit.kt @@ -7,9 +7,14 @@ import gov.nasa.jpl.aerie.types.ActivityDirectiveId /** * Edits that can be made to the plan. * - * Currently only creating new activities is supported. + * All edits are invertible. */ sealed interface Edit { + /** + * Returns the reverse operation. + * + * If both `E` and `E.inverse()` are applied, the plan is unchanged. + */ fun inverse(): Edit /** Create a new activity from a given directive. */ diff --git a/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/utils/EasyEditablePlanDriver.kt b/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/utils/EasyEditablePlanDriver.kt index a7d897c5a9..fb03bf44a9 100644 --- a/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/utils/EasyEditablePlanDriver.kt +++ b/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/utils/EasyEditablePlanDriver.kt @@ -126,8 +126,13 @@ abstract class EasyEditablePlanDriver( ) private var committedChanges = Commit(setOf(), mutableSetOf()) - var uncommittedChanges = mutableListOf() + private var uncommittedChanges = mutableListOf() + /** Whether there are uncommitted changes. */ + val isDirty + get() = uncommittedChanges.isNotEmpty() + + /** The total reduced set of changes made to the plan. */ val totalDiff: Set get() = committedChanges.diff diff --git a/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/utils/PerishableSimulationResults.kt b/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/utils/PerishableSimulationResults.kt index bc86085e5c..b60425270c 100644 --- a/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/utils/PerishableSimulationResults.kt +++ b/procedural/scheduling/src/main/kotlin/gov/nasa/ammos/aerie/procedural/scheduling/utils/PerishableSimulationResults.kt @@ -2,6 +2,7 @@ package gov.nasa.ammos.aerie.procedural.scheduling.utils import gov.nasa.ammos.aerie.procedural.timeline.plan.SimulationResults +/** Simulation results whose staleness can be changed after creation. */ interface PerishableSimulationResults: SimulationResults { - fun setStale(stale: Boolean) + /***/ fun setStale(stale: Boolean) } diff --git a/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/SimulationResults.kt b/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/SimulationResults.kt index 7d8e49f7cd..fdf86f5c7d 100644 --- a/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/SimulationResults.kt +++ b/procedural/timeline/src/main/kotlin/gov/nasa/ammos/aerie/procedural/timeline/plan/SimulationResults.kt @@ -37,6 +37,8 @@ interface SimulationResults { /** Queries all activity instances, deserializing them as [AnyInstance]. **/ fun instances() = instances(null, AnyInstance.deserializer()) + /** The input directives that were used for this simulation. */ fun inputDirectives(deserializer: (SerializedValue) -> A): Directives + /** The input directives that were used for this simulation, deserialized as [AnyDirective]. */ fun inputDirectives() = inputDirectives(AnyDirective.deserializer()) } diff --git a/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/goals/Procedure.java b/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/goals/Procedure.java index 7578d85a7c..91e68cffe6 100644 --- a/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/goals/Procedure.java +++ b/scheduler-driver/src/main/java/gov/nasa/jpl/aerie/scheduler/goals/Procedure.java @@ -74,7 +74,7 @@ public void run( procedureMapper.deserialize(SerializedValue.of(this.args)).run(editablePlan); - if (!editablePlan.getUncommittedChanges().isEmpty()) { + if (editablePlan.isDirty()) { throw new IllegalStateException("procedural goal %s had changes that were not committed or rolled back".formatted(jarPath.getFileName())); } for (final var edit : editablePlan.getTotalDiff()) {