From ca21508481cf677bef8c21a20a38a7b07d4fc4b2 Mon Sep 17 00:00:00 2001
From: Frank Rohde <frank.rohde@tu-dresden.de>
Date: Tue, 14 Dec 2021 17:57:10 +0100
Subject: [PATCH] Controller-layer can handle srs-conversion

---
 .../eventfilter/eventFilter.java              |   4 +
 .../UseCaseController/Administration.java     | 136 +++++++++++++++++-
 .../UseCaseController/PositionMonitoring.java |   7 +-
 3 files changed, 142 insertions(+), 5 deletions(-)

diff --git a/src/main/java/ipos/project/Functionality/eventfilter/eventFilter.java b/src/main/java/ipos/project/Functionality/eventfilter/eventFilter.java
index b7e95bc..e95840f 100644
--- a/src/main/java/ipos/project/Functionality/eventfilter/eventFilter.java
+++ b/src/main/java/ipos/project/Functionality/eventfilter/eventFilter.java
@@ -34,6 +34,10 @@ public class eventFilter {
         return this.monitoringRequest.getSerializationType();
     }
 
+    public String getRefSystemId(){
+        return this.monitoringRequest.getRefSystemId();
+    }
+
     private String getFusionStrategy(){
         return this.monitoringRequest.getFusionStrategy();
     }
diff --git a/src/main/java/ipos/project/UseCaseController/Administration.java b/src/main/java/ipos/project/UseCaseController/Administration.java
index 6d62afd..d82bdfc 100644
--- a/src/main/java/ipos/project/UseCaseController/Administration.java
+++ b/src/main/java/ipos/project/UseCaseController/Administration.java
@@ -1,13 +1,15 @@
 package ipos.project.UseCaseController;
 
