Skip to content
Snippets Groups Projects
Commit 0e2c0f00 authored by René Schöne's avatar René Schöne
Browse files

working on real collaboration

- update config structure
- fixed exit and rewind
- reread config on rewind
- read regions on both sites
- add demo commands for site B
- create svg at model-command for site-B, and publish filename
- enhance compute-operations: source location can be collaboration zone as well, add wait command when zone is not owned and occupied
- connect occupiedCollaborationZoneNames with self-loop and "moving-in" and "moving-out" logic
parent 18d88605
Branches
Tags
No related merge requests found
Pipeline #13555 passed
Showing
with 317 additions and 96 deletions
...@@ -12,13 +12,19 @@ import java.util.List; ...@@ -12,13 +12,19 @@ import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true) @JsonIgnoreProperties(ignoreUnknown = true)
public class Configuration { public class Configuration {
public String mqttHost; public String mqttHost;
public String filenameInitialSceneA;
public String filenameRegions; public String filenameRegions;
public String coordinatorMqttTopicPrefix; public String coordinatorMqttTopicPrefix;
public List<ReachabilityConfig> reachability; public ConfigurationForA forA;
public ConfigurationForB forB;
public static class ReachabilityConfig { public static class ConfigurationForA {
public String filename; public String filenameInitialScene;
}
public static class ConfigurationForB {
public List<String> reachability;
public List<String> topicsSceneUpdate;
public String topicCommand;
} }
public boolean useCoordinator() { public boolean useCoordinator() {
......
...@@ -65,11 +65,13 @@ public abstract class SharedMainParts<MqttHandler extends SharedMainParts.MqttHa ...@@ -65,11 +65,13 @@ public abstract class SharedMainParts<MqttHandler extends SharedMainParts.MqttHa
mainHandler.newConnection(TOPIC_EXIT, bytes -> { mainHandler.newConnection(TOPIC_EXIT, bytes -> {
logger.info("Got exit command"); logger.info("Got exit command");
exitCondition.countDown(); exitCondition.countDown();
startCondition.countDown();
logger.debug("exit latch count = {}, start latch count= {}", logger.debug("exit latch count = {}, start latch count= {}",
exitCondition.getCount(), startCondition.getCount()); exitCondition.getCount(), startCondition.getCount());
}); });
mainHandler.newConnection(TOPIC_MODEL, bytes -> logStatus(new String(bytes))); mainHandler.newConnection(TOPIC_MODEL, bytes -> logStatus(new String(bytes)));
mainHandler.newConnection(TOPIC_REWIND, bytes -> mainHandler.newConnection(TOPIC_REWIND, bytes ->
new Thread(() -> {
{ {
try { try {
rewind("rewind"); rewind("rewind");
...@@ -77,6 +79,7 @@ public abstract class SharedMainParts<MqttHandler extends SharedMainParts.MqttHa ...@@ -77,6 +79,7 @@ public abstract class SharedMainParts<MqttHandler extends SharedMainParts.MqttHa
logger.catching(e); logger.catching(e);
} }
} }
}).start()
); );
if (config.useCoordinator()) { if (config.useCoordinator()) {
logger.info("Using coordinator logic"); logger.info("Using coordinator logic");
...@@ -136,11 +139,14 @@ public abstract class SharedMainParts<MqttHandler extends SharedMainParts.MqttHa ...@@ -136,11 +139,14 @@ public abstract class SharedMainParts<MqttHandler extends SharedMainParts.MqttHa
logger.debug("Closing previous connections for {}", cellName); logger.debug("Closing previous connections for {}", cellName);
model.ragconnectCloseConnections(); model.ragconnectCloseConnections();
} }
config = Util.parseConfig(pathToConfig.toFile());
logger.debug("Creating world model for {}", cellName); logger.debug("Creating world model for {}", cellName);
model = createWorldModel(); model = createWorldModel();
logger.debug("Reading robots for {}", cellName); logger.debug("Reading robots for {}", cellName);
readRobotsAndReachability(); readInitialConfigs();
logger.debug("Setup model connection for {}", cellName); logger.debug("Setup model connection for {}", cellName);
model.ragconnectCheckIncremental(); model.ragconnectCheckIncremental();
...@@ -172,7 +178,7 @@ public abstract class SharedMainParts<MqttHandler extends SharedMainParts.MqttHa ...@@ -172,7 +178,7 @@ public abstract class SharedMainParts<MqttHandler extends SharedMainParts.MqttHa
protected abstract WorldModel createWorldModel() throws Exception; protected abstract WorldModel createWorldModel() throws Exception;
protected abstract void readRobotsAndReachability() throws Exception; protected abstract void readInitialConfigs() throws Exception;
protected abstract void connectEndpoints() throws IOException; protected abstract void connectEndpoints() throws IOException;
......
...@@ -4,7 +4,9 @@ import de.tudresden.inf.st.placeA.ast.MqttHandler; ...@@ -4,7 +4,9 @@ import de.tudresden.inf.st.placeA.ast.MqttHandler;
import de.tudresden.inf.st.placeA.ast.Scene; import de.tudresden.inf.st.placeA.ast.Scene;
import de.tudresden.inf.st.placeA.ast.WorldModelA; import de.tudresden.inf.st.placeA.ast.WorldModelA;
import de.tudresden.inf.st.ros3rag.common.SharedMainParts; 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.io.IOException;
import static de.tudresden.inf.st.ros3rag.common.Util.mqttUri; import static de.tudresden.inf.st.ros3rag.common.Util.mqttUri;
...@@ -62,14 +64,18 @@ public class MainA extends SharedMainParts<MqttHandler, WorldModelA> { ...@@ -62,14 +64,18 @@ public class MainA extends SharedMainParts<MqttHandler, WorldModelA> {
@Override @Override
protected WorldModelA createWorldModel() throws Exception { protected WorldModelA createWorldModel() throws Exception {
de.tudresden.inf.st.ceti.Scene scene = readScene( de.tudresden.inf.st.ceti.Scene scene = readScene(
UtilA.pathToDirectoryOfPlaceA().resolve(config.filenameInitialSceneA) UtilA.pathToDirectoryOfPlaceA().resolve(config.forA.filenameInitialScene)
); );
Scene myScene = UtilA.convert(scene); Scene myScene = UtilA.convert(scene);
return new WorldModelA().setScene(myScene); return new WorldModelA().setScene(myScene);
} }
@Override @Override
protected void readRobotsAndReachability() { protected void readInitialConfigs() throws IOException {
// read and set regions
File regionFile = UtilA.pathToDirectoryOfPlaceA().resolve(config.filenameRegions).toFile();
UtilA.setRegions(model, Util.parseRegionConfig(regionFile));
// no robots to be set // no robots to be set
} }
......
package de.tudresden.inf.st.placeA; package de.tudresden.inf.st.placeA;
import de.tudresden.inf.st.placeA.ast.*; import de.tudresden.inf.st.placeA.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 de.tudresden.inf.st.ros3rag.common.Util;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -23,6 +25,17 @@ public class UtilA { ...@@ -23,6 +25,17 @@ public class UtilA {
return new ExposingASTNode().exposed_apply_ConvertScene(scene); 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) { static void updatePositionOfObjectToLocation(Scene scene, String objName, String locationName) {
ObjectOfInterest obj = scene.resolveObjectOfInterest(objName); ObjectOfInterest obj = scene.resolveObjectOfInterest(objName);
ObjectOfInterest location = scene.resolveObjectOfInterest(locationName); ObjectOfInterest location = scene.resolveObjectOfInterest(locationName);
......
mqttHost: "192.168.0.122"
filenameRegions: "src/main/resources/regions-a-placeworld.json"
forA:
filenameInitialScene: "src/main/resources/config-scene-a-placeworld.json"
coordinatorMqttTopicPrefix: "coordinating/rag-a"
...@@ -4,6 +4,7 @@ receive indexed WorldModelB.OtherScene ; ...@@ -4,6 +4,7 @@ receive indexed WorldModelB.OtherScene ;
receive WorldModelB.TestingOtherScene ; receive WorldModelB.TestingOtherScene ;
receive Robot.CanReachObjectOfInterestWrapper using ParseReachability, ConvertReachability ; receive Robot.CanReachObjectOfInterestWrapper using ParseReachability, ConvertReachability ;
receive Robot.OwnedCollaborationZoneNames using ConfigChangeCommandCheckForOwnedCollaborationZone ; receive Robot.OwnedCollaborationZoneNames using ConfigChangeCommandCheckForOwnedCollaborationZone ;
receive Robot.OccupiedCollaborationZoneNames using CommandCheckForOccupiedCollaborationZone ;
// --- sending --- // --- sending ---
send WorldModelB.NextOperation using PrintOperation ; send WorldModelB.NextOperation using PrintOperation ;
...@@ -27,7 +28,7 @@ ConfigChangeCommandCheckForOwnedCollaborationZone maps byte[] bytes to String {: ...@@ -27,7 +28,7 @@ ConfigChangeCommandCheckForOwnedCollaborationZone maps byte[] bytes to String {:
if (!command.hasConfigChange()) { if (!command.hasConfigChange()) {
reject(); reject();
} }
System.out.println(command); // System.out.println(command);
de.tudresden.inf.st.ceti.ConfigChange cc = command.getConfigChange(); de.tudresden.inf.st.ceti.ConfigChange cc = command.getConfigChange();
Scene scene = worldModelB().getMyScene(); Scene scene = worldModelB().getMyScene();
ObjectOfInterest obj = scene.resolveObjectOfInterest(cc.getIdCollaborationZone()); ObjectOfInterest obj = scene.resolveObjectOfInterest(cc.getIdCollaborationZone());
...@@ -49,3 +50,71 @@ ConfigChangeCommandCheckForOwnedCollaborationZone maps byte[] bytes to String {: ...@@ -49,3 +50,71 @@ ConfigChangeCommandCheckForOwnedCollaborationZone maps byte[] bytes to String {:
} }
return String.join(",", collaborationZoneNames); 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 = worldModelB().getMyScene();
Robot thisRobot = (Robot) this;
// // 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();
}
ObjectOfInterest obj = scene.resolveObjectOfInterest(pp.getIdPlace());
DropOffLocation loc = obj.asDropOffLocation();
if (loc.isCollaborationZone()) {
CollaborationZone cz = loc.asCollaborationZone();
String specialIncomingName = "(>)" + cz.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);
:}
...@@ -165,24 +165,45 @@ aspect Computation { ...@@ -165,24 +165,45 @@ aspect Computation {
Vertex transit = previousVertex; Vertex transit = previousVertex;
for (Edge edge : shortestPath) { for (Edge edge : shortestPath) {
Vertex target = edge.getFrom().equals(transit) ? edge.getTo() : edge.getFrom(); 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(); DropOffLocation targetLocation = worldModelB().getMyScene().resolveObjectOfInterest(target.asVertexWithObjectOfInterest().getNameOfObjectOfInterest()).asDropOffLocation();
// Robot executingRobot = worldModelB().findRobot(edge.asEdgeWithRobot().getNameOfRobot()); // Robot executingRobot = worldModelB().findRobot(edge.asEdgeWithRobot().getNameOfRobot());
worldModelB().findRobot(edge.asEdgeWithRobot().getNameOfRobot()).ifPresentOrElse(executingRobot -> { worldModelB().findRobot(edge.asEdgeWithRobot().getNameOfRobot()).ifPresentOrElse(executingRobot -> {
if (targetLocation.isCollaborationZone()) { /* for both locations, in case it is a collaboration zone, we need to ensure the following:
/* here we need to check, if the collaboration zone is
(a) claimed by the executing robot, and (a) claimed by the executing robot, and
(b) occupied by another robot, and (b) not occupied by another robot, and
(c) free (as no movable object is contained) -- this should be reflected in the graph! (c) free (as no movable object is contained) -- this should be reflected in the graph!
*/ */
if (sourceLocation.isCollaborationZone()) {
CollaborationZone cz = sourceLocation.asCollaborationZone();
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)) {
result.add(Evacuate.of(cz.occupient(), cz));
}
if (!cz.hasOwner() || (cz.hasOwner() && !cz.owner().equals(executingRobot))) {
if (cz.hasOccupient() && !cz.occupient().equals(executingRobot)) {
result.add(Wait.of());
} else {
result.add(ConfigChange.of(executingRobot, cz));
}
}
}
if (targetLocation.isCollaborationZone()) {
CollaborationZone cz = targetLocation.asCollaborationZone(); CollaborationZone cz = targetLocation.asCollaborationZone();
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 // order is important here, first add Evacuate, then ConfigChange
if (cz.hasOccupient() && !cz.occupient().equals(executingRobot)) { if (cz.hasOccupient() && !cz.occupient().equals(executingRobot)) {
result.add(Evacuate.of(cz.occupient(), cz)); result.add(Evacuate.of(cz.occupient(), cz));
} }
if (!cz.hasOwner() || (cz.hasOwner() && !cz.owner().equals(executingRobot))) { if (!cz.hasOwner() || (cz.hasOwner() && !cz.owner().equals(executingRobot))) {
if (cz.hasOccupient() && !cz.occupient().equals(executingRobot)) {
result.add(Wait.of());
} else {
result.add(ConfigChange.of(executingRobot, cz)); result.add(ConfigChange.of(executingRobot, cz));
} }
} }
}
result.add(PickAndPlace.of(executingRobot, getObject(), targetLocation)); result.add(PickAndPlace.of(executingRobot, getObject(), targetLocation));
}, () -> result.add(new ErrorOperation("Could not find robot with name " + edge.asEdgeWithRobot().getNameOfRobot()))); }, () -> result.add(new ErrorOperation("Could not find robot with name " + edge.asEdgeWithRobot().getNameOfRobot())));
transit = target; transit = target;
...@@ -229,6 +250,10 @@ aspect Computation { ...@@ -229,6 +250,10 @@ aspect Computation {
return result; return result;
} }
public static Wait Wait.of() {
return new Wait();
}
//--- getNextOperation --- //--- getNextOperation ---
syn Operation WorldModelB.getNextOperation() { syn Operation WorldModelB.getNextOperation() {
if (diffToOperations().getNumChild() == 0) { if (diffToOperations().getNumChild() == 0) {
...@@ -306,6 +331,7 @@ aspect AttributeMappings { ...@@ -306,6 +331,7 @@ aspect AttributeMappings {
.setIdCollaborationZone(getCollaborationZone().getName()) .setIdCollaborationZone(getCollaborationZone().getName())
.build()) .build())
.build().toByteArray(); .build().toByteArray();
eq Wait.toProtobufByteArray() = null;
} }
aspect Navigation { aspect Navigation {
...@@ -323,17 +349,28 @@ aspect Navigation { ...@@ -323,17 +349,28 @@ aspect Navigation {
// eq WorldModelB.getChild().allMappings() = getLocationMapping(); // eq WorldModelB.getChild().allMappings() = getLocationMapping();
syn boolean CollaborationZone.hasOccupient() = occupient() != null; syn boolean CollaborationZone.hasOccupient() = occupient() != null;
syn Robot CollaborationZone.occupient() { syn Robot CollaborationZone.occupient() {
// (>) == moving in, (^) == evacuate/moving out
for (Robot robot : worldModelB().getRobotList()) { for (Robot robot : worldModelB().getRobotList()) {
if (getName().equals(robot.getOccupiedCollaborationZoneName())) { for (String zoneName : arrayAsList(robot.getOccupiedCollaborationZoneNames())) {
if (zoneName.startsWith("(>)") && zoneName.substring(3).equals(getName())) {
// robot is currently moving into this zone. always regard it as occupied by it
return robot;
}
if (zoneName.startsWith("(^)") && zoneName.substring(3).equals(getName()) && robot.isBusy()) {
// robot is busy moving out of this zone. regard it as occupied as long as the robot is busy
return robot;
}
if (zoneName.equals(getName())) {
return robot; return robot;
} }
} }
}
return null; return null;
} }
syn boolean CollaborationZone.hasOwner() = owner() != null; syn boolean CollaborationZone.hasOwner() = owner() != null;
syn Robot CollaborationZone.owner() { syn Robot CollaborationZone.owner() {
for (Robot robot : worldModelB().getRobotList()) { for (Robot robot : worldModelB().getRobotList()) {
List<String> collaborationZoneNames = Arrays.asList(robot.getOwnedCollaborationZoneNames().split(",")); List<String> collaborationZoneNames = arrayAsList(robot.getOwnedCollaborationZoneNames());
if (collaborationZoneNames.contains(getName())) { if (collaborationZoneNames.contains(getName())) {
return robot; return robot;
} }
...@@ -341,6 +378,7 @@ aspect Navigation { ...@@ -341,6 +378,7 @@ aspect Navigation {
return null; return null;
} }
syn List<String> Robot.ownedCollaborationZonesAsList() = arrayAsList(getOwnedCollaborationZoneNames()); syn List<String> Robot.ownedCollaborationZonesAsList() = arrayAsList(getOwnedCollaborationZoneNames());
syn List<String> Robot.occupiedCollaborationZonesAsList() = arrayAsList(getOccupiedCollaborationZoneNames());
eq Region.locationList() { eq Region.locationList() {
List<DropOffLocation> result = new ArrayList<>(); List<DropOffLocation> result = new ArrayList<>();
if (!worldModelB().hasMyScene()) { return result; } if (!worldModelB().hasMyScene()) { return result; }
...@@ -398,18 +436,24 @@ aspect Printing { ...@@ -398,18 +436,24 @@ aspect Printing {
eq Evacuate.prettyPrint() { eq Evacuate.prettyPrint() {
return "+Evacuate: " + getRobotToExecute().prettyPrint() + " from " + getCollaborationZone().prettyPrint() + "+"; return "+Evacuate: " + getRobotToExecute().prettyPrint() + " from " + getCollaborationZone().prettyPrint() + "+";
} }
eq Wait.prettyPrint() {
return "+Wait+";
}
} }
aspect DumpAst { aspect DumpAst {
public void WorldModelB.dumpAst(java.util.function.Consumer<de.tudresden.inf.st.jastadd.dumpAst.ast.DumpBuilder> options) { 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("[:\\.]", "-"); String now = java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME).replaceAll("[:\\.]", "-");
try { try {
de.tudresden.inf.st.jastadd.dumpAst.ast.DumpBuilder builder = de.tudresden.inf.st.jastadd.dumpAst.ast.Dumper.read(this); de.tudresden.inf.st.jastadd.dumpAst.ast.DumpBuilder builder = de.tudresden.inf.st.jastadd.dumpAst.ast.Dumper.read(this);
options.accept(builder); options.accept(builder);
//builder.dumpAsPNG(java.nio.file.Paths.get("images/" + now + ".png")); //builder.dumpAsPNG(java.nio.file.Paths.get("images/" + now + ".png"));
builder.dumpAsSVG(java.nio.file.Paths.get("images/" + now + ".svg")); 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) { } catch (java.io.IOException e) {
e.printStackTrace(); e.printStackTrace();
return null;
} }
} }
} }
......
WorldModelB ::= Region* Robot* [MyScene:Scene] OtherScene:LogicalScene* /NextOperation:Operation/ TestingOtherScene:LogicalScene* ; WorldModelB ::= Region* Robot* [MyScene:Scene] OtherScene:LogicalScene* /NextOperation:Operation/ TestingOtherScene:LogicalScene* ;
// FIXME inline CanReachObjectOfInterestWrapper // FIXME inline CanReachObjectOfInterestWrapper
Robot ::= <Name:String> CanReachObjectOfInterestWrapper <OwnedCollaborationZoneNames> <OccupiedCollaborationZoneName> ; Robot ::= <Name:String> CanReachObjectOfInterestWrapper <OwnedCollaborationZoneNames> <OccupiedCollaborationZoneNames> ;
// relations into nodes received by RagConnect are not allowed // relations into nodes received by RagConnect are not allowed
//rel Robot.OwnedCollaborationZone* <-> CollaborationZone.Owner? ; //rel Robot.OwnedCollaborationZone* <-> CollaborationZone.Owner? ;
//rel Robot.OccupiedCollaborationZone? <-> CollaborationZone.Occupient? ; //rel Robot.OccupiedCollaborationZone? <-> CollaborationZone.Occupient? ;
...@@ -34,3 +34,5 @@ rel ConfigChange.CollaborationZone -> CollaborationZone ; ...@@ -34,3 +34,5 @@ rel ConfigChange.CollaborationZone -> CollaborationZone ;
Evacuate : Operation ; Evacuate : Operation ;
rel Evacuate.CollaborationZone -> CollaborationZone ; rel Evacuate.CollaborationZone -> CollaborationZone ;
Wait : Operation ;
package de.tudresden.inf.st.placeB; package de.tudresden.inf.st.placeB;
import de.tudresden.inf.st.ceti.Object;
import de.tudresden.inf.st.ceti.Reachability; import de.tudresden.inf.st.ceti.Reachability;
import de.tudresden.inf.st.placeB.ast.*; import de.tudresden.inf.st.placeB.ast.*;
import de.tudresden.inf.st.ros3rag.common.Configuration; import de.tudresden.inf.st.ros3rag.common.Configuration;
import de.tudresden.inf.st.ros3rag.common.SharedMainParts; 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.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.function.Function;
import static de.tudresden.inf.st.ros3rag.common.Util.mqttUri; import static de.tudresden.inf.st.ros3rag.common.Util.mqttUri;
...@@ -17,19 +22,16 @@ import static de.tudresden.inf.st.ros3rag.common.Util.mqttUri; ...@@ -17,19 +22,16 @@ import static de.tudresden.inf.st.ros3rag.common.Util.mqttUri;
* @author rschoene - Initial contribution * @author rschoene - Initial contribution
*/ */
public class MainB extends SharedMainParts<MqttHandler, WorldModelB> { public class MainB extends SharedMainParts<MqttHandler, WorldModelB> {
private final String TOPIC_MY_SCENE_UPDATE_FROM_ROS;
private final String TOPIC_COMMAND;
private final String TOPIC_OTHER_SCENE_UPDATE_FROM_PLACE_A;
private final String TOPIC_DEMO_MOVE_objectRed1_RED; private final String TOPIC_DEMO_MOVE_objectRed1_RED;
private final String TOPIC_MODEL_SVG_PATH;
private de.tudresden.inf.st.ceti.Scene demo_scene;
MainB(String configFile) { MainB(String configFile) {
super("place-b", UtilB.pathToDirectoryOfPlaceB().resolve(configFile)); super("place-b", UtilB.pathToDirectoryOfPlaceB().resolve(configFile));
this.TOPIC_MY_SCENE_UPDATE_FROM_ROS = cellName + "/scene/update";
this.TOPIC_COMMAND = cellName + "/command";
this.TOPIC_OTHER_SCENE_UPDATE_FROM_PLACE_A = "place-a/logical/update";
this.TOPIC_DEMO_MOVE_objectRed1_RED = cellName + "/demo/move/objectRed1/red"; this.TOPIC_DEMO_MOVE_objectRed1_RED = cellName + "/demo/move/objectRed1/red";
this.TOPIC_MODEL_SVG_PATH = cellName + "/model/svg/path";
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
...@@ -47,6 +49,47 @@ public class MainB extends SharedMainParts<MqttHandler, WorldModelB> { ...@@ -47,6 +49,47 @@ public class MainB extends SharedMainParts<MqttHandler, WorldModelB> {
mainHandler.newConnection(TOPIC_DEMO_MOVE_objectRed1_RED, bytes -> mainHandler.newConnection(TOPIC_DEMO_MOVE_objectRed1_RED, bytes ->
UtilB.updatePositionOfObjectToLocation(model.getMyScene(), "objectRed1", "binRed") UtilB.updatePositionOfObjectToLocation(model.getMyScene(), "objectRed1", "binRed")
); );
mainHandler.newConnection("demo/initial_scene", bytes -> {
try {
demo_scene = Util.readScene(UtilB.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();
}
});
mainHandler.newConnection("demo/arm1/active", bytes ->
updateAndPublishScene("arm1", robot -> robot.toBuilder().setActive(true).build()));
mainHandler.newConnection("demo/arm1/inactive", bytes ->
updateAndPublishScene("arm1", robot -> robot.toBuilder().setActive(false).build()));
mainHandler.newConnection("demo/arm2/active", bytes ->
updateAndPublishScene("arm2", robot -> robot.toBuilder().setActive(true).build()));
mainHandler.newConnection("demo/arm2/inactive", bytes ->
updateAndPublishScene("arm2", robot -> robot.toBuilder().setActive(false).build()));
mainHandler.newConnection("demo/big-blue/cz", bytes ->
updateAndPublishScene("bigBlue", bigBlue -> {
Object.Builder builder = bigBlue.toBuilder();
builder.getPosBuilder()
.setX(0.0012)
.setY(0.65)
.setZ(0.94);
return builder.build();
})
);
mainHandler.newConnection("demo/big-blue/g1", bytes ->
updateAndPublishScene("bigBlue", bigBlue -> {
Object.Builder builder = bigBlue.toBuilder();
builder.getPosBuilder()
.setX(0.1)
.setY(1.0)
.setZ(0.93);
return builder.build();
})
);
}
private void updateAndPublishScene(String objectName, Function<Object, Object> change) {
UtilB.updateObject(demo_scene, objectName, change);
mainHandler.publish(config.forB.topicsSceneUpdate.get(0), demo_scene.toByteArray());
} }
@Override @Override
...@@ -57,13 +100,17 @@ public class MainB extends SharedMainParts<MqttHandler, WorldModelB> { ...@@ -57,13 +100,17 @@ public class MainB extends SharedMainParts<MqttHandler, WorldModelB> {
} }
@Override @Override
protected void readRobotsAndReachability() throws Exception { protected void readInitialConfigs() throws Exception {
model.setMyScene(new Scene()); model.setMyScene(new Scene());
// read and set regions
File regionBFile = UtilB.pathToDirectoryOfPlaceB().resolve(config.filenameRegions).toFile();
UtilB.setRegions(model, Util.parseRegionConfig(regionBFile));
// init robots and reachability // init robots and reachability
for (Configuration.ReachabilityConfig reachabilityConfig : config.reachability) { for (String reachabilityFileName : config.forB.reachability) {
// assumption: robots do not change during runtime, so we have stable connections // assumption: robots do not change during runtime, so we have stable connections
Path path = UtilB.pathToDirectoryOfPlaceB().resolve(Paths.get(reachabilityConfig.filename)); Path path = UtilB.pathToDirectoryOfPlaceB().resolve(Paths.get(reachabilityFileName));
Reachability reachability = UtilB.readReachability(path); Reachability reachability = UtilB.readReachability(path);
Robot robot = UtilB.createRobot(reachability.getIdRobot()); Robot robot = UtilB.createRobot(reachability.getIdRobot());
...@@ -76,17 +123,33 @@ public class MainB extends SharedMainParts<MqttHandler, WorldModelB> { ...@@ -76,17 +123,33 @@ public class MainB extends SharedMainParts<MqttHandler, WorldModelB> {
@Override @Override
protected void connectEndpoints() throws IOException { protected void connectEndpoints() throws IOException {
model.connectMyScene(mqttUri(TOPIC_MY_SCENE_UPDATE_FROM_ROS, config)); for (String topic : config.forB.topicsSceneUpdate) {
model.connectOtherScene(mqttUri(TOPIC_OTHER_SCENE_UPDATE_FROM_PLACE_A, config), 0); model.connectMyScene(mqttUri(topic, config));
model.connectNextOperation(mqttUri(TOPIC_COMMAND, config), false); }
model.connectOtherScene(mqttUri("place-a/logical/update", config), 0);
model.connectNextOperation(mqttUri(config.forB.topicCommand, config), false);
for (Robot robot : model.getRobotList()) { for (Robot robot : model.getRobotList()) {
// self-loop // self-loop
robot.connectOwnedCollaborationZoneNames(mqttUri(TOPIC_COMMAND, config)); robot.connectOwnedCollaborationZoneNames(mqttUri(config.forB.topicCommand, config));
robot.connectOccupiedCollaborationZoneNames(mqttUri(config.forB.topicCommand, config));
} }
} }
@Override @Override
protected String getModelInfos(WorldModelB worldModelB, boolean detailed) { protected String getModelInfos(WorldModelB worldModelB, boolean detailed) {
try {
String filename = model.dumpAst(builder -> {
builder.excludeChildren("Orientation", "Size");
builder.excludeRelations("ContainedInRegion");
builder.includeNonterminalAttributes("LogicalScene", "diffScenes", "diffToOperations");
builder.includeAttributes("realRegion", "computeOperations");
builder.includeNullNodes();
});
mainHandler.publish(TOPIC_MODEL_SVG_PATH, filename.getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
logger.catching(e);
}
return UtilB.getModelInfos(model, detailed); return UtilB.getModelInfos(model, detailed);
} }
......
...@@ -4,7 +4,6 @@ import de.tudresden.inf.st.ceti.Object; ...@@ -4,7 +4,6 @@ import de.tudresden.inf.st.ceti.Object;
import de.tudresden.inf.st.ceti.Reachability; import de.tudresden.inf.st.ceti.Reachability;
import de.tudresden.inf.st.placeB.ast.*; import de.tudresden.inf.st.placeB.ast.*;
import de.tudresden.inf.st.ros3rag.common.Configuration; import de.tudresden.inf.st.ros3rag.common.Configuration;
import de.tudresden.inf.st.ros3rag.common.Configuration.ReachabilityConfig;
import de.tudresden.inf.st.ros3rag.common.Util; import de.tudresden.inf.st.ros3rag.common.Util;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -18,7 +17,6 @@ import java.util.Arrays; ...@@ -18,7 +17,6 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
...@@ -64,7 +62,7 @@ public class SimpleMainB { ...@@ -64,7 +62,7 @@ public class SimpleMainB {
@SuppressWarnings("unused" ) @SuppressWarnings("unused" )
Scenario[] allScenarios = new Scenario[] { s2022, sMini, sPlaceworld, sPlaceworldManual }; Scenario[] allScenarios = new Scenario[] { s2022, sMini, sPlaceworld, sPlaceworldManual };
final Scenario scenario = sPlaceworldManual; final Scenario scenario = sPlaceworld;
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
System.out.println("Running SimpleMainB"); System.out.println("Running SimpleMainB");
...@@ -81,11 +79,10 @@ public class SimpleMainB { ...@@ -81,11 +79,10 @@ public class SimpleMainB {
config.mqttHost = scenario.mqttHost; config.mqttHost = scenario.mqttHost;
String filenameInitialSceneB = "src/main/resources/config-scene-b-" + scenario.suffix + ".json"; String filenameInitialSceneB = "src/main/resources/config-scene-b-" + scenario.suffix + ".json";
config.filenameRegions = "src/main/resources/regions-b-" + scenario.suffix + ".json"; config.filenameRegions = "src/main/resources/regions-b-" + scenario.suffix + ".json";
ReachabilityConfig reachabilityR1 = new ReachabilityConfig(); config.forB.reachability = Arrays.asList(
reachabilityR1.filename = "src/main/resources/reachability-b-r1-" + scenario.suffix + ".json"; "src/main/resources/reachability-b-r1-" + scenario.suffix + ".json",
ReachabilityConfig reachabilityR2 = new ReachabilityConfig(); "src/main/resources/reachability-b-r2-" + scenario.suffix + ".json"
reachabilityR2.filename = "src/main/resources/reachability-b-r2-" + scenario.suffix + ".json"; );
config.reachability = Arrays.asList(reachabilityR1, reachabilityR2);
Configuration configA = new Configuration(); Configuration configA = new Configuration();
String filenameInitialSceneA = "src/main/resources/config-scene-a-" + scenario.suffix + ".json"; String filenameInitialSceneA = "src/main/resources/config-scene-a-" + scenario.suffix + ".json";
...@@ -108,21 +105,21 @@ public class SimpleMainB { ...@@ -108,21 +105,21 @@ public class SimpleMainB {
mqttHandler.waitUntilReady(2, TimeUnit.SECONDS); mqttHandler.waitUntilReady(2, TimeUnit.SECONDS);
model.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS); model.ragconnectSetupMqttWaitUntilReady(2, TimeUnit.SECONDS);
Scene myScene; Scene myScene = new Scene();
// read initial scene // read initial scene
Path initialSceneFile = UtilB.pathToDirectoryOfPlaceB().resolve(filenameInitialSceneB); Path initialSceneFile = UtilB.pathToDirectoryOfPlaceB().resolve(filenameInitialSceneB);
if (initialSceneFile.toFile().exists()) {
de.tudresden.inf.st.ceti.Scene initialScene = Util.readScene(initialSceneFile); de.tudresden.inf.st.ceti.Scene initialScene = Util.readScene(initialSceneFile);
if (scenario.loadAndChangeScenes) { if (scenario.loadAndChangeScenes) {
myScene = UtilB.convert(initialScene); myScene = UtilB.convert(initialScene);
} else { } else {
myScene = new Scene();
mqttHandler.newConnection("coordinating/rag-b/command", bytes -> { mqttHandler.newConnection("coordinating/rag-b/command", bytes -> {
if (new String(bytes).equals("start")) { if (new String(bytes).equals("start")) {
mqttHandler.publish(scenario.topicSceneUpdateB, initialScene.toByteArray()); mqttHandler.publish(scenario.topicSceneUpdateB, initialScene.toByteArray());
} }
}); });
} }
}
model.setMyScene(myScene); model.setMyScene(myScene);
// read and set regions // read and set regions
...@@ -130,9 +127,9 @@ public class SimpleMainB { ...@@ -130,9 +127,9 @@ public class SimpleMainB {
UtilB.setRegions(model, Util.parseRegionConfig(regionBFile)); UtilB.setRegions(model, Util.parseRegionConfig(regionBFile));
// init robots and reachability // init robots and reachability
for (ReachabilityConfig reachabilityConfig : config.reachability) { for (String reachabilityFileName : config.forB.reachability) {
// assumption: robots do not change during runtime, so we have stable connections // assumption: robots do not change during runtime, so we have stable connections
Path path = UtilB.pathToDirectoryOfPlaceB().resolve(Paths.get(reachabilityConfig.filename)); Path path = UtilB.pathToDirectoryOfPlaceB().resolve(Paths.get(reachabilityFileName));
Reachability reachability = UtilB.readReachability(path); Reachability reachability = UtilB.readReachability(path);
Robot robot = UtilB.createRobot(reachability.getIdRobot()); Robot robot = UtilB.createRobot(reachability.getIdRobot());
...@@ -188,7 +185,9 @@ public class SimpleMainB { ...@@ -188,7 +185,9 @@ public class SimpleMainB {
LogicalScene logicalSceneFromPlaceA = sceneFromPlaceA.getLogicalScene(); LogicalScene logicalSceneFromPlaceA = sceneFromPlaceA.getLogicalScene();
byte[] bytesToSend = _ragconnect__apply__TreeDefaultLogicalSceneToBytesMapping(logicalSceneFromPlaceA); byte[] bytesToSend = _ragconnect__apply__TreeDefaultLogicalSceneToBytesMapping(logicalSceneFromPlaceA);
if (scenario.loadAndChangeScenes) { if (scenario.loadAndChangeScenes && initialSceneFile.toFile().exists()) {
de.tudresden.inf.st.ceti.Scene initialScene = Util.readScene(initialSceneFile);
describedWait(1, "send new logical scene" ); describedWait(1, "send new logical scene" );
mqttHandler.publish(topicUpdateFromPlaceA, bytesToSend); mqttHandler.publish(topicUpdateFromPlaceA, bytesToSend);
...@@ -246,7 +245,7 @@ public class SimpleMainB { ...@@ -246,7 +245,7 @@ public class SimpleMainB {
de.tudresden.inf.st.ceti.Scene scene, de.tudresden.inf.st.ceti.Scene scene,
@SuppressWarnings("SameParameterValue" ) String objectName, @SuppressWarnings("SameParameterValue" ) String objectName,
Position newPosition) { Position newPosition) {
return updateObject(scene, objectName, obj -> { return UtilB.updateObject(scene, objectName, obj -> {
Object.Builder builder = obj.toBuilder(); Object.Builder builder = obj.toBuilder();
builder.getPosBuilder() builder.getPosBuilder()
.setX(newPosition.getX()) .setX(newPosition.getX())
...@@ -259,30 +258,7 @@ public class SimpleMainB { ...@@ -259,30 +258,7 @@ public class SimpleMainB {
static de.tudresden.inf.st.ceti.Scene updateNotBusyOfRobot( static de.tudresden.inf.st.ceti.Scene updateNotBusyOfRobot(
de.tudresden.inf.st.ceti.Scene scene, de.tudresden.inf.st.ceti.Scene scene,
String objectName) { String objectName) {
return updateObject(scene, objectName, obj -> obj.toBuilder().setActive(false).build()); return UtilB.updateObject(scene, objectName, obj -> obj.toBuilder().setActive(false).build());
}
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;
} }
......
package de.tudresden.inf.st.placeB; package de.tudresden.inf.st.placeB;
import com.google.protobuf.util.JsonFormat; import com.google.protobuf.util.JsonFormat;
import de.tudresden.inf.st.ceti.Object;
import de.tudresden.inf.st.ceti.Reachability; import de.tudresden.inf.st.ceti.Reachability;
import de.tudresden.inf.st.placeB.ast.*; import de.tudresden.inf.st.placeB.ast.*;
import de.tudresden.inf.st.ros3rag.common.RegionConfiguration; import de.tudresden.inf.st.ros3rag.common.RegionConfiguration;
...@@ -12,7 +13,8 @@ import org.apache.logging.log4j.Logger; ...@@ -12,7 +13,8 @@ import org.apache.logging.log4j.Logger;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.stream.Collectors; import java.util.List;
import java.util.function.Function;
/** /**
* Static utility methods used only for place B. * Static utility methods used only for place B.
...@@ -153,6 +155,29 @@ public class UtilB { ...@@ -153,6 +155,29 @@ public class UtilB {
model.setRegionList(result); 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") @SuppressWarnings("rawtypes")
static class ExposingASTNode extends ASTNode { static class ExposingASTNode extends ASTNode {
public Scene exposed_apply_ConvertScene(de.tudresden.inf.st.ceti.Scene pbScene) throws Exception { public Scene exposed_apply_ConvertScene(de.tudresden.inf.st.ceti.Scene pbScene) throws Exception {
......
mqttHost: "localhost" mqttHost: "192.168.0.122"
useReachability: true filenameRegions: "src/main/resources/regions-b-placeworld.json"
forB:
topicsSceneUpdate:
- "/ceti_cell_placeworld/scene/update"
- "/ceti_cell_2_placeworld/scene/update"
topicCommand: "/ceti_cell_placeworld/command"
reachability: reachability:
- filename: "src/main/resources/reachability-b-arm1-placeworld.json" - "src/main/resources/reachability-b-arm1-placeworld.json"
- filename: "src/main/resources/reachability-b-arm2-placeworld.json" - "src/main/resources/reachability-b-arm2-placeworld.json"
coordinatorMqttTopicPrefix: "coordinating/rag-b" coordinatorMqttTopicPrefix: "coordinating/rag-b"
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
{ "name": "B", "positions": ["B1", "B2"] }, { "name": "B", "positions": ["B1", "B2"] },
{ "name": "C", "positions": ["C1"] }, { "name": "C", "positions": ["C1"] },
{ "name": "G", "positions": ["G1"] }, { "name": "G", "positions": ["G1"] },
{ "name": "E", "positions": ["E1"] } { "name": "E", "positions": ["E1"] },
{ "name": "CZ", "positions": ["cz1"] }
] ]
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment