Skip to content

Commit 4981ca6

Browse files
committed
Expose mission model to procedures
1 parent b7e6513 commit 4981ca6

File tree

8 files changed

+120
-4
lines changed

8 files changed

+120
-4
lines changed

contrib/src/main/java/gov/nasa/jpl/aerie/contrib/models/NamedResource.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import gov.nasa.jpl.aerie.merlin.framework.resources.NameableResource;
44

55
public abstract class NamedResource<D> implements NameableResource<D> {
6-
private String name = "";
6+
private String name = "ERROR: Name was not set during model construction";
77

88
@Override
99
public String getName() {

e2e-tests/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ dependencies {
6464
implementation project(':merlin-sdk')
6565
implementation project(':type-utils')
6666
implementation project(':contrib')
67+
compileOnly project(':examples:banananation')
6768

6869
testImplementation "com.zaxxer:HikariCP:5.1.0"
6970
testImplementation("org.postgresql:postgresql:42.6.0")
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package gov.nasa.jpl.aerie.e2e.procedural.scheduling.procedures;
2+
3+
import gov.nasa.ammos.aerie.procedural.scheduling.Goal;
4+
import gov.nasa.ammos.aerie.procedural.scheduling.annotations.SchedulingProcedure;
5+
import gov.nasa.ammos.aerie.procedural.scheduling.plan.EditablePlan;
6+
import gov.nasa.ammos.aerie.procedural.timeline.payloads.activities.DirectiveStart;
7+
import gov.nasa.ammos.aerie.procedural.timeline.util.WithModel;
8+
import gov.nasa.jpl.aerie.banananation.Mission;
9+
import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue;
10+
import org.jetbrains.annotations.NotNull;
11+
12+
import java.util.Map;
13+
14+
/**
15+
* Creates a bite banana every time /producer changes
16+
*/
17+
@SchedulingProcedure
18+
public record ModelIntegrationGoal(int quantity) implements Goal, WithModel<Mission> {
19+
@Override
20+
public void run(@NotNull final EditablePlan plan) {
21+
final var changes = plan.simulate().resource(model().producer).changes().highlightTrue();
22+
for (final var interval: changes) {
23+
plan.create("BiteBanana", new DirectiveStart.Absolute(interval.start), Map.of("biteSize", SerializedValue.of(1)));
24+
}
25+
plan.commit();
26+
}
27+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package gov.nasa.jpl.aerie.e2e.procedural.scheduling;
2+
3+
import gov.nasa.jpl.aerie.e2e.types.GoalInvocationId;
4+
import gov.nasa.jpl.aerie.e2e.utils.GatewayRequests;
5+
import org.junit.jupiter.api.AfterEach;
6+
import org.junit.jupiter.api.BeforeEach;
7+
import org.junit.jupiter.api.Test;
8+
9+
import javax.json.Json;
10+
import javax.json.JsonValue;
11+
import java.io.IOException;
12+
import java.util.Objects;
13+
14+
import static org.junit.jupiter.api.Assertions.assertEquals;
15+
import static org.junit.jupiter.api.Assertions.assertTrue;
16+
17+
public class ModelIntegrationTests extends ProceduralSchedulingSetup {
18+
private int procedureJarId;
19+
private GoalInvocationId procedureId;
20+
21+
@BeforeEach
22+
void localBeforeEach() throws IOException {
23+
try (final var gateway = new GatewayRequests(playwright)) {
24+
procedureJarId = gateway.uploadJarFile("build/libs/ModelIntegrationGoal.jar");
25+
// Add Scheduling Procedure
26+
procedureId = hasura.createSchedulingSpecProcedure(
27+
"Test Scheduling Procedure",
28+
procedureJarId,
29+
specId,
30+
0
31+
);
32+
}
33+
}
34+
35+
@AfterEach
36+
void localAfterEach() throws IOException {
37+
hasura.deleteSchedulingGoal(procedureId.goalId());
38+
}
39+
40+
@Test
41+
void testModelIntegration() throws IOException {
42+
final var args = Json.createObjectBuilder().add("quantity", 2).build();
43+
hasura.updateSchedulingSpecGoalArguments(procedureId.invocationId(), args);
44+
45+
final var secondProcedure = hasura.createSchedulingSpecProcedure(
46+
"Test Scheduling Procedure 2",
47+
procedureJarId,
48+
specId,
49+
1);
50+
51+
hasura.updateSchedulingSpecGoalArguments(secondProcedure.invocationId(), args);
52+
53+
hasura.insertActivityDirective(
54+
planId,
55+
"ChangeProducer",
56+
"1h",
57+
Json.createObjectBuilder().add("producer", Json.createValue("p")).build()
58+
);
59+
60+
hasura.awaitScheduling(specId);
61+
62+
final var plan = hasura.getPlan(planId);
63+
final var activities = plan.activityDirectives();
64+
65+
assertEquals(2, activities.size());
66+
}
67+
}

procedural/examples/banana-procedures/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ dependencies {
2424
implementation project(':type-utils')
2525
implementation project(':contrib')
2626

27+
implementation project(":examples:banananation")
28+
2729
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.0'
2830
testImplementation project(':procedural:utils')
2931
testImplementation project(':orchestration-utils')

procedural/examples/banana-procedures/src/main/java/gov/nasa/ammos/aerie/procedural/examples/bananaprocedures/procedures/SimulationDemo.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
package gov.nasa.ammos.aerie.procedural.examples.bananaprocedures.procedures;
22

3+
import gov.nasa.ammos.aerie.procedural.timeline.util.WithModel;
4+
import gov.nasa.jpl.aerie.banananation.Mission;
35
import gov.nasa.jpl.aerie.merlin.protocol.types.Duration;
46
import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue;
57
import gov.nasa.ammos.aerie.procedural.scheduling.Goal;
68
import gov.nasa.ammos.aerie.procedural.scheduling.annotations.SchedulingProcedure;
79
import gov.nasa.ammos.aerie.procedural.scheduling.plan.EditablePlan;
8-
import gov.nasa.ammos.aerie.procedural.timeline.collections.profiles.Real;
910
import gov.nasa.ammos.aerie.procedural.timeline.payloads.activities.DirectiveStart;
1011
import org.jetbrains.annotations.NotNull;
1112

1213
import java.util.Map;
1314

1415
@SchedulingProcedure
15-
public record SimulationDemo(int quantity) implements Goal {
16+
public record SimulationDemo(int quantity) implements Goal, WithModel<Mission> {
1617
@Override
1718
public void run(@NotNull final EditablePlan plan) {
1819

1920
var simResults = plan.latestResults();
2021
if (simResults == null) simResults = plan.simulate();
2122

22-
final var lowFruit = simResults.resource("/fruit", Real.deserializer()).lessThan(3.5).isolateTrue();
23+
final var lowFruit = simResults.resource(model().fruit).lessThan(3.5).isolateTrue();
2324
final var bites = simResults.instances("BiteBanana");
2425

2526
final var connections = lowFruit.starts().shift(Duration.MINUTE.negate())
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package gov.nasa.ammos.aerie.procedural.timeline.util
2+
3+
interface WithModel<M> {
4+
@Suppress("unchecked_cast")
5+
fun model(): M {
6+
if (modelSingleton == null) {
7+
throw IllegalStateException("modelSingleton was not initialized.")
8+
}
9+
10+
return modelSingleton as M
11+
}
12+
13+
companion object {
14+
@JvmStatic var modelSingleton: Any? = null
15+
}
16+
}

scheduler-worker/src/main/java/gov/nasa/jpl/aerie/scheduler/worker/services/SynchronousSchedulerAgent.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.stream.Collectors;
2323

2424
import gov.nasa.ammos.aerie.procedural.timeline.payloads.ExternalEvent;
25+
import gov.nasa.ammos.aerie.procedural.timeline.util.WithModel;
2526
import gov.nasa.jpl.aerie.merlin.driver.MissionModel;
2627
import gov.nasa.jpl.aerie.merlin.driver.MissionModelLoader;
2728
import gov.nasa.jpl.aerie.merlin.driver.SimulationEngineConfiguration;
@@ -129,6 +130,7 @@ public void schedule(
129130
ensureRequestIsCurrent(specification, request);
130131
//create scheduler problem seeded with initial plan
131132
final var schedulerMissionModel = loadMissionModel(planMetadata);
133+
WithModel.setModelSingleton(schedulerMissionModel.missionModel.getModel());
132134
final var planningHorizon = new PlanningHorizon(
133135
specification.horizonStartTimestamp().toInstant(),
134136
specification.horizonEndTimestamp().toInstant()

0 commit comments

Comments
 (0)