From b5bb1c020168ac914bc9e665799f9a9f016f51a9 Mon Sep 17 00:00:00 2001 From: rschoene <rene.schoene@tu-dresden.de> Date: Wed, 27 Apr 2022 20:21:23 +0200 Subject: [PATCH] more work to get relations converted to terminals --- .../src/main/resources/jastadd/types.jadd | 22 ++++++++- .../src/main/resources/jastadd/types.relast | 4 +- .../src/main/jastadd/WorldModelB.connect | 20 +++++---- .../src/main/jastadd/WorldModelB.jadd | 45 ++++++++++++++++--- .../src/main/jastadd/WorldModelB.relast | 8 ++-- .../tudresden/inf/st/placeB/SimpleMainB.java | 2 +- .../de/tudresden/inf/st/placeB/UtilB.java | 5 +-- 7 files changed, 81 insertions(+), 25 deletions(-) diff --git a/ros3rag.common/src/main/resources/jastadd/types.jadd b/ros3rag.common/src/main/resources/jastadd/types.jadd index f31b6ab..a0290bf 100644 --- a/ros3rag.common/src/main/resources/jastadd/types.jadd +++ b/ros3rag.common/src/main/resources/jastadd/types.jadd @@ -103,7 +103,7 @@ aspect Computation { logicalRegion.setName(region.getName()); result.addLogicalRegion(logicalRegion); for (MovableObject movableObject : getMovableObjectList()) { - for (DropOffLocation location : region.getLocationList()) { + for (DropOffLocation location : region.locationList()) { if (movableObject.isLocatedAt(location)) { LogicalMovableObject logicalObject = objects.get(movableObject); logicalRegion.addContainedObject(logicalObject); @@ -168,6 +168,26 @@ aspect Navigation { // must be "implemented" in concrete world models, i.e., an equation must be defined inh JastAddList<Region> Scene.regionList(); + + syn List<Region> DropOffLocation.containedInRegion() { + List<Region> result = new ArrayList<>(); + for (Region region : containingScene().regionList()) { + List<String> locationNames = Arrays.asList(region.getLocationNames().split(",")); + if (locationNames.contains(getName())) { + result.add(region); + } + } + return result; + } + + protected static List<String> ASTNode.arrayAsList(String array) { + if (array == null || array.length() == 0) { + return new ArrayList<>(); + } + return new ArrayList<>(Arrays.asList(array.split(","))); + } + syn List<String> Region.locationNamesAsList() = arrayAsList(getLocationNames()) ; + syn List<DropOffLocation> Region.locationList(); } aspect Printing { diff --git a/ros3rag.common/src/main/resources/jastadd/types.relast b/ros3rag.common/src/main/resources/jastadd/types.relast index 0be3487..c31c1c3 100644 --- a/ros3rag.common/src/main/resources/jastadd/types.relast +++ b/ros3rag.common/src/main/resources/jastadd/types.relast @@ -23,8 +23,8 @@ rel LogicalRegion.ContainedObject* <-> LogicalMovableObject.LocatedAt* ; // TODO could lead to problems when including this information and sending it //rel LogicalMovableObject.MyLocation? -> DropOffLocation ; -Region ::= <Name:String> ; -rel Region.Location* <-> DropOffLocation.ContainedInRegion* ; +Region ::= <Name:String> <LocationNames> ; +//rel Region.Location* <-> DropOffLocation.ContainedInRegion* ; // TODO should this be only in site-B?? CollaborationZone : DropOffLocation ; diff --git a/ros3rag.placeB/src/main/jastadd/WorldModelB.connect b/ros3rag.placeB/src/main/jastadd/WorldModelB.connect index 6529e04..379efaa 100644 --- a/ros3rag.placeB/src/main/jastadd/WorldModelB.connect +++ b/ros3rag.placeB/src/main/jastadd/WorldModelB.connect @@ -3,7 +3,7 @@ receive WorldModelB.MyScene using ParseScene, ConvertScene ; receive indexed WorldModelB.OtherScene ; receive WorldModelB.TestingOtherScene ; receive Robot.CanReachObjectOfInterestWrapper using ParseReachability, ConvertReachability ; -receive Robot.DummyOwnedCollaborationZone using ConfigChangeCommandCheckForOwnedCollaborationZone ; +receive Robot.OwnedCollaborationZoneNames using ConfigChangeCommandCheckForOwnedCollaborationZone ; receive Robot.Busy using ConfigChangeCommandCheckForBusy ; // --- sending --- @@ -35,18 +35,20 @@ ConfigChangeCommandCheckForOwnedCollaborationZone maps byte[] bytes to String {: DropOffLocation loc = obj.asDropOffLocation(); CollaborationZone cz = loc.asCollaborationZone(); Robot thisRobot = (Robot) this; - if (thisRobot.getName().equals(cc.getIdRobotNewOwner()) && !thisRobot.getOwnedCollaborationZoneList().contains(cz)) { + List<String> collaborationZoneNames = thisRobot.ownedCollaborationZonesAsList(); + boolean robotIsNewOwner = thisRobot.getName().equals(cc.getIdRobotNewOwner()); + boolean collaborationZoneAlreadyOwned = collaborationZoneNames.contains(cc.getIdCollaborationZone()); + if (robotIsNewOwner && !collaborationZoneAlreadyOwned) { // config change is for this robot, add collaboration zone - thisRobot.addOwnedCollaborationZone(cz); - reject(); - } - if (!thisRobot.getName().equals(cc.getIdRobotNewOwner()) && thisRobot.getOwnedCollaborationZoneList().contains(cz)) { + collaborationZoneNames.add(cc.getIdCollaborationZone()); + } else if (!robotIsNewOwner && collaborationZoneAlreadyOwned) { // config change is for another robot, remove collaboration zone - thisRobot.removeOwnedCollaborationZone(cz); + collaborationZoneNames.remove(cc.getIdCollaborationZone()); + } else { + // otherwise don't change reject(); } - // need return to make compiler happy - return ""; + return String.join(",", collaborationZoneNames); :} ConfigChangeCommandCheckForBusy maps byte[] bytes to boolean {: diff --git a/ros3rag.placeB/src/main/jastadd/WorldModelB.jadd b/ros3rag.placeB/src/main/jastadd/WorldModelB.jadd index 6a66bfc..c96e250 100644 --- a/ros3rag.placeB/src/main/jastadd/WorldModelB.jadd +++ b/ros3rag.placeB/src/main/jastadd/WorldModelB.jadd @@ -138,7 +138,7 @@ aspect Computation { try { previousLocation.correspondingVertex(); } catch (NullPointerException e) { - return error("Could not resolve WorldModelB"); + return error("Could not resolve WorldModelB linked to previousLocation " + previousLocation.nameAndHash()); } return previousLocation.correspondingVertex().map(previousVertex -> { Region region = getNewRegion().realRegion(); @@ -146,10 +146,16 @@ aspect Computation { return error("No region found for " + getNewRegion().nameAndHash()); } // pick location from newRegion, that is free - return region.getLocationList().stream() + return region.locationList().stream() .filter(location -> location.getObjectLocatedHere() == null) .findFirst() .map(newLocation -> { + // (workaround) check if WorldModelB is not null ... could happen if scene has no parent + try { + newLocation.correspondingVertex(); + } catch (NullPointerException e) { + return error("Could not resolve WorldModelB linked to newLocation " + newLocation.nameAndHash()); + } return newLocation.correspondingVertex().map(newVertex -> { List<Edge> shortestPath = previousVertex.BFS(newVertex); if (shortestPath == null || shortestPath.isEmpty()) { @@ -170,10 +176,10 @@ aspect Computation { */ CollaborationZone cz = targetLocation.asCollaborationZone(); // order is important here, first add Evacuate, then ConfigChange - if (cz.hasOccupient() && !cz.getOccupient().equals(executingRobot)) { - result.add(Evacuate.of(cz.getOccupient(), cz)); + if (cz.hasOccupient() && !cz.occupient().equals(executingRobot)) { + result.add(Evacuate.of(cz.occupient(), cz)); } - if (!cz.hasOwner() || (cz.hasOwner() && !cz.getOwner().equals(executingRobot))) { + if (!cz.hasOwner() || (cz.hasOwner() && !cz.owner().equals(executingRobot))) { result.add(ConfigChange.of(executingRobot, cz)); } } @@ -259,7 +265,7 @@ aspect Computation { } syn DropOffLocation Region.firstFreeDropOffLocation() { - for (DropOffLocation location : getLocationList()) { + for (DropOffLocation location : locationList()) { if (location.getObjectLocatedHere() == null) { return location; } @@ -346,6 +352,33 @@ aspect Navigation { //--- allMappings --- // inh LocationMapping LogicalDropOffLocation.allMappings(); // eq WorldModelB.getChild().allMappings() = getLocationMapping(); + syn boolean CollaborationZone.hasOccupient() = occupient() != null; + syn Robot CollaborationZone.occupient() { + for (Robot robot : worldModelB().getRobotList()) { + if (getName().equals(robot.getOccupiedCollaborationZoneName())) { + return robot; + } + } + return null; + } + syn boolean CollaborationZone.hasOwner() = owner() != null; + syn Robot CollaborationZone.owner() { + for (Robot robot : worldModelB().getRobotList()) { + List<String> collaborationZoneNames = Arrays.asList(robot.getOwnedCollaborationZoneNames().split(",")); + if (collaborationZoneNames.contains(getName())) { + return robot; + } + } + return null; + } + syn List<String> Robot.ownedCollaborationZonesAsList() = arrayAsList(getOwnedCollaborationZoneNames()); + eq Region.locationList() { + List<DropOffLocation> result = new ArrayList<>(); + for (String locationName : locationNamesAsList()) { + result.add(worldModelB().getMyScene().resolveObjectOfInterest(locationName).asDropOffLocation()); + } + return result; + } } aspect GlueForShared { diff --git a/ros3rag.placeB/src/main/jastadd/WorldModelB.relast b/ros3rag.placeB/src/main/jastadd/WorldModelB.relast index 919d372..856d1b0 100644 --- a/ros3rag.placeB/src/main/jastadd/WorldModelB.relast +++ b/ros3rag.placeB/src/main/jastadd/WorldModelB.relast @@ -1,8 +1,10 @@ WorldModelB ::= Region* Robot* [MyScene:Scene] OtherScene:LogicalScene* /NextOperation:Operation/ TestingOtherScene:LogicalScene* ; -Robot ::= <Name:String> CanReachObjectOfInterestWrapper <Busy:boolean> <DummyOwnedCollaborationZone> ; -rel Robot.OwnedCollaborationZone* <-> CollaborationZone.Owner? ; -rel Robot.OccupiedCollaborationZone? <-> CollaborationZone.Occupient? ; +// FIXME inline CanReachObjectOfInterestWrapper +Robot ::= <Name:String> CanReachObjectOfInterestWrapper <Busy:boolean> <OwnedCollaborationZoneNames> <OccupiedCollaborationZoneName> ; +// relations into nodes received by RagConnect are not allowed +//rel Robot.OwnedCollaborationZone* <-> CollaborationZone.Owner? ; +//rel Robot.OccupiedCollaborationZone? <-> CollaborationZone.Occupient? ; abstract Difference ; rel Difference.Object -> LogicalMovableObject ; diff --git a/ros3rag.placeB/src/main/java/de/tudresden/inf/st/placeB/SimpleMainB.java b/ros3rag.placeB/src/main/java/de/tudresden/inf/st/placeB/SimpleMainB.java index c65771d..5895d96 100644 --- a/ros3rag.placeB/src/main/java/de/tudresden/inf/st/placeB/SimpleMainB.java +++ b/ros3rag.placeB/src/main/java/de/tudresden/inf/st/placeB/SimpleMainB.java @@ -113,7 +113,7 @@ public class SimpleMainB { model.connectMyScene(Util.mqttUri(topicSceneUpdateB, config)); for (Robot robot : model.getRobotList()) { robot.connectBusy(Util.mqttUri(topicCommand, config)); - robot.connectDummyOwnedCollaborationZone(Util.mqttUri(topicCommand, config)); + robot.connectOwnedCollaborationZoneNames(Util.mqttUri(topicCommand, config)); } model.connectNextOperation(Util.mqttUri(topicCommand, config), true); diff --git a/ros3rag.placeB/src/main/java/de/tudresden/inf/st/placeB/UtilB.java b/ros3rag.placeB/src/main/java/de/tudresden/inf/st/placeB/UtilB.java index 8de49d5..622b717 100644 --- a/ros3rag.placeB/src/main/java/de/tudresden/inf/st/placeB/UtilB.java +++ b/ros3rag.placeB/src/main/java/de/tudresden/inf/st/placeB/UtilB.java @@ -12,6 +12,7 @@ import org.apache.logging.log4j.Logger; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.stream.Collectors; /** * Static utility methods used only for place B. @@ -143,9 +144,7 @@ public class UtilB { for (RegionDefinition def : config.regions) { Region region = new Region(); region.setName(def.name); - for (String position : def.positions) { - region.addLocation(model.getMyScene().resolveObjectOfInterest(position).asDropOffLocation()); - } + region.setLocationNames(String.join(",", def.positions)); result.add(region); } model.setRegionList(result); -- GitLab