diff --git a/libs/ragconnect-0.2.2.jar b/libs/ragconnect-0.2.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..c2a95e44dc2a392419f58a5a31731d0e7e61849f Binary files /dev/null and b/libs/ragconnect-0.2.2.jar differ diff --git a/ros3rag.common/src/main/java/de/tudresden/inf/st/ros3rag/common/Util.java b/ros3rag.common/src/main/java/de/tudresden/inf/st/ros3rag/common/Util.java index 65f58a1e667398f4b4b8fe59880e5fae9e02def9..af978eb6022b4e2d6a1f7b68a1c5903655fe0cae 100644 --- a/ros3rag.common/src/main/java/de/tudresden/inf/st/ros3rag/common/Util.java +++ b/ros3rag.common/src/main/java/de/tudresden/inf/st/ros3rag/common/Util.java @@ -81,6 +81,8 @@ public class Util { private final static Set<String> modules = new HashSet<>() {{ add("ros3rag.placeA"); add("ros3rag.placeB"); + add("ros3rag.old.a"); + add("ros3rag.old.b"); add("ros3rag.common"); add("ros3rag.coordinator"); }}; diff --git a/ros3rag.common/src/main/resources/old-jastadd/types.connect b/ros3rag.common/src/main/resources/old-jastadd/types.connect new file mode 100644 index 0000000000000000000000000000000000000000..1d21d81d358d380c0f0f928654a0075d5cfdc513 --- /dev/null +++ b/ros3rag.common/src/main/resources/old-jastadd/types.connect @@ -0,0 +1,64 @@ +ParseScene maps byte[] bytes to de.tudresden.inf.st.ceti.Scene {: + return de.tudresden.inf.st.ceti.Scene.parseFrom(bytes); +:} + +ConvertScene maps de.tudresden.inf.st.ceti.Scene pbScene to Scene {: + var result = new Scene(); + for (var pbObject : pbScene.getObjectsList()) { + ObjectOfInterest obj; + switch (pbObject.getType()) { + case BOX: + // BOX == MovableObject + MovableObject movableObject = new MovableObject(); + result.addMovableObject(movableObject); + obj = movableObject; + break; + case DROP_OFF_LOCATION: + // DROP_OFF_LOCATION == DropOffLocation + DropOffLocation dropOffLocation = new DropOffLocation(); + result.addDropOffLocation(dropOffLocation); + obj = dropOffLocation; + break; + case COLLABORATION_ZONE: + // COLLABORATION_ZONE == CollaborationZone + CollaborationZone cz = new CollaborationZone(); + result.addDropOffLocation(cz); + obj = cz; + break; + case ARM: + // ARM == RobotObject + RobotObject ro = new RobotObject(); + ro.setState(pbObject.getState()); + result.addRobotObject(ro); + obj = ro; + break; + default: + // ignore object, continue for loop + continue; + } + obj.setName(pbObject.getId()); + + // position + var pos = new Position(); + pos.setX(pbObject.getPos().getX()); + pos.setY(pbObject.getPos().getY()); + pos.setZ(pbObject.getPos().getZ()); + obj.setPosition(pos); + + // orientation + var orient = new Orientation(); + orient.setX(pbObject.getOrientation().getX()); + orient.setY(pbObject.getOrientation().getY()); + orient.setZ(pbObject.getOrientation().getZ()); + orient.setW(pbObject.getOrientation().getW()); + obj.setOrientation(orient); + + // size + var size = new Size(); + size.setLength(pbObject.getSize().getLength()); + size.setWidth(pbObject.getSize().getWidth()); + size.setHeight(pbObject.getSize().getHeight()); + obj.setSize(size); + } + return result; +:} diff --git a/ros3rag.common/src/main/resources/old-jastadd/types.jadd b/ros3rag.common/src/main/resources/old-jastadd/types.jadd new file mode 100644 index 0000000000000000000000000000000000000000..8ee7d98d85588cca63675ff54ac47761ac74dbce --- /dev/null +++ b/ros3rag.common/src/main/resources/old-jastadd/types.jadd @@ -0,0 +1,337 @@ +import org.apache.commons.math3.geometry.euclidean.threed.Rotation; +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; +import java.util.*; + +aspect Resolving { + //--- resolveObjectOfInterest --- + syn ObjectOfInterest Scene.resolveObjectOfInterest(String name) { + for (DropOffLocation location : getDropOffLocationList()) { + if (location.getName().equals(name)) { + return location; + } + } + for (MovableObject movableObject : getMovableObjectList()) { + if (movableObject.getName().equals(name)) { + return movableObject; + } + } + for (RobotObject robotObject : getRobotObjectList()) { + if (robotObject.getName().equals(name)) { + return robotObject; + } + } + return null; + } + + //--- resolveLogicalObjectOfInterest --- + syn LogicalObjectOfInterest LogicalScene.resolveLogicalObjectOfInterest(String name) { + for (LogicalRegion region : getLogicalRegionList()) { + if (region.getName().equals(name)) { + return region; + } + } + for (LogicalMovableObject movableObject : getLogicalMovableObjectList()) { + if (movableObject.getName().equals(name)) { + return movableObject; + } + } + return null; + } + + syn DropOffLocation LogicalMovableObject.myLocation() { + // classical reference attribute (was relation, but not allowed with RagConnect) + ObjectOfInterest obj = containingScene().resolveObjectOfInterest(getNameOfMyLocation()); + return obj == null ? null : obj.asDropOffLocation(); + } +} + +aspect Computation { + //--- isLocatedAt --- + syn boolean MovableObject.isLocatedAt(DropOffLocation location) { + Orientation orient = location.getOrientation(); + Position locationPosition = location.getPosition(); + // true to do normalization, first parameter is scalar value + Rotation locationRotation = new Rotation(orient.getW(), orient.getX(), orient.getY(), orient.getZ(), true); + + Position pos = this.getPosition(); + // first do translation of objectVector to coordinate system of location + Vector3D objectVector = new Vector3D(pos.getX() - locationPosition.getX(), + pos.getY() - locationPosition.getY(), + pos.getZ() - locationPosition.getZ()); + + // apply rotation on this point + Vector3D rotatedObjectVector = locationRotation.applyInverseTo(objectVector); + + // check whether coordinates are within the bounds of the given location + Size locationSize = location.getSize(); + // we use half of the size of to the position as it is in the center of the location + double halfLocationLength = 0.5 * locationSize.getLength(); + double halfLocationWidth = 0.5 * locationSize.getWidth(); +// double halfLocationHeight = 0.5 * locationSize.getHeight(); + + double rotatedX = rotatedObjectVector.getX(); + double rotatedY = rotatedObjectVector.getY(); + double rotatedZ = rotatedObjectVector.getZ(); + +// System.out.printf("min: (%f , %f , %f). rotated: (%f , %f , %f), max: (%f , %f , %f)%n", +// -halfLocationLength, -halfLocationWidth, -halfLocationHeight, +// rotatedX, rotatedY, rotatedZ, +// halfLocationLength, +// halfLocationWidth, +// halfLocationHeight); + + return LT(-halfLocationLength, rotatedX) && LT(rotatedX, halfLocationLength) && + LT(-halfLocationWidth, rotatedY) && LT(rotatedY, halfLocationWidth); // && + //LT(-halfLocationHeight, rotatedZ) && LT(rotatedZ, halfLocationHeight); + } + + syn MovableObject DropOffLocation.getObjectLocatedHere() { + for (MovableObject obj : containingScene().getMovableObjects()) { + if (obj.isLocatedAt(this)) { + return obj; + } + } + return null; + } + + //--- getLogicalScene --- + syn LogicalScene Scene.getLogicalScene() { + var result = new LogicalScene(); + Map<MovableObject, LogicalMovableObject> objects = new HashMap<>(); + for (MovableObject movableObject : getMovableObjectList()) { + LogicalMovableObject newLogicalMovableObject = new LogicalMovableObject(); + newLogicalMovableObject.setName(movableObject.getName()); + result.addLogicalMovableObject(newLogicalMovableObject); + objects.put(movableObject, newLogicalMovableObject); + } + for (Region region : regionList()) { + LogicalRegion logicalRegion = new LogicalRegion(); + logicalRegion.setName(region.getName()); + result.addLogicalRegion(logicalRegion); + for (MovableObject movableObject : getMovableObjectList()) { + for (DropOffLocation location : region.locationList()) { + if (movableObject.isLocatedAt(location)) { + LogicalMovableObject logicalObject = objects.get(movableObject); + logicalRegion.addContainedObject(logicalObject); + logicalObject.setNameOfMyLocation(location.getName()); + } + } + } + } + return result; + } + + private static final double MovableObject.DELTA = 0.0001; + + //--- LT --- + /** + * @return d1 <= d2 (within a DELTA) + */ + private boolean MovableObject.LT(double d1, double d2) { + return org.apache.commons.math3.util.Precision.compareTo(d1, d2, DELTA) <= 0; + } +} + +aspect Navigation { + // --- isDropOffLocation --- + syn boolean ObjectOfInterest.isDropOffLocation() = false; + eq DropOffLocation.isDropOffLocation() = true; + + // --- asDropOffLocation --- + syn DropOffLocation ObjectOfInterest.asDropOffLocation() = null; + eq DropOffLocation.asDropOffLocation() = this; + + // --- isRobotObject --- + syn boolean ObjectOfInterest.isRobotObject() = false; + eq RobotObject.isRobotObject() = true; + + // --- asRobotObject --- + syn RobotObject ObjectOfInterest.asRobotObject() = null; + eq RobotObject.asRobotObject() = this; + + // --- isLogicalRegion --- + syn boolean LogicalObjectOfInterest.isLogicalRegion() = false; + eq LogicalRegion.isLogicalRegion() = true; + + // --- asLogicalRegion --- + syn LogicalRegion LogicalObjectOfInterest.asLogicalRegion() = null; + eq LogicalRegion.asLogicalRegion() = this; + + // --- isLogicalMovableObject --- + syn boolean LogicalObjectOfInterest.isLogicalMovableObject() = false; + eq LogicalMovableObject.isLogicalMovableObject() = true; + + // --- asLogicalMovableObject --- + syn LogicalMovableObject LogicalObjectOfInterest.asLogicalMovableObject() = null; + eq LogicalMovableObject.asLogicalMovableObject() = this; + + inh Scene DropOffLocation.containingScene(); + inh Scene MovableObject.containingScene(); + inh Scene LogicalMovableObject.containingScene(); + eq Scene.getChild().containingScene() = this; + + syn boolean LogicalMovableObject.hasLocatedAt() = !getLocatedAtList().isEmpty(); + + // 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(); + + syn Set<String> LogicalMovableObject.regionNameSet() { + return getLocatedAtList().stream().map(LogicalRegion::getName).collect(java.util.stream.Collectors.toSet()); + } +} + +aspect Printing { + //--- prettyPrint --- + syn String JastAddList.prettyPrint() { + return prettyPrint(Object::toString); + } + syn String JastAddList.prettyPrint(java.util.function.Function<T, String> toString) { + return java.util.stream.StreamSupport.stream(Spliterators.spliteratorUnknownSize(this.iterator(), 16), false).map(toString::apply).collect(java.util.stream.Collectors.joining(", ", "[", "]")); + } + + syn String Scene.prettyPrint() { + StringBuilder sb = new StringBuilder(); + if (getNumDropOffLocation() == 0) { + sb.append(" no locations\n"); + } else { + for (var location : getDropOffLocationList()) { + sb.append(" location ").append(location.prettyPrint()).append("\n"); + } + } + if (getNumMovableObject() == 0) { + sb.append(" no objects\n"); + } else { + for (var obj : getMovableObjectList()) { + sb.append(" obj ").append(obj.prettyPrint()).append("\n"); + } + } + return sb.toString(); + } + + syn String MovableObject.prettyPrint() { + return "<obj " + nameAndHash() + getPosition().prettyPrint() + getOrientation().prettyPrint() + getSize().prettyPrint() + ">"; + } + + syn String DropOffLocation.prettyPrint() { + return "{" + printPrefix() + " " + getName() + getPosition().prettyPrint() + getOrientation().prettyPrint() + getSize().prettyPrint() + "}"; + } + + syn String DropOffLocation.printPrefix() = "loc"; + eq CollaborationZone.printPrefix() = "CZ"; + + syn String Region.prettyPrint() { + return "{reg " + nameAndHash() + "}"; + } + + syn String Position.prettyPrint() { + return " pos=(" + getX() + "," + getY() + "," + getZ() + ")"; + } + + syn String Orientation.prettyPrint() { + return " orient=(" + getX() + "," + getY() + "," + getZ() + "," + getW() + ")"; + } + + syn String Size.prettyPrint() { + return " size=(" + getLength() + "," + getWidth() + "," + getHeight() + ")"; + } + + syn String LogicalScene.prettyPrint() { + StringBuilder sb = new StringBuilder(); + if (getNumLogicalRegion() == 0) { + sb.append(" no region\n"); + } else { + // TODO + for (LogicalRegion region : getLogicalRegionList()) { + sb.append(" region ").append(region.prettyPrint()); + if (!region.getContainedObjectList().isEmpty()) { + sb.append(" (objects: ").append(region.getContainedObjectList().stream().map(LogicalMovableObject::getName).collect(java.util.stream.Collectors.joining(","))).append(")"); + } + sb.append("\n"); + } + } + if (getNumLogicalMovableObject() == 0) { + sb.append(" no objects\n"); + } else { + for (LogicalMovableObject obj : getLogicalMovableObjectList()) { + sb.append(" obj ").append(obj.prettyPrint()); + if (obj.hasLocatedAt()) { + sb.append(" (locatedAt: ").append(obj.getLocatedAtList().stream().map(LogicalRegion::nameAndHash).collect(java.util.stream.Collectors.joining(","))).append(")"); + } + sb.append("\n"); + } + } + return sb.toString(); + } + + syn String LogicalMovableObject.prettyPrint() { + return "<lObj " + nameAndHash() + ">"; + } + syn String LogicalRegion.prettyPrint() { + return "{lReg " + nameAndHash() + "}"; + } + + syn String LogicalObjectOfInterest.nameAndHash() = getName() + "@" + Integer.toHexString(hashCode()); + syn String ObjectOfInterest.nameAndHash() = getName() + "@" + Integer.toHexString(hashCode()); + syn String Region.nameAndHash() = getName() + "@" + Integer.toHexString(hashCode()); +} + +aspect ConvenienceMethods { + // --- of --- + public static DropOffLocation DropOffLocation.of(String name, + Position position, Orientation orientation, Size size) { + var location = new DropOffLocation(); + initObjectOfInterest(location, name, position, orientation, size); + return location; + } + + public static MovableObject MovableObject.of(String name, Position position) { + var location = new MovableObject(); + initObjectOfInterest(location, name, position, + Orientation.of(0, 0, 0, 0), Size.of(0, 0, 0)); + return location; + } + + protected static void ObjectOfInterest.initObjectOfInterest(ObjectOfInterest object, String name, + Position position, Orientation orientation, Size size) { + object.setName(name); + object.setPosition(position); + object.setOrientation(orientation); + object.setSize(size); + } + + public static Position Position.of(double x, double y, double z) { + return new Position(x, y, z); + } + + public static Orientation Orientation.of(double x, double y, double z, double w) { + return new Orientation(x, y, z, w); + } + + public static Size Size.of(double length, double width, double height) { + return new Size(length, width, height); + } +} + +aspect Glue { + class MqttHandler implements de.tudresden.inf.st.ros3rag.common.SharedMainParts.MqttHandlerWrapper<MqttHandler> {} +} diff --git a/ros3rag.common/src/main/resources/old-jastadd/types.relast b/ros3rag.common/src/main/resources/old-jastadd/types.relast new file mode 100644 index 0000000000000000000000000000000000000000..c5585b92ce2e51aa1930e25d63cbe1bc114764e7 --- /dev/null +++ b/ros3rag.common/src/main/resources/old-jastadd/types.relast @@ -0,0 +1,27 @@ +Position ::= <X:double> <Y:double> <Z:double> ; +Size ::= <Length:double> <Width:double> <Height:double> ; +Orientation ::= <X:double> <Y:double> <Z:double> <W:double> ; + +// Regions cannot be contained in scene, but must be retrieved via attribute +Scene ::= DropOffLocation* MovableObject* RobotObject* /LogicalScene/ ; + +ObjectOfInterest ::= <Name:String> Position Size Orientation ; + +DropOffLocation : ObjectOfInterest ; +MovableObject : ObjectOfInterest ; +RobotObject : ObjectOfInterest ::= <State:de.tudresden.inf.st.ceti.Object.State> ; + +LogicalScene ::= LogicalRegion* LogicalMovableObject* ; +LogicalObjectOfInterest ::= <Name:String> ; +LogicalRegion : LogicalObjectOfInterest ; +LogicalMovableObject : LogicalObjectOfInterest ::= <NameOfMyLocation> ; +rel LogicalRegion.ContainedObject* <-> LogicalMovableObject.LocatedAt* ; + +// could lead to problems when including this information and sending it +//rel LogicalMovableObject.MyLocation? -> DropOffLocation ; + +Region ::= <Name:String> <LocationNames> ; +//rel Region.Location* <-> DropOffLocation.ContainedInRegion* ; + +// only used in site-B, but needed here for parsing the scene +CollaborationZone : DropOffLocation ; diff --git a/ros3rag.common/src/main/resources/tasks.gradle b/ros3rag.common/src/main/resources/tasks.gradle index 938cb0b6d844fb138245b1cec1b83bc92251af32..b0c1d7800c824f2fa15ba10e06c65c3a7726cc32 100644 --- a/ros3rag.common/src/main/resources/tasks.gradle +++ b/ros3rag.common/src/main/resources/tasks.gradle @@ -1,9 +1,14 @@ -// setting default value +// setting default values try { project.ext.ragConnectProtocols } catch(ignored) { project.ext.ragConnectProtocols = 'mqtt' } +try { + project.ext.useOldRagConnect +} catch(ignored) { + project.ext.useOldRagConnect = false +} dependencies { jastadd2 "org.jastadd:jastadd2:2.3.5-dresden-6" @@ -42,6 +47,28 @@ task ragConnect(type: JavaExec) { } +task mergeFilesForOldRagConnect { + mkdir 'src/gen/workaround/' + (file('src/gen/workaround/merged.relast')).text = file(project.ext.ragConnectInputGrammar).getText() + new File(file(project.ext.sharedJastAddDir), 'types.relast').getText() + (file('src/gen/workaround/merged.connect')).text = file(project.ext.ragConnectInputConnect).getText() + new File(file(project.ext.sharedJastAddDir), 'types.connect').getText() +} + +task oldRagConnect(type: JavaExec) { + group = 'Build' + main = '-jar' + + args([ + '../libs/ragconnect-0.2.2.jar', +// '--verbose', + '--o=src/gen/jastadd', + file('src/gen/workaround/merged.relast'), + file('src/gen/workaround/merged.connect'), + '--rootNode=' + project.ext.ragConnectRootNode, + '--protocols=' + project.ext.ragConnectProtocols, + '--List=JastAddList' + ]) +} + // Input files for relast //def relastFiles = ["src/gen/jastadd/MinimalModel.relast", "src/gen/jastadd/RagConnect.relast"] @@ -50,8 +77,7 @@ task grammar2uml(type: JavaExec) { classpath = configurations.grammar2uml args([ - '--verbose', - 'src/gen/jastadd/types.relast' + '--verbose' ] + project.ext.relastFiles) } @@ -73,11 +99,10 @@ task relastToJastAdd(type: JavaExec) { "--jastAddList=JastAddList", "--serializer=jackson", "--resolverHelper", - "--file", - "src/gen/jastadd/types.relast" + "--file" ] + project.ext.relastFiles - inputs.files project.ext.relastFiles + ['src/gen/jastadd/types.relast'] + inputs.files project.ext.relastFiles outputs.files file("./src/gen/jastadd/model.ast"), file("./src/gen/jastadd/model.jadd") } @@ -127,7 +152,11 @@ jastadd { // jastaddOptions = ["--lineColumnNumbers", "--visitCheck=true", "--rewrite=cnta", "--cache=all"] // default options are: '--rewrite=cnta', '--safeLazy', '--visitCheck=false', '--cacheCycle=false' - extraJastAddOptions = [ + extraJastAddOptions = project.ext.useOldRagConnect ? [ + '--lineColumnNumbers', + '--List=JastAddList', + ] : + [ '--lineColumnNumbers', '--List=JastAddList', '--cache=all', @@ -143,4 +172,9 @@ cleanGen.doFirst { // Workflow configuration for phases generateAst.dependsOn relastToJastAdd -relastToJastAdd.dependsOn ragConnect +if (project.ext.useOldRagConnect) { + oldRagConnect.dependsOn mergeFilesForOldRagConnect + relastToJastAdd.dependsOn oldRagConnect +} else { + relastToJastAdd.dependsOn ragConnect +} diff --git a/ros3rag.old.a/.gitignore b/ros3rag.old.a/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..87b4cdd3d7c6a41502ca98703abeeb69a1d536fb --- /dev/null +++ b/ros3rag.old.a/.gitignore @@ -0,0 +1,5 @@ +build +src/gen-res/ +src/gen/ +out/ +*.class diff --git a/ros3rag.old.a/build.gradle b/ros3rag.old.a/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..7a6e03b0b05047705403a48078b29135cc2519d8 --- /dev/null +++ b/ros3rag.old.a/build.gradle @@ -0,0 +1,34 @@ +buildscript { + repositories.mavenCentral() + dependencies { + classpath group: 'org.jastadd', name: 'jastaddgradle', version: "${jastadd_gradle_version}" + } +} + +plugins { + id 'ros3rag.java-application-conventions' + id 'ros3rag.java-old-ragconnect-conventions' +} + +mainClassName = 'de.tudresden.inf.st.old.a.OldMainA' + +task simpleRun(type: JavaExec) { + group 'application' + classpath sourceSets.main.runtimeClasspath + main = "de.tudresden.inf.st.old.a.OldSimpleMainA" + +} + +dependencies { + implementation project(':ros3rag.common') +} + +ext.sharedJastAddDir = 'src/main/jastadd/old-shared' +ext.ragConnectInputGrammar = 'src/main/jastadd/OldWorldModelA.relast' +ext.ragConnectInputConnect = 'src/main/jastadd/OldWorldModelA.connect' +ext.ragConnectRootNode = 'ArtificialRoot' +ext.relastFiles = ["src/gen/jastadd/merged.relast", "src/gen/jastadd/RagConnect.relast"] +ext.jastaddAstPackage = 'de.tudresden.inf.st.old.a.ast' +ext.useOldRagConnect = true + +apply from: '../ros3rag.common/src/main/resources/tasks.gradle' diff --git a/ros3rag.old.a/src/main/jastadd/Additional.jadd b/ros3rag.old.a/src/main/jastadd/Additional.jadd new file mode 100644 index 0000000000000000000000000000000000000000..d3d5e23b7fa4a1dbb5eb9fd63727a44742e3a2d3 --- /dev/null +++ b/ros3rag.old.a/src/main/jastadd/Additional.jadd @@ -0,0 +1,16 @@ +aspect NewComputationNeededForOldRagConnect { + syn String WorldModelA.getLogicalSceneAsNtaToken() { + // copied from placeA/src/gen/jastadd/RagConnect.jadd -> ASTNode._ragconnect__apply__TreeDefaultLogicalSceneToBytesMapping(LogicalScene input) + java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); + com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory(); + try { + com.fasterxml.jackson.core.JsonGenerator generator = factory.createGenerator(outputStream, com.fasterxml.jackson.core.JsonEncoding.UTF8); + getLogicalScene().serialize(generator); + generator.flush(); + } catch (IOException | SerializationException e) { + e.printStackTrace(); + return null; + } + return outputStream.toString(); + } +} diff --git a/ros3rag.old.a/src/main/jastadd/OldWorldModelA.connect b/ros3rag.old.a/src/main/jastadd/OldWorldModelA.connect new file mode 100644 index 0000000000000000000000000000000000000000..65d03e47f6dc7802b95fe44e84f2a018c1ddbfc5 --- /dev/null +++ b/ros3rag.old.a/src/main/jastadd/OldWorldModelA.connect @@ -0,0 +1,7 @@ +// --- receiving --- +//receive WorldModelA.Scene using ParseScene, ConvertScene ; + +// --- sending --- +send WorldModelA.LogicalSceneAsNtaToken ; + +// probably need dependency definitions? diff --git a/ros3rag.old.a/src/main/jastadd/OldWorldModelA.jadd b/ros3rag.old.a/src/main/jastadd/OldWorldModelA.jadd new file mode 100644 index 0000000000000000000000000000000000000000..85580b4d450c90ff9b836b9ccfb20799a4459459 --- /dev/null +++ b/ros3rag.old.a/src/main/jastadd/OldWorldModelA.jadd @@ -0,0 +1,22 @@ +aspect Navigation { + //--- worldModelA --- + inh WorldModelA ASTNode.worldModelA(); + eq WorldModelA.getChild().worldModelA() = this; +} + +aspect Glue { + class ArtificialRoot implements de.tudresden.inf.st.ros3rag.common.SharedMainParts.WorldModelWrapper {} + + //--- getLogicalScene --- + syn LogicalScene WorldModelA.getLogicalScene() = hasScene() ? getScene().getLogicalScene() : new LogicalScene(); + + eq WorldModelA.getScene().regionList() = getRegionList(); + eq Region.locationList() { + List<DropOffLocation> result = new ArrayList<>(); + if (!worldModelA().hasScene()) { return result; } + for (String locationName : locationNamesAsList()) { + result.add(worldModelA().getScene().resolveObjectOfInterest(locationName).asDropOffLocation()); + } + return result; + } +} diff --git a/ros3rag.old.a/src/main/jastadd/OldWorldModelA.relast b/ros3rag.old.a/src/main/jastadd/OldWorldModelA.relast new file mode 100644 index 0000000000000000000000000000000000000000..90bea5f02498d78f36bf90d76eeb17488a0560dc --- /dev/null +++ b/ros3rag.old.a/src/main/jastadd/OldWorldModelA.relast @@ -0,0 +1,3 @@ +ArtificialRoot ::= WorldModelA ; + +WorldModelA ::= Region* [Scene] /LogicalScene/ /<LogicalSceneAsNtaToken>/ ; diff --git a/ros3rag.old.a/src/main/jastadd/forwardsComp.jadd b/ros3rag.old.a/src/main/jastadd/forwardsComp.jadd new file mode 100644 index 0000000000000000000000000000000000000000..00ab287ea1c39896c0a5f42b53d7a6972e9cad19 --- /dev/null +++ b/ros3rag.old.a/src/main/jastadd/forwardsComp.jadd @@ -0,0 +1,5 @@ +aspect BackwardsCompatibility { + public void ArtificialRoot.ragconnectCheckIncremental() { + // empty by definition (no incremental evaluation) + } +} diff --git a/ros3rag.old.a/src/main/jastadd/old-shared b/ros3rag.old.a/src/main/jastadd/old-shared new file mode 120000 index 0000000000000000000000000000000000000000..1a2dff41ee8ae3f38e6ee93f962b4a983b0cbc3a --- /dev/null +++ b/ros3rag.old.a/src/main/jastadd/old-shared @@ -0,0 +1 @@ +../../../../ros3rag.common/src/main/resources/old-jastadd \ No newline at end of file diff --git a/ros3rag.old.a/src/main/java/de/tudresden/inf/st/old/a/OldMainA.java b/ros3rag.old.a/src/main/java/de/tudresden/inf/st/old/a/OldMainA.java new file mode 100644 index 0000000000000000000000000000000000000000..e7645576b8d4d7722c64aac41b7d218cdcac2028 --- /dev/null +++ b/ros3rag.old.a/src/main/java/de/tudresden/inf/st/old/a/OldMainA.java @@ -0,0 +1,94 @@ +package de.tudresden.inf.st.old.a; + +import de.tudresden.inf.st.old.a.ast.ArtificialRoot; +import de.tudresden.inf.st.old.a.ast.MqttHandler; +import de.tudresden.inf.st.old.a.ast.Scene; +import de.tudresden.inf.st.old.a.ast.WorldModelA; +import de.tudresden.inf.st.ros3rag.common.SharedMainParts; +import de.tudresden.inf.st.ros3rag.common.Util; + +import java.io.File; +import java.io.IOException; + +import static de.tudresden.inf.st.ros3rag.common.Util.mqttUri; +import static de.tudresden.inf.st.ros3rag.common.Util.readScene; + +/** + * Entry point for RAG model in place A. + * + * @author rschoene - Initial contribution + */ +public class OldMainA extends SharedMainParts<MqttHandler, ArtificialRoot> { + private final String TOPIC_SCENE_UPDATE_FROM_ROS; + private final String TOPIC_SCENE_UPDATE_TO_PLACE_B; + + private final String TOPIC_DEMO_MOVE_objectRed1_BLUE; + private final String TOPIC_DEMO_MOVE_objectRed1_RED; + private final String TOPIC_EVAL_MOVE; + + OldMainA(String configFile) { + super("place-a", OldUtilA.pathToDirectoryOfPlaceA().resolve(configFile)); + this.TOPIC_SCENE_UPDATE_FROM_ROS = cellName + "/scene/update"; + this.TOPIC_SCENE_UPDATE_TO_PLACE_B = cellName + "/logical/update"; + + this.TOPIC_DEMO_MOVE_objectRed1_BLUE = cellName + "/demo/move/objectRed1/blue"; + this.TOPIC_DEMO_MOVE_objectRed1_RED = cellName + "/demo/move/objectRed1/red"; + this.TOPIC_EVAL_MOVE = cellName + "/eval/move"; + } + + public static void main(String[] args) throws Exception { + String configFile = args.length == 0 ? "src/main/resources/config-a.yaml" : args[0]; + new OldMainA(configFile).run(); + } + + @Override + protected MqttHandler createMqttHandler() { + return new MqttHandler("mainHandlerA"); + } + + @Override + protected void createSpecificMainHandlerConnections() { + mainHandler.newConnection(TOPIC_DEMO_MOVE_objectRed1_BLUE, bytes -> + OldUtilA.updatePositionOfObjectToLocation(model.getWorldModelA().getScene(), "objectRed1", "binBlue") + ); + mainHandler.newConnection(TOPIC_DEMO_MOVE_objectRed1_RED, bytes -> + OldUtilA.updatePositionOfObjectToLocation(model.getWorldModelA().getScene(), "objectRed1", "binRed") + ); + mainHandler.newConnection(TOPIC_EVAL_MOVE, bytes -> { + String[] tokens = new String(bytes).split(" to "); + String objectName = tokens[0]; + String locationName = tokens[1]; + OldUtilA.updatePositionOfObjectToLocation(model.getWorldModelA().getScene(), objectName, locationName); + }); + } + + @Override + protected ArtificialRoot createWorldModel() throws Exception { + de.tudresden.inf.st.ceti.Scene scene = readScene( + OldUtilA.pathToDirectoryOfPlaceA().resolve(config.forA.filenameInitialScene) + ); + Scene myScene = OldUtilA.convert(scene); + WorldModelA worldModel = new WorldModelA().setScene(myScene); + return new ArtificialRoot().setWorldModelA(worldModel); + } + + @Override + protected void readInitialConfigs() throws IOException { + // read and set regions + File regionFile = OldUtilA.pathToDirectoryOfPlaceA().resolve(config.filenameRegions).toFile(); + OldUtilA.setRegions(model.getWorldModelA(), Util.parseRegionConfig(regionFile)); + + // no robots to be set + } + + @Override + protected void connectEndpoints() throws IOException { +// model.connectScene(mqttUri(TOPIC_SCENE_UPDATE_FROM_ROS, config)); + model.getWorldModelA().connectLogicalSceneAsNtaToken(mqttUri(TOPIC_SCENE_UPDATE_TO_PLACE_B, config), true); + } + + @Override + protected String getModelInfos(ArtificialRoot artificialRoot, boolean detailed) { + return OldUtilA.getModelInfos(artificialRoot.getWorldModelA(), detailed); + } +} diff --git a/ros3rag.old.a/src/main/java/de/tudresden/inf/st/old/a/OldSimpleMainA.java b/ros3rag.old.a/src/main/java/de/tudresden/inf/st/old/a/OldSimpleMainA.java new file mode 100644 index 0000000000000000000000000000000000000000..1641138d82b0d0c3ecfef967877eea3887b928d7 --- /dev/null +++ b/ros3rag.old.a/src/main/java/de/tudresden/inf/st/old/a/OldSimpleMainA.java @@ -0,0 +1,138 @@ +package de.tudresden.inf.st.old.a; + +import de.tudresden.inf.st.old.a.ast.*; +import org.apache.commons.math3.geometry.euclidean.threed.Rotation; +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Scanner; +import java.util.concurrent.TimeUnit; + +import static de.tudresden.inf.st.ros3rag.common.Util.readScene; + +/** + * Testing features for placeA. + * + * @author rschoene - Initial contribution + */ +public class OldSimpleMainA { + private static final Logger logger = LogManager.getLogger(OldSimpleMainA.class); + + @SuppressWarnings("CommentedOutCode") + public static void main(String[] args) throws Exception { +// testLocatedAt(); +// testBuildModelA(); + testReadSceneConfig(); + } + + @SuppressWarnings("CommentedOutCode") + private static void testReadSceneConfig() throws Exception { + final var path = OldUtilA.pathToDirectoryOfPlaceA().resolve("src/main/resources/config-scene-a.json"); + de.tudresden.inf.st.ceti.Scene scene = readScene(path); + Scene myScene = OldUtilA.convert(scene); + + ArtificialRoot root = new ArtificialRoot(); + + WorldModelA model = new WorldModelA(); + model.setScene(myScene); + root.setWorldModelA(model); + + // send initial scene once +// MqttHandler publisher = new MqttHandler().dontSendWelcomeMessage().setHost("localhost"); +// publisher.publish("scene/init", scene.toByteArray()); + logger.fatal("Skipping publishing to scene/init for now"); + + root.ragconnectCheckIncremental(); + root.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS); + +// model.connectScene("mqtt://localhost/scene/update"); + model.connectLogicalSceneAsNtaToken("mqtt://localhost/logical/scene/update", true); + } + + @SuppressWarnings("unused") + private static void testBuildModelA() { + WorldModelA model = new WorldModelA(); + + // scene + var scene = new Scene(); + model.setScene(scene); + scene.addMovableObject(MovableObject.of("obj1", Position.of(1, 2, 3))); + scene.addDropOffLocation(DropOffLocation.of("placeAlfa", + Position.of(0, 0, 0), + Orientation.of(0, 0, 0, 1), + Size.of(1, 1, 1))); + scene.addDropOffLocation(DropOffLocation.of("placeBeta", + Position.of(1, 1, 1), + Orientation.of(0, 0, 0, 1), + Size.of(1, 1, 1))); + scene.addDropOffLocation(DropOffLocation.of("placeGamma", + Position.of(2, 2, 2), + Orientation.of(0, 0, 0, 1), + Size.of(2, 2, 2))); + logger.info("obj1 at gamma: {}", + scene.getMovableObject(0).isLocatedAt(scene.getDropOffLocation(2))); + + // check logical scene + var logicalScene = scene.getLogicalScene(); + logger.info("logicalScene:\n{}", logicalScene.prettyPrint()); + } + + @SuppressWarnings("unused") + private static void testLocatedAt() { + Rotation r = new Rotation(0, 0, 1, 0, false); + Vector3D v = new Vector3D(1, 2, 3); + r.applyTo(v); + + var modelA = new WorldModelA(); + var sceneA = new Scene(); + modelA.setScene(sceneA); + + // rotate bin2 by 90°, so width and height should effectively be swapped afterwards + Vector3D start = new Vector3D(1, 0, 0); + Vector3D end = new Vector3D(0, 0, 1); + Rotation rot = new Rotation(start, end); + + DropOffLocation bin1 = DropOffLocation.of("Bin1", + Position.of(1, 1, 1), + Orientation.of(0, 0, 0, 1), + Size.of(2, 3, 4)); + DropOffLocation bin2 = DropOffLocation.of("Bin2", + Position.of(1, 1, 1), + Orientation.of((float) rot.getQ1(), (float) rot.getQ2(), (float) rot.getQ3(), (float) rot.getQ0()), + Size.of(2, 3, 4)); + MovableObject objectA = MovableObject.of("ObjectA", + Position.of(0, 0, 0)); + MovableObject objectB = MovableObject.of("ObjectB", + Position.of(1, 1, 1)); + sceneA.addDropOffLocation(bin1) + .addMovableObject(objectA) + .addMovableObject(objectB); + + /* + 0.0 <= x <= 2.0 + -0.5 <= y <= 2.5 + -1.0 <= z <= 3.0 + */ + + logger.info("ObjectA locatedAt Bin1: {}", objectA.isLocatedAt(bin1)); + logger.info("ObjectB locatedAt Bin1: {}", objectB.isLocatedAt(bin1)); + logger.info("ObjectA locatedAt Bin2: {}", objectA.isLocatedAt(bin2)); + logger.info("ObjectB locatedAt Bin2: {}", objectB.isLocatedAt(bin2)); + Scanner scanner = new Scanner(System.in); + while (true) { + try { + System.out.print("x: "); + float x = scanner.nextFloat(); + System.out.print("y: "); + float y = scanner.nextFloat(); + System.out.print("z: "); + float z = scanner.nextFloat(); + MovableObject object = MovableObject.of("temp", Position.of(x, y, z)); + System.out.println("located at Bin2? : " + object.isLocatedAt(bin2)); + } catch (Exception e) { + break; + } + } + } +} diff --git a/ros3rag.old.a/src/main/java/de/tudresden/inf/st/old/a/OldUtilA.java b/ros3rag.old.a/src/main/java/de/tudresden/inf/st/old/a/OldUtilA.java new file mode 100644 index 0000000000000000000000000000000000000000..1da9db4beb5104e3f9178a72e61349f293dedb5b --- /dev/null +++ b/ros3rag.old.a/src/main/java/de/tudresden/inf/st/old/a/OldUtilA.java @@ -0,0 +1,84 @@ +package de.tudresden.inf.st.old.a; + +import de.tudresden.inf.st.old.a.ast.*; +import de.tudresden.inf.st.ros3rag.common.RegionConfiguration; +import de.tudresden.inf.st.ros3rag.common.RegionConfiguration.RegionDefinition; +import de.tudresden.inf.st.ros3rag.common.Util; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.nio.file.Path; + +/** + * Static utility methods used only for place A. + * + * @author rschoene - Initial contribution + */ +public class OldUtilA { + private static final Logger logger = LogManager.getLogger(OldUtilA.class); + + static Path pathToDirectoryOfPlaceA() { + return Util.pathToModuleDirectory("ros3rag.old.a"); + } + + static Scene convert(de.tudresden.inf.st.ceti.Scene scene) throws Exception { + return new ExposingASTNode().exposed_apply_ConvertScene(scene); + } + + static void setRegions(WorldModelA model, RegionConfiguration config) { + JastAddList<Region> result = new JastAddList<>(); + for (RegionDefinition def : config.regions) { + Region region = new Region(); + region.setName(def.name); + region.setLocationNames(String.join(",", def.positions)); + result.add(region); + } + model.setRegionList(result); + } + + static void updatePositionOfObjectToLocation(Scene scene, String objName, String locationName) { + ObjectOfInterest obj = scene.resolveObjectOfInterest(objName); + ObjectOfInterest location = scene.resolveObjectOfInterest(locationName); + if (obj != null && location != null) { + // move objectRed1 to binBlue + logger.info("Got " + obj + " and location " + location); + logger.debug("before to {} at {}\n{}", locationName, location.getPosition(), + scene.prettyPrint()); + + obj.setPosition(Position.of(location.getPosition().getX(), + location.getPosition().getY(), + location.getPosition().getZ())); + + logger.debug("after\n{}", scene.prettyPrint()); + } else { + logger.error("Obj (" + obj + ") or location (" + location + ") are null"); + } + } + + public static String getModelInfos(WorldModelA model, boolean detailed) { + StringBuilder sb = new StringBuilder(); + if (detailed) { + // also include "normal" scene + sb.append("myScene:"); + if (model.hasScene()) { + sb.append("\n").append(model.getScene().prettyPrint()); + } else { + sb.append(" (unset)\n"); + } + } + sb.append("myLogicalScene:"); + if (model.hasScene()) { + sb.append("\n").append(model.getScene().getLogicalScene().prettyPrint()); + } else { + sb.append(" (unset)\n"); + } + return sb.toString(); + } + + @SuppressWarnings("rawtypes") + static class ExposingASTNode extends ASTNode { + public Scene exposed_apply_ConvertScene(de.tudresden.inf.st.ceti.Scene pbScene) throws Exception { + return _apply_ConvertScene(pbScene); + } + } +} diff --git a/ros3rag.old.a/src/main/resources b/ros3rag.old.a/src/main/resources new file mode 120000 index 0000000000000000000000000000000000000000..8fd64e88271c6953242ad5f5ff2666ff332882ce --- /dev/null +++ b/ros3rag.old.a/src/main/resources @@ -0,0 +1 @@ +../../../ros3rag.placeA/src/main/resources \ No newline at end of file diff --git a/ros3rag.old.b/.gitignore b/ros3rag.old.b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..3447a4e17f56acc57a97d96cfec3bd43d90a05d9 --- /dev/null +++ b/ros3rag.old.b/.gitignore @@ -0,0 +1,6 @@ +build +src/gen-res/ +src/gen/ +out/ +*.class +images/ diff --git a/ros3rag.old.b/build.gradle b/ros3rag.old.b/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..516dbc7c7a4883a17d7a2bd3ca62afa4f97e1e59 --- /dev/null +++ b/ros3rag.old.b/build.gradle @@ -0,0 +1,36 @@ +buildscript { + repositories.mavenLocal() + repositories.mavenCentral() + dependencies { + classpath group: 'org.jastadd', name: 'jastaddgradle', version: "${jastadd_gradle_version}" + } +} + +plugins { + id 'ros3rag.java-application-conventions' + id 'ros3rag.java-old-ragconnect-conventions' +} + +mainClassName = 'de.tudresden.inf.st.old.b.OldMainB' + +task simpleRun(type: JavaExec) { + group 'application' + classpath sourceSets.main.runtimeClasspath + main = "de.tudresden.inf.st.old.b.OldSimpleMainB" + standardInput = System.in +} + +dependencies { + implementation project(':ros3rag.common') + testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: "${jupiter_version}" +} + +ext.sharedJastAddDir = 'src/main/jastadd/old-shared' +ext.ragConnectInputGrammar = 'src/main/jastadd/OldWorldModelB.relast' +ext.ragConnectInputConnect = 'src/main/jastadd/OldWorldModelB.connect' +ext.ragConnectRootNode = 'ArtificialRoot' +ext.relastFiles = ["src/gen/jastadd/merged.relast", "src/main/jastadd/BFS/BFS.relast", "src/main/jastadd/OldRobotReachabilityToBFS.relast", "src/gen/jastadd/RagConnect.relast"] +ext.jastaddAstPackage = 'de.tudresden.inf.st.old.b.ast' +ext.useOldRagConnect = true + +apply from: '../ros3rag.common/src/main/resources/tasks.gradle' diff --git a/ros3rag.old.b/src/main/jastadd/Additional.jadd b/ros3rag.old.b/src/main/jastadd/Additional.jadd new file mode 100644 index 0000000000000000000000000000000000000000..a8d2e113e9c1632a841cbc836520336a99bd6312 --- /dev/null +++ b/ros3rag.old.b/src/main/jastadd/Additional.jadd @@ -0,0 +1,44 @@ +aspect NewComputationNeededForOldRagConnect { + syn nta Opt<Scene> WorldModelB.getMySceneOpt() { + if (getMySceneAsProtobuf() == null) { + return new Opt<Scene>(); + } else { + try { + return new Opt<Scene>(ASTNode._apply_ConvertScene(getMySceneAsProtobuf())); + } catch (Exception e) { + e.printStackTrace(); + return new Opt<Scene>(); + } + } + } + + syn nta JastAddList<LogicalScene> WorldModelB.getOtherSceneList() { + if (getOtherSceneAsJson().equals("")) { + return new JastAddList<LogicalScene>(); + } else { + try { + com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper(); + com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory(); + com.fasterxml.jackson.core.JsonParser parser = factory.createParser(getOtherSceneAsJson()); + LogicalScene logicalScene = LogicalScene.deserialize((com.fasterxml.jackson.databind.JsonNode)mapper.readTree(parser)); + parser.close(); + return new JastAddList<LogicalScene>().addChild(logicalScene); + } catch (IOException | DeserializationException e) { + e.printStackTrace(); + return new JastAddList<LogicalScene>(); + } + } + } + + syn de.tudresden.inf.st.ceti.Command WorldModelB.getNextOperationAsNtaToken() { + return getNextOperation().toCommand(); + } + + refine JsonToModel public static WorldModelB WorldModelB.deserialize(com.fasterxml.jackson.databind.JsonNode node) throws DeserializationException { + throw new DeserializationException("Unable to deserialize child node of type \"WorldModelB\""); + } + + refine ModelToJson public void WorldModelB.serialize(com.fasterxml.jackson.core.JsonGenerator g, String fieldName) throws SerializationException { + throw new SerializationException("unable to serialize WorldModelB"); + } +} diff --git a/ros3rag.old.b/src/main/jastadd/BFS/BFS.jrag b/ros3rag.old.b/src/main/jastadd/BFS/BFS.jrag new file mode 100644 index 0000000000000000000000000000000000000000..9112eee1dbe640ba6773d56627a8b1d63842dcf0 --- /dev/null +++ b/ros3rag.old.b/src/main/jastadd/BFS/BFS.jrag @@ -0,0 +1,68 @@ +import java.util.*; + +aspect BFS { + //--- BFS --- + syn List<Edge> Vertex.BFS(Vertex goal) { + Map<Vertex, Edge> pred = new HashMap<>(); + Queue<Vertex> Q = new LinkedList<>(); + Set<Vertex> seen = new HashSet<>(); + seen.add(this); + Q.add(this); + while (!Q.isEmpty()) { + Vertex v = Q.remove(); + if (v.equals(goal)) { + return reconstructFrom(goal, pred); + } + for (Edge e : v.getOutgoingList()) { + Vertex w = e.getTo(); + if (seen.contains(w)) { + continue; + } + seen.add(w); + pred.put(w, e); + Q.add(w); + } + for (Edge e : v.getIncomingList()) { + if (!e.getBidirectional()) { continue; } + Vertex w = e.getFrom(); + if (seen.contains(w)) { + continue; + } + seen.add(w); + pred.put(w, e); + Q.add(w); + } + } + // failure + return null; + } + + //--- reconstructFrom --- + private List<Edge> Vertex.reconstructFrom(Vertex goal, Map<Vertex, Edge> pred) { + // used at the end of BFS to back-track path from goal to start + List<Edge> result = new ArrayList<>(); + Vertex current = goal; + while (!current.equals(this)) { + Edge e = pred.get(current); + result.add(e); + current = e.getFrom().equals(current) ? e.getTo() : e.getFrom(); + } +// result.add(this); + Collections.reverse(result); + return result; + } + + //--- prettyPrint --- + public String Graph.prettyPrint() { + StringJoiner sj = new StringJoiner(", ", "Graph {\n", "\n}"); + if (!hasVertex()) { sj.add("<no vertices>"); } + for (Vertex v : getVertexList()) { sj.add(v.toString()); } + sj.add("\n"); + if (!hasEdge()) { sj.add("<no edges>"); } + for (Edge e : getEdgeList()) { sj.add(e.prettyPrint()); } + return sj.toString(); + } + public String Edge.prettyPrint() { + return this.toString() + " : " + getFrom() + (getBidirectional() ? " <-> " : " -> ") + getTo(); + } +} diff --git a/ros3rag.old.b/src/main/jastadd/BFS/BFS.relast b/ros3rag.old.b/src/main/jastadd/BFS/BFS.relast new file mode 100644 index 0000000000000000000000000000000000000000..c3931ad536b40be9d04dfe733a542e8f56360c37 --- /dev/null +++ b/ros3rag.old.b/src/main/jastadd/BFS/BFS.relast @@ -0,0 +1,5 @@ +Graph ::= Vertex* Edge* ; +Vertex ; +Edge ::= <Bidirectional:boolean> ; +rel Edge.From <-> Vertex.Outgoing* ; +rel Edge.To <-> Vertex.Incoming* ; diff --git a/ros3rag.old.b/src/main/jastadd/OldRobotReachabilityToBFS.jrag b/ros3rag.old.b/src/main/jastadd/OldRobotReachabilityToBFS.jrag new file mode 100644 index 0000000000000000000000000000000000000000..5ec92e5420a08745c4b8807fdab063cc073fea7c --- /dev/null +++ b/ros3rag.old.b/src/main/jastadd/OldRobotReachabilityToBFS.jrag @@ -0,0 +1,91 @@ +aspect RobotReachabilityToBFS { + //--- toReachabilityGraph --- + syn nta Graph WorldModelB.toReachabilityGraph() { + Graph result = new Graph(); + if (!hasMyScene()) { + return result; + } + Map<ObjectOfInterest, Vertex> mapping = new HashMap<>(); + // TODO insert vertices for objects, if they are contained in a location. or remove objects altogether? + for (DropOffLocation loc : getMyScene().getDropOffLocationList()) { + VertexWithObjectOfInterest vertex = new VertexWithObjectOfInterest(); + vertex.setNameOfObjectOfInterest(loc.getName()); + result.addVertex(vertex); + mapping.put(loc, vertex); + } +// for (LogicalMovableObject obj : getMyScene().getLogicalScene().getLogicalMovableObjectList()) { +// Vertex vertex = new Vertex(); +// vertex.setObjectOfInterest(obj); +// result.addVertex(vertex); +// mapping.put(obj, vertex); +// } + for (Robot robot : getRobotList()) { + if (robot.isBusy()) { + continue; + } + List<DropOffLocation> reachableLocations = robot.reachableObjects().stream() + .filter(Objects::nonNull) + .filter(ObjectOfInterest::isDropOffLocation) + .map(ObjectOfInterest::asDropOffLocation) + .collect(java.util.stream.Collectors.toList()); + // bidirectional edges between locations by default + // unidirectional edges from all occupied locations to free locations + // no edge if both locations are occupied + for (DropOffLocation loc : reachableLocations) { + for (DropOffLocation other : reachableLocations) { + if (loc == other) { continue; } + if (loc.getObjectLocatedHere() != null && other.getObjectLocatedHere() != null) { continue; } + EdgeWithRobot edge = new EdgeWithRobot(); + edge.setNameOfRobot(robot.getName()); + edge.setBidirectional(loc.getObjectLocatedHere() == null); + edge.setFrom(mapping.get(loc)); + edge.setTo(mapping.get(other)); + result.addEdge(edge); + } + } + } + return result; + } + + //--- correspondingVertex --- + syn Optional<Vertex> LogicalObjectOfInterest.correspondingVertex() = worldModelB().correspondingVertex(this.getName()); + syn Optional<Vertex> ObjectOfInterest.correspondingVertex() = worldModelB().correspondingVertex(this.getName()); + syn Optional<Vertex> WorldModelB.correspondingVertex(String name) { + if (!hasMyScene()) { + return Optional.empty(); + } + for (Vertex v : toReachabilityGraph().getVertexList()) { + if (v.isVertexWithObjectOfInterest() && v.asVertexWithObjectOfInterest().getNameOfObjectOfInterest().equals(name)) { + return Optional.of(v); + } + } + return Optional.empty(); + } +} + +aspect Printing { + public String VertexWithObjectOfInterest.toString() { + return "V(" + getNameOfObjectOfInterest() + ")"; + } + public String EdgeWithRobot.toString() { + return "E[" + getNameOfRobot() + "]"; + } +} + +aspect Navigation { + // --- isVertexWithObjectOfInterest --- + syn boolean Vertex.isVertexWithObjectOfInterest() = false; + eq VertexWithObjectOfInterest.isVertexWithObjectOfInterest() = true; + + // --- asVertexWithObjectOfInterest --- + syn VertexWithObjectOfInterest Vertex.asVertexWithObjectOfInterest() = null; + eq VertexWithObjectOfInterest.asVertexWithObjectOfInterest() = this; + + // --- isEdgeWithRobot --- + syn boolean Edge.isEdgeWithRobot() = false; + eq EdgeWithRobot.isEdgeWithRobot() = true; + + // --- asEdgeWithRobot --- + syn EdgeWithRobot Edge.asEdgeWithRobot() = null; + eq EdgeWithRobot.asEdgeWithRobot() = this; +} diff --git a/ros3rag.old.b/src/main/jastadd/OldRobotReachabilityToBFS.relast b/ros3rag.old.b/src/main/jastadd/OldRobotReachabilityToBFS.relast new file mode 100644 index 0000000000000000000000000000000000000000..96a4b0cdda9cfda9d2e79037853f6e537a510126 --- /dev/null +++ b/ros3rag.old.b/src/main/jastadd/OldRobotReachabilityToBFS.relast @@ -0,0 +1,4 @@ +//rel Vertex.ObjectOfInterest -> ObjectOfInterest ; +VertexWithObjectOfInterest : Vertex ::= <NameOfObjectOfInterest> ; +//rel Edge.Robot -> Robot ; +EdgeWithRobot : Edge ::= <NameOfRobot> ; diff --git a/ros3rag.old.b/src/main/jastadd/OldWorldModelB.connect b/ros3rag.old.b/src/main/jastadd/OldWorldModelB.connect new file mode 100644 index 0000000000000000000000000000000000000000..165fa1a5d2a1ec717882bf8d3d0c7977a5d58f56 --- /dev/null +++ b/ros3rag.old.b/src/main/jastadd/OldWorldModelB.connect @@ -0,0 +1,189 @@ +// --- receiving --- +receive WorldModelB.MySceneAsProtobuf using ParseScene ; +receive WorldModelB.OtherSceneAsJson ; +//ONLY-IN-NEW receive Robot.CanReachObjectOfInterest using ParseReachability, ConvertReachability ; +receive Robot.OwnedCollaborationZoneNames using ConfigChangeCommandCheckForOwnedCollaborationZone ; +receive Robot.OccupiedCollaborationZoneNames using CommandCheckForOccupiedCollaborationZone ; +receive Robot.CurrentPosition ; +//ONLY-IN-NEW receive indexed with add WorldModelB.ExecutedOperation using ParseCommand, ConvertCommand ; + +ParseReachability maps byte[] bytes to de.tudresden.inf.st.ceti.Reachability {: + return de.tudresden.inf.st.ceti.Reachability.parseFrom(bytes); +:} + +ConvertReachability maps de.tudresden.inf.st.ceti.Reachability r to JastAddList<CanReachObjectOfInterest> {: + var result = new JastAddList<CanReachObjectOfInterest>(); + for (var objReach : r.getObjectsList()) { + if (objReach.getReachable()) { + result.addChild(new CanReachObjectOfInterest().setObjectName(objReach.getIdObject())); + } + } + return result; +:} + +ParseCommand maps byte[] bytes to de.tudresden.inf.st.ceti.Command {: + return de.tudresden.inf.st.ceti.Command.parseFrom(bytes); +:} + +ConvertCommand maps de.tudresden.inf.st.ceti.Command command to Operation {: + WorldModelB model = singletonWorldModelB; + if (command.hasPickAndPlace()) { + return new PickAndPlace() + .setObjectToPick(model.getMyScene().getLogicalScene().resolveLogicalObjectOfInterest(command.getPickAndPlace().getIdPick()).asLogicalMovableObject()) + .setTargetLocation(model.getMyScene().resolveObjectOfInterest(command.getPickAndPlace().getIdPlace()).asDropOffLocation()) + .setRobotToExecute(model.findRobot(command.getPickAndPlace().getIdRobot()).get()); + } else if (command.hasConfigChange()) { + return new ConfigChange() + .setCollaborationZone(model.getMyScene().resolveObjectOfInterest(command.getConfigChange().getIdCollaborationZone()).asDropOffLocation().asCollaborationZone()) + .setRobotToExecute(model.findRobot(command.getConfigChange().getIdRobotNewOwner()).get()); + } else if (command.hasEvacuate()) { + return new Evacuate() + .setCollaborationZone(model.getMyScene().resolveObjectOfInterest(command.getEvacuate().getIdCollaborationZone()).asDropOffLocation().asCollaborationZone()) + .setRobotToExecute(model.findRobot(command.getEvacuate().getIdRobot()).get()); + } + return new ErrorOperation().setErrorMessage("Could not parse operation " + command); +:} + +// --- sending --- +send WorldModelB.NextOperationAsNtaToken using PrintCommand ; +// (direct manipulation is dangerous) send WorldModelB.NextOperation using PrintAndRememberOperation ; +send Robot.MyPosition ; +// (direct manipulation is dangerous) send Robot.myPosition(String) using ImmediateUpdate ; + +PrintCommand maps de.tudresden.inf.st.ceti.Command cmd to byte[] {: + if (cmd == null) { + // here we accept, that cmd can be null (it will print an exception in the log, but no message will be sent) + reject(); + } + return cmd.toByteArray(); +:} + +// (direct manipulation is dangerous) +//PrintAndRememberOperation maps Operation op to byte[] {: +// byte[] result = op.toProtobufByteArray(); +// if (result == null) { +// reject(); +// } +// ((WorldModelB) this).addExecutedOperation(op); +// return result; +//:} +// +// (direct manipulation is dangerous) +//ImmediateUpdate maps String pos to String {: +// Robot robot = (Robot) this; +// robot.setCurrentPosition(pos); +// return pos; +//:} + +ConfigChangeCommandCheckForOwnedCollaborationZone maps byte[] bytes to String {: + de.tudresden.inf.st.ceti.Command command = null; + try { + command = de.tudresden.inf.st.ceti.Command.parseFrom(bytes); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + reject(); + } + // if the command is not a ConfigChange command, do not change anything + if (!command.hasConfigChange()) { + reject(); + } +// System.out.println(command); + de.tudresden.inf.st.ceti.ConfigChange cc = command.getConfigChange(); + Scene scene = singletonWorldModelB.getMyScene(); + ObjectOfInterest obj = scene.resolveObjectOfInterest(cc.getIdCollaborationZone()); + DropOffLocation loc = obj.asDropOffLocation(); + CollaborationZone cz = loc.asCollaborationZone(); + Robot thisRobot = hackTemporaryRobot; + 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 + collaborationZoneNames.add(cc.getIdCollaborationZone()); + } else if (!robotIsNewOwner && collaborationZoneAlreadyOwned) { + // config change is for another robot, remove collaboration zone + collaborationZoneNames.remove(cc.getIdCollaborationZone()); + } else { + // otherwise don't change + reject(); + } + return String.join(",", collaborationZoneNames); +:} + +CommandCheckForOccupiedCollaborationZone maps byte[] bytes to String {: + de.tudresden.inf.st.ceti.Command command = null; + try { + command = de.tudresden.inf.st.ceti.Command.parseFrom(bytes); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + reject(); + } + // if the command is not the correct command type, do not change anything + if (!command.hasPickAndPlace() && !command.hasEvacuate()) { + reject(); + } +// System.out.println(command); + + Scene scene = singletonWorldModelB.getMyScene(); + Robot thisRobot = hackTemporaryRobot; + +// // get current value, but remove every "moving out" zone +// List<String> occupiedZoneNames = thisRobot.occupiedCollaborationZonesAsList().stream() +// .filter(!zone -> zone.startsWith("(^)")) +// .collect(java.util.stream.Collectors.toList()); + + // with a new command, begin with a clean occ list + List<String> occupiedZoneNames = new java.util.ArrayList<>(); + + // (>) == moving in, (^) == evacuate/moving out + boolean updated = false; + if (command.hasPickAndPlace()) { + de.tudresden.inf.st.ceti.PickAndPlace pp = command.getPickAndPlace(); + + // if the command is not executed by this robot, do not change anything + if (!thisRobot.getName().equals(pp.getIdRobot())) { + reject(); + } + + // if target is collaboration zone + ObjectOfInterest obj = scene.resolveObjectOfInterest(pp.getIdPlace()); + DropOffLocation loc = obj.asDropOffLocation(); + if (loc.isCollaborationZone()) { + String specialIncomingName = "(>)" + loc.getName(); + if (!occupiedZoneNames.contains(specialIncomingName)) { + occupiedZoneNames.add(specialIncomingName); + updated = true; + } + } + // if object is located at collaboration zone + LogicalObjectOfInterest logicalObj = scene.getLogicalScene().resolveLogicalObjectOfInterest(pp.getIdPick()); + LogicalMovableObject toBePicked = logicalObj.asLogicalMovableObject(); + DropOffLocation sourceLocation = toBePicked.myLocation(); + if (sourceLocation != null && sourceLocation.isCollaborationZone()) { + String specialIncomingName = "(^)" + sourceLocation.getName(); + if (!occupiedZoneNames.contains(specialIncomingName)) { + occupiedZoneNames.add(specialIncomingName); + updated = true; + } + } + } else if (command.hasEvacuate()) { + de.tudresden.inf.st.ceti.Evacuate ev = command.getEvacuate(); + + // if the command is not executed by this robot, do not change anything + if (!thisRobot.getName().equals(ev.getIdRobot())) { + reject(); + } + ObjectOfInterest obj = scene.resolveObjectOfInterest(ev.getIdCollaborationZone()); + DropOffLocation loc = obj.asDropOffLocation(); + if (loc.isCollaborationZone()) { + CollaborationZone cz = loc.asCollaborationZone(); + String specialEvacuateName = "(^)" + cz.getName(); + if (!occupiedZoneNames.contains(specialEvacuateName)) { + occupiedZoneNames.add(specialEvacuateName); + updated = true; + } + } + } + if (!updated) { + reject(); + } + return String.join(",", occupiedZoneNames); +:} diff --git a/ros3rag.old.b/src/main/jastadd/OldWorldModelB.jadd b/ros3rag.old.b/src/main/jastadd/OldWorldModelB.jadd new file mode 100644 index 0000000000000000000000000000000000000000..fc133eb15804137beaed2b9a11749a4dc6507866 --- /dev/null +++ b/ros3rag.old.b/src/main/jastadd/OldWorldModelB.jadd @@ -0,0 +1,647 @@ +aspect Computation { + static boolean ASTNode.VERBOSE = false; + + //--- unspecifiedRegion --- + syn nta LogicalRegion WorldModelB.unspecifiedRegion() = new LogicalRegion().setName("<unspecified>"); + + //--- mergedOtherScene --- + syn nta LogicalScene WorldModelB.mergedOtherScene() { + // return empty scene, if there are no other scenes (yet) + if (!hasOtherScene()) { + return new LogicalScene(); + } + // return scene, if there is exactly one. (TODO: check if copy is needed here) + if (getNumOtherScene() == 1) { + return getOtherScene(0); + } + var result = new LogicalScene(); + // use getOtherSceneList() and merge by name all regions, objects and relations into one new, unified scene + Map<String, LogicalRegion> mergedRegions = new HashMap<>(); + Map<String, LogicalMovableObject> mergedObjects = new HashMap<>(); + // first create all regions + for (LogicalScene scene : getOtherSceneList()) { + for (LogicalRegion region : scene.getLogicalRegionList()) { + if (!mergedRegions.containsKey(region.getName())) { + LogicalRegion copyOfRegion = new LogicalRegion(); + copyOfRegion.setName(region.getName()); + mergedRegions.put(region.getName(), copyOfRegion); + result.addLogicalRegion(copyOfRegion); + } + } + } + // then create all objects, and set LocatedAt relation (checking for possible conflicts) + for (LogicalScene scene : getOtherSceneList()) { + for (LogicalMovableObject obj : scene.getLogicalMovableObjectList()) { + if (mergedObjects.containsKey(obj.getName())) { + // object already known + LogicalMovableObject knownObj = mergedObjects.get(obj.getName()); + for (LogicalRegion region : obj.getLocatedAtList()) { + LogicalRegion knownRegionOfObj = mergedRegions.get(region.getName()); + if (!knownObj.getLocatedAtList().contains(knownRegionOfObj)) { + // obj has region that is not yet add to knownObj + knownObj.addLocatedAt(knownRegionOfObj); + } + } + } else { + // object not known, needs to be created + LogicalMovableObject newObj = new LogicalMovableObject(); + newObj.setName(obj.getName()); + for (LogicalRegion region : obj.getLocatedAtList()) { + newObj.addLocatedAt(mergedRegions.get(region.getName())); + } + mergedObjects.put(obj.getName(), newObj); + result.addLogicalMovableObject(newObj); + } + } + } + return result; + } + + //--- diffScenes --- + syn nta JastAddList<Difference> WorldModelB.diffScenes() { + var result = new JastAddList<Difference>(); + if (!hasMyScene() || !hasOtherScene()) { + // without my and at least one other scene, there are no differences + return result; + } + var myLogicalScene = getMyScene().getLogicalScene(); + for (LogicalMovableObject otherObject : mergedOtherScene().getLogicalMovableObjectList()) { + LogicalObjectOfInterest myGenericObject = myLogicalScene.resolveLogicalObjectOfInterest(otherObject.getName()); + if (myGenericObject == null) { + // new object, currently not handled + var diff = new DifferenceNewObject(); + diff.setObject(otherObject); + result.add(diff); + continue; + } + if (!myGenericObject.isLogicalMovableObject()) { + if (VERBOSE) { + System.err.println("MovableObject " + otherObject.getName() + " is not a MovableObject in myScene. Skipping!"); + } + continue; + } + LogicalMovableObject myObject = myGenericObject.asLogicalMovableObject(); + if (myObject.hasLocatedAt() && !otherObject.hasLocatedAt()) { + if (myObject.getLocatedAtList().size() > 1) { + if (VERBOSE) { + System.err.println("More than one region found for my " + myObject.getName() + ", using only first."); + } + } + var diff = new DifferenceObjectMisplaced(); + diff.setObject(myObject); + // use first region + diff.setPreviousRegion(myObject.getLocatedAtList().get(0)); + result.add(diff); + continue; + } + if (myObject.getLocatedAtList().size() > 1) { + if (VERBOSE) { + System.err.println("More than one region found for my " + myObject.getName() + ", using only first."); + } + } + if (otherObject.getLocatedAtList().size() > 1) { + if (VERBOSE) { + System.err.println("More than one region found for other " + otherObject.getName() + ", using only first."); + } + } + Set<String> myRegions = myObject.regionNameSet(); + Set<String> otherRegions = otherObject.regionNameSet(); + if (!myObject.hasLocatedAt() && !otherObject.hasLocatedAt() || + (myObject.hasLocatedAt() && otherObject.hasLocatedAt() && + myRegions.equals(otherRegions))) { + // no diff if: otherObject has no region information, or if both objects are located at same region(s) + // otherObject is always non-null, so this case does not need to be treated + continue; + } + var difference = new DifferenceObjectAtWrongPlace(); + difference.setObject(myObject); + if (myObject.hasLocatedAt()) { + difference.setPreviousRegion(myObject.getLocatedAtList().get(0)); + } + difference.setNewRegion(otherObject.getLocatedAtList().get(0)); + result.add(difference); + } + return result; + } + + //--- diffToOperations --- + syn nta JastAddList<Operation> WorldModelB.diffToOperations() { + var result = new JastAddList<Operation>(); + for (Difference difference : diffScenes()) { + for (Operation operation : difference.computeOperations()) { + result.add(operation); + } + } + return result; + } + + //--- computeOperations --- + syn List<Operation> Difference.computeOperations(); + eq DifferenceObjectAtWrongPlace.computeOperations() { + // need to use position of object and pick one from new region + + DropOffLocation previousLocation = getObject().myLocation(); + if (previousLocation == null) { + return error("No previous location"); + } + // (workaround) check if WorldModelB is not null ... could happen if scene has no parent + try { + previousLocation.correspondingVertex(); + } catch (NullPointerException e) { + return error("Could not resolve WorldModelB linked to previousLocation " + previousLocation.nameAndHash()); + } + return previousLocation.correspondingVertex().map(previousVertex -> { + Region region = getNewRegion().realRegion(); + if (region == null) { + return error("No region found for " + getNewRegion().nameAndHash()); + } + // pick location from newRegion, that is free + 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()) { + return error("No sequence of operations to move " + getObject().getName() + (hasPreviousRegion() ? " from " + getPreviousRegion().getName() : "") + " to " + getNewRegion().getName()); + } + List<Operation> result = new ArrayList<>(); + Vertex transit = previousVertex; + for (Edge edge : shortestPath) { + Vertex target = edge.getFrom().equals(transit) ? edge.getTo() : edge.getFrom(); + DropOffLocation sourceLocation = worldModelB().getMyScene().resolveObjectOfInterest(previousVertex.asVertexWithObjectOfInterest().getNameOfObjectOfInterest()).asDropOffLocation(); + DropOffLocation targetLocation = worldModelB().getMyScene().resolveObjectOfInterest(target.asVertexWithObjectOfInterest().getNameOfObjectOfInterest()).asDropOffLocation(); +// Robot executingRobot = worldModelB().findRobot(edge.asEdgeWithRobot().getNameOfRobot()); + worldModelB().findRobot(edge.asEdgeWithRobot().getNameOfRobot()).ifPresentOrElse(executingRobot -> { + /* for both locations, in case it is a collaboration zone, we need to ensure the following: + (a) claimed by the executing robot, and + (b) not occupied by another robot, and + (c) free (as no movable object is contained) -- this should be reflected in the graph! + */ + if (sourceLocation.isCollaborationZone()) { + CollaborationZone cz = sourceLocation.asCollaborationZone(); + if (VERBOSE) { + System.out.println("source is cz, occ:" + (cz.hasOccupient() ? cz.occupient().nameAndHash() : "none") + ", owner: " + (cz.hasOwner() ? cz.owner().nameAndHash() : "none")); + } + // order is important here, first add Evacuate, then ConfigChange + if (cz.hasOccupient() && !cz.occupient().equals(executingRobot)) { + if (cz.occupient().isBusy()) { + result.add(Wait.of()); + } else { + result.add(Evacuate.of(cz.occupient(), cz)); + } + } + if (!cz.hasOwner() || (cz.hasOwner() && !cz.owner().equals(executingRobot))) { + if (cz.hasOccupient() && (!cz.occupient().equals(executingRobot) || cz.occupient().isBusy())) { + result.add(Wait.of()); + } else { + result.add(ConfigChange.of(executingRobot, cz)); + } + } + } + if (targetLocation.isCollaborationZone()) { + CollaborationZone cz = targetLocation.asCollaborationZone(); + if (VERBOSE) { + System.out.println("target is cz, occ:" + (cz.hasOccupient() ? cz.occupient().nameAndHash() : "none") + ", owner: " + (cz.hasOwner() ? cz.owner().nameAndHash() : "none")); + } + // order is important here, first add Evacuate, then ConfigChange + if (cz.hasOccupient() && !cz.occupient().equals(executingRobot)) { + if (cz.occupient().isBusy()) { + result.add(Wait.of()); + } else { + result.add(Evacuate.of(cz.occupient(), cz)); + } + } + if (!cz.hasOwner() || (cz.hasOwner() && !cz.owner().equals(executingRobot))) { + if (cz.hasOccupient() && (!cz.occupient().equals(executingRobot) || cz.occupient().isBusy())) { + result.add(Wait.of()); + } else { + result.add(ConfigChange.of(executingRobot, cz)); + } + } + } + result.add(PickAndPlace.of(executingRobot, getObject(), targetLocation)); + }, () -> result.add(new ErrorOperation().setErrorMessage("Could not find robot with name " + edge.asEdgeWithRobot().getNameOfRobot()))); + transit = target; + } + return result; + }).orElseGet(() -> error("Could not resolve graph vertex of new region " + getNewRegion().nameAndHash())); + }).orElseGet(() -> error("Could not find a free location in " + getNewRegion().nameAndHash() + " for " + getObject().nameAndHash())); + }).orElseGet(() -> error("Could not resolve graph vertex of previous location " + previousLocation.nameAndHash())); + } + eq DifferenceNewObject.computeOperations() { + // FIXME. stub, may be implemented later + return Collections.emptyList(); + } + eq DifferenceObjectMisplaced.computeOperations() { + // FIXME. stub, may be implemented later + return Collections.emptyList(); + } + + //--- error --- + protected static List<Operation> Difference.error(String message) { + return Collections.singletonList(new ErrorOperation().setErrorMessage(message)); + } + + //--- Operation.of --- + public static PickAndPlace PickAndPlace.of(Robot robot, LogicalMovableObject obj, DropOffLocation target) { + PickAndPlace result = new PickAndPlace(); + result.setRobotToExecute(robot); + result.setObjectToPick(obj); + result.setTargetLocation(target); + return result; + } + + public static ConfigChange ConfigChange.of(Robot robot, CollaborationZone cz) { + ConfigChange result = new ConfigChange(); + result.setRobotToExecute(robot); + result.setCollaborationZone(cz); + return result; + } + + public static Evacuate Evacuate.of(Robot robot, CollaborationZone cz) { + Evacuate result = new Evacuate(); + result.setRobotToExecute(robot); + result.setCollaborationZone(cz); + return result; + } + + public static Wait Wait.of() { + return new Wait(); + } + + syn Operation WorldModelB.lastOperationFor(Robot robot) { + if (robot == null) { + return null; + } + for (int index = getNumExecutedOperation() - 1; index >= 0; index--) { + Operation op = getExecutedOperation(index); + if (robot.equals(op.getRobotToExecute())) { + return op; + } + } + return null; + } + + syn nta ErrorOperation WorldModelB.errorNoOperationComputed() = new ErrorOperation().setErrorMessage("No operation computed!"); + syn nta ErrorOperation WorldModelB.errorDuplicateOperation() = new ErrorOperation().setErrorMessage("Do not send duplicate operation twice!"); + syn nta ErrorOperation WorldModelB.errorNoExecutableOperation() = new ErrorOperation().setErrorMessage("No executable operation found!"); + //--- getNextOperation --- + syn Operation WorldModelB.getNextOperation() { + if (diffToOperations().getNumChild() == 0) { + return errorNoOperationComputed(); + } + for (Operation op : diffToOperations()) { + Robot executingRobot = op.getRobotToExecute(); + if (!op.isErrorOperation()) { + if (op.equals(lastOperationFor(executingRobot))) { + return errorDuplicateOperation(); + } + return op; + } + } + return errorNoExecutableOperation(); + } + +// //--- canReach --- | TODO not used +// syn boolean Robot.canReach(String objectName) { +// for (CanReachObjectOfInterest canReachObj : getCanReachObjectOfInterestList()) { +// if (canReachObj.getObjectName().equals(objectName)) { +// return true; +// } +// } +// return false; +// } + + //--- reachableObjects --- + syn List<ObjectOfInterest> Robot.reachableObjects() { + if (!worldModelB().hasMyScene()) { + return Collections.emptyList(); + } + List<ObjectOfInterest> result = new ArrayList<>(); + for (CanReachObjectOfInterest canReachObj : getCanReachObjectOfInterestList()) { + result.add(worldModelB().getMyScene().resolveObjectOfInterest(canReachObj.getObjectName())); + } + return result; + } + + syn DropOffLocation Region.firstFreeDropOffLocation() { + for (DropOffLocation location : locationList()) { + if (location.getObjectLocatedHere() == null) { + return location; + } + } + return null; + } + + syn String Robot.getMyPosition() { + //TODO "(^)" "(>)" + RobotObject myRobotObject = myRobotObject(); + de.tudresden.inf.st.ceti.Object.State myState = myRobotObject != null ? myRobotObject.getState() : de.tudresden.inf.st.ceti.Object.State.STATE_UNKNOWN; + String pre = "eval of my pos for " + getName() + " .. current-pos: " + getCurrentPosition() + ", occ: '" + getOccupiedCollaborationZoneNames() + "', state: " + (myRobotObject != null ? myRobotObject.getState() : "null") + " -> "; + for (String zoneName : arrayAsList(getOccupiedCollaborationZoneNames())) { + if (zoneName.startsWith("(>)")) { + String targetZone = zoneName.substring(3); + // (1) + String currentTarget = getCurrentPosition().startsWith("(") ? getCurrentPosition().substring(3) : getCurrentPosition(); + if (!targetZone.equals(currentTarget) && myState == de.tudresden.inf.st.ceti.Object.State.STATE_IDLE) { + return logAndReturn(pre, "(+)" + targetZone); + } + } + // (2) // getCurrentPosition().startsWith("(+)") && + if (isStateMoving(myState)) { + return logAndReturn(pre, zoneName); + } + // (3) + if (getCurrentPosition().startsWith("(>)") && myState == de.tudresden.inf.st.ceti.Object.State.STATE_IDLE) { + return logAndReturn(pre, getCurrentPosition().substring(3)); + } + if (zoneName.startsWith("(^)")) { + String sourceZone = zoneName.substring(3); + // (4) + if (!getCurrentPosition().startsWith("(^)") && !getCurrentPosition().equals("safe") && myState == de.tudresden.inf.st.ceti.Object.State.STATE_IDLE) { + return logAndReturn(pre, "(-)" + sourceZone); + } + // (6) + if (getCurrentPosition().startsWith("(^)") && myState == de.tudresden.inf.st.ceti.Object.State.STATE_IDLE) { + return logAndReturn(pre, "safe"); + } + } + // (5) + if (getCurrentPosition().startsWith("(-)") && isStateMoving(myState)) { + return logAndReturn(pre, "(^)" + getCurrentPosition().substring(3)); + } + } + // no-op + return logAndReturn(pre, getCurrentPosition()); + } + + private String Robot.logAndReturn(String pre, String returnValue) { + if (VERBOSE) { + System.out.println(pre + returnValue); + } + return returnValue; + } + + private boolean Robot.isStateMoving(de.tudresden.inf.st.ceti.Object.State state) { + return state == de.tudresden.inf.st.ceti.Object.State.STATE_MOVING || state == de.tudresden.inf.st.ceti.Object.State.STATE_PICKING || state == de.tudresden.inf.st.ceti.Object.State.STATE_PLACING; + } +} + +aspect AttributeMappings { + //--- toCommand --- + syn de.tudresden.inf.st.ceti.Command Operation.toCommand() = null; + eq ErrorOperation.toCommand() { + if (VERBOSE) { + System.err.println(getErrorMessage()); + } + return null; + } + eq PickAndPlace.toCommand() = de.tudresden.inf.st.ceti.Command.newBuilder() + .setPickAndPlace(de.tudresden.inf.st.ceti.PickAndPlace.newBuilder() + .setIdRobot(getRobotToExecute().getName()) + .setIdPick(getObjectToPick().getName()) + .setIdPlace(getTargetLocation().getName()) + .build()) + .build(); + eq ConfigChange.toCommand() = de.tudresden.inf.st.ceti.Command.newBuilder() + .setConfigChange(de.tudresden.inf.st.ceti.ConfigChange.newBuilder() + .setIdRobotNewOwner(getRobotToExecute().getName()) + .setIdCollaborationZone(getCollaborationZone().getName()) + .build()) + .build(); + eq Evacuate.toCommand() = de.tudresden.inf.st.ceti.Command.newBuilder() + .setEvacuate(de.tudresden.inf.st.ceti.Evacuate.newBuilder() + .setIdRobot(getRobotToExecute().getName()) + .setIdCollaborationZone(getCollaborationZone().getName()) + .build()) + .build(); + eq Wait.toCommand() = null; +} + +aspect Navigation { + // --- isCollaborationZone --- + syn boolean DropOffLocation.isCollaborationZone() = false; + eq CollaborationZone.isCollaborationZone() = true; + + // --- asCollaborationZone --- + syn CollaborationZone DropOffLocation.asCollaborationZone() = null; + eq CollaborationZone.asCollaborationZone() = this; + + //--- worldModelB --- + inh WorldModelB ASTNode.worldModelB(); + eq WorldModelB.getChild().worldModelB() = this; + + syn boolean Operation.isErrorOperation() = false; + eq ErrorOperation.isErrorOperation() = true; + + syn boolean Operation.isPickAndPlace() = false; + eq PickAndPlace.isPickAndPlace() = true; + + syn boolean Operation.isConfigChange() = false; + eq ConfigChange.isConfigChange() = true; + + syn boolean Operation.isEvacuate() = false; + eq Evacuate.isEvacuate() = true; + + syn ErrorOperation Operation.asErrorOperation() = null; + eq ErrorOperation.asErrorOperation() = this; + + syn PickAndPlace Operation.asPickAndPlace() = null; + eq PickAndPlace.asPickAndPlace() = this; + + syn ConfigChange Operation.asConfigChange() = null; + eq ConfigChange.asConfigChange() = this; + + syn Evacuate Operation.asEvacuate() = null; + eq Evacuate.asEvacuate() = this; + + syn Region LogicalRegion.realRegion() { + if (hasWorldModelB()) { + return worldModelB().findRegion(getName()); + } + return new Region().setName("unknown region for " + getName()); + } + + private boolean LogicalRegion.hasWorldModelB() { + ASTNode parent = getParent(); + while (parent.getParent() != null) { + parent = parent.getParent(); + } + return parent instanceof WorldModelB; + } + + //--- allMappings --- + // inh LocationMapping LogicalDropOffLocation.allMappings(); + // eq WorldModelB.getChild().allMappings() = getLocationMapping(); + syn boolean CollaborationZone.hasOccupient() = occupient() != null; + syn Robot CollaborationZone.occupient() { + // (>) == moving in, (^) == evacuate/moving out + for (Robot robot : worldModelB().getRobotList()) { + String zoneName = robot.getCurrentPosition().startsWith("(") ? robot.getCurrentPosition().substring(3) : robot.getCurrentPosition(); + if (zoneName.equals(getName())) { + // robot is currently in this zone, or moving into or out of this zone. always regard it as occupied by it + return robot; + } + } + return null; + } + syn boolean CollaborationZone.hasOwner() = owner() != null; + syn Robot CollaborationZone.owner() { + for (Robot robot : worldModelB().getRobotList()) { + List<String> collaborationZoneNames = arrayAsList(robot.getOwnedCollaborationZoneNames()); + if (collaborationZoneNames.contains(getName())) { + return robot; + } + } + return null; + } + syn List<String> Robot.ownedCollaborationZonesAsList() = arrayAsList(getOwnedCollaborationZoneNames()); + syn List<String> Robot.occupiedCollaborationZonesAsList() = arrayAsList(getOccupiedCollaborationZoneNames()); + eq Region.locationList() { + List<DropOffLocation> result = new ArrayList<>(); + if (!worldModelB().hasMyScene()) { + return result; + } + for (String locationName : locationNamesAsList()) { + result.add(worldModelB().getMyScene().resolveObjectOfInterest(locationName).asDropOffLocation()); + } + return result; + } + + syn boolean Robot.isBusy() { + if (getCurrentPosition().startsWith("(")) { + return true; + } + RobotObject obj = myRobotObject(); + return obj != null && obj.getState() != de.tudresden.inf.st.ceti.Object.State.STATE_IDLE; + } + + syn RobotObject Robot.myRobotObject() { + ObjectOfInterest obj = worldModelB().getMyScene().resolveObjectOfInterest(getName()); + return obj != null ? obj.asRobotObject() : null; + } +} + +aspect GlueForShared { + //--- resolveLogicalObjectOfInterest --- + // uncache Difference.resolveLogicalObjectOfInterest + inh LogicalObjectOfInterest Difference.resolveLogicalObjectOfInterest(String name); + eq WorldModelB.diffScenes().resolveLogicalObjectOfInterest(String name) = getMyScene().getLogicalScene().resolveLogicalObjectOfInterest(name); + + class ArtificialRoot implements de.tudresden.inf.st.ros3rag.common.SharedMainParts.WorldModelWrapper { + } + + eq WorldModelB.getMyScene().regionList() = getRegionList(); +} + +aspect Printing { + //--- prettyPrint --- + syn String Robot.prettyPrint() = "~Robot " + nameAndHash() + "~"; + syn String Robot.nameAndHash() = getName() + "@" + Integer.toHexString(hashCode()); + + syn String Difference.prettyPrint(); + eq DifferenceObjectAtWrongPlace.prettyPrint() { + return "-DifferenceObjectAtWrongPlace of " + getObject().prettyPrint() + ": " + (hasPreviousRegion() ? getPreviousRegion().prettyPrint() : "_") + " -> " + getNewRegion().prettyPrint() + "-"; + } + eq DifferenceNewObject.prettyPrint() { + return "-DifferenceNewObject of " + getObject().prettyPrint() + "-"; + } + eq DifferenceObjectMisplaced.prettyPrint() { + return "-DifferenceObjectMisplaced of " + getObject().prettyPrint() + ": " + getPreviousRegion().prettyPrint() + "-"; + } + + syn String Operation.prettyPrint(); + eq PickAndPlace.prettyPrint() { + return "+PickAndPlace by " + getRobotToExecute().prettyPrint() + " of " + getObjectToPick().prettyPrint() + " -> " + getTargetLocation().prettyPrint() + "+"; + } + eq ErrorOperation.prettyPrint() { + return "+Error: " + getErrorMessage() + "+"; + } + eq ConfigChange.prettyPrint() { + return "+ConfigChange: " + getRobotToExecute().prettyPrint() + " owns " + getCollaborationZone().prettyPrint() + "+"; + } + eq Evacuate.prettyPrint() { + return "+Evacuate: " + getRobotToExecute().prettyPrint() + " from " + getCollaborationZone().prettyPrint() + "+"; + } + eq Wait.prettyPrint() { + return "+Wait+"; + } +} + +aspect DumpAst { + public String WorldModelB.dumpAst(java.util.function.Consumer<de.tudresden.inf.st.jastadd.dumpAst.ast.DumpBuilder> options) { + String now = java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME).replaceAll("[:\\.]", "-"); + try { + de.tudresden.inf.st.jastadd.dumpAst.ast.DumpBuilder builder = de.tudresden.inf.st.jastadd.dumpAst.ast.Dumper.read(this); + options.accept(builder); + //builder.dumpAsPNG(java.nio.file.Paths.get("images/" + now + ".png")); + java.nio.file.Path path = java.nio.file.Paths.get("images/" + now + ".svg"); + builder.dumpAsSVG(path); + return path.getFileName().toString(); + } catch (java.io.IOException e) { + e.printStackTrace(); + return null; + } + } +} + +aspect Comparison { + boolean Operation.equals(Operation other) { return false; } + boolean PickAndPlace.equals(Operation other) { + if (other == null || !other.isPickAndPlace()) { + return false; + } + PickAndPlace otherPickAndPlace = other.asPickAndPlace(); + return getRobotToExecute().equals(otherPickAndPlace.getRobotToExecute()) && + getObjectToPick().getName().equals(otherPickAndPlace.getObjectToPick().getName()) && + getTargetLocation().getName().equals(otherPickAndPlace.getTargetLocation().getName()); + } + boolean ConfigChange.equals(Operation other) { + if (other == null || !other.isConfigChange()) { + return false; + } + ConfigChange otherConfigChange = other.asConfigChange(); + return getRobotToExecute().equals(otherConfigChange.getRobotToExecute()) && + getCollaborationZone().getName().equals(otherConfigChange.getCollaborationZone().getName()); + } + boolean Evacuate.equals(Operation other) { + if (other == null || !other.isEvacuate()) { + return false; + } + Evacuate otherEvacuate = other.asEvacuate(); + return getRobotToExecute().equals(otherEvacuate.getRobotToExecute()) && + getCollaborationZone().getName().equals(otherEvacuate.getCollaborationZone().getName()); + } +} + +aspect Resolving { + //--- findRobot --- + public Optional<Robot> WorldModelB.findRobot(String name) { + for (Robot robot : getRobotList()) { + if (robot.getName().equals(name)) { + return Optional.of(robot); + } + } + return Optional.empty(); + } + + // TODO use Optional here, or not? + public Region WorldModelB.findRegion(String name) { + for (Region region : getRegionList()) { + if (region.getName().equals(name)) { + return region; + } + } + return null; + } + + // // do not resolve real regions and real locations (send by site-A) + // refine RefResolverStubs eq LogicalMovableObject.resolveMyLocationByToken(String name) = null; +} diff --git a/ros3rag.old.b/src/main/jastadd/OldWorldModelB.relast b/ros3rag.old.b/src/main/jastadd/OldWorldModelB.relast new file mode 100644 index 0000000000000000000000000000000000000000..46e19cf4abfebfe5eacc2047668f6e44c5cf0170 --- /dev/null +++ b/ros3rag.old.b/src/main/jastadd/OldWorldModelB.relast @@ -0,0 +1,36 @@ +ArtificialRoot ::= WorldModelB ; + +// OtherScene will always be a list of one scene at most (maybe change later to reflect this. but will change quite a few place +WorldModelB ::= Region* Robot* <MySceneAsProtobuf:de.tudresden.inf.st.ceti.Scene> /[MyScene:Scene]/ <OtherSceneAsJson> /OtherScene:LogicalScene*/ ExecutedOperation:Operation* /NextOperation:Operation/ /<NextOperationAsNtaToken:de.tudresden.inf.st.ceti.Command>/ ; + +Robot ::= <Name:String> CanReachObjectOfInterest* <OwnedCollaborationZoneNames> <OccupiedCollaborationZoneNames> <CurrentPosition> /<MyPosition>/ ; +// relations into nodes received by RagConnect are not allowed +//rel Robot.OwnedCollaborationZone* <-> CollaborationZone.Owner? ; +//rel Robot.OccupiedCollaborationZone? <-> CollaborationZone.Occupient? ; + +CanReachObjectOfInterest ::= <ObjectName:String> ; + +abstract Difference ; +rel Difference.Object -> LogicalMovableObject ; +DifferenceObjectAtWrongPlace : Difference ; +rel DifferenceObjectAtWrongPlace.PreviousRegion? -> LogicalRegion ; +rel DifferenceObjectAtWrongPlace.NewRegion -> LogicalRegion ; +DifferenceNewObject : Difference ; +DifferenceObjectMisplaced : Difference ; +rel DifferenceObjectMisplaced.PreviousRegion -> LogicalRegion ; + +abstract Operation ; +rel Operation.RobotToExecute? -> Robot ; +ErrorOperation : Operation ::= <ErrorMessage:String> ; + +PickAndPlace : Operation ; +rel PickAndPlace.ObjectToPick -> LogicalMovableObject ; +rel PickAndPlace.TargetLocation -> DropOffLocation ; + +ConfigChange : Operation ; +rel ConfigChange.CollaborationZone -> CollaborationZone ; + +Evacuate : Operation ; +rel Evacuate.CollaborationZone -> CollaborationZone ; + +Wait : Operation ; diff --git a/ros3rag.old.b/src/main/jastadd/forwardsComp.jadd b/ros3rag.old.b/src/main/jastadd/forwardsComp.jadd new file mode 100644 index 0000000000000000000000000000000000000000..7406eb8f53fd0e68fb7fe3b189ef9c8e889fc2e2 --- /dev/null +++ b/ros3rag.old.b/src/main/jastadd/forwardsComp.jadd @@ -0,0 +1,96 @@ +aspect ForwardsCompatibility { + public void ArtificialRoot.ragconnectCheckIncremental() { + // empty by definition (no incremental evaluation) + } + static WorldModelB ASTNode.singletonWorldModelB; + refine ASTNode public WorldModelB.WorldModelB() { + refined(); + singletonWorldModelB = this; + } + + static Robot ASTNode.hackTemporaryRobot; +// refine MqttHandler public boolean MqttHandler.newConnection(String topic, java.util.function.Consumer<byte[]> callback) { +// if (topic.equals("/ceti_cell_placeworld/command")) { +// // add decorator consumer to set hackTemporaryRobot +// java.util.function.Consumer<byte[]> decoratedConsumer = input -> { +// +// }; +// } +// refined(); +// } + refine ROS2RAG public boolean Robot.connectOwnedCollaborationZoneNames(String uriString) throws java.io.IOException { + String scheme,host, path; +java.net.URI uri; +try { + uri = new java.net.URI(uriString); + scheme = uri.getScheme(); + host = uri.getHost(); + path = uri.getPath(); +} catch (java.net.URISyntaxException e) { + System.err.println(e.getMessage()); // Maybe re-throw error? + return false; +} + + java.util.function.Consumer<byte[]> consumer = message -> { + String result_apply_ConfigChangeCommandCheckForOwnedCollaborationZone; + hackTemporaryRobot = this; +try { + result_apply_ConfigChangeCommandCheckForOwnedCollaborationZone = _apply_ConfigChangeCommandCheckForOwnedCollaborationZone(message); +} catch (Exception e) { + e.printStackTrace(); + return; +} +if (getOwnedCollaborationZoneNames() != null ? getOwnedCollaborationZoneNames().equals(result_apply_ConfigChangeCommandCheckForOwnedCollaborationZone) : result_apply_ConfigChangeCommandCheckForOwnedCollaborationZone == null) { + return; +} + + setOwnedCollaborationZoneNames(result_apply_ConfigChangeCommandCheckForOwnedCollaborationZone); + }; + switch (scheme) { + case "mqtt": return _mqttHandler().newConnection(uri, consumer); + default: + System.err.println("Unknown protocol '" + scheme + "'."); + return false; + } +} + + refine ROS2RAG public boolean Robot.connectOccupiedCollaborationZoneNames(String uriString) throws java.io.IOException { + String scheme,host, path; +java.net.URI uri; +try { + uri = new java.net.URI(uriString); + scheme = uri.getScheme(); + host = uri.getHost(); + path = uri.getPath(); +} catch (java.net.URISyntaxException e) { + System.err.println(e.getMessage()); // Maybe re-throw error? + return false; +} + + java.util.function.Consumer<byte[]> consumer = message -> { + String result_apply_CommandCheckForOccupiedCollaborationZone; + hackTemporaryRobot = this; +try { + result_apply_CommandCheckForOccupiedCollaborationZone = _apply_CommandCheckForOccupiedCollaborationZone(message); +} catch (Exception e) { + e.printStackTrace(); + return; +} +if (getOccupiedCollaborationZoneNames() != null ? getOccupiedCollaborationZoneNames().equals(result_apply_CommandCheckForOccupiedCollaborationZone) : result_apply_CommandCheckForOccupiedCollaborationZone == null) { + return; +} + + setOccupiedCollaborationZoneNames(result_apply_CommandCheckForOccupiedCollaborationZone); + }; + switch (scheme) { + case "mqtt": return _mqttHandler().newConnection(uri, consumer); + default: + System.err.println("Unknown protocol '" + scheme + "'."); + return false; + } +} + + static void ASTNode.reject() { + throw new RuntimeException("poor mans reject. please ignore."); + } +} diff --git a/ros3rag.old.b/src/main/jastadd/old-shared b/ros3rag.old.b/src/main/jastadd/old-shared new file mode 120000 index 0000000000000000000000000000000000000000..1a2dff41ee8ae3f38e6ee93f962b4a983b0cbc3a --- /dev/null +++ b/ros3rag.old.b/src/main/jastadd/old-shared @@ -0,0 +1 @@ +../../../../ros3rag.common/src/main/resources/old-jastadd \ No newline at end of file diff --git a/ros3rag.old.b/src/main/java/de/tudresden/inf/st/old/b/OldMainB.java b/ros3rag.old.b/src/main/java/de/tudresden/inf/st/old/b/OldMainB.java new file mode 100644 index 0000000000000000000000000000000000000000..7cf3c3e473feeb47483d56ed60b2254b41d01cb7 --- /dev/null +++ b/ros3rag.old.b/src/main/java/de/tudresden/inf/st/old/b/OldMainB.java @@ -0,0 +1,199 @@ +package de.tudresden.inf.st.old.b; + +import de.tudresden.inf.st.ceti.Object; +import de.tudresden.inf.st.old.b.ast.*; +import de.tudresden.inf.st.ros3rag.common.SharedMainParts; +import de.tudresden.inf.st.ros3rag.common.Util; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.function.Function; + +import static de.tudresden.inf.st.ros3rag.common.Util.mqttUri; + +/** + * Entry point for RAG model in place B. + * + * @author rschoene - Initial contribution + */ +public class OldMainB extends SharedMainParts<MqttHandler, ArtificialRoot> { + private final String TOPIC_MODEL_SVG_PATH; + + private de.tudresden.inf.st.ceti.Scene demo_scene; + + OldMainB(String configFile) { + super("place-b", OldUtilB.pathToDirectoryOfPlaceB().resolve(configFile)); + + this.TOPIC_MODEL_SVG_PATH = cellName + "/model/svg/path"; + } + + public static void main(String[] args) throws Exception { + String configFile = args.length == 0 ? "src/main/resources/config-b.yaml" : args[0]; + new OldMainB(configFile).run(); + } + + @Override + public void run() throws Exception { + // ensure that directory "images" exists + File imagesDirectory = Paths.get("images/").toFile(); + if (!imagesDirectory.exists()) { + boolean success = imagesDirectory.mkdir(); + if (!success) { + logger.debug("Failed to create directory {}", imagesDirectory.getAbsolutePath()); + } + } + + super.run(); + } + + @Override + protected MqttHandler createMqttHandler() { + return new MqttHandler("mainHandlerB"); + } + + @Override + protected void createSpecificMainHandlerConnections() { + mainHandler.newConnection("place-b/demo", bytes -> { + String command = new String(bytes); + int colonIndex = command.indexOf(":"); + if (colonIndex == -1) { + logger.error("Unknown demo command {}", command); + return; + } + String key = command.substring(0, colonIndex); + String value = command.substring(colonIndex + 1); + int slashIndex; + switch (key) { + case "scene": + if (!value.equals("initial")) { + logger.warn("Can only send initial scene, but got {}. Sending initial scene.", command); + } + try { + demo_scene = Util.readScene(OldUtilB.pathToDirectoryOfPlaceB().resolve("src/main/resources/config-scene-b-placeworld-manual.json")); + mainHandler.publish(config.forB.topicsSceneUpdate.get(0), demo_scene.toByteArray()); + } catch (IOException e) { + e.printStackTrace(); + } + break; + case "robot": + slashIndex = value.indexOf("/"); + String robot = value.substring(0, slashIndex); + String stateString = "STATE_" + value.substring(slashIndex + 1).toUpperCase(); + Object.State state = Object.State.valueOf(stateString); + updateAndPublishScene(robot, r -> r.toBuilder().setState(state).build()); + break; + case "object": + slashIndex = value.indexOf("/"); + String obj = value.substring(0, slashIndex); + String location = value.substring(slashIndex + 1); + Position pos = model.getWorldModelB().getMyScene().resolveObjectOfInterest(location).asDropOffLocation().getPosition(); + updateAndPublishScene(obj, o -> { + Object.Builder builder = o.toBuilder(); + builder.getPosBuilder() + .setX(pos.getX()) + .setY(pos.getY()) + .setZ(pos.getZ()); + return builder.build(); + }); + break; + default: + logger.error("Unknown demo command {}", command); + } + }); + } + + private void updateAndPublishScene(String objectName, Function<Object, Object> change) { + demo_scene = OldUtilB.updateObject(demo_scene, objectName, change); + mainHandler.publish(config.forB.topicsSceneUpdate.get(0), demo_scene.toByteArray()); + } + + @Override + protected ArtificialRoot createWorldModel() { + WorldModelB worldModel = new WorldModelB(); +// worldModel.ragconnectResetEvaluationCounter(); + worldModel.addOtherScene(new LogicalScene()); + return new ArtificialRoot().setWorldModelB(worldModel); + } + + @Override + protected void readInitialConfigs() throws Exception { + model.getWorldModelB().setMyScene(new Scene()); + + // read and set regions + File regionBFile = OldUtilB.pathToDirectoryOfPlaceB().resolve(config.filenameRegions).toFile(); + OldUtilB.setRegions(model.getWorldModelB(), Util.parseRegionConfig(regionBFile)); + + // init robots and reachability + // assumption: robots do not change during runtime, so we have stable connections + Path path = OldUtilB.pathToDirectoryOfPlaceB().resolve(Paths.get(config.forB.filenameReachability)); + OldReachabilityConfiguration reachability = OldUtilB.readReachability(path.toFile()); + + for (OldReachabilityConfiguration.RobotConfiguration robotConfiguration : reachability.robots) { + Robot robot = OldUtilB.createRobot(robotConfiguration.name); + model.getWorldModelB().addRobot(robot); + + JastAddList<CanReachObjectOfInterest> reachabilityList = OldUtilB.convertToReachability(robotConfiguration.reachableLocations); + robot.setCanReachObjectOfInterestList(reachabilityList); + } + } + + @Override + protected void connectEndpoints() throws IOException { + for (String topic : config.forB.topicsSceneUpdate) { + checkSuccess(model.getWorldModelB().connectMySceneAsProtobuf(mqttUri(topic, config)), + "MySceneAsProtobuf"); + } + checkSuccess(model.getWorldModelB().connectOtherSceneAsJson(mqttUri("place-a/logical/update", config)), + "OtherSceneAsJson"); + checkSuccess(model.getWorldModelB().connectNextOperationAsNtaToken(mqttUri(config.forB.topicCommand, config), false), + "NextOperation"); + // indexed add not supported!! +// checkSuccess(model.getWorldModelB().connectExecutedOperation(mqttUri(config.forB.topicCommand, config)), +// "OperationHistory"); + for (Robot robot : model.getWorldModelB().getRobotList()) { + // self-loop + checkSuccess(robot.connectOwnedCollaborationZoneNames(mqttUri(config.forB.topicCommand, config)), + "OwnedCollaborationZoneNames (" + robot.getName() + ")"); + checkSuccess(robot.connectOccupiedCollaborationZoneNames(mqttUri(config.forB.topicCommand, config)), + "OccupiedCollaborationZoneNames (" + robot.getName() + ")"); + + String topicPosition = joinTopics("place-b", robot.getName(), "position"); + checkSuccess(robot.connectCurrentPosition(mqttUri(topicPosition, config)), + "CurrentPosition (" + robot.getName() + ")"); + checkSuccess(robot.connectMyPosition(mqttUri(topicPosition, config), true), + "MyPosition (" + robot.getName() + ")"); + } + } + + private void checkSuccess(boolean connectSuccess, String target) { + if (!connectSuccess) { + logger.warn("Did not connect successfully to {}", target); + } + } + + @Override + protected String getModelInfos(ArtificialRoot artificialRoot, boolean detailed) { +// Thread t = new Thread(() -> { + try { + String filename = artificialRoot.getWorldModelB().dumpAst(builder -> { + builder.excludeChildren("Orientation", "Size"); + builder.excludeRelations("ContainedInRegion"); + builder.includeNonterminalAttributes("LogicalScene", "diffScenes", "diffToOperations"); + builder.includeAttributes("realRegion", "computeOperations", "myPosition"); + builder.includeNullNodes(); + }); + mainHandler.publish(TOPIC_MODEL_SVG_PATH, filename.getBytes(StandardCharsets.UTF_8)); + } catch (Exception e) { + logger.catching(e); + } +// }); +// t.setDaemon(true); +// t.start(); + + return OldUtilB.getModelInfos(artificialRoot.getWorldModelB(), detailed); + } + +} diff --git a/ros3rag.old.b/src/main/java/de/tudresden/inf/st/old/b/OldReachabilityConfiguration.java b/ros3rag.old.b/src/main/java/de/tudresden/inf/st/old/b/OldReachabilityConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..87ca6434bf32c1a6f0a319e3276358b49eb7c11d --- /dev/null +++ b/ros3rag.old.b/src/main/java/de/tudresden/inf/st/old/b/OldReachabilityConfiguration.java @@ -0,0 +1,17 @@ +package de.tudresden.inf.st.old.b; + +import java.util.List; + +/** + * Data class for reachability information. + * + * @author rschoene - Initial contribution + */ +public class OldReachabilityConfiguration { + public List<RobotConfiguration> robots; + + public static class RobotConfiguration { + public String name; + public List<String> reachableLocations; + } +} diff --git a/ros3rag.old.b/src/main/java/de/tudresden/inf/st/old/b/OldSimpleMainB.java b/ros3rag.old.b/src/main/java/de/tudresden/inf/st/old/b/OldSimpleMainB.java new file mode 100644 index 0000000000000000000000000000000000000000..89b0db03285b5c4fb0d76e52f4506dfb632af105 --- /dev/null +++ b/ros3rag.old.b/src/main/java/de/tudresden/inf/st/old/b/OldSimpleMainB.java @@ -0,0 +1,434 @@ +package de.tudresden.inf.st.old.b; + +import de.tudresden.inf.st.ceti.Object; +import de.tudresden.inf.st.old.b.ast.*; +import de.tudresden.inf.st.ros3rag.common.Configuration; +import de.tudresden.inf.st.ros3rag.common.Util; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * Testing features for placeB. + * + * @author rschoene - Initial contribution + */ +public class OldSimpleMainB { + private static final Logger logger = LogManager.getLogger(OldSimpleMainB.class); + + static class Scenario { + final String suffix; + final boolean loadAndChangeScenes; + final boolean exitAutomatically; + final String mqttHost; + final String topicSceneUpdateB; + final String topicCommand; + Scenario(String suffix) { + this(suffix, true, true, + "localhost", "place-b/scene/update", "place-b/command"); + } + Scenario(String suffix, boolean loadAndChangeScenes, boolean exitAutomatically, + String mqttHost, String topicSceneUpdateB, String topicCommand) { + this.suffix = suffix; + this.loadAndChangeScenes = loadAndChangeScenes; + this.exitAutomatically = exitAutomatically; + this.mqttHost = mqttHost; + this.topicSceneUpdateB = topicSceneUpdateB; + this.topicCommand = topicCommand; + } + } + Scenario s2022 = new Scenario("2022"); + Scenario sMini = new Scenario("mini"); + Scenario sPlaceworld = new Scenario("placeworld", false, false, + "192.168.0.122", + "/ceti_cell_placeworld/scene/update", + "/ceti_cell_placeworld/command"); + Scenario sPlaceworldManual = new Scenario("placeworld-manual", false, false, + "localhost", + "/ceti_cell_placeworld/scene/update", + "/ceti_cell_placeworld/command"); + + @SuppressWarnings("unused" ) + Scenario[] allScenarios = new Scenario[] { s2022, sMini, sPlaceworld, sPlaceworldManual }; + + final Scenario scenario = sMini; + + public static void main(String[] args) throws Exception { + System.out.println("Running SimpleMainB"); + new OldSimpleMainB().run(args); + } + + @SuppressWarnings({"unused"}) + private void run(String[] args) throws Exception { + readModelAndReceiveFromA(); + } + + private void readModelAndReceiveFromA() throws Exception { + Configuration config = new Configuration(); + config.mqttHost = scenario.mqttHost; + String filenameInitialSceneB = "src/main/resources/config-scene-b-" + scenario.suffix + ".json"; + config.filenameRegions = "src/main/resources/regions-b-" + scenario.suffix + ".json"; + config.forB = new Configuration.ConfigurationForB(); + config.forB.filenameReachability = "src/main/resources/reachability-b-" + scenario.suffix + ".json"; + + Configuration configA = new Configuration(); + String filenameInitialSceneA = "src/main/resources/config-scene-a-" + scenario.suffix + ".json"; + configA.filenameRegions = "src/main/resources/regions-a-" + scenario.suffix + ".json"; + + final String topicSceneUpdateB = scenario.topicSceneUpdateB; + final String topicUpdateFromPlaceA = "update/logical/fromA"; + final String topicCommand = scenario.topicCommand; + final String topicExit = "place-b/exit"; + final String topicModel = "place-b/model"; + final String topicModelStatus = "place-b/status"; + + logger.info("Using scenario {}", scenario.suffix); + + ArtificialRoot root = new ArtificialRoot(); + + WorldModelB model = new WorldModelB(); + model.addOtherScene(new LogicalScene()); + root.setWorldModelB(model); + + MqttHandler mqttHandler = new MqttHandler().dontSendWelcomeMessage(); + mqttHandler.setHost(config.mqttHost); + mqttHandler.waitUntilReady(2, TimeUnit.SECONDS); + root.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS); + + Scene myScene = new Scene(); + // read initial scene + Path initialSceneFile = OldUtilB.pathToDirectoryOfPlaceB().resolve(filenameInitialSceneB); + if (initialSceneFile.toFile().exists()) { + de.tudresden.inf.st.ceti.Scene initialScene = Util.readScene(initialSceneFile); + if (scenario.loadAndChangeScenes) { + myScene = OldUtilB.convert(initialScene); + } else { + mqttHandler.newConnection("coordinating/rag-b/command", bytes -> { + if (new String(bytes).equals("start")) { + mqttHandler.publish(scenario.topicSceneUpdateB, initialScene.toByteArray()); + } + }); + } + } + model.setMyScene(myScene); + + // read and set regions + File regionBFile = OldUtilB.pathToDirectoryOfPlaceB().resolve(config.filenameRegions).toFile(); + OldUtilB.setRegions(model, Util.parseRegionConfig(regionBFile)); + + // init robots and reachability + // assumption: robots do not change during runtime, so we have stable connections + Path path = OldUtilB.pathToDirectoryOfPlaceB().resolve(Paths.get(config.forB.filenameReachability)); + OldReachabilityConfiguration reachability = OldUtilB.readReachability(path.toFile()); + for (OldReachabilityConfiguration.RobotConfiguration robotConfiguration : reachability.robots) { + + Robot robot = OldUtilB.createRobot(robotConfiguration.name); + model.addRobot(robot); + + JastAddList<CanReachObjectOfInterest> reachabilityList = OldUtilB.convertToReachability(robotConfiguration.reachableLocations); + robot.setCanReachObjectOfInterestList(reachabilityList); + } + + Runnable close = () -> { + logger.info("Exiting ..."); + mqttHandler.close(); + root.ragconnectCloseConnections(); + }; + Runtime.getRuntime().addShutdownHook(new Thread(close)); + + model.connectOtherSceneAsJson(Util.mqttUri(topicUpdateFromPlaceA, config)); + model.connectMySceneAsProtobuf(Util.mqttUri(topicSceneUpdateB, config)); + for (Robot robot : model.getRobotList()) { + robot.connectOwnedCollaborationZoneNames(Util.mqttUri(topicCommand, config)); + } + model.connectNextOperationAsNtaToken(Util.mqttUri(topicCommand, config), true); + + // prepare exit condition + final CountDownLatch exitCondition = new CountDownLatch(1); + mqttHandler.newConnection(topicExit, bytes -> exitCondition.countDown()); + logger.info("Quit via " + topicExit); + + // prepare model status + mqttHandler.newConnection(topicModel, bytes -> { + String message = new String(bytes); + model.dumpAst(builder -> { + builder.excludeChildren("Orientation", "Size"); + builder.excludeRelations("ContainedInRegion"); + builder.includeNonterminalAttributes("LogicalScene", "diffScenes", "diffToOperations"); + builder.includeAttributes("realRegion", "computeOperations"); + builder.includeNullNodes(); + }); + String content = OldUtilB.getModelInfos(model, message.equals("Start") || message.startsWith("detail")); + logger.info("WorldModel\n{}", content); + mqttHandler.publish(topicModelStatus, content.getBytes(StandardCharsets.UTF_8)); + }); + + // read scene from A, serialize it and send it via mqtt + Path sceneAFile = Util.pathToModuleDirectory("ros3rag.placeA").resolve(filenameInitialSceneA); + File regionAFile = Util.pathToModuleDirectory("ros3rag.placeA").resolve(configA.filenameRegions).toFile(); + de.tudresden.inf.st.ceti.Scene scenePlaceA = Util.readScene(sceneAFile); + Scene sceneFromPlaceA = OldUtilB.convert(scenePlaceA); + // need to "wrap" the scene in a world model to access regions. will use one from site-B here for convenience + WorldModelB tempWorldModel = new WorldModelB(); + tempWorldModel.setMyScene(sceneFromPlaceA); + OldUtilB.setRegions(tempWorldModel, Util.parseRegionConfig(regionAFile)); + LogicalScene logicalSceneFromPlaceA = sceneFromPlaceA.getLogicalScene(); + byte[] bytesToSend = _ragconnect__apply__TreeDefaultLogicalSceneToBytesMapping(logicalSceneFromPlaceA); + + if (scenario.loadAndChangeScenes && initialSceneFile.toFile().exists()) { + de.tudresden.inf.st.ceti.Scene initialScene = Util.readScene(initialSceneFile); + + describedWait(1, "send new logical scene" ); + mqttHandler.publish(topicUpdateFromPlaceA, bytesToSend); + + describedWait(2, "print model status" ); + mqttHandler.publish(topicModel, "detailed".getBytes(StandardCharsets.UTF_8)); + + // set object O1 to position of P-E in sceneB and publish it + describedWait(3, "send updated sceneB (P-E)"); + de.tudresden.inf.st.ceti.Scene scene = updatePositionOfObject(initialScene, "O1", myScene.resolveObjectOfInterest("P-E").getPosition()); + mqttHandler.publish(topicSceneUpdateB, scene.toByteArray()); + + describedWait(4, "set R1 to not busy"); + scene = updateNotBusyOfRobot(scene, "R1"); + + describedWait(5, "print model status"); + mqttHandler.publish(topicModel, "detailed".getBytes(StandardCharsets.UTF_8)); + + // set object O1 to position of P2.2 in sceneB and publish it + describedWait(6, "send updated sceneB (P2.2)"); + scene = updatePositionOfObject(scene, "O1", myScene.resolveObjectOfInterest("P2.2").getPosition()); + mqttHandler.publish(topicSceneUpdateB, scene.toByteArray()); + + describedWait(7, "print model status"); + mqttHandler.publish(topicModel, "detailed".getBytes(StandardCharsets.UTF_8)); + + describedWait(8, "set R2 to not busy"); + scene = updateNotBusyOfRobot(scene, "R2"); + mqttHandler.publish(topicSceneUpdateB, scene.toByteArray()); + + describedWait(9, "print model status"); + mqttHandler.publish(topicModel, "detailed".getBytes(StandardCharsets.UTF_8)); + } else { + mqttHandler.newConnection("coordinating/rag-a/command", bytes -> { + if (new String(bytes).equals("start")) { + mqttHandler.publish(topicUpdateFromPlaceA, bytesToSend); + } + }); + } + + if (scenario.exitAutomatically) { + TimeUnit.SECONDS.sleep(5); + exitCondition.countDown(); + } + + exitCondition.await(); + } + + static void describedWait(int stepNr, String description) throws InterruptedException { + logger.info("({}) Wait 2 secs, then {}", stepNr, description); + TimeUnit.SECONDS.sleep(2); + logger.info(description); + } + + static de.tudresden.inf.st.ceti.Scene updatePositionOfObject( + de.tudresden.inf.st.ceti.Scene scene, + @SuppressWarnings("SameParameterValue" ) String objectName, + Position newPosition) { + return OldUtilB.updateObject(scene, objectName, obj -> { + Object.Builder builder = obj.toBuilder(); + builder.getPosBuilder() + .setX(newPosition.getX()) + .setY(newPosition.getY()) + .setZ(newPosition.getZ()); + return builder.build(); + }); + } + + static de.tudresden.inf.st.ceti.Scene updateNotBusyOfRobot( + de.tudresden.inf.st.ceti.Scene scene, + String objectName) { + return OldUtilB.updateObject(scene, objectName, obj -> obj.toBuilder().setState(Object.State.STATE_MOVING).build()); + } + + + // copied from WorldModelA + protected static byte[] _ragconnect__apply__TreeDefaultLogicalSceneToBytesMapping(LogicalScene input) throws Exception { + java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream(); + com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory(); + com.fasterxml.jackson.core.JsonGenerator generator = factory.createGenerator(outputStream, com.fasterxml.jackson.core.JsonEncoding.UTF8); + input.serialize(generator); + generator.flush(); + return outputStream.toString().getBytes(); + } + + @SuppressWarnings("unused") + private void printReachability(WorldModelB model) { + System.out.println("ModelInfos:"); + System.out.println(OldUtilB.getModelInfos(model, true)); + + System.out.println("Reachability:"); + model.getRobotList().forEach(r -> System.out.println(r.getName() + ": " + r.reachableObjects().stream().map(ObjectOfInterest::getName).collect(Collectors.joining(", ")))); + + System.out.println("ReachabilityGraph:"); + System.out.println(model.toReachabilityGraph().prettyPrint()); + } + + @SuppressWarnings("unused") + private void printShortestPath(WorldModelB model, String source, String target) { + LogicalRegion sourceLocation = model.getMyScene().getLogicalScene() + .resolveLogicalObjectOfInterest(source).asLogicalRegion(); + LogicalRegion targetLocation = model.getMyScene().getLogicalScene() + .resolveLogicalObjectOfInterest(target).asLogicalRegion(); + + List<Edge> bfs = sourceLocation.correspondingVertex().orElseThrow().BFS(targetLocation.correspondingVertex().orElseThrow()); + + System.out.println("Shortest path from " + sourceLocation.getName() + " to " + targetLocation.getName() + ": " + bfs); + } + + @SuppressWarnings("unused") + private void testBFS() { + /* + A B + | \ | + C - D + */ + Graph g = new Graph(); + Vertex a = makeVertex("a"); + Vertex b = makeVertex("b"); + Vertex c = makeVertex("c"); + Vertex d = makeVertex("d"); + Edge ac = makeEdge(a, c); + Edge ad = makeEdge(a, d); + Edge cd = makeEdge(c, d); + Edge db = makeEdge(d, b); + g.addVertex(a); + g.addVertex(b); + g.addVertex(c); + g.addVertex(d); + g.addEdge(ac); + g.addEdge(ad); + g.addEdge(cd); + g.addEdge(db); + + System.out.println(a.BFS(b)); + } + + private Vertex makeVertex(String name) { + return new Vertex() { + @Override + public String toString() { + return name; + } + }; + } + + private Edge makeEdge(Vertex from, Vertex to) { + Edge result = new Edge(); + result.setFrom(from); + result.setTo(to); + return result; + } + + @SuppressWarnings("unused") + private void testDistance() throws Exception { + de.tudresden.inf.st.ceti.Scene scene = Util.readScene( + OldUtilB.pathToDirectoryOfPlaceB().resolve("src/main/resources/config-scene-b.json") + ); + + Scene myScene = OldUtilB.convert(scene); + float arm1X = 0f; + float arm1Y = 0f; + float arm1Z = 0.75f; + + float arm2X = 1f; + float arm2Y = 0f; + float arm2Z = 0.75f; + + for (var location : myScene.getDropOffLocationList()) { + check(arm1X, arm1Y, arm1Z, location.getPosition(), "arm1", location.getName()); + check(arm2X, arm2Y, arm2Z, location.getPosition(), "arm2", location.getName()); + } + } + + private void check(double x, double y, double z, Position position, String robotName, String locationName) { + double dx = x - position.getX(); + double dy = y - position.getY(); + double dz = z - position.getZ(); + + if (Math.sqrt(dx*dx + dy*dy) < 0.05) { + System.out.println(robotName + " too close to " + locationName); + } + if (Math.sqrt(dx*dx + dy*dy + dz*dz) > 0.75) { + System.out.println(robotName + " too far away from " + locationName); + } + } + + @SuppressWarnings("unused") + private void testBuildModelB() { + WorldModelB model = new WorldModelB(); + + // robots + model.addRobot(OldUtilB.createRobot("Alice", "placeAlfa", "placeBeta")); + model.addRobot(OldUtilB.createRobot("Bob", "placeBeta", "placeGamma")); + + // myScene + var myScene = new Scene(); + myScene.addMovableObject(MovableObject.of("obj1", Position.of(0, 0, 0))); + myScene.addDropOffLocation(DropOffLocation.of("placeAlfa", + Position.of(0, 0, 0), + Orientation.of(0, 0, 0, 1), + Size.of(1, 1, 1))); + myScene.addDropOffLocation(DropOffLocation.of("placeBeta", + Position.of(1, 1, 1), + Orientation.of(0, 0, 0, 1), + Size.of(1, 1, 1))); + myScene.addDropOffLocation(DropOffLocation.of("placeGamma", + Position.of(3, 3, 3), + Orientation.of(0, 0, 0, 1), + Size.of(2, 2, 2))); + logger.info("obj1 at alfa: {}", + myScene.getMovableObject(0).isLocatedAt(myScene.getDropOffLocation(0))); + model.setMyScene(myScene); + + // otherScene + var otherScene = new LogicalScene(); + LogicalMovableObject otherObj1 = new LogicalMovableObject().setName("obj1"); + otherScene.addLogicalMovableObject(otherObj1); + otherScene.addLogicalRegion(new LogicalRegion().setName("placeAlfa")); + otherScene.addLogicalRegion(new LogicalRegion().setName("placeBeta")); + LogicalRegion otherGamma = new LogicalRegion().setName("placeGamma"); + otherGamma.addContainedObject(otherObj1); + otherScene.addLogicalRegion(otherGamma); + model.addOtherScene(otherScene); + + // printing and testing + printModelInfos(model); + + // now simulate, that Alice has moved obj1 to placeBeta + myScene.getMovableObject(0).setPosition(Position.of(1, 1, 1)); + logger.warn("Moving obj1 manually to beta"); + + printModelInfos(model); + + // now simulate, that Bob has moved obj1 to placeGamma + myScene.getMovableObject(0).setPosition(Position.of(3, 3, 3)); + logger.warn("Moving obj1 manually to gamma"); + + // expect error-operation + printModelInfos(model); + } + + private void printModelInfos(WorldModelB model) { + logger.info(OldUtilB.getModelInfos(model)); + } +} diff --git a/ros3rag.old.b/src/main/java/de/tudresden/inf/st/old/b/OldUtilB.java b/ros3rag.old.b/src/main/java/de/tudresden/inf/st/old/b/OldUtilB.java new file mode 100644 index 0000000000000000000000000000000000000000..f3f33936baabbc54b06a2ed416dea1c9fcdc11f2 --- /dev/null +++ b/ros3rag.old.b/src/main/java/de/tudresden/inf/st/old/b/OldUtilB.java @@ -0,0 +1,180 @@ +package de.tudresden.inf.st.old.b; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.tudresden.inf.st.ceti.Object; +import de.tudresden.inf.st.old.b.ast.*; +import de.tudresden.inf.st.ros3rag.common.RegionConfiguration; +import de.tudresden.inf.st.ros3rag.common.RegionConfiguration.RegionDefinition; +import de.tudresden.inf.st.ros3rag.common.Util; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.List; +import java.util.function.Function; + +/** + * Static utility methods used only for place B. + * + * @author rschoene - Initial contribution + */ +public class OldUtilB { + private static final Logger logger = LogManager.getLogger(OldUtilB.class); + + static OldReachabilityConfiguration readReachability(File reachabilityFile) throws IOException { + logger.info("Using reachability config file: {}", reachabilityFile.getAbsolutePath()); + ObjectMapper mapper = new ObjectMapper(); + return mapper.readValue(reachabilityFile, OldReachabilityConfiguration.class); + } + + static Path pathToDirectoryOfPlaceB() { + return Util.pathToModuleDirectory("ros3rag.old.b"); + } + + static Robot createRobot(String name, String... canReach) { + Robot result = new Robot().setName(name).setCurrentPosition("unknown"); + + for (String canReachName : canReach) { + result.addCanReachObjectOfInterest(new CanReachObjectOfInterest(canReachName)); + } + return result; + } + + private static String resolveObjName(WorldModelB model, String objName) { + if (!model.hasMyScene()) { + return "\"" + objName + "\""; + } + try { + return model.getMyScene().resolveObjectOfInterest(objName).getName(); + } catch (NullPointerException ignore) { + return "+" + objName + "(not resolved)+"; + } + } + + static String getModelInfos(WorldModelB model) { + return getModelInfos(model, false); + } + + static String getModelInfos(WorldModelB model, boolean detailed) { + StringBuilder sb = new StringBuilder(); + sb.append("myRobots: ") + .append(model.getRobotList().prettyPrint( + robot -> robot.getName() + + "(" + (robot.isBusy() ? "busy" : "free") + + ", canReach: " + + robot.getCanReachObjectOfInterestList().prettyPrint( + canReachObj -> resolveObjName(model, canReachObj.getObjectName())) + + ")")) + .append("\n"); + if (detailed) { + // also include "normal" scene + sb.append("myScene:"); + if (model.hasMyScene()) { + sb.append("\n").append(model.getMyScene().prettyPrint()); + } else { + sb.append(" (unset)\n"); + } + } + sb.append("myLogicalScene:"); + if (model.hasMyScene()) { + sb.append("\n").append(model.getMyScene().getLogicalScene().prettyPrint()); + } else { + sb.append(" (unset)\n"); + } + sb.append("otherScene:"); + if (model.hasOtherScene()) { + sb.append("\n").append(model.mergedOtherScene().prettyPrint()); + } else { + sb.append(" (unset)\n"); + } + sb.append("Diff: ").append(model.diffScenes().prettyPrint(Difference::prettyPrint)).append("\n"); + if (detailed) { + sb.append("Graph: ").append(model.toReachabilityGraph().prettyPrint()).append("\n"); + } + sb.append("Operations: ").append(model.diffToOperations().prettyPrint(Operation::prettyPrint)).append("\n"); + sb.append("Next operation: ").append(model.getNextOperation().prettyPrint()).append("\n"); + sb.append("Operation History: ").append(model.getExecutedOperations().prettyPrint(Operation::prettyPrint)).append("\n"); +// String summary = model.ragconnectEvaluationCounterSummary(); +// sb.append("EvaluationCounter:\n").append(summary); +// sb.append("% skipped: ").append(percentageSkipped(summary)).append("\n"); + return sb.toString(); + } + + static double percentageSkipped(String summary) { + int sumCall = 0; + int sumSkipped = 0; + try { + for (String line : summary.split("\n")) { + String[] tokens = line.split(","); + if (tokens.length == 0 || tokens[0].equals("parentTypeName")) { + continue; + } + sumCall += Integer.parseInt(tokens[4]); + sumSkipped += Integer.parseInt(tokens[6]); + } + } catch (NumberFormatException e) { + logger.catching(e); + } + if (sumCall == 0) { + return 0; + } + return sumSkipped * 100.0 / sumCall; + } + + static Scene convert(de.tudresden.inf.st.ceti.Scene scene) throws Exception { + return new ExposingASTNode().exposed_apply_ConvertScene(scene); + } + + static JastAddList<CanReachObjectOfInterest> convertToReachability(List<String> reachableLocations) { + JastAddList<CanReachObjectOfInterest> result = new JastAddList<>(); + reachableLocations.forEach(location -> result.addChild(new CanReachObjectOfInterest(location))); + return result; + } + + static void setRegions(WorldModelB model, RegionConfiguration config) { + JastAddList<Region> result = new JastAddList<>(); + for (RegionDefinition def : config.regions) { + Region region = new Region(); + region.setName(def.name); + region.setLocationNames(String.join(",", def.positions)); + result.add(region); + } + model.setRegionList(result); + } + + static de.tudresden.inf.st.ceti.Scene updateObject( + de.tudresden.inf.st.ceti.Scene scene, + String objectName, + Function<Object, Object> change) { + List<Object> objectsList = scene.getObjectsList(); + Object newObj = null; + int index, objectsListSize; + for (index = 0, objectsListSize = objectsList.size(); index < objectsListSize; index++) { + Object obj = objectsList.get(index); + if (obj.getId().equals(objectName)) { + newObj = change.apply(obj); + break; + } + } + if (newObj == null) { + logger.error("Did not find object {}!", objectName); + } else { + scene = scene.toBuilder().setObjects(index, newObj).build(); + logger.info("Update {} in scene to:\n {}", objectName, newObj); + } + return scene; + } + + @SuppressWarnings("rawtypes") + static class ExposingASTNode extends ASTNode { + public Scene exposed_apply_ConvertScene(de.tudresden.inf.st.ceti.Scene pbScene) throws Exception { + return _apply_ConvertScene(pbScene); + } +// public CanReachObjectOfInterestWrapper exposed_apply_ConvertReachability(de.tudresden.inf.st.ceti.Reachability r) throws Exception { +// return _ragconnect__apply_ConvertReachability(r); +// } + } + +} diff --git a/ros3rag.old.b/src/main/resources b/ros3rag.old.b/src/main/resources new file mode 120000 index 0000000000000000000000000000000000000000..6c8b4ad6a116f4b2f549614fbf69beb1784c408f --- /dev/null +++ b/ros3rag.old.b/src/main/resources @@ -0,0 +1 @@ +../../../ros3rag.placeB/src/main/resources \ No newline at end of file diff --git a/ros3rag.placeA/build.gradle b/ros3rag.placeA/build.gradle index 5e90f00c02c0ffe44d5e15740f9d6c6702702c4e..bef7375749dbb33acd61ec3f609152950ff0d611 100644 --- a/ros3rag.placeA/build.gradle +++ b/ros3rag.placeA/build.gradle @@ -27,7 +27,7 @@ ext.sharedJastAddDir = 'src/main/jastadd/shared' ext.ragConnectInputGrammar = 'src/main/jastadd/WorldModelA.relast' ext.ragConnectInputConnect = 'src/main/jastadd/WorldModelA.connect' ext.ragConnectRootNode = 'WorldModelA' -ext.relastFiles = ["src/gen/jastadd/WorldModelA.relast", "src/gen/jastadd/RagConnect.relast"] +ext.relastFiles = ["src/gen/jastadd/types.relast", "src/gen/jastadd/WorldModelA.relast", "src/gen/jastadd/RagConnect.relast"] ext.jastaddAstPackage = 'de.tudresden.inf.st.placeA.ast' apply from: '../ros3rag.common/src/main/resources/tasks.gradle' diff --git a/ros3rag.placeB/build.gradle b/ros3rag.placeB/build.gradle index 5a2da9d4f49dc04cf2096201b826400e2e32dd21..2ceb2594ab0e6e3269484c2af24bcf6b62c2c2f0 100644 --- a/ros3rag.placeB/build.gradle +++ b/ros3rag.placeB/build.gradle @@ -29,7 +29,7 @@ ext.sharedJastAddDir = 'src/main/jastadd/shared' ext.ragConnectInputGrammar = 'src/main/jastadd/WorldModelB.relast' ext.ragConnectInputConnect = 'src/main/jastadd/WorldModelB.connect' ext.ragConnectRootNode = 'WorldModelB' -ext.relastFiles = ["src/gen/jastadd/WorldModelB.relast", "src/main/jastadd/BFS/BFS.relast", "src/main/jastadd/RobotReachabilityToBFS.relast", "src/gen/jastadd/RagConnect.relast"] +ext.relastFiles = ["src/gen/jastadd/types.relast", "src/gen/jastadd/WorldModelB.relast", "src/main/jastadd/BFS/BFS.relast", "src/main/jastadd/RobotReachabilityToBFS.relast", "src/gen/jastadd/RagConnect.relast"] ext.jastaddAstPackage = 'de.tudresden.inf.st.placeB.ast' apply from: '../ros3rag.common/src/main/resources/tasks.gradle' diff --git a/ros3rag.scaling.a/build.gradle b/ros3rag.scaling.a/build.gradle index b858870b90b5d9a12547cc2432465c7a90842645..52373c1ca92c3a58a484d552a0886bb310b0a87c 100644 --- a/ros3rag.scaling.a/build.gradle +++ b/ros3rag.scaling.a/build.gradle @@ -27,7 +27,7 @@ ext.sharedJastAddDir = 'src/main/jastadd/shared' ext.ragConnectInputGrammar = 'src/main/jastadd/ScalingModelA.relast' ext.ragConnectInputConnect = 'src/main/jastadd/ScalingModelA.connect' ext.ragConnectRootNode = 'CompleteWorld' -ext.relastFiles = ["src/gen/jastadd/ScalingModelA.relast", "src/gen/jastadd/RagConnect.relast"] +ext.relastFiles = ["src/gen/jastadd/types.relast", "src/gen/jastadd/ScalingModelA.relast", "src/gen/jastadd/RagConnect.relast"] ext.jastaddAstPackage = 'de.tudresden.inf.st.scaling.a.ast' apply from: '../ros3rag.common/src/main/resources/tasks.gradle' diff --git a/ros3rag.scaling.b/build.gradle b/ros3rag.scaling.b/build.gradle index 27c72a4d782507584ead0e6bd459e03337007165..e8158b2a2023c96d9211d0c731f565b135d3d983 100644 --- a/ros3rag.scaling.b/build.gradle +++ b/ros3rag.scaling.b/build.gradle @@ -28,7 +28,7 @@ ext.sharedJastAddDir = 'src/main/jastadd/fromPlaceB/shared' ext.ragConnectInputGrammar = 'src/main/jastadd/fromPlaceB/WorldModelB.relast' ext.ragConnectInputConnect = 'src/main/jastadd/fromPlaceB/WorldModelB.connect' ext.ragConnectRootNode = 'WorldModelB' -ext.relastFiles = ["src/gen/jastadd/WorldModelB.relast", "src/main/jastadd/fromPlaceB/BFS/BFS.relast", "src/main/jastadd/fromPlaceB/RobotReachabilityToBFS.relast", "src/gen/jastadd/RagConnect.relast"] +ext.relastFiles = ["src/gen/jastadd/types.relast", "src/gen/jastadd/WorldModelB.relast", "src/main/jastadd/fromPlaceB/BFS/BFS.relast", "src/main/jastadd/fromPlaceB/RobotReachabilityToBFS.relast", "src/gen/jastadd/RagConnect.relast"] ext.jastaddAstPackage = 'de.tudresden.inf.st.scaling.b.ast' apply from: '../ros3rag.common/src/main/resources/tasks.gradle' diff --git a/settings.gradle b/settings.gradle index bf9973ba7eefa23a0b986f3166d505ca55f85d4e..dd56cbc8dbbeb26c57f31e2a79a915a7a8409c9a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,3 +14,6 @@ include 'ros3rag.common' include 'ros3rag.scaling.a' include 'ros3rag.scaling.b' + +include 'ros3rag.old.a' +include 'ros3rag.old.b'