-import ipos.project.DataModellntegration.iPos_Datamodel.Agent;
-import ipos.project.DataModellntegration.iPos_Datamodel.POI;
-import ipos.project.DataModellntegration.iPos_Datamodel.ReferenceSystem;
-import ipos.project.DataModellntegration.iPos_Datamodel.Zone;
+import ipos.project.DataModellntegration.iPos_Datamodel.*;
 import ipos.project.Functionality.DataServices;
 import org.apache.logging.log4j.LogManager;
 import org.springframework.stereotype.Component;
 
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
 
 @Component
 public class Administration {
@@ -22,6 +24,7 @@ public class Administration {
 
     public static void handleZone(Zone zone){
         LOG.info("handling zone-object: " + zone.toString());
+        Administration.transformToRootCoordinates(zone);
         DataServices.addZone(zone);
     }
 
@@ -33,12 +36,137 @@ public class Administration {
     public static void handleRefSystem(ReferenceSystem refSystem) {
         // muss checken, ob das RefSystem auf das ggf. verwiesen wird - tatsächlich existiert. Falls nicht: Speicherung ablehnen
         LOG.info("handling refSystem-object: " + refSystem.toString());
+        //Administration.transformToRootCoordinates(refSystem);
+        // nur sicherstellen das alle Bezugssysteme wirklich existieren
         DataServices.addRefSystem(refSystem);
     }
 
     public static void handlePoi(POI poi) {
         // muss checken, ob das RefSystem auf das verwiesen wird - tatsächlich existiert. Falls nicht: Speicherung ablehnen
         LOG.info("handling poi-object: " + poi.toString());
+        Administration.transformToRootCoordinates(poi);
         DataServices.addPoi(poi);
     }
+
+    public static void transformToRootCoordinates(PositionEvent posEvent) {
+        Administration.transformToRootCoordinates(posEvent.getPlacing());
+    }
+
+    public static void transformToRootCoordinates(Zone zone) {
+         zone.getSpace().stream()
+                .map(Administration::transformToRootCoordinates);
+    }
+
+    public static Space transformToRootCoordinates(Space space) {
+        Administration.transformToRootCoordinates(space.getCentrePoint());
+        return space;
+    }
+
+    public static void transformToRootCoordinates(ReferenceSystem refSystem) {
+        Administration.transformToRootCoordinates(refSystem.getOrigin());
+    }
+
+    public static void transformToRootCoordinates(POI poi) {
+        Administration.transformToRootCoordinates(poi.getPlacing());
+    }
+
+    /**
+     * Function recursively transforms a placing into a ROOT-placing. In each step the placing
+     * is transformed in a placing of the SRS that the origin of its current SRS has been defined
+     * in. Recursion is stopped after obtaining a ROOT-placing.
+     * @param placing
+     */
+    public static void transformToRootCoordinates(Placing placing) {
+        if (isNotRootPosition(placing.getPosition())) {
+            Position positionToBeTransformed = placing.getPosition();
+            ReferenceSystem nextTransformationGoal_SRS = positionToBeTransformed.getReferenceSystem().getOrigin().getPosition().getReferenceSystem();
+            SRSConversion.switchSRS(positionToBeTransformed, nextTransformationGoal_SRS); // assumption: not only position is changed but also ReferenceSystem-object is updated
+            transformToRootCoordinates(placing); // recursion stops when placing.getPosition() has been transformed in a ROOT-position
+        }
+    }
+
+    public static void transformToRootCoordinates(Position position) {
+        Orientation dummyOrientation = createDummyOrientation();
+        Placing placing = DataServices.createPlacing(position, dummyOrientation);
+        transformToRootCoordinates(placing); // placing.getPosition() points to the position-object that was passed to this function. The contents of this object will be changed by this call.
+    }
+
+    private static Orientation createDummyOrientation() {
+        return DataServices.createOrientation(0, 0, 0, 0);
+    }
+
+    private static boolean isRootPosition(Position position) {
+        return !isNotRootPosition(position);
+    }
+
+    private static boolean isRootPosition(String srsId){
+        return !isNotRootPosition(srsId);
+    }
+
+    private static boolean isNotRootPosition(Position position) {
+        return isNotRootPosition(position.getReferenceSystem().getId());
+    }
+
+    private static boolean isNotRootPosition(String srsId){
+        return srsId != PositionMonitoring.SRS_ID_ROOT;
+    }
+
+    /**
+     * Warning: This function does not check whether SRSConversion is actually necessary.
+     * Use function Administration::isNotRootPosition to check whether SRSConversion is necessary,
+     * before calling this function
+     * @param orientation
+
+    public static void transformToRootCoordinates(Position position, Orientation orientation) {
+        // Komponente SRSConversion aufrufen
+
+                        SRSConversion.switchSRS(rootPlacing, DataServices.getReferenceSystemByIdOrNull("CeTI_SRS"));
+                        SRSConversion.switchSRS(cetiPlacing, DataServices.getReferenceSystemByIdOrNull("CeTI_SRS"));
+    }
+     */
+
+    /**
+     * This function expects the position posEvent to be defined in reference to the ROOT-SRS
+     * @param posEvent
+     * @param refSystemId
+     */
+    public static void transformToRequesterCoordinates(PositionEvent posEvent, String refSystemId) {
+        if(posEvent.getPlacing().getPosition().getReferenceSystem().getId() != PositionMonitoring.SRS_ID_ROOT){
+            LOG.warn("Warning: Function transformToRequesterCoordinates was called with a position that is not defined in reference to the ROOT-SRS. " +
+                    "All internal data processing should be based on ROOT-positions.");
+            return;
+        }
+        if(isRootPosition(refSystemId)){
+            return; // nothing to be done, as posEvent is it is assumed that posEvent is already a ROOT-position
+        }
+        ReferenceSystem finalTarget = DataServices.getReferenceSystemByIdOrNull(refSystemId);
+        Placing placingToBeTransformed = posEvent.getPlacing();
+        List<ReferenceSystem> allTargetsFromRootToFinal = computeTargets(finalTarget);
+        transformPlacingSuccessively(placingToBeTransformed, allTargetsFromRootToFinal);
+        // Komponente SRSConversion zur Transformation der ROOT-Position posEvent in das SRS refSystemId
+    }
+
+    /**
+     * Assumption: Sooner or later each target depends on ROOT-SRS
+     * @param target
+     * @return
+     */
+    private static List<ReferenceSystem> computeTargets(ReferenceSystem target) {
+        if (isRootPosition(target.getId())){
+            List<ReferenceSystem> targets = new LinkedList<>();
+            return targets; // ROOT-SRS itself is not a target, therefore it is not added to the list
+        }else {
+            ReferenceSystem nextTarget = target.getOrigin().getPosition().getReferenceSystem();
+            List<ReferenceSystem> targets = computeTargets(nextTarget);
+            targets.add(target); // targets[0]: the SRS that the ROOT-position should be transformed into; targets[targets.size()-1]: final target, i.e., requester-SRS
+            return targets;
+        }
+
+    }
+
+    private static void transformPlacingSuccessively(Placing placingToBeTransformed, List<ReferenceSystem> transformationTargets) {
+        for (ReferenceSystem transTarget : transformationTargets){
+            SRSConversion.switchSRS(placingToBeTransformed, transTarget);
+        }
+    }
 }
diff --git a/src/main/java/ipos/project/UseCaseController/PositionMonitoring.java b/src/main/java/ipos/project/UseCaseController/PositionMonitoring.java
index c12e296..8591bc9 100644
--- a/src/main/java/ipos/project/UseCaseController/PositionMonitoring.java
+++ b/src/main/java/ipos/project/UseCaseController/PositionMonitoring.java
@@ -41,6 +41,7 @@ public class PositionMonitoring {
     public static final String TOPIC_WINDOW = "Human_at_Window_Side";
     public static final String ZONE_ID_DOOR = "cobot1_door_zone";
     public static final String ZONE_ID_WINDOW = "cobot1_window_zone";
+    public static final String SRS_ID_ROOT = "ROOT";
 
     public static final int SDF_TIME_INTERVAL = 2500; // recent milliseconds to take into account for sensor data fusion
 
@@ -211,6 +212,8 @@ public class PositionMonitoring {
         // TODO: Update currentPlacing attribute of the affected localizableObject
         LOG.info("Received <" + posEvent + ">");
         logging_sdfindfro(posEvent);
+        Administration.transformToRootCoordinates(posEvent);
+        LOG.info("Position after transformation to ROOT-coordinates: " + posEvent.getPlacing().getPosition().toString());
 
         boolean posEventMeetsSdfAccuracyCondition = SensorDataFusion.isMostAccuratePositionAvailable(posEvent);
         List<FilteringResult> filteringResults = new LinkedList<>();
@@ -259,7 +262,8 @@ public class PositionMonitoring {
                 continue;
             }
             PositionEvent posEventCopy = createShallowCopyOfPosEvent(posEvent);
-            posEventCopy.getZonedescriptors().addAll(zoneDescriptorsEFilterResult);
+            posEventCopy.getZonedescriptors().addAll(zoneDescriptorsEFilterResult); // ZoneDescriptors-Collection of PositionEvent was empty up until this point of execution
+            Administration.transformToRequesterCoordinates(posEventCopy, eFilter.getRefSystemId());
             SimpleSceneIntegration.receiveMessage(posEventCopy, monitoringTaskId, getFirstNotificationTypeOrUndefined(zoneDescriptorsEFilterResult), eFilter.getSerializationType());
         }
     }
@@ -277,6 +281,7 @@ public class PositionMonitoring {
             if( containsExitNotification(zoneDescriptorsEFilterResult)){
                 PositionEvent posEventCopy = createShallowCopyOfPosEvent(posEvent);
                 posEventCopy.getZonedescriptors().addAll(zoneDescriptorsEFilterResult);
+                Administration.transformToRequesterCoordinates(posEventCopy, eFilter.getRefSystemId());
                 SimpleSceneIntegration.receiveMessage(posEventCopy, monitoringTaskId, getFirstNotificationTypeOrUndefined(zoneDescriptorsEFilterResult), eFilter.getSerializationType());
                 sentAlready.add(monitoringTaskId);
             }
-- 
GitLab