diff --git a/goal.sh b/goal.sh new file mode 100755 index 0000000000000000000000000000000000000000..7f5c04923a49bf659e1a9f2680c0507e55de48f3 --- /dev/null +++ b/goal.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +./gradlew :ros2rag.goal:installDist +./ros2rag.goal/build/install/ros2rag.goal/bin/ros2rag.goal $@ diff --git a/ros2rag.common/proto/trajectory.proto b/ros2rag.common/proto/trajectory.proto new file mode 100644 index 0000000000000000000000000000000000000000..2724b79c3ba3ed20efa99b6c66e6d415e8f3075d --- /dev/null +++ b/ros2rag.common/proto/trajectory.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; + +package plan; + +message Trajectory { + + message Position { + double x = 1; + double y = 2; + double z = 3; + } + + repeated Position pos = 1; +} diff --git a/ros2rag.goal/.gitignore b/ros2rag.goal/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..87b4cdd3d7c6a41502ca98703abeeb69a1d536fb --- /dev/null +++ b/ros2rag.goal/.gitignore @@ -0,0 +1,5 @@ +build +src/gen-res/ +src/gen/ +out/ +*.class diff --git a/ros2rag.goal/build.gradle b/ros2rag.goal/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..c6ee36c57fce4032365deb999b3e72393dd31b9c --- /dev/null +++ b/ros2rag.goal/build.gradle @@ -0,0 +1,146 @@ +apply plugin: 'jastadd' +apply plugin: 'application' +apply plugin: 'com.google.protobuf' + +sourceCompatibility = 1.8 + +mainClassName = 'de.tudresden.inf.st.ros2rag.goal.GoalMain' + +repositories { + jcenter() +} + +buildscript { + repositories.jcenter() + dependencies { + classpath 'org.jastadd:jastaddgradle:1.13.3' + classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.12' + } +} + +configurations { + baseRuntimeClasspath +} + +sourceSets.main.java.srcDir "src/gen/java" +jar.manifest.attributes('Main-Class': 'de.tudresden.inf.st.ros2rag.goal.GoalMain') + +dependencies { + implementation project (':ros2rag.base') + implementation project (':ros2rag.common') + baseRuntimeClasspath project (':ros2rag.base') + api group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: "${jackson_version}" + api group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: "${jackson_version}" + implementation group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' + api group: 'com.google.protobuf', name: 'protobuf-java', version: '3.0.0' + api group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15' + + jastadd2 "org.jastadd:jastadd:2.3.4" +} + +test { + useJUnitPlatform() + + maxHeapSize = '1G' +} + +// Input files for relast +def relastFiles = ["src/gen/jastadd/Grammar.relast"] + +// phases: Ros2Rag -> RelAst -> JastAdd +// phase: Ros2Rag +task ros2rag(type: JavaExec) { + classpath = configurations.baseRuntimeClasspath + + group = 'Build' + main = 'org.jastadd.ros2rag.compiler.Compiler' + + args([ + '--verbose', + '--outputDir=src/gen/jastadd', + '--inputGrammar=src/main/jastadd/GoalModel.relast', + '--inputRos2Rag=src/main/jastadd/GoalModel.ros2rag', + '--rootNode=GoalModel' + ]) +} + +// phase: RelAst +task relastToJastAdd(type: JavaExec) { + group = 'Build' + main = "-jar" + + args(["../libs/relast.jar", + "--grammarName=./src/gen/jastadd/model", + "--useJastAddNames", + "--listClass=java.util.ArrayList", + "--jastAddList=JastAddList", + "--resolverHelper", + "--file"] + + + relastFiles) + + inputs.files relastFiles + outputs.files file("./src/gen/jastadd/model.ast"), file("./src/gen/jastadd/model.jadd") +} + +// phase: JastAdd +jastadd { + configureModuleBuild() + modules { + //noinspection GroovyAssignabilityCheck + module("ros2rag goal") { + + java { + basedir "src/" + include "main/**/*.java" + include "gen/**/*.java" + } + + jastadd { + basedir "src/" + include "main/jastadd/**/*.ast" + include "main/jastadd/**/*.jadd" + include "main/jastadd/**/*.jrag" + include "gen/jastadd/**/*.ast" + include "gen/jastadd/**/*.jadd" + include "gen/jastadd/**/*.jrag" + } + } + } + + cleanGen.doFirst { + delete "src/gen/java/org" + delete "src/gen-res/BuildInfo.properties" + } + + preprocessParser.doFirst { + + args += ["--no-beaver-symbol"] + + } + + module = "ros2rag goal" + + astPackage = 'de.tudresden.inf.st.ros2rag.goal.ast' + + genDir = 'src/gen/java' + + buildInfoDir = 'src/gen-res' + + // jastaddOptions = ["--lineColumnNumbers", "--visitCheck=true", "--rewrite=cnta", "--cache=all"] + // default options are: '--rewrite=cnta', '--safeLazy', '--visitCheck=false', '--cacheCycle=false' + extraJastAddOptions = ["--lineColumnNumbers", '--List=JastAddList'] +} + +// Workflow configuration for phases +generateAst.dependsOn relastToJastAdd +relastToJastAdd.dependsOn ros2rag + +protobuf { + // create strange directories, so use default here +// generatedFilesBaseDir = "$projectDir/src/gen/java" + protoc { + // The artifact spec for the Protobuf Compiler + artifact = 'com.google.protobuf:protoc:3.0.0' + } +} diff --git a/ros2rag.goal/src/main/jastadd/Computation.jrag b/ros2rag.goal/src/main/jastadd/Computation.jrag new file mode 100644 index 0000000000000000000000000000000000000000..c64146e8de760553aaf7aef779c80d94306137b2 --- /dev/null +++ b/ros2rag.goal/src/main/jastadd/Computation.jrag @@ -0,0 +1,101 @@ +aspect Computation { +// syn boolean RobotArm.isInSafetyZone() { +// System.out.println("isInSafetyZone()"); +// for (Link link : getLinkList()) { +// if (model().getZoneModel().isInSafetyZone(link.getCurrentPosition())) { +// return true; +// } +// } +// return model().getZoneModel().isInSafetyZone(getEndEffector().getCurrentPosition()); +// } +// +// cache ZoneModel.isInSafetyZone(IntPosition pos); +// syn boolean ZoneModel.isInSafetyZone(IntPosition pos) { +// System.out.println("isInSafetyZone(" + pos + ")"); +// for (Zone sz : getSafetyZoneList()) { +// for (Coordinate coordinate : sz.getCoordinateList()) { +// if (coordinate.getPosition().equals(pos)) { +// return true; +// } +// } +// } +// return false; +// } +// +// syn double RobotArm.getAppropriateSpeed() { +// return isInSafetyZone() ? 0.4d : 1.0d; +// } + syn Workflow GoalModel.getWorkflow() { + Workflow result = new Workflow(); + Step lastStep = null; + int index = 0; + for (WorkPose workPose : getWorkPoseList()) { + MoveToStep moveToStep = new MoveToStep(); + moveToStep.setId(index++); + moveToStep.setPosition(workPose.getPosition()); + if (lastStep != null) { + lastStep.setSuccessor(moveToStep); + } else { + // this is the first move-to-step + result.setCurrentStep(moveToStep.getId()); + } + result.addStep(moveToStep); + WorkStep workStep = new WorkStep(); + workStep.setId(index++); + workStep.setDuration(workPose.getDuration()); + moveToStep.setSuccessor(workStep); + result.addStep(workStep); + lastStep = moveToStep; + } + FinishedStep finish = new FinishedStep(); + finish.setId(index); + result.addStep(finish); + if (lastStep != null) { + lastStep.setSuccessor(finish); + } + return result; + } + + syn int Workflow.getReadyForThisStep() { + return currentStep().readyForThisStep(); + } + + syn int Step.readyForThisStep(); + eq MoveToStep.readyForThisStep() { + // check if we have reached the destination yet + if (isNear(model().getRobotState().getCurrentPosition(), getPosition())) { + return getSuccessor().getId(); + } + // we haven't reached the destination, so we are not ready and return our id + return getId(); + } + eq WorkStep.readyForThisStep() { + // check if we have "worked" long enough + if (lastStarted() + getDuration() >= model().getRobotState().getLastUpdate()) { + // proceed to next step + return getSuccessor().getId(); + } + // we haven't worked long enough, so we are not ready and return our id + return getId(); + } + eq FinishedStep.readyForThisStep() { + // we always want to stay in this step + return getId(); + } + + syn DoublePosition Workflow.getNextPosition() { + return currentStep().nextPosition(); + } + syn DoublePosition Step.nextPosition(); + eq MoveToStep.nextPosition() = getPosition(); + eq WorkStep.nextPosition() = getPredecessor().nextPosition(); + eq FinishedStep.nextPosition() = getPredecessor().nextPosition(); + + private static final double MoveToStep.DELTA = 0.1; + private boolean MoveToStep.isNear(DoublePosition one, DoublePosition other) { + return Math.abs(one.getX() - other.getX()) < DELTA && + Math.abs(one.getY() - other.getY()) < DELTA && + Math.abs(one.getZ() - other.getZ()) < DELTA; + } + +} diff --git a/ros2rag.goal/src/main/jastadd/GoalModel.jadd b/ros2rag.goal/src/main/jastadd/GoalModel.jadd new file mode 100644 index 0000000000000000000000000000000000000000..f114361784e4a9db8f8ac0674408220999108399 --- /dev/null +++ b/ros2rag.goal/src/main/jastadd/GoalModel.jadd @@ -0,0 +1,47 @@ +aspect GrammarTypes { + public class DoublePosition { + private final double x, y, z; + + private DoublePosition(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public static DoublePosition of(double x, double y, double z) { + return new DoublePosition(x, y, z); + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getZ() { + return z; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DoublePosition that = (DoublePosition) o; + return x == that.x && + y == that.y && + z == that.z; + } + + @Override + public int hashCode() { + return java.util.Objects.hash(x, y, z); + } + + @Override + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } + } +} diff --git a/ros2rag.goal/src/main/jastadd/GoalModel.relast b/ros2rag.goal/src/main/jastadd/GoalModel.relast new file mode 100644 index 0000000000000000000000000000000000000000..8c1b2c33425c4e0fe27e100063fadf886d24fee1 --- /dev/null +++ b/ros2rag.goal/src/main/jastadd/GoalModel.relast @@ -0,0 +1,15 @@ +GoalModel ::= WorkPose* /Workflow/ RobotState ; + +RobotState ::= <CurrentPosition:DoublePosition> <LastUpdate:long> ; + +WorkPose ::= <Position:DoublePosition> <Duration:long> ; // Position in [m,m,m], Duration in ms + +Workflow ::= Step* /<ReadyForThisStep:int>/ /<NextPosition:DoublePosition>/ <CurrentStep:int> <CurrentStepStart:long> ; // NextPosition in [m,m,m]; CurrentStepStart in ms; ReadyForThisStep and CurrentStep are step ids + +abstract Step ::= <Id:int> ; // Started in ms +MoveToStep : Step ::= <Position:DoublePosition> ; // Position in [m,m,m] +WorkStep : Step ::= <Duration:long> ; // Duration in ms +FinishedStep : Step ; + +rel Step.successor <-> Step.predecessor; +//rel GoalModel.currentStep? -> Step; diff --git a/ros2rag.goal/src/main/jastadd/GoalModel.ros2rag b/ros2rag.goal/src/main/jastadd/GoalModel.ros2rag new file mode 100644 index 0000000000000000000000000000000000000000..1e99b20fc0f176e60e7621931180a53a19ca1515 --- /dev/null +++ b/ros2rag.goal/src/main/jastadd/GoalModel.ros2rag @@ -0,0 +1,48 @@ +/** + * Version 2020-05-28 + */ +// --- update definitions --- +read RobotState.CurrentPosition using ParseLinkState, LinkStateToDoublePosition ; +read RobotState.LastUpdate using TickWhenLinkState ; +write Workflow.ReadyForThisStep ; // |_ Those two roles encode are attribute-driven rewrite (via mqtt) +read Workflow.CurrentStep ; // | +write Workflow.NextPosition using CreateTrajectoryMessage, SerializeTrajectory ; + +// --- dependency definitions --- +Workflow.ReadyForThisStep canDependOn RobotState.LastUpdate as LastUpdateDependency ; +Workflow.ReadyForThisStep canDependOn RobotState.CurrentPosition as PositionDependency ; + +Workflow.NextPosition canDependOn Workflow.CurrentStep as OnStepChangeDependency ; + +// --- mapping definitions --- +ParseLinkState maps byte[] bytes to panda.Linkstate.PandaLinkState {: +// System.out.println("ParseLinkState"); + return panda.Linkstate.PandaLinkState.parseFrom(bytes); +:} + +TickWhenLinkState maps byte[] bytes to long {: +// System.out.println("TickWhenLinkState"); + return System.currentTimeMillis(); +:} + +SerializeTrajectory maps plan.TrajectoryOuterClass.Trajectory t to byte[] {: +// System.out.println("SerializeTrajectory"); + return t.toByteArray(); +:} + +LinkStateToDoublePosition maps panda.Linkstate.PandaLinkState pls to DoublePosition {: +// System.out.println("LinkStateToDoublePosition"); + panda.Linkstate.PandaLinkState.Position p = pls.getPos(); + return DoublePosition.of(p.getPositionX(), p.getPositionY(), p.getPositionZ()); +:} + +CreateTrajectoryMessage maps DoublePosition dp to plan.TrajectoryOuterClass.Trajectory {: + // compute intermediate points at ROS side, not here + return plan.TrajectoryOuterClass.Trajectory.newBuilder() + .addPos(plan.TrajectoryOuterClass.Trajectory.Position.newBuilder() + .setX(dp.getX()) + .setY(dp.getY()) + .setZ(dp.getZ()) + .build()) + .build(); +:} diff --git a/ros2rag.goal/src/main/jastadd/Navigation.jrag b/ros2rag.goal/src/main/jastadd/Navigation.jrag new file mode 100644 index 0000000000000000000000000000000000000000..56d596c2a33dcb6d33bb4028fee173b4a61db01a --- /dev/null +++ b/ros2rag.goal/src/main/jastadd/Navigation.jrag @@ -0,0 +1,27 @@ +aspect Navigation { +// inh Model RobotArm.model(); +// eq Model.getRobotArm().model() = this; +// +// inh RobotArm Link.containingRobotArm(); +// eq RobotArm.getLink().containingRobotArm() = this; +// eq RobotArm.getEndEffector().containingRobotArm() = this; + syn Step Workflow.currentStep() { + return resolveStep(getCurrentStep()); + } + + syn Step Workflow.resolveStep(int id) { + for (Step step : getSteps()) { + if (step.getId() == id) { + return step; + } + } + System.err.println("Could not resolve step with id " + id); + return null; + } + + inh GoalModel Step.model(); + eq GoalModel.getChild().model() = this; + + inh long Step.lastStarted(); + eq Workflow.getStep().lastStarted() = getCurrentStepStart(); +} diff --git a/ros2rag.goal/src/main/jastadd/Printing.jrag b/ros2rag.goal/src/main/jastadd/Printing.jrag new file mode 100644 index 0000000000000000000000000000000000000000..cc2c91bbbb17d3bd885d1bb41765b4fad7f362cf --- /dev/null +++ b/ros2rag.goal/src/main/jastadd/Printing.jrag @@ -0,0 +1,6 @@ +aspect Printing { + syn String Step.prettyPrint(); + eq MoveToStep.prettyPrint() = getId() + "Move to " + getPosition(); + eq WorkStep.prettyPrint() = getId() + "Work " + getDuration(); + eq FinishedStep.prettyPrint() = getId() + "Finish"; +} diff --git a/ros2rag.goal/src/main/java/de/tudresden/inf/st/ros2rag/goal/GoalMain.java b/ros2rag.goal/src/main/java/de/tudresden/inf/st/ros2rag/goal/GoalMain.java new file mode 100644 index 0000000000000000000000000000000000000000..39e94bbe1043e6d0c2aab981d1d1a1b07ba7d7d8 --- /dev/null +++ b/ros2rag.goal/src/main/java/de/tudresden/inf/st/ros2rag/goal/GoalMain.java @@ -0,0 +1,141 @@ +package de.tudresden.inf.st.ros2rag.goal; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import de.tudresden.inf.st.ros2rag.common.DataConfiguration.DataWorkPose; +import de.tudresden.inf.st.ros2rag.common.Util; +import de.tudresden.inf.st.ros2rag.goal.ast.*; +import de.tudresden.inf.st.ros2rag.common.DataConfiguration; +import de.tudresden.inf.st.ros2rag.common.DataConfiguration.ActualConfiguration; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import plan.TrajectoryOuterClass; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Testing Ros2Rag without generating something. + * + * @author rschoene - Initial contribution + */ +public class GoalMain { + + private static final Logger logger = LogManager.getLogger(GoalMain.class); + private MqttHandler mainHandler; + private GoalModel model; + + public void run(String[] args) throws IOException, InterruptedException { + File configFile = new File(args.length == 0 ? "../ros2rag.common/config.yaml" : args[0]); + + // --- No configuration below this line --- + + ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + System.out.println("Using config file: " + configFile.getAbsolutePath()); + ActualConfiguration config = mapper.readValue(configFile, DataConfiguration.class).panda_mqtt_connector; + + model = new GoalModel(); + Util.setMqttHost(model::MqttSetHost, config); + + for (DataWorkPose dataWorkPose : config.goal_poses) { + WorkPose workPose = new WorkPose(); + double[] position = {0, 0, 0}; + String[] positionSplit = dataWorkPose.position.split(" "); + for (int i = 0; i < positionSplit.length; i++) { + position[i] = Double.parseDouble(positionSplit[i]); + } + workPose.setPosition(DoublePosition.of(position[0], position[1], position[2])); + workPose.setDuration(Long.parseLong(dataWorkPose.wait)); + model.addWorkPose(workPose); + } + RobotState robotState = new RobotState(); + robotState.setCurrentPosition(DoublePosition.of(0, 0, 0)); + robotState.setLastUpdate(0); + model.setRobotState(robotState); + + model.MqttWaitUntilReady(2, TimeUnit.SECONDS); + + logger.debug("Setting dependencies"); + /* + Workflow.ReadyForThisStep canDependOn RobotState.LastUpdate as LastUpdateDependency ; + Workflow.ReadyForThisStep canDependOn RobotState.CurrentPosition as PositionDependency ; + Workflow.NextPosition canDependOn Workflow.CurrentStep as OnStepChangeDependency ; + */ + model.getWorkflow().addLastUpdateDependency(robotState); + model.getWorkflow().addPositionDependency(robotState); + model.getWorkflow().addOnStepChangeDependency(model.getWorkflow()); + + logger.debug("Connecting to topics"); + /* + read RobotState.CurrentPosition using ParseLinkState, LinkStateToDoublePosition ; + read RobotState.LastUpdate using TickWhenLinkState ; + write Workflow.ReadyForThisStep ; // |_ Those two roles encode are attribute-driven rewrite (via mqtt) + read Workflow.CurrentStep ; // | + write Workflow.NextPosition using CreateTrajectoryMessage, SerializeTrajectory ; + */ + Util.iterateLinks((isEndEffector, topic, name) -> { + if (isEndEffector) { + robotState.connectCurrentPosition(topic); + robotState.connectLastUpdate(topic); + } + }, config); + model.getWorkflow().connectCurrentStep(config.topics.nextStep); + model.getWorkflow().connectReadyForThisStep(config.topics.nextStep, false); + model.getWorkflow().connectNextPosition(config.topics.trajectory, false); + + logStatus("Start"); + CountDownLatch exitCondition = new CountDownLatch(1); + + logger.info("To print the current model states, send a message to the topic 'model'."); + logger.info("To exit the system cleanly, send a message to the topic 'exit', or use Ctrl+C."); + + mainHandler = new MqttHandler("mainHandler").dontSendWelcomeMessage(); + Util.setMqttHost(mainHandler::setHost, config); + mainHandler.waitUntilReady(2, TimeUnit.SECONDS); + mainHandler.newConnection("exit", bytes -> exitCondition.countDown()); + mainHandler.newConnection("model", bytes -> logStatus(new String(bytes))); + +// sendInitialDataConfig(mainHandler, config.topics.dataConfig); + + Runtime.getRuntime().addShutdownHook(new Thread(this::close)); + + exitCondition.await(); + + this.close(); + } + +// private void sendInitialDataConfig(MqttHandler mainHandler, String dataConfigTopic) { +// Dataconfig.DataConfig dataConfig = Dataconfig.DataConfig.newBuilder() +// .setEnablePosition(true) +// .setEnableOrientation(false) +// .setEnableTwistAngular(false) +// .setEnableTwistLinear(false) +// .setPublishRate(100) +// .build(); +// mainHandler.publish(dataConfigTopic, dataConfig.toByteArray(), true); +// } + + private void logStatus(String prefix) { + StringBuilder sb = new StringBuilder(prefix).append("\n"); + for (Step step : model.getWorkflow().getSteps()) { + sb.append(" ").append(step.prettyPrint()).append("\n"); + } + sb.append("CurrentStep: ").append(model.getWorkflow().getCurrentStep()) + .append(", lastStart: ").append(model.getWorkflow().getCurrentStepStart()).append("\n"); + sb.append("CurrentPosition: ").append(model.getRobotState().getCurrentPosition()) + .append(", lastUpdate: ").append(model.getRobotState().getLastUpdate()).append("\n"); + logger.info(sb.toString()); + } + + private void close() { + logger.info("Exiting ..."); + mainHandler.close(); + model.MqttCloseConnections(); + } + + public static void main(String[] args) throws IOException, InterruptedException { + new GoalMain().run(args); + } +} diff --git a/ros2rag.goal/src/main/proto b/ros2rag.goal/src/main/proto new file mode 120000 index 0000000000000000000000000000000000000000..bb7d2bae29902b994e92987325a878a0fe318c69 --- /dev/null +++ b/ros2rag.goal/src/main/proto @@ -0,0 +1 @@ +../../../ros2rag.common/proto/ \ No newline at end of file diff --git a/ros2rag.goal/src/main/resources/log4j2.xml b/ros2rag.goal/src/main/resources/log4j2.xml new file mode 100644 index 0000000000000000000000000000000000000000..98d9c02e1bef12b4efb000298de7903f3ae8bf74 --- /dev/null +++ b/ros2rag.goal/src/main/resources/log4j2.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration status="INFO"> + <Appenders> + <Console name="Console" target="SYSTEM_OUT"> + <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{1.} - %msg%n"/> + </Console> + </Appenders> + <Loggers> + <Root level="debug"> + <AppenderRef ref="Console"/> + </Root> + </Loggers> +</Configuration> diff --git a/ros2rag.receiverstub/src/main/java/de/tudresden/inf/st/ros2rag/receiverstub/ReceiverMain.java b/ros2rag.receiverstub/src/main/java/de/tudresden/inf/st/ros2rag/receiverstub/ReceiverMain.java index 54b8458adb378b5d63c7dee3617cee1738acf926..8487e621e28b26dd5abc7b78757f797f6f56a411 100644 --- a/ros2rag.receiverstub/src/main/java/de/tudresden/inf/st/ros2rag/receiverstub/ReceiverMain.java +++ b/ros2rag.receiverstub/src/main/java/de/tudresden/inf/st/ros2rag/receiverstub/ReceiverMain.java @@ -5,14 +5,16 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.google.protobuf.InvalidProtocolBufferException; import config.Dataconfig.DataConfig; import config.Robotconfig.RobotConfig; -import de.tudresden.inf.st.ros2rag.starter.Util; import de.tudresden.inf.st.ros2rag.starter.ast.MqttHandler; -import de.tudresden.inf.st.ros2rag.starter.data.DataConfiguration; -import de.tudresden.inf.st.ros2rag.starter.data.DataConfiguration.ActualConfiguration; +import de.tudresden.inf.st.ros2rag.common.Util; +import de.tudresden.inf.st.ros2rag.common.DataConfiguration; +import de.tudresden.inf.st.ros2rag.common.DataConfiguration.ActualConfiguration; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import panda.Linkstate.PandaLinkState; +import plan.TrajectoryOuterClass; +import plan.TrajectoryOuterClass.Trajectory; import java.io.File; import java.io.IOException; @@ -39,10 +41,12 @@ public class ReceiverMain { AtomicInteger topicMaxLength = new AtomicInteger(); MqttHandler receiver = new MqttHandler("receiver stub"); - Util.setMqttHost(receiver, config); + Util.setMqttHost(receiver::setHost, config); receiver.waitUntilReady(2, TimeUnit.SECONDS); receiver.newConnection(config.topics.robotConfig, this::printRobotConfig); receiver.newConnection(config.topics.dataConfig, this::printDataConfig); + receiver.newConnection(config.topics.trajectory, this::printTrajectory); + receiver.newConnection(config.topics.nextStep, this::printNextStep); Util.iterateLinks((isEndEffector, topic, name) -> { receiver.newConnection(topic, this::printPandaLinkState); @@ -124,7 +128,31 @@ public class ReceiverMain { } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } + } + + private void printTrajectory(byte[] bytes) { + try { + logger.debug("Got a trajectory message, parsing ..."); + if (logger.isInfoEnabled()) { + Trajectory trajectory = Trajectory.parseFrom(bytes); + StringBuilder sb = new StringBuilder("trajectory:"); + for (Trajectory.Position pos : trajectory.getPosList()) { + sb.append(" pos(") + .append(String.format("% .5f,", pos.getX())) + .append(String.format("% .5f,", pos.getY())) + .append(String.format("% .5f", pos.getZ())) + .append(")"); + } + logger.info(sb.toString()); + } + } catch (InvalidProtocolBufferException e) { + e.printStackTrace(); + } + } + private void printNextStep(byte[] bytes) { + logger.info("nextStep: {}", + java.nio.ByteBuffer.wrap(bytes).getInt()); } }