diff --git a/sim/contrib/examples/AEB/configs/systemConfigBlueprint.xml b/sim/contrib/examples/AEB/configs/systemConfigBlueprint.xml
index fcbdac7cbb132b1198300bf2b0550817d006a47a..0c84330e673792ef7e99e057dc327551a3353778 100755
--- a/sim/contrib/examples/AEB/configs/systemConfigBlueprint.xml
+++ b/sim/contrib/examples/AEB/configs/systemConfigBlueprint.xml
@@ -37,14 +37,25 @@
                 <parameters/>
             </component>
             <component>
-                <id>SensorFusion</id>
+                <id>SensorAggregation</id>
+                <schedule>
+                    <priority>351</priority>
+                    <offset>0</offset>
+                    <cycle>100</cycle>
+                    <response>0</response>
+                </schedule>
+                <library>SensorAggregation_OSI</library>
+                <parameters/>
+            </component>
+            <component>
+                <id>SensorFusionErrorless</id>
                 <schedule>
                     <priority>350</priority>
                     <offset>0</offset>
                     <cycle>100</cycle>
                     <response>0</response>
                 </schedule>
-                <library>SensorFusion_OSI</library>
+                <library>SensorFusionErrorless_OSI</library>
                 <parameters/>
             </component>
             <component>
@@ -550,17 +561,6 @@
                     <input>2</input>
                 </target>
             </connection>
-            <connection>
-                <id>9190</id>
-                <source>
-                    <component>SensorFusion</component>
-                    <output>0</output>
-                </source>
-                <target>
-                    <component>AEB</component>
-                    <input>0</input>
-                </target>
-            </connection>
             <connection>
                 <id>9292</id>
                 <source>
@@ -588,6 +588,28 @@
                     <input>100</input>
                 </target>
             </connection>
+            <connection>
+                <id>9390</id>
+                <source>
+                    <component>SensorAggregation</component>
+                    <output>0</output>
+                </source>
+                <target>
+                    <component>SensorFusionErrorless</component>
+                    <input>0</input>
+                </target>
+            </connection>
+            <connection>
+                <id>9490</id>
+                <source>
+                    <component>SensorFusionErrorless</component>
+                    <output>0</output>
+                </source>
+                <target>
+                    <component>AEB</component>
+                    <input>0</input>
+                </target>
+            </connection>
             <connection>
                 <id>9581</id>
                 <source>
@@ -618,7 +640,7 @@
                     <output>0</output>
                 </source>
                 <target>
-                    <component>SensorFusion</component>
+                    <component>SensorAggregation</component>
                     <input>0</input>
                 </target>
             </connection>
diff --git a/sim/contrib/examples/AEB/masterConfig.xml b/sim/contrib/examples/AEB/masterConfig.xml
index 9257e8b8598137c434b620a1d9fbb52543fcd69b..7cc7bd575eb4c6bb04762fd8a3e0e3fc9421ffec 100644
--- a/sim/contrib/examples/AEB/masterConfig.xml
+++ b/sim/contrib/examples/AEB/masterConfig.xml
@@ -1,7 +1,7 @@
 <masterConfig>
   <logLevel>0</logLevel>
   <logFileMaster>OpenPassMaster.log</logFileMaster>
-  <slave>OpenPassSlave</slave>
+  <slave>OpenPassSlave.exe</slave>
   <libraries>lib</libraries>
   <slaveConfigs>
     <slaveConfig>
diff --git a/sim/contrib/examples/Static AgentProfiles/configs/systemConfigBlueprint.xml b/sim/contrib/examples/Static AgentProfiles/configs/systemConfigBlueprint.xml
index fcbdac7cbb132b1198300bf2b0550817d006a47a..0c84330e673792ef7e99e057dc327551a3353778 100755
--- a/sim/contrib/examples/Static AgentProfiles/configs/systemConfigBlueprint.xml	
+++ b/sim/contrib/examples/Static AgentProfiles/configs/systemConfigBlueprint.xml	
@@ -37,14 +37,25 @@
                 <parameters/>
             </component>
             <component>
-                <id>SensorFusion</id>
+                <id>SensorAggregation</id>
+                <schedule>
+                    <priority>351</priority>
+                    <offset>0</offset>
+                    <cycle>100</cycle>
+                    <response>0</response>
+                </schedule>
+                <library>SensorAggregation_OSI</library>
+                <parameters/>
+            </component>
+            <component>
+                <id>SensorFusionErrorless</id>
                 <schedule>
                     <priority>350</priority>
                     <offset>0</offset>
                     <cycle>100</cycle>
                     <response>0</response>
                 </schedule>
-                <library>SensorFusion_OSI</library>
+                <library>SensorFusionErrorless_OSI</library>
                 <parameters/>
             </component>
             <component>
@@ -550,17 +561,6 @@
                     <input>2</input>
                 </target>
             </connection>
-            <connection>
-                <id>9190</id>
-                <source>
-                    <component>SensorFusion</component>
-                    <output>0</output>
-                </source>
-                <target>
-                    <component>AEB</component>
-                    <input>0</input>
-                </target>
-            </connection>
             <connection>
                 <id>9292</id>
                 <source>
@@ -588,6 +588,28 @@
                     <input>100</input>
                 </target>
             </connection>
+            <connection>
+                <id>9390</id>
+                <source>
+                    <component>SensorAggregation</component>
+                    <output>0</output>
+                </source>
+                <target>
+                    <component>SensorFusionErrorless</component>
+                    <input>0</input>
+                </target>
+            </connection>
+            <connection>
+                <id>9490</id>
+                <source>
+                    <component>SensorFusionErrorless</component>
+                    <output>0</output>
+                </source>
+                <target>
+                    <component>AEB</component>
+                    <input>0</input>
+                </target>
+            </connection>
             <connection>
                 <id>9581</id>
                 <source>
@@ -618,7 +640,7 @@
                     <output>0</output>
                 </source>
                 <target>
-                    <component>SensorFusion</component>
+                    <component>SensorAggregation</component>
                     <input>0</input>
                 </target>
             </connection>
diff --git a/sim/contrib/examples/Static AgentProfiles/masterConfig.xml b/sim/contrib/examples/Static AgentProfiles/masterConfig.xml
index 9257e8b8598137c434b620a1d9fbb52543fcd69b..7cc7bd575eb4c6bb04762fd8a3e0e3fc9421ffec 100644
--- a/sim/contrib/examples/Static AgentProfiles/masterConfig.xml	
+++ b/sim/contrib/examples/Static AgentProfiles/masterConfig.xml	
@@ -1,7 +1,7 @@
 <masterConfig>
   <logLevel>0</logLevel>
   <logFileMaster>OpenPassMaster.log</logFileMaster>
-  <slave>OpenPassSlave</slave>
+  <slave>OpenPassSlave.exe</slave>
   <libraries>lib</libraries>
   <slaveConfigs>
     <slaveConfig>
diff --git a/sim/contrib/examples/StaticAgentCollision/configs/systemConfigBlueprint.xml b/sim/contrib/examples/StaticAgentCollision/configs/systemConfigBlueprint.xml
index 395ddccfeeaf475850b685224c0b0bb3b2046636..0c84330e673792ef7e99e057dc327551a3353778 100644
--- a/sim/contrib/examples/StaticAgentCollision/configs/systemConfigBlueprint.xml
+++ b/sim/contrib/examples/StaticAgentCollision/configs/systemConfigBlueprint.xml
@@ -37,14 +37,25 @@
                 <parameters/>
             </component>
             <component>
-                <id>SensorFusion</id>
+                <id>SensorAggregation</id>
+                <schedule>
+                    <priority>351</priority>
+                    <offset>0</offset>
+                    <cycle>100</cycle>
+                    <response>0</response>
+                </schedule>
+                <library>SensorAggregation_OSI</library>
+                <parameters/>
+            </component>
+            <component>
+                <id>SensorFusionErrorless</id>
                 <schedule>
                     <priority>350</priority>
                     <offset>0</offset>
                     <cycle>100</cycle>
                     <response>0</response>
                 </schedule>
-                <library>SensorFusion_OSI</library>
+                <library>SensorFusionErrorless_OSI</library>
                 <parameters/>
             </component>
             <component>
@@ -110,7 +121,7 @@
                 </parameters>
             </component>
             <component>
-                <id>PrioritizerLateralVehicleComponents</id>
+                <id>PrioritizerSteeringVehicleComponents</id>
                 <schedule>
                     <priority>150</priority>
                     <offset>0</offset>
@@ -154,17 +165,6 @@
                 <library>Algorithm_Longitudinal</library>
                 <parameters/>
             </component>
-            <component>
-                <id>Algorithm_LateralVehicleComponents</id>
-                <schedule>
-                    <priority>100</priority>
-                    <offset>0</offset>
-                    <cycle>100</cycle>
-                    <response>0</response>
-                </schedule>
-                <library>Algorithm_Lateral</library>
-                <parameters/>
-            </component>
             <component>
                 <id>Algorithm_LateralAfdm</id>
                 <schedule>
@@ -417,17 +417,6 @@
                     <input>1</input>
                 </target>
             </connection>
-            <connection>
-                <id>1412</id>
-                <source>
-                    <component>Algorithm_LateralVehicleComponents</component>
-                    <output>0</output>
-                </source>
-                <target>
-                    <component>PrioritizerSteering</component>
-                    <input>0</input>
-                </target>
-            </connection>
             <connection>
                 <id>1512</id>
                 <source>
@@ -494,11 +483,11 @@
             <connection>
                 <id>2414</id>
                 <source>
-                    <component>PrioritizerLateralVehicleComponents</component>
+                    <component>PrioritizerSteeringVehicleComponents</component>
                     <output>0</output>
                 </source>
                 <target>
-                    <component>Algorithm_LateralVehicleComponents</component>
+                    <component>PrioritizerSteering</component>
                     <input>0</input>
                 </target>
                 <target>
@@ -572,17 +561,6 @@
                     <input>2</input>
                 </target>
             </connection>
-            <connection>
-                <id>9190</id>
-                <source>
-                    <component>SensorFusion</component>
-                    <output>0</output>
-                </source>
-                <target>
-                    <component>AEB</component>
-                    <input>0</input>
-                </target>
-            </connection>
             <connection>
                 <id>9292</id>
                 <source>
@@ -606,12 +584,30 @@
                     <input>100</input>
                 </target>
                 <target>
-                    <component>Algorithm_LateralVehicleComponents</component>
+                    <component>Dynamics_RegularDriving</component>
                     <input>100</input>
                 </target>
+            </connection>
+            <connection>
+                <id>9390</id>
+                <source>
+                    <component>SensorAggregation</component>
+                    <output>0</output>
+                </source>
                 <target>
-                    <component>Dynamics_RegularDriving</component>
-                    <input>100</input>
+                    <component>SensorFusionErrorless</component>
+                    <input>0</input>
+                </target>
+            </connection>
+            <connection>
+                <id>9490</id>
+                <source>
+                    <component>SensorFusionErrorless</component>
+                    <output>0</output>
+                </source>
+                <target>
+                    <component>AEB</component>
+                    <input>0</input>
                 </target>
             </connection>
             <connection>
@@ -636,10 +632,6 @@
                     <component>Algorithm_LateralAfdm</component>
                     <input>101</input>
                 </target>
-                <target>
-                    <component>Algorithm_LateralVehicleComponents</component>
-                    <input>101</input>
-                </target>
             </connection>
             <connection>
                 <id>9900</id>
@@ -648,7 +640,7 @@
                     <output>0</output>
                 </source>
                 <target>
-                    <component>SensorFusion</component>
+                    <component>SensorAggregation</component>
                     <input>0</input>
                 </target>
             </connection>
diff --git a/sim/contrib/examples/StaticAgentCollision/masterConfig.xml b/sim/contrib/examples/StaticAgentCollision/masterConfig.xml
index 9257e8b8598137c434b620a1d9fbb52543fcd69b..7cc7bd575eb4c6bb04762fd8a3e0e3fc9421ffec 100644
--- a/sim/contrib/examples/StaticAgentCollision/masterConfig.xml
+++ b/sim/contrib/examples/StaticAgentCollision/masterConfig.xml
@@ -1,7 +1,7 @@
 <masterConfig>
   <logLevel>0</logLevel>
   <logFileMaster>OpenPassMaster.log</logFileMaster>
-  <slave>OpenPassSlave</slave>
+  <slave>OpenPassSlave.exe</slave>
   <libraries>lib</libraries>
   <slaveConfigs>
     <slaveConfig>
diff --git a/sim/doc/DoxyGen/Function/ExampleFiles/systemConfigBlueprint.xml b/sim/doc/DoxyGen/Function/ExampleFiles/systemConfigBlueprint.xml
index d1e45a7c7fc43c91d13de2663a3029659eaeefb1..f80f9981d4b005598fb04314922900521d46118d 100644
--- a/sim/doc/DoxyGen/Function/ExampleFiles/systemConfigBlueprint.xml
+++ b/sim/doc/DoxyGen/Function/ExampleFiles/systemConfigBlueprint.xml
@@ -17,7 +17,7 @@
             <component>
                 <id>Sensor_Driver</id>
                 <schedule>
-                    <priority>490</priority>
+                    <priority>390</priority>
                     <offset>0</offset>
                     <cycle>100</cycle>
                     <response>0</response>
@@ -37,14 +37,25 @@
                 <parameters/>
             </component>
             <component>
-                <id>SensorFusion</id>
+                <id>SensorAggregation</id>
+                <schedule>
+                    <priority>351</priority>
+                    <offset>0</offset>
+                    <cycle>100</cycle>
+                    <response>0</response>
+                </schedule>
+                <library>SensorAggregation_OSI</library>
+                <parameters/>
+            </component>
+            <component>
+                <id>SensorFusionErrorless</id>
                 <schedule>
                     <priority>350</priority>
                     <offset>0</offset>
                     <cycle>100</cycle>
                     <response>0</response>
                 </schedule>
-                <library>SensorFusion_OSI</library>
+                <library>SensorFusionErrorless_OSI</library>
                 <parameters/>
             </component>
             <component>
@@ -61,7 +72,7 @@
             <component>
                 <id>ComponentController</id>
                 <schedule>
-                    <priority>1</priority>
+                    <priority>200</priority>
                     <offset>0</offset>
                     <cycle>100</cycle>
                     <response>0</response>
@@ -69,6 +80,17 @@
                 <library>ComponentController</library>
                 <parameters/>
             </component>
+            <component>
+                <id>OpenScenarioActions</id>
+                <schedule>
+                    <priority>400</priority>
+                    <offset>0</offset>
+                    <cycle>100</cycle>
+                    <response>0</response>
+                </schedule>
+                <library>OpenScenarioActions</library>
+                <parameters/>
+            </component>
             <component>
                 <id>AEB</id>
                 <schedule>
@@ -340,17 +362,6 @@
                     <input>2</input>
                 </target>
             </connection>
-            <connection>
-                <id>283</id>
-                <source>
-                    <component>Dynamics_TrajectoryFollower</component>
-                    <output>83</output>
-                </source>
-                <target>
-                    <component>ComponentController</component>
-                    <input>100</input>
-                </target>
-            </connection>
             <connection>
                 <id>301</id>
                 <source>
@@ -540,14 +551,14 @@
                 </target>
             </connection>
             <connection>
-                <id>9190</id>
+                <id>8471</id>
                 <source>
-                    <component>SensorFusion</component>
+                    <component>OpenScenarioActions</component>
                     <output>0</output>
                 </source>
                 <target>
-                    <component>AEB</component>
-                    <input>0</input>
+                    <component>Dynamics_TrajectoryFollower</component>
+                    <input>2</input>
                 </target>
             </connection>
             <connection>
@@ -577,6 +588,28 @@
                     <input>100</input>
                 </target>
             </connection>
+            <connection>
+                <id>9390</id>
+                <source>
+                    <component>SensorAggregation</component>
+                    <output>0</output>
+                </source>
+                <target>
+                    <component>SensorFusionErrorless</component>
+                    <input>0</input>
+                </target>
+            </connection>
+            <connection>
+                <id>9490</id>
+                <source>
+                    <component>SensorFusionErrorless</component>
+                    <output>0</output>
+                </source>
+                <target>
+                    <component>AEB</component>
+                    <input>0</input>
+                </target>
+            </connection>
             <connection>
                 <id>9581</id>
                 <source>
@@ -607,7 +640,7 @@
                     <output>0</output>
                 </source>
                 <target>
-                    <component>SensorFusion</component>
+                    <component>SensorAggregation</component>
                     <input>0</input>
                 </target>
             </connection>
diff --git a/sim/doc/DoxyGen/Function/Markdown/Simulation/Input_Output/Input_Output.md b/sim/doc/DoxyGen/Function/Markdown/Simulation/Input_Output/Input_Output.md
index b89fc6cdd0a1f70d5fa396682f3d2429aa0f9551..48c173d82c39b4c65a00629df51b0c6c80aeb363 100644
--- a/sim/doc/DoxyGen/Function/Markdown/Simulation/Input_Output/Input_Output.md
+++ b/sim/doc/DoxyGen/Function/Markdown/Simulation/Input_Output/Input_Output.md
@@ -97,6 +97,9 @@ The table below can be used as orientation when a new module is introduced.
 |---|-----------|-----------|-----------|-----------|
 | ParametersAgentModules| ParametersAgent| 500 | Parameters | Sets all init-data and is updated cyclically |
 | OpenScenarioActions | OpenScenarioActions | 400 | ADAS | Reads events from OpenScenario Actions and forwards them to other components |
+| SensorObjectDetector | Sensor_OSI | 398 | Sensor | Gets instantiated multiple time (one time per sensor) |
+| SensorAggregation | SensorAggregation_OSI | 351 | Sensor | - |
+| SensorFusionErrorless | SensorFusionErrorless_OSI | 350 | Sensor | - |
 | AlgorithmAgentFollowingDriverModel | AlgorithmAgentFollowingDriverModel | 310 | DriverModels | - |
 | AEB | AlgorithmAutonomousEmergencyBraking | 250 | ADAS | - |
 | ComponentController | ComponentController | 200 | ADAS | Manages vehicle component states with regard to other vehicle component states and conditions and in response to events. |
@@ -179,6 +182,8 @@ With corresponding defined indices :
 | ComponentController                       | Special           | 83 |
 | OpenScenarioActions                       | Special           | 84 |
 | Parameter_Vehicle                         | Sensor            | 92 | 
+| SensorAggregation                         | Sensor            | 93 | 
+| SensorFusion                              | Sensor            | 94 | 
 | Sensor_Driver                             | Sensor            | 95 | 
 
 **Ids for Signals (last two digits)**
@@ -206,6 +211,7 @@ With corresponding defined indices :
 | SecondaryDriverTasks          | Algorithm             | 19      |
 | Trajectory                    | OpenScenarioActions   | 71      |
 | SensorDriver                  | Sensor                | 81      |
+| SensorData                    | Sensor                | 90      |
 | ParametersVehicle             | Parameters            | 92      |
 
 \subsubsection io_input_systemconfigblueprint_paramters Parameters
diff --git a/sim/doc/DoxyGen/Function/Markdown/Simulation/Input_Output/Scenario.md b/sim/doc/DoxyGen/Function/Markdown/Simulation/Input_Output/Scenario.md
index d7b4cb4bbd7b35e63894027705f8b3b4981d946b..a02c33261ee10966f52edc3f9c5d16cf14495e12 100644
--- a/sim/doc/DoxyGen/Function/Markdown/Simulation/Input_Output/Scenario.md
+++ b/sim/doc/DoxyGen/Function/Markdown/Simulation/Input_Output/Scenario.md
@@ -188,7 +188,7 @@ Although OpenSCENARIO also states other ways for defining a position, we current
 Unlike OpenSCENARIO we also allow some of these values to be stochastic.
 This is marked by adding a subtag  <Stochastics value="valuetype" stdDeviation="value" lowerBound="value" upperBound="value"/> to the <LanePosition> or <SpeedAction> tag.
 The stochastics tag is intended to be used as NormalDistribution, but it is up to each module using it to define the actual usage.
-The valuetype can either be s, offset, velocity or rate.
+The valuetype can either be s, offset (if inside LanePosition), velocity or rate (if inside SpeedAction).
 The value defined as attribute of the LanePosition/SpeedActionDynamics/AbsoluteTargetSpeed tag is then taken as mean value.
 The VisibilityAction is optional.
 If VisibilityAction is not defined the agent will be spawned.
@@ -215,6 +215,7 @@ Example
 							<SpeedActionTarget>
 								<AbsoluteTargetSpeed value="10.0" />
 							</SpeedActionTarget>
+                            <Stochastics value="velocity" stdDeviation="2.0" lowerBound="5.0" upperBound="15.0"/>
 						</SpeedAction>
 					</LongitudinalAction>
 				</PrivateAction>
diff --git a/sim/doc/OSI World Setup Guide.pdf b/sim/doc/OSI World Setup Guide.pdf
index d5828165a7ad7e3fae64655ea91bb12bd9e25cfa..5d0fcf3b9143016e5b206566571c858c184da6fd 100644
Binary files a/sim/doc/OSI World Setup Guide.pdf and b/sim/doc/OSI World Setup Guide.pdf differ
diff --git a/sim/src/common/commonTools.h b/sim/src/common/commonTools.h
index c9ae21d843d5099dfb0df91b96a0b8a41ba948d4..0b3c00ab93f05519b35d3f06893b4e7aa273345c 100644
--- a/sim/src/common/commonTools.h
+++ b/sim/src/common/commonTools.h
@@ -117,6 +117,56 @@ static double CalculateMomentInertiaYaw(double mass, double length, double width
     return std::make_optional<Common::Vector2d>(intersectionPointX, intersectionPointY);
 }
 
+//! Calculates the net distance of the x and y coordinates of two bounding boxes
+//!
+//! \param ownBoundingBox       first bounding box
+//! \param otherBoundingBox     second bounding box
+//! \return net distance x, net distance y
+[[maybe_unused]] static std::pair<double, double> GetCartesianNetDistance(polygon_t ownBoundingBox, polygon_t otherBoundingBox)
+{
+    double ownMaxX{std::numeric_limits<double>::lowest()};
+    double ownMinX{std::numeric_limits<double>::max()};
+    double ownMaxY{std::numeric_limits<double>::lowest()};
+    double ownMinY{std::numeric_limits<double>::max()};
+    for (const auto& point : ownBoundingBox.outer())
+    {
+        ownMaxX = std::max(ownMaxX, bg::get<0>(point));
+        ownMinX = std::min(ownMinX, bg::get<0>(point));
+        ownMaxY = std::max(ownMaxY, bg::get<1>(point));
+        ownMinY = std::min(ownMinY, bg::get<1>(point));
+    }
+    double otherMaxX{std::numeric_limits<double>::lowest()};
+    double otherMinX{std::numeric_limits<double>::max()};
+    double otherMaxY{std::numeric_limits<double>::lowest()};
+    double otherMinY{std::numeric_limits<double>::max()};
+    for (const auto& point : otherBoundingBox.outer())
+    {
+        otherMaxX = std::max(otherMaxX, bg::get<0>(point));
+        otherMinX = std::min(otherMinX, bg::get<0>(point));
+        otherMaxY = std::max(otherMaxY, bg::get<1>(point));
+        otherMinY = std::min(otherMinY, bg::get<1>(point));
+    }
+    double netX{0.0};
+    if (ownMaxX < otherMinX)
+    {
+        netX = otherMinX - ownMaxX;
+    }
+    if (ownMinX > otherMaxX)
+    {
+        netX = otherMaxX - ownMinX;
+    }
+    double netY{0.0};
+    if (ownMaxY < otherMinY)
+    {
+        netY = otherMinY - ownMaxY;
+    }
+    if (ownMinY > otherMaxY)
+    {
+        netY = otherMaxY - ownMinY;
+    }
+    return {netX, netY};
+}
+
 //-----------------------------------------------------------------------------
 //! @brief Tokenizes string by delimiter.
 //!
diff --git a/sim/src/components/SensorFusion_OSI/src/sensorFusionQuery.h b/sim/src/common/sensorFusionQuery.h
similarity index 61%
rename from sim/src/components/SensorFusion_OSI/src/sensorFusionQuery.h
rename to sim/src/common/sensorFusionQuery.h
index d836532fd2f65fd65e0a0d18ff061a34f6700476..4ac4f2457313fec6d6aab7fc11e7daf053e025d6 100644
--- a/sim/src/components/SensorFusion_OSI/src/sensorFusionQuery.h
+++ b/sim/src/common/sensorFusionQuery.h
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (c) 2018, 2019 in-tech GmbH
+* Copyright (c) 2018, 2019, 2020 in-tech GmbH
 * Copyright (c) 2020 HLRS, University of Stuttgart.
 *
 * This program and the accompanying materials are made
@@ -22,33 +22,39 @@
 
 #include "osi3/osi_sensordata.pb.h"
 
-class SensorFusionHelperFunctions
+namespace SensorFusionHelperFunctions
 {
-public:
-    static std::vector<osi3::DetectedMovingObject> RetrieveMovingObjectsBySensorId(std::vector<int> sensorIds, const osi3::SensorData &sensorData)
+    std::vector<osi3::DetectedMovingObject> RetrieveMovingObjectsBySensorId(std::vector<int> sensorIds, const osi3::SensorData &sensorData)
     {
         std::vector<osi3::DetectedMovingObject> result;
         auto detectedMovingObjects = sensorData.moving_object();
         for (const auto& object : detectedMovingObjects)
         {
-            if(std::count(sensorIds.cbegin(), sensorIds.cend(), object.header().sensor_id(0).value()) > 0)
+            for (auto sensorId : object.header().sensor_id())
             {
-                result.push_back(object);
+                if(std::count(sensorIds.cbegin(), sensorIds.cend(), sensorId.value()) > 0)
+                {
+                    result.push_back(object);
+                    break;
+                }
             }
         }
         return result;
     }
 
-
-    static std::vector<osi3::DetectedStationaryObject> RetrieveStationaryObjectsBySensorId(std::vector<int> sensorIds, const osi3::SensorData &sensorData)
+    std::vector<osi3::DetectedStationaryObject> RetrieveStationaryObjectsBySensorId(std::vector<int> sensorIds, const osi3::SensorData &sensorData)
     {
         std::vector<osi3::DetectedStationaryObject> result;
         auto detectedStationaryObjects = sensorData.stationary_object();
         for (const auto& object : detectedStationaryObjects)
         {
-            if(std::count(sensorIds.cbegin(), sensorIds.cend(), object.header().sensor_id(0).value()) > 0)
+            for (auto sensorId : object.header().sensor_id())
             {
-                result.push_back(object);
+                if(std::count(sensorIds.cbegin(), sensorIds.cend(), sensorId.value()) > 0)
+                {
+                    result.push_back(object);
+                    break;
+                }
             }
         }
         return result;
diff --git a/sim/src/components/Algorithm_AEB/src/autonomousEmergencyBraking.cpp b/sim/src/components/Algorithm_AEB/src/autonomousEmergencyBraking.cpp
index 450d70397445e89494dba7587b91d7e84e44ebf6..1d4a42053fd1a37bbfe9d820239e3447564dc655 100644
--- a/sim/src/components/Algorithm_AEB/src/autonomousEmergencyBraking.cpp
+++ b/sim/src/components/Algorithm_AEB/src/autonomousEmergencyBraking.cpp
@@ -19,7 +19,7 @@
 
 #include "common/commonTools.h"
 #include "common/eventTypes.h"
-#include "components/SensorFusion_OSI/src/sensorFusionQuery.h"
+#include "common/sensorFusionQuery.h"
 #include "boundingBoxCalculation.h"
 
 AlgorithmAutonomousEmergencyBrakingImplementation::AlgorithmAutonomousEmergencyBrakingImplementation(
diff --git a/sim/src/components/CMakeLists.txt b/sim/src/components/CMakeLists.txt
index b59e9c4c283d361d63d8e67cbb68c65d0bf4de28..93c655ccd9efb90d74143a617cb1cb21c34cbf70 100644
--- a/sim/src/components/CMakeLists.txt
+++ b/sim/src/components/CMakeLists.txt
@@ -31,7 +31,8 @@ add_subdirectory(Dynamics_TF)
 add_subdirectory(LimiterAccVehComp)
 add_subdirectory(OpenScenarioActions)
 add_subdirectory(Parameters_Vehicle)
-add_subdirectory(SensorFusion_OSI)
+add_subdirectory(SensorAggregation_OSI)
+add_subdirectory(SensorFusionErrorless_OSI)
 #add_subdirectory(Sensor_Distance)
 add_subdirectory(Sensor_Driver)
 add_subdirectory(Sensor_OSI)
diff --git a/sim/src/components/SensorAggregation_OSI/CMakeLists.txt b/sim/src/components/SensorAggregation_OSI/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..17e86e631b0eb781462761bf948ed1a00923e854
--- /dev/null
+++ b/sim/src/components/SensorAggregation_OSI/CMakeLists.txt
@@ -0,0 +1,21 @@
+set(COMPONENT_NAME SensorAggregation_OSI)
+
+add_compile_definitions(SENSOR_AGGREGATION_LIBRARY)
+
+add_openpass_target(
+  NAME ${COMPONENT_NAME} TYPE library LINKAGE shared COMPONENT core
+
+  HEADERS
+    sensorAggregation.h
+    src/sensorAggregationImpl.h
+
+  SOURCES
+    sensorAggregation.cpp
+    src/sensorAggregationImpl.cpp
+
+  LIBRARIES
+    Qt5::Core
+    Common
+
+  LINKOSI
+)
diff --git a/sim/src/components/SensorAggregation_OSI/SensorAggregation_OSI.pro b/sim/src/components/SensorAggregation_OSI/SensorAggregation_OSI.pro
new file mode 100644
index 0000000000000000000000000000000000000000..bd80d9db1b3773decfb3f1402a166d95efe4c175
--- /dev/null
+++ b/sim/src/components/SensorAggregation_OSI/SensorAggregation_OSI.pro
@@ -0,0 +1,40 @@
+# /*********************************************************************
+# * Copyright (c) 2017, 2018, 2019 in-tech GmbH
+# *
+# * This program and the accompanying materials are made
+# * available under the terms of the Eclipse Public License 2.0
+# * which is available at https://www.eclipse.org/legal/epl-2.0/
+# *
+# * SPDX-License-Identifier: EPL-2.0
+# **********************************************************************/
+
+#-----------------------------------------------------------------------------
+# \file  SensorAggregation_OSI.pro
+# \brief This file contains the information for the QtCreator-project of the
+# module SensorAggregation_OSI
+#-----------------------------------------------------------------------------/
+
+DEFINES += SENSOR_AGGREGATION_LIBRARY
+CONFIG += OPENPASS_LIBRARY
+include(../../../global.pri)
+
+
+SUBDIRS += .\
+    src
+
+INCLUDEPATH += \
+    $$SUBDIRS \
+    ../../.. \
+    ../..
+
+SOURCES += \
+    sensorAggregation.cpp \
+    src/sensorAggregationImpl.cpp
+
+HEADERS += \
+    sensorAggregation.h \
+    src/sensorAggregationImpl.h
+
+LIBS += \
+    -lopen_simulation_interface \
+    -lprotobuf
diff --git a/sim/src/components/SensorAggregation_OSI/sensorAggregation.cpp b/sim/src/components/SensorAggregation_OSI/sensorAggregation.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..55d1941aa07cc125ce122fad77352d8e49911e46
--- /dev/null
+++ b/sim/src/components/SensorAggregation_OSI/sensorAggregation.cpp
@@ -0,0 +1,172 @@
+/*******************************************************************************
+* Copyright (c) 2017, 2018, 2019, 2020 in-tech GmbH
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+
+//-----------------------------------------------------------------------------
+/** \file  SensorAggregation.cpp */
+//-----------------------------------------------------------------------------
+
+#include "sensorAggregation.h"
+#include "src/sensorAggregationImpl.h"
+
+const std::string Version = "0.0.1";
+static const CallbackInterface *Callbacks = nullptr;
+
+extern "C" SENSOR_AGGREGATION_SHARED_EXPORT const std::string &OpenPASS_GetVersion()
+{
+    return Version;
+}
+
+extern "C" SENSOR_AGGREGATION_SHARED_EXPORT ModelInterface *OpenPASS_CreateInstance(
+        std::string componentName,
+        bool isInit,
+        int priority,
+        int offsetTime,
+        int responseTime,
+        int cycleTime,
+        StochasticsInterface *stochastics,
+        WorldInterface *world,
+        const ParameterInterface *parameters,
+        PublisherInterface * const publisher,
+        AgentInterface *agent,
+        const CallbackInterface *callbacks)
+{
+    Callbacks = callbacks;
+
+    try
+    {
+        return (ModelInterface*)(new (std::nothrow) SensorAggregationImplementation(
+                                     componentName,
+                                     isInit,
+                                     priority,
+                                     offsetTime,
+                                     responseTime,
+                                     cycleTime,
+                                     stochastics,
+                                     world,
+                                     parameters,
+                                     publisher,
+                                     callbacks,
+                                     agent));
+    }
+    catch(const std::runtime_error &ex)
+    {
+        if(Callbacks != nullptr)
+        {
+            Callbacks->Log(CbkLogLevel::Error, __FILE__, __LINE__, ex.what());
+        }
+
+        return nullptr;
+    }
+    catch(...)
+    {
+        if(Callbacks != nullptr)
+        {
+            Callbacks->Log(CbkLogLevel::Error, __FILE__, __LINE__, "unexpected exception");
+        }
+
+        return nullptr;
+    }
+}
+
+extern "C" SENSOR_AGGREGATION_SHARED_EXPORT void OpenPASS_DestroyInstance(ModelInterface *implementation)
+{
+    delete (SensorAggregationImplementation*)implementation;
+}
+
+extern "C" SENSOR_AGGREGATION_SHARED_EXPORT bool OpenPASS_UpdateInput(ModelInterface *implementation,
+                                                             int localLinkId,
+                                                             const std::shared_ptr<SignalInterface const> &data,
+                                                             int time)
+{
+    try
+    {
+        implementation->UpdateInput(localLinkId, data, time);
+    }
+    catch(const std::runtime_error &ex)
+    {
+        if(Callbacks != nullptr)
+        {
+            Callbacks->Log(CbkLogLevel::Error, __FILE__, __LINE__, ex.what());
+        }
+
+        return false;
+    }
+    catch(...)
+    {
+        if(Callbacks != nullptr)
+        {
+            Callbacks->Log(CbkLogLevel::Error, __FILE__, __LINE__, "unexpected exception");
+        }
+
+        return false;
+    }
+
+    return true;
+}
+
+extern "C" SENSOR_AGGREGATION_SHARED_EXPORT bool OpenPASS_UpdateOutput(ModelInterface *implementation,
+                                                              int localLinkId,
+                                                              std::shared_ptr<SignalInterface const> &data,
+                                                              int time)
+{
+    try
+    {
+        implementation->UpdateOutput(localLinkId, data, time);
+    }
+    catch(const std::runtime_error &ex)
+    {
+        if(Callbacks != nullptr)
+        {
+            Callbacks->Log(CbkLogLevel::Error, __FILE__, __LINE__, ex.what());
+        }
+
+        return false;
+    }
+    catch(...)
+    {
+        if(Callbacks != nullptr)
+        {
+            Callbacks->Log(CbkLogLevel::Error, __FILE__, __LINE__, "unexpected exception");
+        }
+
+        return false;
+    }
+
+    return true;
+}
+
+extern "C" SENSOR_AGGREGATION_SHARED_EXPORT bool OpenPASS_Trigger(ModelInterface *implementation,
+                                                         int time)
+{
+    try
+    {
+        implementation->Trigger(time);
+    }
+    catch(const std::runtime_error &ex)
+    {
+        if(Callbacks != nullptr)
+        {
+            Callbacks->Log(CbkLogLevel::Error, __FILE__, __LINE__, ex.what());
+        }
+
+        return false;
+    }
+    catch(...)
+    {
+        if(Callbacks != nullptr)
+        {
+            Callbacks->Log(CbkLogLevel::Error, __FILE__, __LINE__, "unexpected exception");
+        }
+
+        return false;
+    }
+
+    return true;
+}
diff --git a/sim/src/components/SensorAggregation_OSI/sensorAggregation.h b/sim/src/components/SensorAggregation_OSI/sensorAggregation.h
new file mode 100644
index 0000000000000000000000000000000000000000..18f703a402c94b1b2bdade3b10f863a62358aea0
--- /dev/null
+++ b/sim/src/components/SensorAggregation_OSI/sensorAggregation.h
@@ -0,0 +1,30 @@
+/*******************************************************************************
+* Copyright (c) 2017, 2019, 2020 in-tech GmbH
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+
+//-----------------------------------------------------------------------------
+/** @file  SensorAggregation.h
+*	@brief This file provides the exported methods.
+*
+*   This file provides the exported methods which are available outside of the library. */
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include <QtCore/qglobal.h>
+
+#if defined(SENSOR_AGGREGATION_LIBRARY)
+#  define SENSOR_AGGREGATION_SHARED_EXPORT Q_DECL_EXPORT
+#else
+#  define SENSOR_AGGREGATION_SHARED_EXPORT Q_DECL_IMPORT
+#endif
+
+#include "include/modelInterface.h"
+
+
diff --git a/sim/src/components/SensorFusion_OSI/src/sensorFusionImpl.cpp b/sim/src/components/SensorAggregation_OSI/src/sensorAggregationImpl.cpp
similarity index 86%
rename from sim/src/components/SensorFusion_OSI/src/sensorFusionImpl.cpp
rename to sim/src/components/SensorAggregation_OSI/src/sensorAggregationImpl.cpp
index a8bc50c94267a91ae5e26e09d735edda4edbe31f..37654892172f01a0514f4589487708825b1dc4f4 100644
--- a/sim/src/components/SensorFusion_OSI/src/sensorFusionImpl.cpp
+++ b/sim/src/components/SensorAggregation_OSI/src/sensorAggregationImpl.cpp
@@ -9,13 +9,13 @@
 *******************************************************************************/
 
 //-----------------------------------------------------------------------------
-/** \brief SensorFusion.cpp */
+/** \brief sensorAggregationImpl.cpp */
 //-----------------------------------------------------------------------------
 
-#include "sensorFusionImpl.h"
+#include "sensorAggregationImpl.h"
 #include <qglobal.h>
 
-SensorFusionImplementation::SensorFusionImplementation(
+SensorAggregationImplementation::SensorAggregationImplementation(
         std::string componentName,
         bool isInit,
         int priority,
@@ -44,7 +44,7 @@ SensorFusionImplementation::SensorFusionImplementation(
 {
 }
 
-void SensorFusionImplementation::UpdateInput(int localLinkId, const std::shared_ptr<SignalInterface const> &data, int time)
+void SensorAggregationImplementation::UpdateInput(int localLinkId, const std::shared_ptr<SignalInterface const> &data, int time)
 {
     if(time != previousTimeStamp) {
         out_sensorData.Clear();
@@ -66,7 +66,7 @@ void SensorFusionImplementation::UpdateInput(int localLinkId, const std::shared_
     out_sensorData.MergeFrom(signal->sensorData);
 }
 
-void SensorFusionImplementation::UpdateOutput(int localLinkId, std::shared_ptr<SignalInterface const> &data, int time)
+void SensorAggregationImplementation::UpdateOutput(int localLinkId, std::shared_ptr<SignalInterface const> &data, int time)
 {
     Q_UNUSED(time);
 
@@ -98,7 +98,7 @@ void SensorFusionImplementation::UpdateOutput(int localLinkId, std::shared_ptr<S
     }
 }
 
-void SensorFusionImplementation::Trigger(int time)
+void SensorAggregationImplementation::Trigger(int time)
 {
     Q_UNUSED(time);
 }
diff --git a/sim/src/components/SensorFusion_OSI/src/sensorFusionImpl.h b/sim/src/components/SensorAggregation_OSI/src/sensorAggregationImpl.h
similarity index 82%
rename from sim/src/components/SensorFusion_OSI/src/sensorFusionImpl.h
rename to sim/src/components/SensorAggregation_OSI/src/sensorAggregationImpl.h
index 3946842f1b004bfed2b1db2a8f250258113c9fcf..83f1ae9d4fe6a621367dd457783ead48c684b16e 100644
--- a/sim/src/components/SensorFusion_OSI/src/sensorFusionImpl.h
+++ b/sim/src/components/SensorAggregation_OSI/src/sensorAggregationImpl.h
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (c) 2017, 2018, 2019 in-tech GmbH
+* Copyright (c) 2017, 2018, 2019, 2020 in-tech GmbH
 * Copyright (c) 2020 HLRS, University of Stuttgart.
 *
 * This program and the accompanying materials are made
@@ -9,11 +9,11 @@
 * SPDX-License-Identifier: EPL-2.0
 *******************************************************************************/
 
-/** \addtogroup SensorFusion
+/** \addtogroup SensorAggregation
 * @{
-* \brief This file models the SensorFusion.
+* \brief This file models the SensorAggregation.
 *
-* \details This file models the SensorFusion which can be part of an agent.
+* \details This file models the SensorAggregation which can be part of an agent.
 *          This module gets OSI SensorData of all sensors of the vehicle and forwards a combined
 *          SensorData to the driver assistance systems.
 *
@@ -48,18 +48,18 @@
 #include "osi3/osi_sensordata.pb.h"
 
 //-----------------------------------------------------------------------------
-/** \brief This class is the SensorFusion module.
+/** \brief This class is the SensorAggregation module.
 * 	\details This class contains all logic regarding the sensor fusion.
 *
-* 	\ingroup SensorFusion
+* 	\ingroup SensorAggregation
 */
 //-----------------------------------------------------------------------------
-class SensorFusionImplementation : public UnrestrictedModelInterface
+class SensorAggregationImplementation : public UnrestrictedModelInterface
 {
 public:
     const std::string COMPONENTNAME = "SensorFusion";
 
-    SensorFusionImplementation(
+    SensorAggregationImplementation(
             std::string componentName,
             bool isInit,
             int priority,
@@ -73,11 +73,11 @@ public:
             const CallbackInterface *callbacks,
             AgentInterface *agent);
 
-    SensorFusionImplementation(const SensorFusionImplementation&) = delete;
-    SensorFusionImplementation(SensorFusionImplementation&&) = delete;
-    SensorFusionImplementation& operator=(const SensorFusionImplementation&) = delete;
-    SensorFusionImplementation& operator=(SensorFusionImplementation&&) = delete;
-    virtual ~SensorFusionImplementation() = default;
+    SensorAggregationImplementation(const SensorAggregationImplementation&) = delete;
+    SensorAggregationImplementation(SensorAggregationImplementation&&) = delete;
+    SensorAggregationImplementation& operator=(const SensorAggregationImplementation&) = delete;
+    SensorAggregationImplementation& operator=(SensorAggregationImplementation&&) = delete;
+    virtual ~SensorAggregationImplementation() = default;
 
     /*!
      * \brief Update Inputs
diff --git a/sim/src/components/SensorFusion_OSI/CMakeLists.txt b/sim/src/components/SensorFusionErrorless_OSI/CMakeLists.txt
similarity index 70%
rename from sim/src/components/SensorFusion_OSI/CMakeLists.txt
rename to sim/src/components/SensorFusionErrorless_OSI/CMakeLists.txt
index e07d54f00f8d3311ef6cf84def0e61353291795f..20b37f3d65bc6a4a86714af92e49e85b02cf0f86 100644
--- a/sim/src/components/SensorFusion_OSI/CMakeLists.txt
+++ b/sim/src/components/SensorFusionErrorless_OSI/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(COMPONENT_NAME SensorFusion_OSI)
+set(COMPONENT_NAME SensorFusionErrorless_OSI)
 
 add_compile_definitions(SENSOR_FUSION_LIBRARY)
 
@@ -6,12 +6,11 @@ add_openpass_target(
   NAME ${COMPONENT_NAME} TYPE library LINKAGE shared COMPONENT core
 
   HEADERS
-    sensorFusion.h
+    sensorFusionErrorless_OSI.h
     src/sensorFusionImpl.h
-    src/sensorFusionQuery.h
 
   SOURCES
-    sensorFusion.cpp
+    sensorFusionErrorless_OSI.cpp
     src/sensorFusionImpl.cpp
 
   LIBRARIES
diff --git a/sim/src/components/SensorFusion_OSI/SensorFusion_OSI.pro b/sim/src/components/SensorFusionErrorless_OSI/SensorFusionErrorless_OSI.pro
similarity index 87%
rename from sim/src/components/SensorFusion_OSI/SensorFusion_OSI.pro
rename to sim/src/components/SensorFusionErrorless_OSI/SensorFusionErrorless_OSI.pro
index a1c21b8fa3d4a1b0d620b01681e4f04eee23b01e..866637e7fe56588a75cae8e602c1e135359fffb7 100644
--- a/sim/src/components/SensorFusion_OSI/SensorFusion_OSI.pro
+++ b/sim/src/components/SensorFusionErrorless_OSI/SensorFusionErrorless_OSI.pro
@@ -9,9 +9,9 @@
 # **********************************************************************/
 
 #-----------------------------------------------------------------------------
-# \file  SensorFusion_OSI.pro
+# \file  SensorAggregation_OSI.pro
 # \brief This file contains the information for the QtCreator-project of the
-# module SensorFusion_OSI
+# module SensorAggregation_OSI
 #-----------------------------------------------------------------------------/
 
 DEFINES += SENSOR_FUSION_LIBRARY
@@ -28,11 +28,11 @@ INCLUDEPATH += \
     ../..
 
 SOURCES += \
-    sensorFusion.cpp \
+    sensorFusionErrorless_OSI.cpp \
     src/sensorFusionImpl.cpp
 
 HEADERS += \
-    sensorFusion.h \
+    sensorFusionErrorless_OSI.h \
     src/sensorFusionImpl.h
 
 LIBS += \
diff --git a/sim/src/components/SensorFusion_OSI/sensorFusion.cpp b/sim/src/components/SensorFusionErrorless_OSI/sensorFusionErrorless_OSI.cpp
similarity index 97%
rename from sim/src/components/SensorFusion_OSI/sensorFusion.cpp
rename to sim/src/components/SensorFusionErrorless_OSI/sensorFusionErrorless_OSI.cpp
index b3c88fdbcba86c0f21468c5d4aa76e818552185e..7178e3f40e44f62ba4b6fb593a2a7bd11463f522 100644
--- a/sim/src/components/SensorFusion_OSI/sensorFusion.cpp
+++ b/sim/src/components/SensorFusionErrorless_OSI/sensorFusionErrorless_OSI.cpp
@@ -12,7 +12,7 @@
 /** \file  SensorFusion.cpp */
 //-----------------------------------------------------------------------------
 
-#include "sensorFusion.h"
+#include "sensorFusionErrorless_OSI.h"
 #include "src/sensorFusionImpl.h"
 
 const std::string Version = "0.0.1";
@@ -41,7 +41,7 @@ extern "C" SENSOR_FUSION_SHARED_EXPORT ModelInterface *OpenPASS_CreateInstance(
 
     try
     {
-        return (ModelInterface*)(new (std::nothrow) SensorFusionImplementation(
+        return (ModelInterface*)(new (std::nothrow) SensorFusionErrorlessImplementation(
                                      componentName,
                                      isInit,
                                      priority,
@@ -77,7 +77,7 @@ extern "C" SENSOR_FUSION_SHARED_EXPORT ModelInterface *OpenPASS_CreateInstance(
 
 extern "C" SENSOR_FUSION_SHARED_EXPORT void OpenPASS_DestroyInstance(ModelInterface *implementation)
 {
-    delete (SensorFusionImplementation*)implementation;
+    delete (SensorFusionErrorlessImplementation*)implementation;
 }
 
 extern "C" SENSOR_FUSION_SHARED_EXPORT bool OpenPASS_UpdateInput(ModelInterface *implementation,
diff --git a/sim/src/components/SensorFusion_OSI/sensorFusion.h b/sim/src/components/SensorFusionErrorless_OSI/sensorFusionErrorless_OSI.h
similarity index 100%
rename from sim/src/components/SensorFusion_OSI/sensorFusion.h
rename to sim/src/components/SensorFusionErrorless_OSI/sensorFusionErrorless_OSI.h
diff --git a/sim/src/components/SensorFusionErrorless_OSI/src/sensorFusionImpl.cpp b/sim/src/components/SensorFusionErrorless_OSI/src/sensorFusionImpl.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2d639d4b2f565d655b5990dfbd819ca4cbdbacf3
--- /dev/null
+++ b/sim/src/components/SensorFusionErrorless_OSI/src/sensorFusionImpl.cpp
@@ -0,0 +1,127 @@
+/*******************************************************************************
+* Copyright (c) 2020 in-tech GmbH
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+
+//-----------------------------------------------------------------------------
+/** \brief sensorFusionImpl.cpp */
+//-----------------------------------------------------------------------------
+
+#include "sensorFusionImpl.h"
+#include <qglobal.h>
+
+SensorFusionErrorlessImplementation::SensorFusionErrorlessImplementation(
+        std::string componentName,
+        bool isInit,
+        int priority,
+        int offsetTime,
+        int responseTime,
+        int cycleTime,
+        StochasticsInterface *stochastics,
+        WorldInterface *world,
+        const ParameterInterface *parameters,
+        PublisherInterface * const publisher,
+        const CallbackInterface *callbacks,
+        AgentInterface *agent) :
+    UnrestrictedModelInterface(
+        componentName,
+        isInit,
+        priority,
+        offsetTime,
+        responseTime,
+        cycleTime,
+        stochastics,
+        world,
+        parameters,
+        publisher,
+        callbacks,
+        agent)
+{
+}
+
+void SensorFusionErrorlessImplementation::UpdateInput(int localLinkId, const std::shared_ptr<SignalInterface const> &data, [[maybe_unused]] int time)
+{
+    std::stringstream log;
+    log << COMPONENTNAME << " (component " << GetComponentName() << ", agent " << GetAgent()->GetId() << ", input data for local link " << localLinkId << ": ";
+    LOG(CbkLogLevel::Debug, log.str());
+
+    const std::shared_ptr<SensorDataSignal const> signal = std::dynamic_pointer_cast<SensorDataSignal const>(data);
+    if(!signal)
+    {
+        const std::string msg = COMPONENTNAME + " invalid signaltype";
+        LOG(CbkLogLevel::Debug, msg);
+        throw std::runtime_error(msg);
+    }
+
+    MergeSensorData(signal->sensorData);
+}
+
+void SensorFusionErrorlessImplementation::UpdateOutput(int localLinkId, std::shared_ptr<SignalInterface const> &data, [[maybe_unused]] int time)
+{
+    std::stringstream log;
+    log << COMPONENTNAME << " (component " << GetComponentName() << ", agent " << GetAgent()->GetId() << ", output data for local link " << localLinkId << ": ";
+    LOG(CbkLogLevel::Debug, log.str());
+
+
+    if(localLinkId == 0)
+    {
+        // to any ADAS
+        try
+        {
+            data = std::make_shared<SensorDataSignal const>(
+                        out_sensorData);
+        }
+        catch(const std::bad_alloc&)
+        {
+            const std::string msg = COMPONENTNAME + " could not instantiate signal";
+            LOG(CbkLogLevel::Debug, msg);
+            throw std::runtime_error(msg);
+        }
+    }
+    else
+    {
+        const std::string msg = COMPONENTNAME + " invalid link";
+        LOG(CbkLogLevel::Debug, msg);
+        throw std::runtime_error(msg);
+    }
+}
+
+void SensorFusionErrorlessImplementation::Trigger(int)
+{
+}
+
+void SensorFusionErrorlessImplementation::MergeSensorData(const osi3::SensorData& in_SensorData)
+{
+    out_sensorData = {};
+    for (auto& movingObject : in_SensorData.moving_object())
+    {
+        auto existingObject = std::find_if(out_sensorData.mutable_moving_object()->begin(), out_sensorData.mutable_moving_object()->end(),
+                                           [&](const auto& object){return movingObject.header().ground_truth_id(0).value() == object.header().ground_truth_id(0).value();});
+        if (existingObject != out_sensorData.mutable_moving_object()->end())
+        {
+            existingObject->mutable_header()->mutable_sensor_id()->MergeFrom(movingObject.header().sensor_id());
+        }
+        else
+        {
+            out_sensorData.add_moving_object()->CopyFrom(movingObject);
+        }
+    }
+    for (auto& stationaryObject : in_SensorData.stationary_object())
+    {
+        auto existingObject = std::find_if(out_sensorData.mutable_stationary_object()->begin(), out_sensorData.mutable_stationary_object()->end(),
+                                           [&](const auto& object){return stationaryObject.header().ground_truth_id(0).value() == object.header().ground_truth_id(0).value();});
+        if (existingObject != out_sensorData.mutable_stationary_object()->end())
+        {
+            existingObject->mutable_header()->mutable_sensor_id()->MergeFrom(stationaryObject.header().sensor_id());
+        }
+        else
+        {
+            out_sensorData.add_stationary_object()->CopyFrom(stationaryObject);
+        }
+    }
+}
diff --git a/sim/src/components/SensorFusionErrorless_OSI/src/sensorFusionImpl.h b/sim/src/components/SensorFusionErrorless_OSI/src/sensorFusionImpl.h
new file mode 100644
index 0000000000000000000000000000000000000000..f382e5b985c07bf9264866f2951814f7045c8344
--- /dev/null
+++ b/sim/src/components/SensorFusionErrorless_OSI/src/sensorFusionImpl.h
@@ -0,0 +1,94 @@
+/*******************************************************************************
+* Copyright (c) 2020 in-tech GmbH
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+
+/** \addtogroup SensorFusionErrorless
+* @{
+* \brief This file models the SensorFusionErrorless.
+*
+* \details This file models the SensorFusionErrorless which can be part of an agent.
+*          This module gets OSI SensorData of the SensorAggregation and combines all
+*          object with the same id into one.
+*
+* \section MODULENAME_Inputs Inputs
+* Input variables:
+* name | meaning
+* -----|------
+* sensorData | SensorData of a single sensor.
+*
+* Input channel IDs:
+* Input Id | signal class | contained variables
+* ----------|--------------|-------------
+*  0 		| SensorDataSignal  | sensorData
+*
+* \section MODULENAME_Outputs Outputs
+* Output variables:
+* name | meaning
+* -----|------
+* out_sensorData | Combined SensorData from all sensors.
+*
+* Output channel IDs:
+* Output Id | signal class | contained variables
+* ----------|--------------|-------------
+*  0 		| SensorDataSignal  | out_sensorData
+*
+* @} */
+
+#pragma once
+
+#include "include/modelInterface.h"
+#include "common/sensorDataSignal.h"
+#include "osi3/osi_sensordata.pb.h"
+
+//-----------------------------------------------------------------------------
+/** \brief This class is the SensorFusionErrorless module.
+* 	\details This class contains all logic regarding the sensor fusion.
+*
+* 	\ingroup SensorFusionErrorless
+*/
+//-----------------------------------------------------------------------------
+class SensorFusionErrorlessImplementation : public UnrestrictedModelInterface
+{
+public:
+    const std::string COMPONENTNAME = "SensorFusion";
+
+    SensorFusionErrorlessImplementation(
+            std::string componentName,
+            bool isInit,
+            int priority,
+            int offsetTime,
+            int responseTime,
+            int cycleTime,
+            StochasticsInterface *stochastics,
+            WorldInterface *world,
+            const ParameterInterface *parameters,
+            PublisherInterface * const publisher,
+            const CallbackInterface *callbacks,
+            AgentInterface *agent);
+
+    SensorFusionErrorlessImplementation(const SensorFusionErrorlessImplementation&) = delete;
+    SensorFusionErrorlessImplementation(SensorFusionErrorlessImplementation&&) = delete;
+    SensorFusionErrorlessImplementation& operator=(const SensorFusionErrorlessImplementation&) = delete;
+    SensorFusionErrorlessImplementation& operator=(SensorFusionErrorlessImplementation&&) = delete;
+    virtual ~SensorFusionErrorlessImplementation() = default;
+
+    virtual void UpdateInput(int localLinkId, const std::shared_ptr<SignalInterface const> &data, int time);
+
+    void UpdateOutput(int localLinkId, std::shared_ptr<SignalInterface const> &data, int time);
+
+    virtual void Trigger(int time);
+
+private:
+
+    void MergeSensorData(const osi3::SensorData& in_SensorData);
+
+    osi3::SensorData out_sensorData;
+};
+
+
diff --git a/sim/src/components/Sensor_Driver/src/sensor_driverImpl.cpp b/sim/src/components/Sensor_Driver/src/sensor_driverImpl.cpp
index 6a969ff71d54023842d283f055a7abfac37e12ae..2306d7b25f6e52a8de4842c41be891c2e60b0172 100644
--- a/sim/src/components/Sensor_Driver/src/sensor_driverImpl.cpp
+++ b/sim/src/components/Sensor_Driver/src/sensor_driverImpl.cpp
@@ -110,7 +110,7 @@ void SensorDriverImplementation::GetNewRoute()
     }
     auto [roadGraph, root] = GetWorld()->GetRoadGraph({roadIds.front(), GetAgent()->GetObjectPosition().mainLocatePoint.at(roadIds.front()).laneId < 0}, maxDepth);
     std::map<RoadGraph::edge_descriptor, double> weights = GetWorld()->GetEdgeWeights(roadGraph);
-    auto [route, target] = RouteCalculation::SampleRoute(roadGraph, root, weights, *GetStochastics());
+    auto target = RouteCalculation::SampleRoute(roadGraph, root, weights, *GetStochastics());
     egoAgent.SetRoadGraph(std::move(roadGraph), root, target);
 }
 
diff --git a/sim/src/components/Sensor_OSI/src/objectDetectorBase.cpp b/sim/src/components/Sensor_OSI/src/objectDetectorBase.cpp
index 25390d1e69a63bdf299ee9ee174896f3e60cc96c..ddc1e160bdf42ba3060c69c025ae53dcd0118718 100644
--- a/sim/src/components/Sensor_OSI/src/objectDetectorBase.cpp
+++ b/sim/src/components/Sensor_OSI/src/objectDetectorBase.cpp
@@ -104,6 +104,45 @@ void ObjectDetectorBase::UpdateOutput(int localLinkId, std::shared_ptr<SignalInt
     }
 }
 
+void ObjectDetectorBase::AddMovingObjectToSensorData(osi3::MovingObject object, point_t ownVelocity, point_t ownAcceleration, point_t ownPosition, double yaw, double yawRate)
+{
+    point_t objectReferencePointGlobal{object.base().position().x(), object.base().position().y()};
+    point_t objectReferencePointLocal = TransformPointToLocalCoordinates(objectReferencePointGlobal, ownPosition, yaw);
+
+    osi3::DetectedMovingObject* detectedObject = sensorData.add_moving_object();
+    detectedObject->mutable_header()->add_ground_truth_id()->set_value(object.id().value());
+    detectedObject->mutable_header()->add_sensor_id()->set_value(id);
+    detectedObject->mutable_base()->mutable_dimension()->CopyFrom(object.base().dimension());
+
+    detectedObject->mutable_base()->mutable_position()->set_x(objectReferencePointLocal.x());
+    detectedObject->mutable_base()->mutable_position()->set_y(objectReferencePointLocal.y());
+    detectedObject->mutable_base()->mutable_orientation()->set_yaw(object.base().orientation().yaw() - yaw);
+    detectedObject->mutable_base()->mutable_orientation_rate()->set_yaw(object.base().orientation_rate().yaw() - yawRate);
+    point_t objectVelocity{object.base().velocity().x(), object.base().velocity().y()};
+    point_t relativeVelocity = CalculateRelativeVector(objectVelocity, ownVelocity, yaw);
+    detectedObject->mutable_base()->mutable_velocity()->set_x(relativeVelocity.x());
+    detectedObject->mutable_base()->mutable_velocity()->set_y(relativeVelocity.y());
+    point_t objectAcceleration{object.base().acceleration().x(), object.base().acceleration().y()};
+    point_t relativeAcceleration = CalculateRelativeVector(objectAcceleration, ownAcceleration, yaw);
+    detectedObject->mutable_base()->mutable_acceleration()->set_x(relativeAcceleration.x());
+    detectedObject->mutable_base()->mutable_acceleration()->set_y(relativeAcceleration.y());
+}
+
+void ObjectDetectorBase::AddStationaryObjectToSensorData(osi3::StationaryObject object, point_t ownPosition, double yaw)
+{
+    point_t objectReferencePointGlobal{object.base().position().x(), object.base().position().y()};
+    point_t objectReferencePointLocal = TransformPointToLocalCoordinates(objectReferencePointGlobal, ownPosition, yaw);
+
+    osi3::DetectedStationaryObject* detectedObject = sensorData.add_stationary_object();
+    detectedObject->mutable_header()->add_ground_truth_id()->set_value(object.id().value());
+    detectedObject->mutable_header()->add_sensor_id()->set_value(id);
+    detectedObject->mutable_base()->mutable_dimension()->CopyFrom(object.base().dimension());
+
+    detectedObject->mutable_base()->mutable_position()->set_x(objectReferencePointLocal.x());
+    detectedObject->mutable_base()->mutable_position()->set_y(objectReferencePointLocal.y());
+    detectedObject->mutable_base()->mutable_orientation()->set_yaw(object.base().orientation().yaw() - yaw);
+}
+
 Position ObjectDetectorBase::GetAbsolutePosition()
 {
     Position absolutePosition;
@@ -269,3 +308,33 @@ void ObjectDetectorBase::ParseBasicParameter()
     position.yaw = doubleParameters.at("Yaw");
     position.roll = doubleParameters.at("Roll");
 }
+
+const osi3::MovingObject* ObjectDetectorBase::FindHostVehicleInSensorView(const osi3::SensorView& sensorView)
+{
+    const auto hostVehicleIt = std::find_if(sensorView.global_ground_truth().moving_object().cbegin(),
+                                            sensorView.global_ground_truth().moving_object().cend(),
+                                            [&sensorView](const osi3::MovingObject& object)
+                                            {
+                                                return object.id().value() == sensorView.host_vehicle_id().value();
+                                            });
+
+    if (hostVehicleIt == sensorView.global_ground_truth().moving_object().cend())
+    {
+        throw std::runtime_error("Host vehicle not in SensorView");
+    }
+
+    return &(*hostVehicleIt);
+}
+
+point_t ObjectDetectorBase::GetHostVehiclePosition(const osi3::MovingObject* hostVehicle) const
+{
+    point_t bbCenterToRear{hostVehicle->vehicle_attributes().bbcenter_to_rear().x(), hostVehicle->vehicle_attributes().bbcenter_to_rear().y()};
+    bt::rotate_transformer<bg::radian, double, 2, 2> rotate(-hostVehicle->base().orientation().yaw());
+    bt::translate_transformer<double, 2, 2> bbCenter(hostVehicle->base().position().x(), hostVehicle->base().position().y());
+    point_t rotatedBbCenterToRear;
+    point_t ownPosition;
+    bg::transform(bbCenterToRear, rotatedBbCenterToRear, rotate);
+    bg::transform(rotatedBbCenterToRear, ownPosition, bbCenter);
+
+    return ownPosition;
+}
diff --git a/sim/src/components/Sensor_OSI/src/objectDetectorBase.h b/sim/src/components/Sensor_OSI/src/objectDetectorBase.h
index 45e8b1f2cfa9278109357bbd68ebab169db88a1c..6472c81f725544098f04b91e456b6b40eb3bb633 100644
--- a/sim/src/components/Sensor_OSI/src/objectDetectorBase.h
+++ b/sim/src/components/Sensor_OSI/src/objectDetectorBase.h
@@ -133,6 +133,27 @@ public:
 
 protected:
 
+    /*!
+     * \brief Adds the information of a detected moving object as DetectedMovingObject to the sensor data
+     *
+     * \param object            detected moving object
+     * \param ownVelocity       velocity of own vehicle in global coordinates
+     * \param ownAcceleration   acceleration of own vehicle in global coordinates
+     * \param ownPosition       position of own vehicle in global coordinates
+     * \param yaw               yaw of own vehicle in global coordinates
+     * \param yawRate           yawRate of own vehicle in global coordinates
+     */
+    void AddMovingObjectToSensorData (osi3::MovingObject object, point_t ownVelocity, point_t ownAcceleration, point_t ownPosition, double yaw, double yawRate);
+
+    /*!
+     * \brief Adds the information of a detected stationary object as DetectedStationaryObject to the sensor data
+     *
+     * \param object            stationary moving object
+     * \param ownPosition       position of own vehicle in global coordinates
+     * \param yaw               yaw of own vehicle in global coordinates
+     */
+    void AddStationaryObjectToSensorData (osi3::StationaryObject object, point_t ownPosition, double yaw);
+
     /*!
      * \brief Returns the absolute position of the sensor
      *
@@ -226,6 +247,12 @@ protected:
    */
    virtual point_t CalculateRelativeVector(const point_t absolute, const point_t own, double yaw);
 
+   //! Returns the MovingObject in the sensor view which was defined as host vehicle (by id)
+   static const osi3::MovingObject* FindHostVehicleInSensorView(const osi3::SensorView& sensorView);
+
+   //! Returns the world coordinate position of the host vehicle
+   point_t GetHostVehiclePosition(const osi3::MovingObject* hostVehicle) const;
+
    std::list<std::pair<int, osi3::SensorData>> detectedObjectsBuffer;
 
    osi3::SensorData sensorData;
diff --git a/sim/src/components/Sensor_OSI/src/sensorGeometric2D.cpp b/sim/src/components/Sensor_OSI/src/sensorGeometric2D.cpp
index 55bda33139cd728c35dfa3e22877e88847437ce1..aec47718be478c054714882fbc4276467ee53a0a 100644
--- a/sim/src/components/Sensor_OSI/src/sensorGeometric2D.cpp
+++ b/sim/src/components/Sensor_OSI/src/sensorGeometric2D.cpp
@@ -221,19 +221,6 @@ polygon_t SensorGeometric2D::CreateFivePointDetectionField() const
     return detectionField;
 }
 
-point_t SensorGeometric2D::GetHostVehiclePosition(const osi3::MovingObject* hostVehicle) const
-{
-    point_t bbCenterToRear{hostVehicle->vehicle_attributes().bbcenter_to_rear().x(), hostVehicle->vehicle_attributes().bbcenter_to_rear().y()};
-    bt::rotate_transformer<bg::radian, double, 2, 2> rotate(-hostVehicle->base().orientation().yaw());
-    bt::translate_transformer<double, 2, 2> bbCenter(hostVehicle->base().position().x(), hostVehicle->base().position().y());
-    point_t rotatedBbCenterToRear;
-    point_t ownPosition;
-    bg::transform(bbCenterToRear, rotatedBbCenterToRear, rotate);
-    bg::transform(rotatedBbCenterToRear, ownPosition, bbCenter);
-
-    return ownPosition;
-}
-
 std::pair<point_t, polygon_t> SensorGeometric2D::CreateSensorDetectionField(const osi3::MovingObject* hostVehicle) const
 {
     polygon_t detectionField;
@@ -326,23 +313,6 @@ SensorDetectionResults SensorGeometric2D::DetectObjects()
     return results;
 }
 
-const osi3::MovingObject* SensorGeometric2D::FindHostVehicleInSensorView(const osi3::SensorView& sensorView)
-{
-    const auto hostVehicleIt = std::find_if(sensorView.global_ground_truth().moving_object().cbegin(),
-                                            sensorView.global_ground_truth().moving_object().cend(),
-                                            [&sensorView](const osi3::MovingObject& object)
-                                            {
-                                                return object.id().value() == sensorView.host_vehicle_id().value();
-                                            });
-
-    if (hostVehicleIt == sensorView.global_ground_truth().moving_object().cend())
-    {
-        throw std::runtime_error("Host vehicle not in SensorView");
-    }
-
-    return &(*hostVehicleIt);
-}
-
 std::pair<std::vector<const osi3::MovingObject*>, std::vector<const osi3::StationaryObject*>> SensorGeometric2D::GetObjectsInDetectionAreaFromSensorView(const osi3::SensorView& sensorView,
                                                                                                                                                          const point_t& sensorPositionGlobal,
                                                                                                                                                          const polygon_t& detectionField) const
@@ -439,45 +409,6 @@ std::pair<std::vector<T>, std::vector<T>> SensorGeometric2D::CalcVisualObstructi
     return std::make_pair(visibleObjects, detectedObjects);
 }
 
-void SensorGeometric2D::AddMovingObjectToSensorData(osi3::MovingObject object, point_t ownVelocity, point_t ownAcceleration, point_t ownPosition, double yaw, double yawRate)
-{
-    point_t objectReferencePointGlobal{object.base().position().x(), object.base().position().y()};
-    point_t objectReferencePointLocal = TransformPointToLocalCoordinates(objectReferencePointGlobal, ownPosition, yaw);
-
-    osi3::DetectedMovingObject* detectedObject = sensorData.add_moving_object();
-    detectedObject->mutable_header()->add_ground_truth_id()->set_value(object.id().value());
-    detectedObject->mutable_header()->add_sensor_id()->set_value(id);
-    detectedObject->mutable_base()->mutable_dimension()->CopyFrom(object.base().dimension());
-
-    detectedObject->mutable_base()->mutable_position()->set_x(objectReferencePointLocal.x());
-    detectedObject->mutable_base()->mutable_position()->set_y(objectReferencePointLocal.y());
-    detectedObject->mutable_base()->mutable_orientation()->set_yaw(object.base().orientation().yaw() - yaw);
-    detectedObject->mutable_base()->mutable_orientation_rate()->set_yaw(object.base().orientation_rate().yaw() - yawRate);
-    point_t objectVelocity{object.base().velocity().x(), object.base().velocity().y()};
-    point_t relativeVelocity = CalculateRelativeVector(objectVelocity, ownVelocity, yaw);
-    detectedObject->mutable_base()->mutable_velocity()->set_x(relativeVelocity.x());
-    detectedObject->mutable_base()->mutable_velocity()->set_y(relativeVelocity.y());
-    point_t objectAcceleration{object.base().acceleration().x(), object.base().acceleration().y()};
-    point_t relativeAcceleration = CalculateRelativeVector(objectAcceleration, ownAcceleration, yaw);
-    detectedObject->mutable_base()->mutable_acceleration()->set_x(relativeAcceleration.x());
-    detectedObject->mutable_base()->mutable_acceleration()->set_y(relativeAcceleration.y());
-}
-
-void SensorGeometric2D::AddStationaryObjectToSensorData(osi3::StationaryObject object, point_t ownPosition, double yaw)
-{
-    point_t objectReferencePointGlobal{object.base().position().x(), object.base().position().y()};
-    point_t objectReferencePointLocal = TransformPointToLocalCoordinates(objectReferencePointGlobal, ownPosition, yaw);
-
-    osi3::DetectedStationaryObject* detectedObject = sensorData.add_stationary_object();
-    detectedObject->mutable_header()->add_ground_truth_id()->set_value(object.id().value());
-    detectedObject->mutable_header()->add_sensor_id()->set_value(id);
-    detectedObject->mutable_base()->mutable_dimension()->CopyFrom(object.base().dimension());
-
-    detectedObject->mutable_base()->mutable_position()->set_x(objectReferencePointLocal.x());
-    detectedObject->mutable_base()->mutable_position()->set_y(objectReferencePointLocal.y());
-    detectedObject->mutable_base()->mutable_orientation()->set_yaw(object.base().orientation().yaw() - yaw);
-}
-
 polygon_t SensorGeometric2D::CalcInitialBrightArea(point_t sensorPosition)
 {
     const double stepSize = 0.1;
diff --git a/sim/src/components/Sensor_OSI/src/sensorGeometric2D.h b/sim/src/components/Sensor_OSI/src/sensorGeometric2D.h
index 10ebd8e7e42edd6980304ce8ed6014ec2d15378a..50badd91481e30c9c92425133c25ae7c5afb472e 100644
--- a/sim/src/components/Sensor_OSI/src/sensorGeometric2D.h
+++ b/sim/src/components/Sensor_OSI/src/sensorGeometric2D.h
@@ -129,27 +129,6 @@ private:
      */
     static double CalcObjectVisibilityPercentage(const polygon_t& boundingBox, const multi_polygon_t &brightArea);
     
-    /*!
-     * \brief Adds the information of a detected moving object as DetectedMovingObject to the sensor data
-     *
-     * \param object            detected moving object
-     * \param ownVelocity       velocity of own vehicle in global coordinates
-     * \param ownAcceleration   acceleration of own vehicle in global coordinates
-     * \param ownPosition       position of own vehicle in global coordinates
-     * \param yaw               yaw of own vehicle in global coordinates
-     * \param yawRate           yawRate of own vehicle in global coordinates
-     */
-    void AddMovingObjectToSensorData (osi3::MovingObject object, point_t ownVelocity, point_t ownAcceleration, point_t ownPosition, double yaw, double yawRate);
-
-    /*!
-     * \brief Adds the information of a detected stationary object as DetectedStationaryObject to the sensor data
-     *
-     * \param object            stationary moving object
-     * \param ownPosition       position of own vehicle in global coordinates
-     * \param yaw               yaw of own vehicle in global coordinates
-     */
-    void AddStationaryObjectToSensorData (osi3::StationaryObject object, point_t ownPosition, double yaw);
-    
     /*!
      * \brief Returns true if opening angle is smaller than pi
      */
@@ -170,8 +149,6 @@ private:
      */
     polygon_t CreateFivePointDetectionField() const;
 
-    point_t GetHostVehiclePosition(const osi3::MovingObject* hostVehicle) const;
-
     std::pair<point_t, polygon_t> CreateSensorDetectionField(const osi3::MovingObject* hostVehicle) const;
     template<typename T>
     static void ApplyVisualObstructionToDetectionArea(multi_polygon_t& brightArea,
@@ -186,7 +163,6 @@ private:
                                                                                                                                           const point_t& sensorPositionGlobal,
                                                                                                                                           const polygon_t& detectionField) const;
 
-    static const osi3::MovingObject* FindHostVehicleInSensorView(const osi3::SensorView& sensorView);
     std::string CreateAgentIdListString(const std::vector<OWL::Id>& owlIds) const;
 
     bool enableVisualObstruction = false;
diff --git a/sim/src/core/slave/framework/dynamicAgentTypeGenerator.cpp b/sim/src/core/slave/framework/dynamicAgentTypeGenerator.cpp
index e8a7b3fa38cc8060cadec44b7696ea89a71c35a7..d6dfda27f47219d6136d8d0a670c452decd9e830 100644
--- a/sim/src/core/slave/framework/dynamicAgentTypeGenerator.cpp
+++ b/sim/src/core/slave/framework/dynamicAgentTypeGenerator.cpp
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (c) 2019 in-tech GmbH
+* Copyright (c) 2019, 2020 in-tech GmbH
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
@@ -111,11 +111,11 @@ DynamicAgentTypeGenerator& DynamicAgentTypeGenerator::GatherVehicleComponents()
 
 DynamicAgentTypeGenerator& DynamicAgentTypeGenerator::GatherSensors()
 {
-    const std::string sensorFusionModulName = "SensorFusion";
+    const std::string sensorAggregationModulName = "SensorAggregation";
 
-    GatherComponent(sensorFusionModulName, agentBuildInformation.agentType);
+    GatherComponent(sensorAggregationModulName, agentBuildInformation.agentType);
 
-    int inputIdSensorFusion = systemConfigBlueprint->GetSystems().at(0)->GetComponents().at(sensorFusionModulName)->GetInputLinks().at(0);
+    int inputIdSensorAggregation = systemConfigBlueprint->GetSystems().at(0)->GetComponents().at(sensorAggregationModulName)->GetInputLinks().at(0);
     int sensorNumber = 0;
     auto vehicleProfile = profiles->GetVehicleProfiles().at(sampledProfiles.vehicleProfileName);
 
@@ -144,8 +144,8 @@ DynamicAgentTypeGenerator& DynamicAgentTypeGenerator::GatherSensors()
 
         if (sensorNumber > 0)
         {
-            agentBuildInformation.agentType->GetComponents().at(sensorFusionModulName)->AddInputLink(sensorNumber,
-                    inputIdSensorFusion + sensorNumber);
+            agentBuildInformation.agentType->GetComponents().at(sensorAggregationModulName)->AddInputLink(sensorNumber,
+                    inputIdSensorAggregation + sensorNumber);
         }
 
         // clone sensor and set specific parameters
diff --git a/sim/src/core/slave/framework/dynamicAgentTypeGenerator.h b/sim/src/core/slave/framework/dynamicAgentTypeGenerator.h
index ab230cf95f0326fb72b640885dbcad056b13869c..35ee9dc896eeaef01e0d2197a290878cbf59af6b 100644
--- a/sim/src/core/slave/framework/dynamicAgentTypeGenerator.h
+++ b/sim/src/core/slave/framework/dynamicAgentTypeGenerator.h
@@ -52,7 +52,8 @@ struct DefaultComponents
         "Algorithm_LongitudinalVehicleComponents",
         "PrioritizerAccelerationVehicleComponents",
         "PrioritizerSteeringVehicleComponents",
-        "LimiterAccelerationVehicleComponents"
+        "LimiterAccelerationVehicleComponents",
+        "SensorFusionErrorless"
     };
 };
 
diff --git a/sim/src/core/slave/importer/road.cpp b/sim/src/core/slave/importer/road.cpp
index c58dd03d803d8096c178f863058c4943af73152a..23352e56670270e4514f355e2ed33103c5e69c9b 100644
--- a/sim/src/core/slave/importer/road.cpp
+++ b/sim/src/core/slave/importer/road.cpp
@@ -19,7 +19,7 @@ extern "C"
 
 namespace
 {
-const double SQRT_PI_2 = std::sqrt(M_PI_2);
+const double SQRT_PI = std::sqrt(M_PI);
 
 } // namespace
 
@@ -220,541 +220,116 @@ double RoadGeometryArc::GetDir(double sOffset) const
     return GetDirArc(sOffset, curvature);
 }
 
-Common::Vector2d RoadGeometrySpiral::HalfCoord(double sOffset, double tOffset) const
+RoadGeometrySpiral::RoadGeometrySpiral(double s, double x, double y, double hdg, double length, double curvStart, double curvEnd)
+    : RoadGeometry{s, x, y, hdg, length}, c_start{curvStart}, c_end{curvEnd}
 {
-    double _curvStart = curvStart;
-    double _curvEnd = curvEnd;
-
-    assert(_curvStart != _curvEnd);
-    assert((0.0 <= _curvStart && 0.0 <= _curvEnd) || (0.0 >= _curvStart && 0.0 >= _curvEnd));
-
-    if (length < sOffset)
+    if (length != 0.0)
     {
-        LOG_INTERN(LogLevel::Warning) << "exceeding length of geometry";
-        sOffset = length;
+        c_dot = (c_end - c_start) / length;
     }
-
-    if (0.0 <= _curvStart && 0.0 <= _curvEnd)
+    else
     {
-        if (_curvStart < _curvEnd)
-        {
-            assert(0.0 != _curvEnd);
-
-            double radiusEnd = 1.0 / _curvEnd;
-
-            // 1. equation (definition of clothoid): const = radiusStart * distanceStart = radiusEnd * distanceEnd
-            // 2. equation: length = distanceEnd - distanceStart
-            // -> distanceEnd = radiusStart * length / (radiusStart - radiusEnd)
-            // -> formed such that equation copes with _curvStart==0 (infinite radiusStart)
-            double distanceEnd = length / (1 - radiusEnd * _curvStart);
-            assert(length <= distanceEnd);
-
-            double distanceStart = distanceEnd - length;
-            double a = std::sqrt(2 * radiusEnd * distanceEnd);
-
-            Common::Vector2d start;
-            (void)fresnl(distanceStart / a / SQRT_PI_2, &start.y, &start.x);
-            start.Scale(a * SQRT_PI_2);
-
-            double distanceOffset = distanceStart + sOffset;
-            Common::Vector2d offset;
-            (void)fresnl(distanceOffset / a / SQRT_PI_2, &offset.y, &offset.x);
-            offset.Scale(a * SQRT_PI_2);
-            offset.Sub(start);
-
-            double tangentAngle = distanceOffset * distanceOffset / a / a;
-            if (0 > _curvEnd)
-            {
-                tangentAngle = -tangentAngle;
-            }
-
-            double normAngle = tangentAngle + M_PI_2;
-            normAngle = std::fmod(normAngle, 2 * M_PI);
-
-            // get perpendicular vector
-            Common::Vector2d norm(1, 0);
-            norm.Rotate(normAngle);
-            norm.Scale(tOffset);
-
-            offset.Add(norm);
-            offset.Rotate(hdg);
-
-            return Common::Vector2d(x + offset.x, y + offset.y);
-        }
-        else // _curvStart > _curvEnd ("curStart != _curvEnd" guaranteed by checks in caller)
-        {
-            std::swap(_curvStart, _curvEnd);
-            sOffset = length - sOffset;
-
-            assert(0.0 != _curvEnd);
-
-            double radiusEnd = 1.0 / _curvEnd;
-
-            // 1. equation (definition of clothoid): const = radiusStart * distanceStart = radiusEnd * distanceEnd
-            // 2. equation: length = distanceEnd - distanceStart
-            // -> distanceEnd = radiusStart * length / (radiusStart - radiusEnd)
-            // -> formed such that equation copes with _curvStart==0 (infinite radiusStart)
-            double distanceEnd = length / (1 - radiusEnd * _curvStart);
-            assert(length <= distanceEnd);
-
-            double distanceStart = distanceEnd - length;
-            double a = std::sqrt(2 * radiusEnd * distanceEnd);
-
-            Common::Vector2d start;
-            (void)fresnl(distanceStart / a / SQRT_PI_2, &start.y, &start.x);
-            start.Scale(a * SQRT_PI_2);
-
-            double distanceOffset = distanceStart + sOffset;
-            Common::Vector2d offset;
-            (void)fresnl(distanceOffset / a / SQRT_PI_2, &offset.y, &offset.x);
-            offset.Scale(a * SQRT_PI_2);
-            offset.Sub(start);
-
-            double tangentAngle = distanceOffset * distanceOffset / a / a;
-            if (0 > _curvEnd)
-            {
-                tangentAngle = -tangentAngle;
-            }
-
-            double normAngle = tangentAngle + M_PI_2;
-            normAngle = std::fmod(normAngle, 2 * M_PI);
-
-            // get perpendicular vector
-            Common::Vector2d norm(1, 0);
-            norm.Rotate(normAngle);
-            norm.Scale(tOffset);
-
-            offset.Add(norm);
-
-            // calculate end point
-            Common::Vector2d endOffset;
-            (void)fresnl(distanceEnd / a / SQRT_PI_2, &endOffset.y, &endOffset.x);
-            endOffset.Scale(a * SQRT_PI_2);
-            endOffset.Sub(start);
-
-            // compensate for inverted curvatures
-            double tangentAngleEnd = distanceEnd * distanceEnd / a / a;
-            if (0 > _curvEnd)
-            {
-                tangentAngleEnd = -tangentAngleEnd;
-            }
-            tangentAngleEnd = -tangentAngleEnd + M_PI;
-
-            offset.Sub(endOffset);
-            offset.y = -offset.y;
-            offset.Rotate(hdg - tangentAngleEnd);
-
-            return Common::Vector2d(x + offset.x, y + offset.y);
-        }
+        c_dot = 0.0;
     }
-    else // 0.0 >= _curvStart && 0.0 >= _curvEnd
-    {
-        _curvStart = -_curvStart;
-        _curvEnd = -_curvEnd;
-
-        if (_curvStart < _curvEnd)
-        {
-            assert(0.0 != _curvEnd);
-
-            double radiusEnd = 1.0 / _curvEnd;
-
-            // 1. equation (definition of clothoid): const = radiusStart * distanceStart = radiusEnd * distanceEnd
-            // 2. equation: length = distanceEnd - distanceStart
-            // -> distanceEnd = radiusStart * length / (radiusStart - radiusEnd)
-            // -> formed such that equation copes with _curvStart==0 (infinite radiusStart)
-            double distanceEnd = length / (1 - radiusEnd * _curvStart);
-            assert(length <= distanceEnd);
 
-            double distanceStart = distanceEnd - length;
-            double a = std::sqrt(2 * radiusEnd * distanceEnd);
-
-            Common::Vector2d start;
-            (void)fresnl(distanceStart / a / SQRT_PI_2, &start.y, &start.x);
-            start.Scale(a * SQRT_PI_2);
-
-            double distanceOffset = distanceStart + sOffset;
-            Common::Vector2d offset;
-            (void)fresnl(distanceOffset / a / SQRT_PI_2, &offset.y, &offset.x);
-            offset.Scale(a * SQRT_PI_2);
-            offset.Sub(start);
-
-            double tangentAngle = distanceOffset * distanceOffset / a / a;
-            if (0 > _curvEnd)
-            {
-                tangentAngle = -tangentAngle;
-            }
-
-            double normAngle = tangentAngle + M_PI_2;
-            normAngle = std::fmod(normAngle, 2 * M_PI);
-
-            // get perpendicular vector
-            Common::Vector2d norm(-1, 0);
-            norm.Rotate(normAngle);
-            norm.Scale(tOffset);
-
-            offset.Add(norm);
-            offset.y = -offset.y;
-            offset.Rotate(hdg);
-
-            return Common::Vector2d(x + offset.x, y + offset.y);
-        }
-        else // _curvStart > _curvEnd ("curStart != _curvEnd" guaranteed by checks in caller)
-        {
-            std::swap(_curvStart, _curvEnd);
-            sOffset = length - sOffset;
-
-            assert(0.0 != _curvEnd);
-
-            double radiusEnd = 1.0 / _curvEnd;
-
-            // 1. equation (definition of clothoid): const = radiusStart * distanceStart = radiusEnd * distanceEnd
-            // 2. equation: length = distanceEnd - distanceStart
-            // -> distanceEnd = radiusStart * length / (radiusStart - radiusEnd)
-            // -> formed such that equation copes with _curvStart==0 (infinite radiusStart)
-            double distanceEnd = length / (1 - radiusEnd * _curvStart);
-            assert(length <= distanceEnd);
-
-            double distanceStart = distanceEnd - length;
-            double a = std::sqrt(2 * radiusEnd * distanceEnd);
-
-            Common::Vector2d start;
-            (void)fresnl(distanceStart / a / SQRT_PI_2, &start.y, &start.x);
-            start.Scale(a * SQRT_PI_2);
-
-            double distanceOffset = distanceStart + sOffset;
-            Common::Vector2d offset;
-            (void)fresnl(distanceOffset / a / SQRT_PI_2, &offset.y, &offset.x);
-            offset.Scale(a * SQRT_PI_2);
-            offset.Sub(start);
-
-            double tangentAngle = distanceOffset * distanceOffset / a / a;
-            if (0 > _curvEnd)
-            {
-                tangentAngle = -tangentAngle;
-            }
-
-            double normAngle = tangentAngle + M_PI_2;
-            normAngle = std::fmod(normAngle, 2 * M_PI);
-
-            // get perpendicular vector
-            Common::Vector2d norm(-1, 0);
-            norm.Rotate(normAngle);
-            norm.Scale(tOffset);
-
-            offset.Add(norm);
-
-            // calculate end point
-            Common::Vector2d endOffset;
-            (void)fresnl(distanceEnd / a / SQRT_PI_2, &endOffset.y, &endOffset.x);
-            endOffset.Scale(a * SQRT_PI_2);
-            endOffset.Sub(start);
-
-            // compensate for inverted curvatures
-            double tangentAngleEnd = distanceEnd * distanceEnd / a / a;
-            if (0 > _curvEnd)
-            {
-                tangentAngleEnd = -tangentAngleEnd;
-            }
-            tangentAngleEnd = tangentAngleEnd - M_PI;
-
-            offset.Sub(endOffset);
-            offset.Rotate(hdg - tangentAngleEnd);
-
-            return Common::Vector2d(x + offset.x, y + offset.y);
-        }
+    if (c_dot != 0.0)
+    {
+        l_start = c_start / c_dot;
     }
-}
-
-Common::Vector2d RoadGeometrySpiral::FullCoord(double sOffset, double tOffset) const
-{
-    if ((0.0 <= curvStart && 0.0 <= curvEnd) || (0.0 >= curvStart && 0.0 >= curvEnd))
+    else
     {
-        return HalfCoord(sOffset, tOffset);
+        l_start = 0.0;
     }
 
-    assert((0.0 > curvStart && 0.0 < curvEnd) || (0.0 < curvStart && 0.0 > curvEnd));
-
-    // one degree of freedom: start position/end position can not be determined
-    LOG_INTERN(LogLevel::Warning) << "could not calculate spiral coordinate";
+    double l_end = l_start + length;
+    double rl;   // helper constant R * L
 
-    return Common::Vector2d();
-}
-
-double RoadGeometrySpiral::HalfCurvature(double sOffset) const
-{
-    double _curvStart = curvStart;
-    double _curvEnd = curvEnd;
-
-    assert(_curvStart != _curvEnd);
-    assert((0.0 <= _curvStart && 0.0 <= _curvEnd) || (0.0 >= _curvStart && 0.0 >= _curvEnd));
-
-    if (length < sOffset)
+    if (c_start != 0.0)
     {
-        LOG_INTERN(LogLevel::Warning) << "exceeding length of geometry";
-        sOffset = length;
+        rl = l_start / c_start;
     }
-
-    if (0.0 <= _curvStart && 0.0 <= _curvEnd)
+    else if (c_end != 0.0)
     {
-        if (_curvStart < _curvEnd)
-        {
-            assert(0.0 != _curvEnd);
-
-            double radiusEnd = 1.0 / _curvEnd;
-
-            // 1. equation (definition of clothoid): const = radiusStart * distanceStart = radiusEnd * distanceEnd
-            // 2. equation: length = distanceEnd - distanceStart
-            // -> distanceEnd = radiusStart * length / (radiusStart - radiusEnd)
-            // -> formed such that equation copes with _curvStart==0 (infinite radiusStart)
-            double distanceEnd = length / (1 - radiusEnd * _curvStart);
-            assert(length <= distanceEnd);
-
-            double distanceStart = distanceEnd - length;
-            double distanceOffset = distanceStart + sOffset;
-
-            // equation const = radiusEnd * distanceEnd = radiusOffset * distanceOffset
-            // -> curvatureOffset = 1 / radiusOffset = distanceOffset / (radiusEnd * distanceEnd)
-            return distanceOffset / radiusEnd / distanceEnd;
-        }
-        else // _curvStart > _curvEnd ("curStart != _curvEnd" guaranteed by checks in caller)
-        {
-            std::swap(_curvStart, _curvEnd);
-            sOffset = length - sOffset;
-
-            assert(0.0 != _curvEnd);
-
-            double radiusEnd = 1.0 / _curvEnd;
-
-            // 1. equation (definition of clothoid): const = radiusStart * distanceStart = radiusEnd * distanceEnd
-            // 2. equation: length = distanceEnd - distanceStart
-            // -> distanceEnd = radiusStart * length / (radiusStart - radiusEnd)
-            // -> formed such that equation copes with _curvStart==0 (infinite radiusStart)
-            double distanceEnd = length / (1 - radiusEnd * _curvStart);
-            assert(length <= distanceEnd);
-
-            double distanceStart = distanceEnd - length;
-            double distanceOffset = distanceStart + sOffset;
-
-            // equation const = radiusEnd * distanceEnd = radiusOffset * distanceOffset
-            // -> curvatureOffset = 1 / radiusOffset = distanceOffset / (radiusEnd * distanceEnd)
-            return distanceOffset / radiusEnd / distanceEnd;
-        }
+        rl = l_end / c_end;
     }
-    else // 0.0 >= _curvStart && 0.0 >= _curvEnd
-    {
-        _curvStart = -_curvStart;
-        _curvEnd = -_curvEnd;
-
-        if (_curvStart < _curvEnd)
-        {
-            assert(0.0 != _curvEnd);
-
-            double radiusEnd = 1.0 / _curvEnd;
-
-            // 1. equation (definition of clothoid): const = radiusStart * distanceStart = radiusEnd * distanceEnd
-            // 2. equation: length = distanceEnd - distanceStart
-            // -> distanceEnd = radiusStart * length / (radiusStart - radiusEnd)
-            // -> formed such that equation copes with _curvStart==0 (infinite radiusStart)
-            double distanceEnd = length / (1 - radiusEnd * _curvStart);
-            assert(length <= distanceEnd);
-
-            double distanceStart = distanceEnd - length;
-            double distanceOffset = distanceStart + sOffset;
-
-            // equation const = radiusEnd * distanceEnd = radiusOffset * distanceOffset
-            // -> curvatureOffset = 1 / radiusOffset = distanceOffset / (radiusEnd * distanceEnd)
-            return -distanceOffset / radiusEnd / distanceEnd;
-        }
-        else // _curvStart > _curvEnd ("curStart != _curvEnd" guaranteed by checks in caller)
-        {
-            std::swap(_curvStart, _curvEnd);
-            sOffset = length - sOffset;
-
-            assert(0.0 != _curvEnd);
-
-            double radiusEnd = 1.0 / _curvEnd;
-
-            // 1. equation (definition of clothoid): const = radiusStart * distanceStart = radiusEnd * distanceEnd
-            // 2. equation: length = distanceEnd - distanceStart
-            // -> distanceEnd = radiusStart * length / (radiusStart - radiusEnd)
-            // -> formed such that equation copes with _curvStart==0 (infinite radiusStart)
-            double distanceEnd = length / (1 - radiusEnd * _curvStart);
-            assert(length <= distanceEnd);
-
-            double distanceStart = distanceEnd - length;
-            double distanceOffset = distanceStart + sOffset;
-
-            // equation const = radiusEnd * distanceEnd = radiusOffset * distanceOffset
-            // -> curvatureOffset = 1 / radiusOffset = distanceOffset / (radiusEnd * distanceEnd)
-            return -distanceOffset / radiusEnd / distanceEnd;
-        }
-    }
-}
-
-double RoadGeometrySpiral::FullCurvature(double sOffset) const
-{
-    if ((0.0 <= curvStart && 0.0 <= curvEnd) || (0.0 >= curvStart && 0.0 >= curvEnd))
+    else
     {
-        return HalfCurvature(sOffset);
+        t_start = 0.0;
+        a = 0.0;
+        sign = 0.0;
+        return;
     }
 
-    assert((0.0 > curvStart && 0.0 < curvEnd) || (0.0 < curvStart && 0.0 > curvEnd));
-
-    // one degree of freedom: start position/end position can not be determined
-    LOG_INTERN(LogLevel::Warning) << "could not calculate spiral curvature";
-
-    return 0.0;
+    t_start = 0.5 * l_start * curvStart;
+    a = std::sqrt(std::abs(rl));
+    sign = std::signbit(rl) ? -1.0 : 1.0;
 }
 
-double RoadGeometrySpiral::HalfDir(double sOffset) const
+Common::Vector2d RoadGeometrySpiral::FullCoord(double sOffset, double tOffset) const
 {
-    double _curvStart = curvStart;
-    double _curvEnd = curvEnd;
-
-    assert(_curvStart != _curvEnd);
-    assert((0.0 <= _curvStart && 0.0 <= _curvEnd) || (0.0 >= _curvStart && 0.0 >= _curvEnd));
-
-    if (length < sOffset)
-    {
-        LOG_INTERN(LogLevel::Warning) << "exceeding length of geometry";
-        sOffset = length;
-    }
-
-    if (0.0 <= _curvStart && 0.0 <= _curvEnd)
-    {
-        if (_curvStart < _curvEnd)
-        {
-            assert(0.0 != _curvEnd);
-
-            double radiusEnd = 1.0 / _curvEnd;
+    // curvature of the spiral at sOffset
+    double curvAtsOffet = c_start + c_dot * sOffset;
 
-            // 1. equation (definition of clothoid): const = radiusStart * distanceStart = radiusEnd * distanceEnd
-            // 2. equation: length = distanceEnd - distanceStart
-            // -> distanceEnd = radiusStart * length / (radiusStart - radiusEnd)
-            // -> formed such that equation copes with _curvStart==0 (infinite radiusStart)
-            double distanceEnd = length / (1 - radiusEnd * _curvStart);
-            assert(length <= distanceEnd);
+    // start and end coordinates of spiral
+    Common::Vector2d start, end;
 
-            double distanceStart = distanceEnd - length;
-            double a = std::sqrt(2 * radiusEnd * distanceEnd);
+    // calculate x and y of spiral start, assuming sOffset = 0 means start of spiral with curvature curvStart
+    (void)fresnl(l_start / a / SQRT_PI, &start.y, &start.x);
+    start.Scale(a * SQRT_PI);
+    start.y *= sign;
 
-            double distanceOffset = distanceStart + sOffset;
-            double tangentAngle = distanceOffset * distanceOffset / a / a;
+    // calculate x and y of spiral end, assuming l_start + sOffset means end of spiral with curvature curvEnd
+    (void)fresnl((l_start + sOffset) / a / SQRT_PI, &end.y, &end.x);
+    end.Scale(a * SQRT_PI);
+    end.y *= sign;
 
-            return hdg + tangentAngle;
-        }
-        else // _curvStart > _curvEnd ("curStart != _curvEnd" guaranteed by checks in caller)
-        {
-            std::swap(_curvStart, _curvEnd);
-            sOffset = length - sOffset;
-
-            assert(0.0 != _curvEnd);
+    // delta x, y from start of spiral to end of spiral
+    auto diff = end - start;
 
-            double radiusEnd = 1.0 / _curvEnd;
+    // tangent angle at end of spiral
+    double t_end = (l_start + sOffset) * curvAtsOffet / 2.0;
 
-            // 1. equation (definition of clothoid): const = radiusStart * distanceStart = radiusEnd * distanceEnd
-            // 2. equation: length = distanceEnd - distanceStart
-            // -> distanceEnd = radiusStart * length / (radiusStart - radiusEnd)
-            // -> formed such that equation copes with _curvStart==0 (infinite radiusStart)
-            double distanceEnd = length / (1 - radiusEnd * _curvStart);
-            assert(length <= distanceEnd);
+    // heading change of spiral
+    double dHdg = t_end - t_start;
 
-            double distanceStart = distanceEnd - length;
-            double a = std::sqrt(2 * radiusEnd * distanceEnd);
+    // rotate delta x, y to match starting direction and origin heading
+    diff.Rotate(-t_start+hdg);
 
-            double distanceOffset = distanceStart + sOffset;
+    // heading at end of spiral
+    auto endHdg = hdg + dHdg;
 
-            double tangentAngle = distanceOffset * distanceOffset / a / a;
+    // calculate t-offset to spiral
+    Common::Vector2d unit{1.0,0};
+    unit.Rotate(endHdg + M_PI_2);
+    unit.Scale(tOffset);
 
-            // compensate for inverted curvatures
-            double tangentAngleEnd = distanceEnd * distanceEnd / a / a;
-
-            return hdg + tangentAngleEnd - tangentAngle;
-        }
-    }
-    else // 0.0 >= _curvStart && 0.0 >= _curvEnd
-    {
-        _curvStart = -_curvStart;
-        _curvEnd = -_curvEnd;
-
-        if (_curvStart < _curvEnd)
-        {
-            assert(0.0 != _curvEnd);
-
-            double radiusEnd = 1.0 / _curvEnd;
-
-            // 1. equation (definition of clothoid): const = radiusStart * distanceStart = radiusEnd * distanceEnd
-            // 2. equation: length = distanceEnd - distanceStart
-            // -> distanceEnd = radiusStart * length / (radiusStart - radiusEnd)
-            // -> formed such that equation copes with _curvStart==0 (infinite radiusStart)
-            double distanceEnd = length / (1 - radiusEnd * _curvStart);
-            assert(length <= distanceEnd);
-
-            double distanceStart = distanceEnd - length;
-            double a = std::sqrt(2 * radiusEnd * distanceEnd);
-
-            double distanceOffset = distanceStart + sOffset;
-
-            double tangentAngle = distanceOffset * distanceOffset / a / a;
-
-            return hdg - tangentAngle;
-        }
-        else // _curvStart > _curvEnd ("curStart != _curvEnd" guaranteed by checks in caller)
-        {
-            std::swap(_curvStart, _curvEnd);
-            sOffset = length - sOffset;
-
-            assert(0.0 != _curvEnd);
-
-            double radiusEnd = 1.0 / _curvEnd;
-
-            // 1. equation (definition of clothoid): const = radiusStart * distanceStart = radiusEnd * distanceEnd
-            // 2. equation: length = distanceEnd - distanceStart
-            // -> distanceEnd = radiusStart * length / (radiusStart - radiusEnd)
-            // -> formed such that equation copes with _curvStart==0 (infinite radiusStart)
-            double distanceEnd = length / (1 - radiusEnd * _curvStart);
-            assert(length <= distanceEnd);
-
-            double distanceStart = distanceEnd - length;
-            double a = std::sqrt(2 * radiusEnd * distanceEnd);
-
-            double distanceOffset = distanceStart + sOffset;
-
-            double tangentAngle = distanceOffset * distanceOffset / a / a;
-
-            // compensate for inverted curvatures
-            double tangentAngleEnd = distanceEnd * distanceEnd / a / a;
+    return diff + unit + Common::Vector2d(x, y);
+}
 
-            return hdg - (tangentAngleEnd - tangentAngle);
-        }
-    }
+double RoadGeometrySpiral::FullCurvature(double sOffset) const
+{
+    return c_start + c_dot * sOffset;
 }
 
 double RoadGeometrySpiral::FullDir(double sOffset) const
 {
-    if ((0.0 <= curvStart && 0.0 <= curvEnd) || (0.0 >= curvStart && 0.0 >= curvEnd))
-    {
-        return HalfDir(sOffset);
-    }
-
-    assert((0.0 > curvStart && 0.0 < curvEnd) || (0.0 < curvStart && 0.0 > curvEnd));
-
-    // one degree of freedom: start position/end position can not be determined
-    LOG_INTERN(LogLevel::Warning) << "could not calculate spiral curvature";
+    // tangent_angle = L / (2 * R) = 0.5 * L * curv
+    // direction change in spiral = tangent_end - tangent_start
 
-    return 0.0;
+    double curvEnd = FullCurvature(sOffset);
+    return hdg + 0.5 * (curvEnd * (l_start + sOffset) - c_start * l_start);
 }
 
 Common::Vector2d RoadGeometrySpiral::GetCoord(double sOffset, double tOffset) const
 {
-    if (0.0 == curvStart && 0.0 == curvEnd)
+    if (0.0 == c_start && 0.0 == c_end)
     {
         return GetCoordLine(sOffset, tOffset);
     }
 
-    if (std::abs(curvStart - curvEnd) < 1e-6 /* assumed to be equal */)
+    if (std::abs(c_start - c_end) < 1e-6 /* assumed to be equal */)
     {
-        return GetCoordArc(sOffset, tOffset, curvStart);
+        return GetCoordArc(sOffset, tOffset, c_start);
     }
 
     return FullCoord(sOffset, tOffset);
@@ -762,14 +337,14 @@ Common::Vector2d RoadGeometrySpiral::GetCoord(double sOffset, double tOffset) co
 
 double RoadGeometrySpiral::GetDir(double sOffset) const
 {
-    if (0.0 == curvStart && 0.0 == curvEnd)
+    if (0.0 == c_start && 0.0 == c_end)
     {
         return GetDirLine(sOffset);
     }
 
-    if (std::abs(curvStart - curvEnd) < 1e-6 /* assumed to be equal */)
+    if (std::abs(c_start - c_end) < 1e-6 /* assumed to be equal */)
     {
-        return GetDirArc(sOffset, curvStart);
+        return GetDirArc(sOffset, c_start);
     }
 
     return FullDir(sOffset);
diff --git a/sim/src/core/slave/importer/road.h b/sim/src/core/slave/importer/road.h
index 4e6af4508ffdda4b72317d7642ad9638d9e367dc..483a3bb7160d51aaee79977bdee896a6d5092c29 100644
--- a/sim/src/core/slave/importer/road.h
+++ b/sim/src/core/slave/importer/road.h
@@ -586,97 +586,46 @@ class RoadGeometryArc : public RoadGeometry
 //-----------------------------------------------------------------------------
 class RoadGeometrySpiral : public RoadGeometry
 {
-  public:
-    RoadGeometrySpiral(double s, double x, double y, double hdg, double length, double curvStart, double curvEnd)
-        : RoadGeometry{s, x, y, hdg, length}, curvStart{curvStart}, curvEnd{curvEnd}
-    {
-    }
+public:
+    RoadGeometrySpiral(double s, double x, double y, double hdg, double length, double curvStart, double curvEnd);
     virtual ~RoadGeometrySpiral() override = default;
     virtual Common::Vector2d GetCoord(double sOffset, double tOffset) const override;
     virtual double GetDir(double sOffset) const override;
 
+private:
     //-----------------------------------------------------------------------------
-    //! Returns the curvature at the start of the spiral.
-    //!
-    //! @return                         curvature at the start of the spiral
-    //-----------------------------------------------------------------------------
-    double GetCurvStart() const
-    {
-        return curvStart;
-    }
-
-    //-----------------------------------------------------------------------------
-    //! Returns the curvature at the end of the spiral.
-    //!
-    //! @return                         curvature at the end of the spiral
-    //-----------------------------------------------------------------------------
-    double GetCurvEnd() const
-    {
-        return curvEnd;
-    }
-
-  private:
-    //-----------------------------------------------------------------------------
-    //! Calculates the x/y coordinates as vector. Only valid if the start and end
-    //! curvature of the spiral are either both positive or negative.
+    //! Calculates the x/y coordinates as vector.
     //!
     //! @param[in]  sOffset    s offset within geometry section
     //! @param[in]  tOffset    offset to the left
     //! @return     vector with the x/y coordinates
     //-----------------------------------------------------------------------------
-    Common::Vector2d HalfCoord(double sOffset, double tOffset) const;
-
-    //-----------------------------------------------------------------------------
-    //! Calculates the x/y coordinates as vector. Returns an empty vector, if start
-    //! and end curvature of the spiral have different signs.
-    //!
-    //! @param[in]  sOffset    s offset within geometry section
-    //! @param[in]  tOffset    offset to the left
-    //! @return     vector with the x/y coordinates, empty vector,
-    //!             if start and end curvature of the spiral have
-    //!             different signs
-    //-----------------------------------------------------------------------------
     Common::Vector2d FullCoord(double sOffset, double tOffset) const;
 
     //-----------------------------------------------------------------------------
-    //! Calculates the curvature. Only valid if the start and end
-    //! curvature of the spiral are either both positive or negative.
+    //! Calculates the curvature.
     //!
     //! @param[in]  sOffset    s offset within geometry section
     //! @return                curvature
     //-----------------------------------------------------------------------------
-    double HalfCurvature(double sOffset) const;
-
-    //-----------------------------------------------------------------------------
-    //! Calculates the curvature. Returns 0.0, if start
-    //! and end curvature of the spiral have different signs.
-    //!
-    //! @param[in]  sOffset    s offset within geometry section
-    //! @return                curvature, 0.0, if start and end curvature
-    //!                        of the spiral have different signs
-    //-----------------------------------------------------------------------------
     double FullCurvature(double sOffset) const;
 
     //-----------------------------------------------------------------------------
-    //! Calculates the direction. Only valid if the start and end
-    //! curvature of the spiral are either both positive or negative.
-    //!
-    //! @param[in]  sOffset    s offset within geometry section
-    //! @return                direction
-    //-----------------------------------------------------------------------------
-    double HalfDir(double sOffset) const;
-
-    //-----------------------------------------------------------------------------
-    //! Calculates the direction. Returns 0.0, if start
-    //! and end curvature of the spiral have different signs.
+    //! Calculates the direction.
     //!
     //! @param[in]  sOffset    s offset within geometry section
     //! @return                direction
     //-----------------------------------------------------------------------------
     double FullDir(double sOffset) const;
 
-    double curvStart;
-    double curvEnd;
+
+    double c_start;  //!< spiral starting curvature
+    double c_end;    //!< spiral end curvature
+    double a;        //!< clothoid parameter of spiral
+    double sign;     //!< direction of curvature change (needes to correct Fresnel integral results)
+    double c_dot;    //!< change of curvature per unit
+    double l_start;  //!< offset of starting point along spiral
+    double t_start;  //!< tangent angle at start point
 };
 
 //-----------------------------------------------------------------------------
diff --git a/sim/src/core/slave/modules/Observation_Log/observationLogConstants.h b/sim/src/core/slave/modules/Observation_Log/observationLogConstants.h
index f21e1f3529e113c05e907ff32229b5b67442a8ec..c0e17f75f5b2e81617bb8339b45296de3e40f77a 100644
--- a/sim/src/core/slave/modules/Observation_Log/observationLogConstants.h
+++ b/sim/src/core/slave/modules/Observation_Log/observationLogConstants.h
@@ -65,7 +65,7 @@ struct OutputTags
     const QString SAMPLE = "Sample";
     const QString SCENERYFILE = "SceneryFile";
     const QString VEHICLEATTRIBUTES = "VehicleAttributes";
-    const QString TRIGGERINGENTITIES = "openpass::type::TriggeringEntities";
+    const QString TRIGGERINGENTITIES = "TriggeringEntities";
     const QString AFFECTEDENTITIES = "AffectedEntities";
 };
 
diff --git a/sim/src/core/slave/modules/World_OSI/RoutePlanning/RouteCalculation.h b/sim/src/core/slave/modules/World_OSI/RoutePlanning/RouteCalculation.h
index 6ecd994608ce7cca671b647da17d0ec09b862aa6..8513189d1d4f4e97d104b03719e2f6377ca1e5b1 100644
--- a/sim/src/core/slave/modules/World_OSI/RoutePlanning/RouteCalculation.h
+++ b/sim/src/core/slave/modules/World_OSI/RoutePlanning/RouteCalculation.h
@@ -15,7 +15,7 @@
 
 namespace RouteCalculation
 {
-    RoadGraphVertex FilterRoadGraphByStartPositionRecursive (const RoadGraph& roadGraph, RoadGraphVertex current, int maxDepth, RoadGraph& filteredGraph)
+    RoadGraphVertex FilterRoadGraphByStartPositionRecursive(const RoadGraph& roadGraph, RoadGraphVertex current, int maxDepth, RoadGraph& filteredGraph)
     {
         const auto& routeElement = get(RouteElement(), roadGraph, current);
         auto newVertex = add_vertex(routeElement, filteredGraph);
@@ -30,20 +30,32 @@ namespace RouteCalculation
         return newVertex;
     }
 
-    std::pair<RoadGraph, RoadGraphVertex> FilterRoadGraphByStartPosition (const RoadGraph& roadGraph, RoadGraphVertex start, int maxDepth)
+    //! Returns the road graph as a tree with defined maximum depth relative to a given start position.
+    //! The same route element can appear multiple times in the result, if there are multiple paths to it from the start position
+    //!
+    //! \param roadGraph    entire road network
+    //! \param start        start position in the network
+    //! \param maxDepth     maximum depth of resulting tree
+    //! \return road network as tree with given root
+    std::pair<RoadGraph, RoadGraphVertex> FilterRoadGraphByStartPosition(const RoadGraph& roadGraph, RoadGraphVertex start, int maxDepth)
     {
         RoadGraph filteredGraph;
         auto root = FilterRoadGraphByStartPositionRecursive(roadGraph, start, maxDepth, filteredGraph);
         return {filteredGraph, root};
     }
 
-    std::pair<RoadGraph, RoadGraphVertex> SampleRoute (const RoadGraph& roadGraph,
-                                                       RoadGraphVertex root,
-                                                       const std::map<RoadGraphEdge, double>& weights,
-                                                       StochasticsInterface& stochastics)
+    //! Random draws a target leaf in the given road graph tree based on the propability of each edge
+    //!
+    //! \param roadGraph    tree of road network starting at the agents current position
+    //! \param root         root vertex of the roadGraph
+    //! \param weights      weight map of all edges of the graph
+    //! \param stochastics  stochastics module
+    //! \return sampled target vertex
+    RoadGraphVertex SampleRoute(const RoadGraph& roadGraph,
+                                RoadGraphVertex root,
+                                const std::map<RoadGraphEdge, double>& weights,
+                                StochasticsInterface& stochastics)
     {
-        RoadGraph route;
-        auto firstVertex = add_vertex(get(RouteElement(), roadGraph, root), route);
         auto current = root;
         bool reachedEnd = false;
         while (!reachedEnd)
@@ -65,14 +77,11 @@ namespace RouteCalculation
                 probalitySum += weights.at(*successor);
                 if (roll <= probalitySum)
                 {
-                    auto secondVertex = add_vertex(get(RouteElement(), roadGraph, target(*successor, roadGraph)), route);
-                    add_edge(firstVertex, secondVertex, route);
                     current = target(*successor, roadGraph);
-                    firstVertex = secondVertex;
                     break;
                 }
             }
         }
-        return {route, firstVertex};
+        return current;
     }
 }
diff --git a/sim/src/sim.pro b/sim/src/sim.pro
index cd5b7f3f51535e1a5585ddd159b262753ca28467..0d8026b0bec122126642102cb7f2b4f99218af1c 100644
--- a/sim/src/sim.pro
+++ b/sim/src/sim.pro
@@ -44,7 +44,8 @@ SUBDIRS = \
     components/Sensor_Driver \
     components/Sensor_OSI \
     components/Sensor_RecordState \
-    components/SensorFusion_OSI \
+    components/SensorAggregation_OSI \
+    components/SensorFusionErrorless_OSI \
     components/SignalPrioritizer
 
 slave.file = core/slave/OpenPassSlave.pro
diff --git a/sim/tests/unitTests/CMakeLists.txt b/sim/tests/unitTests/CMakeLists.txt
index 7c9c91f6eb31589a45d711d40cc7bb45c50ccff7..8450ff6fdfddcf2c88f68a818ee12308ef4e9fad 100644
--- a/sim/tests/unitTests/CMakeLists.txt
+++ b/sim/tests/unitTests/CMakeLists.txt
@@ -10,7 +10,8 @@ add_subdirectory(components/Dynamics_Collision)
 add_subdirectory(components/Dynamics_TF)
 add_subdirectory(components/LimiterAccVehComp)
 add_subdirectory(components/OpenScenarioActions)
-add_subdirectory(components/SensorFusion_OSI)
+add_subdirectory(components/SensorAggregation_OSI)
+add_subdirectory(components/SensorFusionErrorless_OSI)
 add_subdirectory(components/Sensor_Driver)
 add_subdirectory(components/Sensor_OSI)
 add_subdirectory(components/SignalPrioritizer)
diff --git a/sim/tests/unitTests/common/CMakeLists.txt b/sim/tests/unitTests/common/CMakeLists.txt
index ac93f696e095d1da82f7cf0e645d1e5f7515b91e..c3d7fdc9aad957b4056a7a1bbaee466eacf2fb97 100644
--- a/sim/tests/unitTests/common/CMakeLists.txt
+++ b/sim/tests/unitTests/common/CMakeLists.txt
@@ -7,7 +7,10 @@ add_openpass_target(
   LINK_OSI
 
   SOURCES
+    commonHelper_Tests.cpp
     ttcCalculation_Tests.cpp
+    tokenizeString_Tests.cpp
+    vectorToString_Tests.cpp
 
   HEADERS
     ${COMPONENT_SOURCE_DIR}/commonTools.h
diff --git a/sim/tests/unitTests/common/Common_Tests.pro b/sim/tests/unitTests/common/Common_Tests.pro
index 25d0ab58b786fa7509f3ad24778b61bee1dfa09f..a48f5c361ad0f5ba209c88b24c59b682b5eccd48 100644
--- a/sim/tests/unitTests/common/Common_Tests.pro
+++ b/sim/tests/unitTests/common/Common_Tests.pro
@@ -29,6 +29,7 @@ HEADERS += \
     $$UNIT_UNDER_TEST/commonTools.h
 
 SOURCES += \
+    commonHelper_Tests.cpp \
     tokenizeString_Tests.cpp \
     ttcCalculation_Tests.cpp \
     vectorToString_Tests.cpp
diff --git a/sim/tests/unitTests/common/commonHelper_Tests.cpp b/sim/tests/unitTests/common/commonHelper_Tests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fde532a4241efc3345f8b75b9b3b63b3d8d5f19e
--- /dev/null
+++ b/sim/tests/unitTests/common/commonHelper_Tests.cpp
@@ -0,0 +1,48 @@
+# /*********************************************************************
+# * Copyright (c) 2020 in-tech GmbH
+# *
+# * This program and the accompanying materials are made
+# * available under the terms of the Eclipse Public License 2.0
+# * which is available at https://www.eclipse.org/legal/epl-2.0/
+# *
+# * SPDX-License-Identifier: EPL-2.0
+# **********************************************************************/
+
+#include "common/commonTools.h"
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+
+using ::testing::TestWithParam;
+using ::testing::Values;
+using ::testing::Return;
+using ::testing::DoubleNear;
+
+struct CartesianNetDistance_Data
+{
+    polygon_t ownBoundingBox;
+    polygon_t otherBoundingBox;
+    double expectedNetX;
+    double expectedNetY;
+};
+
+class CartesianNetDistanceTest: public ::TestWithParam<CartesianNetDistance_Data>
+{
+};
+
+TEST_P(CartesianNetDistanceTest, GetCartesianNetDistance_ReturnsCorrectDistances)
+{
+    auto data = GetParam();
+    auto [netX, netY] = CommonHelper::GetCartesianNetDistance(data.ownBoundingBox, data.otherBoundingBox);
+
+    ASSERT_THAT(netX, DoubleNear(data.expectedNetX, 1e-3));
+    ASSERT_THAT(netY, DoubleNear(data.expectedNetY, 1e-3));
+}
+
+INSTANTIATE_TEST_CASE_P(CartesianNetDistanceTestCase, CartesianNetDistanceTest, ::testing::Values(
+//                             ownBoundingBox                          otherBoundingBox                                 x y
+    CartesianNetDistance_Data{polygon_t{{{0,0},{1,0},{1,1},{0,1}}},  polygon_t{{{1,0},{2,0},{2,1},{1,1}}},              0,0},
+    CartesianNetDistance_Data{polygon_t{{{-1,0},{0,-1},{1,0},{0,1}}},polygon_t{{{1,1},{2,1},{2,2},{1,2}}},              0,0},
+    CartesianNetDistance_Data{polygon_t{{{-1,0},{0,-1},{1,0},{0,1}}},polygon_t{{{3,4},{4,4},{4,6},{3,6}}},              2,3},
+    CartesianNetDistance_Data{polygon_t{{{-1,0},{0,-1},{1,0},{0,1}}},polygon_t{{{-10,-10},{-8,-10},{-8,-9},{-10,-9}}},-7,-8}
+));
diff --git a/sim/tests/unitTests/components/SensorAggregation_OSI/CMakeLists.txt b/sim/tests/unitTests/components/SensorAggregation_OSI/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..dac9fd9eb98f9841ed5161c3d98a950c55a78026
--- /dev/null
+++ b/sim/tests/unitTests/components/SensorAggregation_OSI/CMakeLists.txt
@@ -0,0 +1,22 @@
+set(COMPONENT_TEST_NAME SensorAggregationOSI_Tests)
+set(COMPONENT_SOURCE_DIR ${OPENPASS_SIMCORE_DIR}/components/SensorAggregation_OSI/src)
+
+add_openpass_target(
+  NAME ${COMPONENT_TEST_NAME} TYPE test COMPONENT core
+  DEFAULT_MAIN
+  LINKOSI
+
+  SOURCES
+    sensorAggregationOSI_Tests.cpp
+    ${COMPONENT_SOURCE_DIR}/sensorAggregationImpl.cpp
+
+  HEADERS
+    ${COMPONENT_SOURCE_DIR}/sensorAggregationImpl.h
+
+  INCDIRS
+    ${COMPONENT_SOURCE_DIR}
+
+  LIBRARIES
+    Qt5::Core
+)
+
diff --git a/sim/tests/unitTests/components/SensorFusion_OSI/sensorFusionOSI_Tests.cpp b/sim/tests/unitTests/components/SensorAggregation_OSI/sensorAggregationOSI_Tests.cpp
similarity index 93%
rename from sim/tests/unitTests/components/SensorFusion_OSI/sensorFusionOSI_Tests.cpp
rename to sim/tests/unitTests/components/SensorAggregation_OSI/sensorAggregationOSI_Tests.cpp
index 561ef51b1aca3320225b2b7be9cf31c756826899..cd430e0c9599aa521116e41f99874a290875b49c 100644
--- a/sim/tests/unitTests/components/SensorFusion_OSI/sensorFusionOSI_Tests.cpp
+++ b/sim/tests/unitTests/components/SensorAggregation_OSI/sensorAggregationOSI_Tests.cpp
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (c) 2019 in-tech GmbH
+* Copyright (c) 2019, 2020 in-tech GmbH
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
@@ -13,7 +13,7 @@
 
 #include "fakeAgent.h"
 
-#include "sensorFusionImpl.h"
+#include "sensorAggregationImpl.h"
 #include "common/sensorDataSignal.h"
 #include "osi3/osi_sensordata.pb.h"
 
@@ -21,7 +21,7 @@ using ::testing::Eq;
 using ::testing::NiceMock;
 using ::testing::Return;
 
-TEST(SensorFusionOSI_Unittest, TestAppendingDetectedObjectsWithinTheSameTimestamp)
+TEST(SensorAggregationOSI_Unittest, TestAppendingDetectedObjectsWithinTheSameTimestamp)
 {
     osi3::SensorData sensorData1;
     auto movingObject1 = sensorData1.add_moving_object();
@@ -42,7 +42,7 @@ TEST(SensorFusionOSI_Unittest, TestAppendingDetectedObjectsWithinTheSameTimestam
     NiceMock<FakeAgent> fakeAgent;
     ON_CALL(fakeAgent, GetId()).WillByDefault(Return(0));
 
-    SensorFusionImplementation sensorFusion("",
+    SensorAggregationImplementation sensorFusion("",
                                             false,
                                             0,
                                             0,
@@ -74,7 +74,7 @@ TEST(SensorFusionOSI_Unittest, TestAppendingDetectedObjectsWithinTheSameTimestam
 }
 
 
-TEST(SensorFusionOSI_Unittest, TestResettingDetectedObjectsInNewTimestamp)
+TEST(SensorAggregationOSI_Unittest, TestResettingDetectedObjectsInNewTimestamp)
 {
     osi3::SensorData sensorData1;
     auto movingObject1 = sensorData1.add_moving_object();
@@ -95,7 +95,7 @@ TEST(SensorFusionOSI_Unittest, TestResettingDetectedObjectsInNewTimestamp)
     NiceMock<FakeAgent> fakeAgent;
     ON_CALL(fakeAgent, GetId()).WillByDefault(Return(0));
 
-    SensorFusionImplementation sensorFusion("",
+    SensorAggregationImplementation sensorFusion("",
                                             false,
                                             0,
                                             0,
diff --git a/sim/tests/unitTests/components/SensorAggregation_OSI/sensorAggregationOSI_Tests.pro b/sim/tests/unitTests/components/SensorAggregation_OSI/sensorAggregationOSI_Tests.pro
new file mode 100644
index 0000000000000000000000000000000000000000..b1802b849b9891d3972ae6775579c0d1e6b7d1a1
--- /dev/null
+++ b/sim/tests/unitTests/components/SensorAggregation_OSI/sensorAggregationOSI_Tests.pro
@@ -0,0 +1,32 @@
+# /*********************************************************************
+# * Copyright (c) 2019 in-tech GmbH
+# *
+# * This program and the accompanying materials are made
+# * available under the terms of the Eclipse Public License 2.0
+# * which is available at https://www.eclipse.org/legal/epl-2.0/
+# *
+# * SPDX-License-Identifier: EPL-2.0
+# **********************************************************************/
+
+CONFIG += OPENPASS_GTEST \
+          OPENPASS_GTEST_DEFAULT_MAIN
+
+include(../../../testing.pri)
+
+UNIT_UNDER_TEST = $$OPEN_SRC/components/SensorAggregation_OSI/src
+
+INCLUDEPATH += \
+    . \
+    $$UNIT_UNDER_TEST \
+    ../../../..
+
+HEADERS += \
+    $$UNIT_UNDER_TEST/sensorAggregationImpl.h
+
+SOURCES += \
+    $$UNIT_UNDER_TEST/sensorAggregationImpl.cpp \
+    sensorAggregationOSI_Tests.cpp
+
+LIBS += \
+    -lopen_simulation_interface \
+    -lprotobuf
diff --git a/sim/tests/unitTests/components/SensorFusion_OSI/CMakeLists.txt b/sim/tests/unitTests/components/SensorFusionErrorless_OSI/CMakeLists.txt
similarity index 71%
rename from sim/tests/unitTests/components/SensorFusion_OSI/CMakeLists.txt
rename to sim/tests/unitTests/components/SensorFusionErrorless_OSI/CMakeLists.txt
index 7cdddcd481c7d45f8267cda10b13802199ec3018..44dc34edc9fcc1bb6a92c20ff532e78118f9c43a 100644
--- a/sim/tests/unitTests/components/SensorFusion_OSI/CMakeLists.txt
+++ b/sim/tests/unitTests/components/SensorFusionErrorless_OSI/CMakeLists.txt
@@ -1,23 +1,22 @@
-set(COMPONENT_TEST_NAME SensorFusionOSI_Tests)
-set(COMPONENT_SOURCE_DIR ${OPENPASS_SIMCORE_DIR}/components/SensorFusion_OSI/src)
+set(COMPONENT_TEST_NAME SensorFusionErrorless_Tests)
+set(COMPONENT_SOURCE_DIR ${OPENPASS_SIMCORE_DIR}/components/SensorFusionErrorless_OSI/src)
 
 add_openpass_target(
   NAME ${COMPONENT_TEST_NAME} TYPE test COMPONENT core
   DEFAULT_MAIN
-  LINKOSI
 
   SOURCES
-    sensorFusionOSI_Tests.cpp
+    sensorFusionErrorless_Tests.cpp
     ${COMPONENT_SOURCE_DIR}/sensorFusionImpl.cpp
 
   HEADERS
     ${COMPONENT_SOURCE_DIR}/sensorFusionImpl.h
-    ${COMPONENT_SOURCE_DIR}/sensorFusionQuery.h
 
   INCDIRS
     ${COMPONENT_SOURCE_DIR}
 
   LIBRARIES
     Qt5::Core
-)
 
+  LINKOSI
+)
diff --git a/sim/tests/unitTests/components/SensorFusionErrorless_OSI/sensorFusionErrorless_Tests.cpp b/sim/tests/unitTests/components/SensorFusionErrorless_OSI/sensorFusionErrorless_Tests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1d06c830882b9d59d735b6334e283cbf1d7b05ee
--- /dev/null
+++ b/sim/tests/unitTests/components/SensorFusionErrorless_OSI/sensorFusionErrorless_Tests.cpp
@@ -0,0 +1,168 @@
+/*******************************************************************************
+* Copyright (c) 2020 in-tech GmbH
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+
+#include "fakeAgent.h"
+
+#include "sensorFusionImpl.h"
+
+using ::testing::Eq;
+
+TEST(SensorFusionErrorless_Tests, SensorDataWithMovingObjects_IsMergedAppropriately)
+{
+    FakeAgent fakeAgent;
+
+    auto sensorFusion = SensorFusionErrorlessImplementation("",
+                                                            false,
+                                                            0,
+                                                            0,
+                                                            0,
+                                                            100,
+                                                            nullptr,
+                                                            nullptr,
+                                                            nullptr,
+                                                            nullptr,
+                                                            nullptr,
+                                                            &fakeAgent);
+    unsigned int idA = 7;
+    unsigned int idB = 8;
+    unsigned int idC = 9;
+
+    unsigned int idSensor1 = 101;
+    unsigned int idSensor2 = 102;
+
+    osi3::SensorData sensorData;
+    auto movingObject1a = sensorData.add_moving_object();
+    movingObject1a->mutable_header()->add_ground_truth_id()->set_value(idA);
+    movingObject1a->mutable_header()->add_sensor_id()->set_value(idSensor1);
+    movingObject1a->mutable_base()->mutable_position()->set_x(10);
+    movingObject1a->mutable_base()->mutable_position()->set_y(11);
+    auto movingObject1b = sensorData.add_moving_object();
+    movingObject1b->mutable_header()->add_ground_truth_id()->set_value(idB);
+    movingObject1b->mutable_header()->add_sensor_id()->set_value(idSensor1);
+    movingObject1b->mutable_base()->mutable_position()->set_x(20);
+    movingObject1b->mutable_base()->mutable_position()->set_y(21);
+
+    auto movingObject2b = sensorData.add_moving_object();
+    movingObject2b->mutable_header()->add_ground_truth_id()->set_value(idB);
+    movingObject2b->mutable_header()->add_sensor_id()->set_value(idSensor2);
+    movingObject2b->mutable_base()->mutable_position()->set_x(20);
+    movingObject2b->mutable_base()->mutable_position()->set_y(21);
+    auto movingObject2c = sensorData.add_moving_object();
+    movingObject2c->mutable_header()->add_ground_truth_id()->set_value(idC);
+    movingObject2c->mutable_header()->add_sensor_id()->set_value(idSensor2);
+    movingObject2c->mutable_base()->mutable_position()->set_x(30);
+    movingObject2c->mutable_base()->mutable_position()->set_y(31);
+
+    auto signal = std::make_shared<SensorDataSignal>(sensorData);
+    sensorFusion.UpdateInput(0, signal, 0);
+
+    sensorFusion.Trigger(0);
+
+    std::shared_ptr<const SignalInterface> output;
+    sensorFusion.UpdateOutput(0, output, 0);
+    auto outSensorDataSignal = std::dynamic_pointer_cast<const SensorDataSignal>(output);
+    auto outSensorData = outSensorDataSignal->sensorData;
+
+    ASSERT_THAT(outSensorData.moving_object_size(), Eq(3));
+    ASSERT_THAT(outSensorData.moving_object(0).header().ground_truth_id(0).value(), Eq(idA));
+    ASSERT_THAT(outSensorData.moving_object(0).header().sensor_id_size(), Eq(1));
+    ASSERT_THAT(outSensorData.moving_object(0).header().sensor_id(0).value(), Eq(idSensor1));
+    ASSERT_THAT(outSensorData.moving_object(0).base().position().x(), Eq(10));
+    ASSERT_THAT(outSensorData.moving_object(0).base().position().y(), Eq(11));
+    ASSERT_THAT(outSensorData.moving_object(1).header().ground_truth_id(0).value(), Eq(idB));
+    ASSERT_THAT(outSensorData.moving_object(1).header().sensor_id_size(), Eq(2));
+    ASSERT_THAT(outSensorData.moving_object(1).header().sensor_id(0).value(), Eq(idSensor1));
+    ASSERT_THAT(outSensorData.moving_object(1).header().sensor_id(1).value(), Eq(idSensor2));
+    ASSERT_THAT(outSensorData.moving_object(1).base().position().x(), Eq(20));
+    ASSERT_THAT(outSensorData.moving_object(1).base().position().y(), Eq(21));
+    ASSERT_THAT(outSensorData.moving_object(2).header().ground_truth_id(0).value(), Eq(idC));
+    ASSERT_THAT(outSensorData.moving_object(2).header().sensor_id_size(), Eq(1));
+    ASSERT_THAT(outSensorData.moving_object(2).header().sensor_id(0).value(), Eq(idSensor2));
+    ASSERT_THAT(outSensorData.moving_object(2).base().position().x(), Eq(30));
+    ASSERT_THAT(outSensorData.moving_object(2).base().position().y(), Eq(31));
+}
+
+TEST(SensorFusionErrorless_Tests, SensorDataWithStationaryObjects_IsMergedAppropriately)
+{
+    FakeAgent fakeAgent;
+
+    auto sensorFusion = SensorFusionErrorlessImplementation("",
+                                                            false,
+                                                            0,
+                                                            0,
+                                                            0,
+                                                            100,
+                                                            nullptr,
+                                                            nullptr,
+                                                            nullptr,
+                                                            nullptr,
+                                                            nullptr,
+                                                            &fakeAgent);
+    unsigned int idA = 7;
+    unsigned int idB = 8;
+    unsigned int idC = 9;
+
+    unsigned int idSensor1 = 101;
+    unsigned int idSensor2 = 102;
+
+    osi3::SensorData sensorData;
+    auto stationaryObject1a = sensorData.add_stationary_object();
+    stationaryObject1a->mutable_header()->add_ground_truth_id()->set_value(idA);
+    stationaryObject1a->mutable_header()->add_sensor_id()->set_value(idSensor1);
+    stationaryObject1a->mutable_base()->mutable_position()->set_x(10);
+    stationaryObject1a->mutable_base()->mutable_position()->set_y(11);
+    auto stationaryObject1b = sensorData.add_stationary_object();
+    stationaryObject1b->mutable_header()->add_ground_truth_id()->set_value(idB);
+    stationaryObject1b->mutable_header()->add_sensor_id()->set_value(idSensor1);
+    stationaryObject1b->mutable_base()->mutable_position()->set_x(20);
+    stationaryObject1b->mutable_base()->mutable_position()->set_y(21);
+
+    auto stationaryObject2b = sensorData.add_stationary_object();
+    stationaryObject2b->mutable_header()->add_ground_truth_id()->set_value(idB);
+    stationaryObject2b->mutable_header()->add_sensor_id()->set_value(idSensor2);
+    stationaryObject2b->mutable_base()->mutable_position()->set_x(20);
+    stationaryObject2b->mutable_base()->mutable_position()->set_y(21);
+    auto stationaryObject2c = sensorData.add_stationary_object();
+    stationaryObject2c->mutable_header()->add_ground_truth_id()->set_value(idC);
+    stationaryObject2c->mutable_header()->add_sensor_id()->set_value(idSensor2);
+    stationaryObject2c->mutable_base()->mutable_position()->set_x(30);
+    stationaryObject2c->mutable_base()->mutable_position()->set_y(31);
+
+    auto signal = std::make_shared<SensorDataSignal>(sensorData);
+    sensorFusion.UpdateInput(0, signal, 0);
+
+    sensorFusion.Trigger(0);
+
+    std::shared_ptr<const SignalInterface> output;
+    sensorFusion.UpdateOutput(0, output, 0);
+    auto outSensorDataSignal = std::dynamic_pointer_cast<const SensorDataSignal>(output);
+    auto outSensorData = outSensorDataSignal->sensorData;
+
+    ASSERT_THAT(outSensorData.stationary_object_size(), Eq(3));
+    ASSERT_THAT(outSensorData.stationary_object(0).header().ground_truth_id(0).value(), Eq(idA));
+    ASSERT_THAT(outSensorData.stationary_object(0).header().sensor_id_size(), Eq(1));
+    ASSERT_THAT(outSensorData.stationary_object(0).header().sensor_id(0).value(), Eq(idSensor1));
+    ASSERT_THAT(outSensorData.stationary_object(0).base().position().x(), Eq(10));
+    ASSERT_THAT(outSensorData.stationary_object(0).base().position().y(), Eq(11));
+    ASSERT_THAT(outSensorData.stationary_object(1).header().ground_truth_id(0).value(), Eq(idB));
+    ASSERT_THAT(outSensorData.stationary_object(1).header().sensor_id_size(), Eq(2));
+    ASSERT_THAT(outSensorData.stationary_object(1).header().sensor_id(0).value(), Eq(idSensor1));
+    ASSERT_THAT(outSensorData.stationary_object(1).header().sensor_id(1).value(), Eq(idSensor2));
+    ASSERT_THAT(outSensorData.stationary_object(1).base().position().x(), Eq(20));
+    ASSERT_THAT(outSensorData.stationary_object(1).base().position().y(), Eq(21));
+    ASSERT_THAT(outSensorData.stationary_object(2).header().ground_truth_id(0).value(), Eq(idC));
+    ASSERT_THAT(outSensorData.stationary_object(2).header().sensor_id_size(), Eq(1));
+    ASSERT_THAT(outSensorData.stationary_object(2).header().sensor_id(0).value(), Eq(idSensor2));
+    ASSERT_THAT(outSensorData.stationary_object(2).base().position().x(), Eq(30));
+    ASSERT_THAT(outSensorData.stationary_object(2).base().position().y(), Eq(31));
+}
diff --git a/sim/tests/unitTests/components/SensorFusion_OSI/sensorFusionOSI_Tests.pro b/sim/tests/unitTests/components/SensorFusionErrorless_OSI/sensorFusionErrorless_Tests.pro
similarity index 87%
rename from sim/tests/unitTests/components/SensorFusion_OSI/sensorFusionOSI_Tests.pro
rename to sim/tests/unitTests/components/SensorFusionErrorless_OSI/sensorFusionErrorless_Tests.pro
index e5f854c80600acead5153fc887e5a2e97b6d8e34..2385b171e0d95076dbd34f7e1c34f31099adf329 100644
--- a/sim/tests/unitTests/components/SensorFusion_OSI/sensorFusionOSI_Tests.pro
+++ b/sim/tests/unitTests/components/SensorFusionErrorless_OSI/sensorFusionErrorless_Tests.pro
@@ -13,7 +13,7 @@ CONFIG += OPENPASS_GTEST \
 
 include(../../../testing.pri)
 
-UNIT_UNDER_TEST = $$OPEN_SRC/components/SensorFusion_OSI/src
+UNIT_UNDER_TEST = $$OPEN_SRC/components/SensorFusionErrorless_OSI/src
 
 INCLUDEPATH += \
     . \
@@ -25,7 +25,7 @@ HEADERS += \
 
 SOURCES += \
     $$UNIT_UNDER_TEST/sensorFusionImpl.cpp \
-    sensorFusionOSI_Tests.cpp
+    sensorFusionErrorless_Tests.cpp
 
 LIBS += \
     -lopen_simulation_interface \
diff --git a/sim/tests/unitTests/components/Sensor_OSI/CMakeLists.txt b/sim/tests/unitTests/components/Sensor_OSI/CMakeLists.txt
index 64039a1d58ee5239d49dbba82b88203b177e6c16..c696684a1a07fd0fcf073c565c267121d228ebca 100644
--- a/sim/tests/unitTests/components/Sensor_OSI/CMakeLists.txt
+++ b/sim/tests/unitTests/components/Sensor_OSI/CMakeLists.txt
@@ -18,6 +18,7 @@ add_openpass_target(
 
   HEADERS
     sensorOSI_Tests.h
+    sensorOSI_TestsCommon.h
     ${COMPONENT_SOURCE_DIR}/objectDetectorBase.h
     ${COMPONENT_SOURCE_DIR}/sensorGeometric2D.h
     ${OPENPASS_SIMCORE_DIR}/core/slave/modules/World_OSI/OWL/DataTypes.h
diff --git a/sim/tests/unitTests/components/Sensor_OSI/sensorOSI_Tests.cpp b/sim/tests/unitTests/components/Sensor_OSI/sensorOSI_Tests.cpp
index 6857000dd58e7219850633982f09452fd8c472ef..a638ab79544e7737f60e022d1c64ac7329de2211 100644
--- a/sim/tests/unitTests/components/Sensor_OSI/sensorOSI_Tests.cpp
+++ b/sim/tests/unitTests/components/Sensor_OSI/sensorOSI_Tests.cpp
@@ -21,7 +21,7 @@
 #include "fakeWorldData.h"
 
 #include "sensorGeometric2D.h"
-
+#include "sensorOSI_TestsCommon.h"
 #include "common/boostGeometryCommon.h"
 
 using ::testing::_;
@@ -33,131 +33,6 @@ using ::testing::ReturnRef;
 using ::testing::StrEq;
 using ::testing::Ne;
 
-double constexpr EPSILON = 1e-9;
-
-bool IsEqual(double lhs, double rhs)
-{
-    return std::abs(lhs - rhs) < EPSILON;
-}
-
-class MovingObjectParameter
-{
-public:
-    MovingObjectParameter(unsigned int id,
-                          Common::Vector2d position,
-                          Common::Vector2d velocity,
-                          Common::Vector2d acceleration,
-                          double yaw) :
-        id(id),
-        position(position),
-        velocity(velocity),
-        acceleration(acceleration),
-        yaw(yaw)
-    {}
-
-    MovingObjectParameter (const osi3::DetectedMovingObject& movingObject)
-    {
-        id = movingObject.header().ground_truth_id(0).value();
-        position = Common::Vector2d(movingObject.base().position().x(), movingObject.base().position().y());
-        velocity = Common::Vector2d(movingObject.base().velocity().x(), movingObject.base().velocity().y());
-        acceleration = Common::Vector2d(movingObject.base().acceleration().x(), movingObject.base().acceleration().y());
-        yaw = movingObject.base().orientation().yaw();
-    }
-
-    bool operator==(const MovingObjectParameter& rhs) const
-    {
-        if (id != rhs.id)
-        {
-            return false;
-        }
-
-        if (position != rhs.position ||
-            velocity != rhs.velocity ||
-            acceleration != rhs.acceleration)
-        {
-            return false;
-        }
-
-        if (!IsEqual(yaw, rhs.yaw))
-        {
-            return false;
-        }
-
-        return true;
-    }
-
-    /// \brief This stream will be shown in case the test fails
-    friend std::ostream& operator<<(std::ostream& os, const MovingObjectParameter& obj)
-    {
-        os << "id: " << obj.id << ", "
-           << "position: (" << obj.position.x << ", " << obj.position.y << "), "
-           << "velocity: (" << obj.velocity.x << ", " << obj.velocity.y << "), "
-           << "acceleration: (" << obj.acceleration.x << ", " << obj.acceleration.y << "), "
-           << "yaw: " << obj.yaw;
-
-        return os;
-    }
-
-    unsigned int id;
-    Common::Vector2d position;
-    Common::Vector2d velocity;
-    Common::Vector2d acceleration;
-    double yaw;
-};
-
-class StationaryObjectParameter
-{
-public:
-    StationaryObjectParameter(unsigned int id,
-                          Common::Vector2d position,
-                          double yaw) :
-        id(id),
-        position(position),
-        yaw(yaw)
-    {}
-
-    StationaryObjectParameter (const osi3::DetectedStationaryObject& stationaryObject)
-    {
-        id = stationaryObject.header().ground_truth_id(0).value();
-        position = Common::Vector2d(stationaryObject.base().position().x(), stationaryObject.base().position().y());
-        yaw = stationaryObject.base().orientation().yaw();
-    }
-
-    bool operator==(const StationaryObjectParameter& rhs)
-    {
-        if (id != rhs.id)
-        {
-            return false;
-        }
-
-        if (position != rhs.position)
-        {
-            return false;
-        }
-
-        if (!IsEqual(yaw, rhs.yaw))
-        {
-            return false;
-        }
-
-        return true;
-    }
-
-    /// \brief This stream will be shown in case the test fails
-    friend std::ostream& operator<<(std::ostream& os, const StationaryObjectParameter& obj)
-    {
-        os << "id: " << obj.id << ", "
-           << "position: (" << obj.position.x << ", " << obj.position.y << "), "
-           << "yaw: " << obj.yaw;
-
-        return os;
-    }
-
-    unsigned int id;
-    Common::Vector2d position;
-    double yaw;
-};
-
 class DetectObjects_Data
 {
 public:
diff --git a/sim/tests/unitTests/components/Sensor_OSI/sensorOSI_Tests.pro b/sim/tests/unitTests/components/Sensor_OSI/sensorOSI_Tests.pro
index 3cf3ae8026f6df1ab1754e5d92b927012a28ab68..4d749dce1a6311af9a0a91cb3fe4f9a54eca201b 100644
--- a/sim/tests/unitTests/components/Sensor_OSI/sensorOSI_Tests.pro
+++ b/sim/tests/unitTests/components/Sensor_OSI/sensorOSI_Tests.pro
@@ -32,7 +32,8 @@ HEADERS += \
     $$WORLD_OSI/OWL/OpenDriveTypeMapper.h \
     $$WORLD_OSI/WorldObjectAdapter.h \
     $$WORLD_OSI/WorldData.h \
-    $$WORLD_OSI/WorldDataException.h
+    $$WORLD_OSI/WorldDataException.h \
+    sensorOSI_TestsCommon.h
 
 SOURCES += \
     $$UNIT_UNDER_TEST/sensorGeometric2D.cpp \
diff --git a/sim/tests/unitTests/components/Sensor_OSI/sensorOSI_TestsCommon.h b/sim/tests/unitTests/components/Sensor_OSI/sensorOSI_TestsCommon.h
new file mode 100644
index 0000000000000000000000000000000000000000..7357bd5f90465568e0d6d1c88d64ddfb72b91cf6
--- /dev/null
+++ b/sim/tests/unitTests/components/Sensor_OSI/sensorOSI_TestsCommon.h
@@ -0,0 +1,122 @@
+#include "common/vector2d.h"
+#include "osi3/osi_detectedobject.pb.h"
+
+double constexpr EPSILON = 1e-9;
+
+class MovingObjectParameter
+{
+public:
+    MovingObjectParameter(unsigned int id,
+                          Common::Vector2d position,
+                          Common::Vector2d velocity,
+                          Common::Vector2d acceleration,
+                          double yaw) :
+        id(id),
+        position(position),
+        velocity(velocity),
+        acceleration(acceleration),
+        yaw(yaw)
+    {}
+
+    MovingObjectParameter (const osi3::DetectedMovingObject& movingObject)
+    {
+        id = movingObject.header().ground_truth_id(0).value();
+        position = Common::Vector2d(movingObject.base().position().x(), movingObject.base().position().y());
+        velocity = Common::Vector2d(movingObject.base().velocity().x(), movingObject.base().velocity().y());
+        acceleration = Common::Vector2d(movingObject.base().acceleration().x(), movingObject.base().acceleration().y());
+        yaw = movingObject.base().orientation().yaw();
+    }
+
+    bool operator==(const MovingObjectParameter& rhs) const
+    {
+        if (id != rhs.id)
+        {
+            return false;
+        }
+
+        if (position != rhs.position ||
+            velocity != rhs.velocity ||
+            acceleration != rhs.acceleration)
+        {
+            return false;
+        }
+
+        if ((yaw - rhs.yaw) > EPSILON)
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    /// \brief This stream will be shown in case the test fails
+    friend std::ostream& operator<<(std::ostream& os, const MovingObjectParameter& obj)
+    {
+        os << "id: " << obj.id << ", "
+           << "position: (" << obj.position.x << ", " << obj.position.y << "), "
+           << "velocity: (" << obj.velocity.x << ", " << obj.velocity.y << "), "
+           << "acceleration: (" << obj.acceleration.x << ", " << obj.acceleration.y << "), "
+           << "yaw: " << obj.yaw;
+
+        return os;
+    }
+
+    unsigned int id;
+    Common::Vector2d position;
+    Common::Vector2d velocity;
+    Common::Vector2d acceleration;
+    double yaw;
+};
+
+class StationaryObjectParameter
+{
+public:
+    StationaryObjectParameter(unsigned int id,
+                          Common::Vector2d position,
+                          double yaw) :
+        id(id),
+        position(position),
+        yaw(yaw)
+    {}
+
+    StationaryObjectParameter (const osi3::DetectedStationaryObject& stationaryObject)
+    {
+        id = stationaryObject.header().ground_truth_id(0).value();
+        position = Common::Vector2d(stationaryObject.base().position().x(), stationaryObject.base().position().y());
+        yaw = stationaryObject.base().orientation().yaw();
+    }
+
+    bool operator==(const StationaryObjectParameter& rhs)
+    {
+        if (id != rhs.id)
+        {
+            return false;
+        }
+
+        if (position != rhs.position)
+        {
+            return false;
+        }
+
+        if ((yaw - rhs.yaw) > EPSILON)
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    /// \brief This stream will be shown in case the test fails
+    friend std::ostream& operator<<(std::ostream& os, const StationaryObjectParameter& obj)
+    {
+        os << "id: " << obj.id << ", "
+           << "position: (" << obj.position.x << ", " << obj.position.y << "), "
+           << "yaw: " << obj.yaw;
+
+        return os;
+    }
+
+    unsigned int id;
+    Common::Vector2d position;
+    double yaw;
+};
diff --git a/sim/tests/unitTests/core/slave/CMakeLists.txt b/sim/tests/unitTests/core/slave/CMakeLists.txt
index 8bb1a5a3be94377bb47030782ba2eef40e8ee9dd..dd133fb549d68c1a6d5950dd1c327535c7621f2e 100644
--- a/sim/tests/unitTests/core/slave/CMakeLists.txt
+++ b/sim/tests/unitTests/core/slave/CMakeLists.txt
@@ -57,6 +57,7 @@ add_openpass_target(
     ${COMPONENT_SOURCE_DIR}/importer/scenarioImporterHelper.cpp
 
     # SceneryImporter
+    roadGeometry_Tests.cpp
     sceneryImporter_Tests.cpp
     ${COMPONENT_SOURCE_DIR}/importer/connection.cpp
     ${COMPONENT_SOURCE_DIR}/importer/junction.cpp
diff --git a/sim/tests/unitTests/core/slave/agentSampler_Tests.cpp b/sim/tests/unitTests/core/slave/agentSampler_Tests.cpp
index 02e9910b33b778423a8b12ebfd07dc40a8430ba7..caa4ca982094eae1ed1f60de1c3597c5648eff47 100644
--- a/sim/tests/unitTests/core/slave/agentSampler_Tests.cpp
+++ b/sim/tests/unitTests/core/slave/agentSampler_Tests.cpp
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (c) 2018, 2019 in-tech GmbH
+* Copyright (c) 2018, 2019, 2020 in-tech GmbH
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
@@ -300,9 +300,9 @@ TEST(DynamicAgentTypeGenerator, GatherSensors)
     std::map<int, std::shared_ptr<SimulationSlave::AgentTypeInterface>> systems = {{0, fakeAgentType}};
     std::map<std::string, std::shared_ptr<SimulationSlave::ComponentType>> components{};
 
-    auto sensorFusion = std::make_shared<SimulationSlave::ComponentType>("SensorFusion", false, 0, 0, 0, 0, "SensorFusion");
-    sensorFusion->AddInputLink(0, 100);
-    components.insert(std::make_pair("SensorFusion", sensorFusion));
+    auto sensorAggregation = std::make_shared<SimulationSlave::ComponentType>("SensorAggregation", false, 0, 0, 0, 0, "SensorAggregation");
+    sensorAggregation->AddInputLink(0, 100);
+    components.insert(std::make_pair("SensorAggregation", sensorAggregation));
 
     auto sensorObjectDetector = std::make_shared<SimulationSlave::ComponentType>("SensorObjectDetector", false, 0, 0, 0, 0, "SensorObjectDetector");
     sensorObjectDetector->AddOutputLink(3, 100);
@@ -317,14 +317,14 @@ TEST(DynamicAgentTypeGenerator, GatherSensors)
     const auto& gatheredComponents = agentBuildInformation.agentType->GetComponents();
 
     ASSERT_THAT(gatheredComponents.size(), Eq(3));
-    ASSERT_THAT(gatheredComponents.count("SensorFusion"), Eq(1));
+    ASSERT_THAT(gatheredComponents.count("SensorAggregation"), Eq(1));
     ASSERT_THAT(gatheredComponents.count("Sensor_5"), Eq(1));
     ASSERT_THAT(gatheredComponents.count("Sensor_7"), Eq(1));
 
-    ASSERT_THAT(gatheredComponents.at("SensorFusion")->GetInputLinks().size(), Eq(2));
-    ASSERT_THAT(gatheredComponents.at("SensorFusion")->GetModelLibrary(), Eq("SensorFusion"));
-    ASSERT_THAT(gatheredComponents.at("SensorFusion")->GetInputLinks().at(0), Eq(100));
-    ASSERT_THAT(gatheredComponents.at("SensorFusion")->GetInputLinks().at(1), Eq(101));
+    ASSERT_THAT(gatheredComponents.at("SensorAggregation")->GetInputLinks().size(), Eq(2));
+    ASSERT_THAT(gatheredComponents.at("SensorAggregation")->GetModelLibrary(), Eq("SensorAggregation"));
+    ASSERT_THAT(gatheredComponents.at("SensorAggregation")->GetInputLinks().at(0), Eq(100));
+    ASSERT_THAT(gatheredComponents.at("SensorAggregation")->GetInputLinks().at(1), Eq(101));
 
     ASSERT_THAT(gatheredComponents.at("Sensor_5")->GetModelLibrary(), Eq("SensorObjectDetector"));
     ASSERT_THAT(gatheredComponents.at("Sensor_5")->GetOutputLinks().at(3), Eq(100));
diff --git a/sim/tests/unitTests/core/slave/openPassSlave_Tests.pro b/sim/tests/unitTests/core/slave/openPassSlave_Tests.pro
index 91dc50f971cbb3aa7fe125ae99873c1393ebdb8e..88494689fded45358f0029771fb038fdcdc1b18e 100644
--- a/sim/tests/unitTests/core/slave/openPassSlave_Tests.pro
+++ b/sim/tests/unitTests/core/slave/openPassSlave_Tests.pro
@@ -101,6 +101,7 @@ SCENERYIMPORTER_TESTS = \
     $$UNIT_UNDER_TEST/importer/road/roadSignal.cpp \
     $$UNIT_UNDER_TEST/importer/road/roadObject.cpp \
     \
+    roadGeometry_Tests.cpp \
     sceneryImporter_Tests.cpp
 
 SCENARIOIMPORTER_TESTS = \
diff --git a/sim/tests/unitTests/core/slave/profilesImporter_Tests.cpp b/sim/tests/unitTests/core/slave/profilesImporter_Tests.cpp
index 86736db319f473a03eb7ffefc73c58e1390f89e8..681ce1fbcf4cad765e0a3d71116f23486150e017 100644
--- a/sim/tests/unitTests/core/slave/profilesImporter_Tests.cpp
+++ b/sim/tests/unitTests/core/slave/profilesImporter_Tests.cpp
@@ -33,7 +33,7 @@ TEST(ProfilesImporter_ImportAllVehicleComponentsOfVehicleProfile, GivenValidXml_
                             "</Profiles>"
                             "<SensorLinks>"
                                 "<SensorLink SensorId=\"0\" InputId=\"Camera\"/>"
-                                "<SensorLink SensorId=\"1\" InputId=\"DrivingCorridor\"/>"
+                                "<SensorLink SensorId=\"1\" InputId=\"OtherSensor\"/>"
                                 "<SensorLink SensorId=\"2\" InputId=\"Camera\"/>"
                             "</SensorLinks>"
                         "</Component>"
@@ -64,7 +64,7 @@ TEST(ProfilesImporter_ImportAllVehicleComponentsOfVehicleProfile, WithMissingCom
                             "</Profiles>"
                             "<SensorLinks>"
                                 "<SensorLink SensorId=\"0\" InputId=\"Camera\"/>"
-                                "<SensorLink SensorId=\"1\" InputId=\"DrivingCorridor\"/>"
+                                "<SensorLink SensorId=\"1\" InputId=\"OtherSensor\"/>"
                                 "<SensorLink SensorId=\"2\" InputId=\"Camera\"/>"
                             "</SensorLinks>"
                         "</Component>"
@@ -87,7 +87,7 @@ TEST(ProfilesImporter_ImportAllVehicleComponentsOfVehicleProfile, SumOfProbabili
                             "</Profiles>"
                             "<SensorLinks>"
                                 "<SensorLink SensorId=\"0\" InputId=\"Camera\"/>"
-                                "<SensorLink SensorId=\"1\" InputId=\"DrivingCorridor\"/>"
+                                "<SensorLink SensorId=\"1\" InputId=\"OtherSensor\"/>"
                                 "<SensorLink SensorId=\"2\" InputId=\"Camera\"/>"
                             "</SensorLinks>"
                         "</Component>"
@@ -110,7 +110,7 @@ TEST(ProfilesImporter_ImportAllSensorsOfVehicleProfile, GivenValidXml_ImportsVal
                         "</Sensor>"
                         "<Sensor Id=\"1\">"
                             "<Position Name=\"Somewhere\" Longitudinal=\"0.0\" Lateral=\"0.0\" Height=\"0.5\" Pitch=\"0.0\" Yaw=\"0.0\" Roll=\"0.0\"/>"
-                            "<Profile Type=\"DrivingCorridor\" Name=\"Camera\"/>"
+                            "<Profile Type=\"OtherSensor\" Name=\"Camera\"/>"
                         "</Sensor>"
                     "</Sensors>"
                 "</root>"
@@ -149,7 +149,7 @@ TEST(ProfilesImporter_ImportAllSensorsOfVehicleProfile, SensorsTagMissing_Throws
                         "</Sensor>"
                         "<Sensor Id=\"1\">"
                             "<Position Name=\"Somewhere\" Longitudinal=\"0.0\" Lateral=\"0.0\" Height=\"0.5\" Pitch=\"0.0\" Yaw=\"0.0\" Roll=\"0.0\"/>"
-                            "<Profile Type=\"DrivingCorridor\" Name=\"Camera\"/>"
+                            "<Profile Type=\"OtherSensor\" Name=\"Camera\"/>"
                         "</Sensor>"
                 "</root>"
                 );
diff --git a/sim/tests/unitTests/core/slave/roadGeometry_Tests.cpp b/sim/tests/unitTests/core/slave/roadGeometry_Tests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ff91a322a3bead1c87c586b69a1e9671b5bb7a34
--- /dev/null
+++ b/sim/tests/unitTests/core/slave/roadGeometry_Tests.cpp
@@ -0,0 +1,267 @@
+/*******************************************************************************
+* Copyright (c) 2020 in-tech GmbH
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+*******************************************************************************/
+
+#include "common/opMath.h"
+
+#include "gtest/gtest.h"
+#include "gmock/gmock.h"
+
+#include "road.h"
+
+using ::testing::DoubleNear;
+
+constexpr double MAX_GEOMETRY_ERROR = 0.001;
+
+struct GeometrySpiral_Data
+{
+    double x;              //!< geometry origin x
+    double y;              //!< geometry origin y
+    double hdg;            //!< geometry origin heading
+    double length;         //!< lenth of spiral between curvature start and end
+    double curvStart;      //!< curvature at s = 0
+    double curvEnd;        //!< curvature at s = length
+
+    double s;              //!< query s coordinate
+    double t;              //!< query t coordinate
+
+    double expected_x;     //!< expected x coordinate for query
+    double expected_y;     //!< expected y coordinate for query
+    double expected_hdg;   //!< expected heading for query
+
+    /// \brief This stream will be shown in case the test fails
+    friend std::ostream& operator<<(std::ostream& os, const GeometrySpiral_Data& obj)
+    {
+       return os
+          << "x: "              << obj.x
+          << ", y: "            << obj.y
+          << ", hdg: "          << obj.hdg
+          << ", length: "       << obj.length
+          << ", curvStart: "    << obj.curvStart
+          << ", curvend: "      << obj.curvEnd
+          << ", s: "            << obj.s
+          << ", t: "            << obj.t
+          << ", expected_x: "   << obj.expected_x
+          << ", expected_y: "   << obj.expected_y
+          << ", expected_hdg: " << obj.expected_hdg;
+    }
+};
+
+class RoadGeometries_Spiral : public ::testing::TestWithParam<GeometrySpiral_Data>
+{
+public:
+    virtual ~RoadGeometries_Spiral()
+    {
+    }
+};
+
+TEST_P(RoadGeometries_Spiral, GetCoordAndGetDir_ReturnCorrectValues)
+{
+    GeometrySpiral_Data data = GetParam();
+
+    const RoadGeometrySpiral rgs{0, data.x, data.y, data.hdg, data.length, data.curvStart, data.curvEnd};
+    const auto res = rgs.GetCoord(data.s, data.t);
+    const auto hdg = rgs.GetDir(data.s);
+
+    EXPECT_THAT(res.x, DoubleNear(data.expected_x, MAX_GEOMETRY_ERROR));
+    EXPECT_THAT(res.y, DoubleNear(data.expected_y, MAX_GEOMETRY_ERROR));
+    EXPECT_THAT(hdg, DoubleNear(data.expected_hdg, MAX_GEOMETRY_ERROR));
+}
+
+INSTANTIATE_TEST_SUITE_P(AtEndOfGeometryAndZeroTAndZeroOrigin, RoadGeometries_Spiral, ::testing::Values(
+    //                   |       origin          | spirial definition | query pos |   expected result        |
+    //                   | x     y           hdg | len c_start  c_end |   s     t |    x        y      hdg   |
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0,  0.00,  0.00, 100.0,  0.0, 100.000,   0.000,  0.0000 },
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0,  0.00,  0.01, 100.0,  0.0,  97.529,  16.371,  0.5000 },
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0,  0.00, -0.01, 100.0,  0.0,  97.529, -16.371, -0.5000 },
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0,  0.01,  0.00, 100.0,  0.0,  93.438,  32.391,  0.5000 },
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0, -0.01,  0.00, 100.0,  0.0,  93.438, -32.391, -0.5000 }
+));
+
+INSTANTIATE_TEST_SUITE_P(AtEndOfGeometryAndZeroTAndNonzeroOrigin, RoadGeometries_Spiral, ::testing::Values(
+    //                   |       origin          | spirial definition | query pos |   expected result        |
+    //                   | x     y           hdg | len c_start  c_end |   s     t |    x        y      hdg   |
+    GeometrySpiral_Data{  1.0,  1.0,         0.0, 100.0,  0.00,  0.00, 100.0,  0.0, 101.000,   1.000,  0.0000 },
+    GeometrySpiral_Data{ -1.0, -1.0,         0.0, 100.0,  0.00,  0.00, 100.0,  0.0,  99.000,  -1.000,  0.0000 },
+    GeometrySpiral_Data{ -1.0,  1.0,         0.0, 100.0,  0.00,  0.00, 100.0,  0.0,  99.000,   1.000,  0.0000 },
+    GeometrySpiral_Data{  1.0, -1.0,         0.0, 100.0,  0.00,  0.00, 100.0,  0.0, 101.000,  -1.000,  0.0000},
+
+    GeometrySpiral_Data{  1.0,  1.0,         0.0, 100.0,  0.00,  0.01, 100.0,  0.0,  98.529,  17.371,  0.5000 },
+    GeometrySpiral_Data{ -1.0, -1.0,         0.0, 100.0,  0.00,  0.01, 100.0,  0.0,  96.529,  15.371,  0.5000 },
+    GeometrySpiral_Data{ -1.0,  1.0,         0.0, 100.0,  0.00,  0.01, 100.0,  0.0,  96.529,  17.371,  0.5000 },
+    GeometrySpiral_Data{  1.0, -1.0,         0.0, 100.0,  0.00,  0.01, 100.0,  0.0,  98.529,  15.371,  0.5000 }
+));
+
+INSTANTIATE_TEST_SUITE_P(AtEndOfGeometryAndNonzeroTAndNonzeroOrigin, RoadGeometries_Spiral, ::testing::Values(
+    //                   |       origin          | spirial definition | query pos |   expected result        |
+    //                   | x     y           hdg | len c_start  c_end |   s     t |    x        y      hdg   |
+    GeometrySpiral_Data{  1.0,  1.0,         0.0, 100.0,  0.00,  0.01, 100.0,  1.0,  98.049,  18.249,  0.5000 },
+    GeometrySpiral_Data{ -1.0, -1.0,         0.0, 100.0,  0.00,  0.01, 100.0,  1.0,  96.049,  16.249,  0.5000 },
+    GeometrySpiral_Data{ -1.0,  1.0,         0.0, 100.0,  0.00,  0.01, 100.0,  1.0,  96.049,  18.249,  0.5000 },
+    GeometrySpiral_Data{  1.0, -1.0,         0.0, 100.0,  0.00,  0.01, 100.0,  1.0,  98.049,  16.249,  0.5000 },
+    GeometrySpiral_Data{  1.0,  1.0,         0.0, 100.0,  0.00,  0.01, 100.0, -1.0,  99.008,  16.494,  0.5000 },
+    GeometrySpiral_Data{ -1.0, -1.0,         0.0, 100.0,  0.00,  0.01, 100.0, -1.0,  97.008,  14.494,  0.5000 },
+    GeometrySpiral_Data{ -1.0,  1.0,         0.0, 100.0,  0.00,  0.01, 100.0, -1.0,  97.008,  16.494,  0.5000 },
+    GeometrySpiral_Data{  1.0, -1.0,         0.0, 100.0,  0.00,  0.01, 100.0, -1.0,  99.008,  14.494,  0.5000 }
+));
+
+INSTANTIATE_TEST_SUITE_P(AtEndOfGeometryAndZeroTAndNonzeroOriginHeading, RoadGeometries_Spiral, ::testing::Values(
+    //                   |       origin          | spirial definition | query pos |   expected result        |
+    //                   | x     y           hdg | len c_start  c_end |   s     t |    x        y      hdg   |
+    GeometrySpiral_Data{  0.0,  0.0,      M_PI_4, 100.0,  0.00,  0.00, 100.0,  0.0,  70.711,  70.711,  0.7854 },
+    GeometrySpiral_Data{  0.0,  0.0,  3 * M_PI_4, 100.0,  0.00,  0.00, 100.0,  0.0, -70.711,  70.711,  2.3570 },
+    GeometrySpiral_Data{  0.0,  0.0, -3 * M_PI_4, 100.0,  0.00,  0.00, 100.0,  0.0, -70.711, -70.711, -2.3570 },
+    GeometrySpiral_Data{  0.0,  0.0,  5 * M_PI_4, 100.0,  0.00,  0.00, 100.0,  0.0, -70.711, -70.711,  3.9270 },
+    GeometrySpiral_Data{  0.0,  0.0,     -M_PI_4, 100.0,  0.00,  0.00, 100.0,  0.0,  70.711, -70.711, -0.7854 },
+    GeometrySpiral_Data{  0.0,  0.0,  7 * M_PI_4, 100.0,  0.00,  0.00, 100.0,  0.0,  70.711, -70.711,  5.4978 },
+
+    GeometrySpiral_Data{  0.0,  0.0,      M_PI_4, 100.0,  0.00,  0.01, 100.0,  0.0,  57.387,  80.540,  1.2854 },
+    GeometrySpiral_Data{  0.0,  0.0,  3 * M_PI_4, 100.0,  0.00,  0.01, 100.0,  0.0, -80.540,  57.387,  2.8562 },
+    GeometrySpiral_Data{  0.0,  0.0, -3 * M_PI_4, 100.0,  0.00,  0.01, 100.0,  0.0, -57.387, -80.540, -1.8562 },
+    GeometrySpiral_Data{  0.0,  0.0,  5 * M_PI_4, 100.0,  0.00,  0.01, 100.0,  0.0, -57.387, -80.540,  4.4270 },
+    GeometrySpiral_Data{  0.0,  0.0,     -M_PI_4, 100.0,  0.00,  0.01, 100.0,  0.0,  80.540, -57.387, -0.2854 },
+    GeometrySpiral_Data{  0.0,  0.0,  7 * M_PI_4, 100.0,  0.00,  0.01, 100.0,  0.0,  80.540, -57.387,  5.9978 }
+));
+
+INSTANTIATE_TEST_SUITE_P(AtEndOfGeometryAndZeroTAndNonzeroOriginAndHeading, RoadGeometries_Spiral, ::testing::Values(
+    //                   |       origin          | spirial definition | query pos |   expected result        |
+    //                   | x     y           hdg | len c_start  c_end |   s     t |    x        y      hdg   |
+    GeometrySpiral_Data{  1.0,  1.0,      M_PI_4, 100.0,  0.00,  0.01, 100.0,  0.0,  58.387,  81.540,  1.2854 },
+    GeometrySpiral_Data{  1.0,  1.0,     -M_PI_4, 100.0,  0.00,  0.01, 100.0,  0.0,  81.540, -56.387, -0.2854 },
+    GeometrySpiral_Data{ -1.0, -1.0,  3 * M_PI_4, 100.0,  0.00, -0.01, 100.0,  0.0, -58.387,  79.540,  1.8562 },
+    GeometrySpiral_Data{ -1.0,  1.0, -3 * M_PI_4, 100.0,  0.00, -0.01, 100.0,  0.0, -81.540, -56.387, -2.8562 },
+    GeometrySpiral_Data{  1.0, -1.0,  5 * M_PI_4, 100.0,  0.00, -0.01, 100.0,  0.0, -79.540, -58.387,  3.4270 }
+));
+
+INSTANTIATE_TEST_SUITE_P(AtEndOfGeometryAndZeroTWithNonzeroStartAndEndCurvature, RoadGeometries_Spiral, ::testing::Values(
+    //                   |       origin          | spirial definition | query pos |   expected result        |
+    //                   | x     y           hdg | len c_start  c_end |   s     t |    x        y      hdg   |
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0,  0.01,  0.02, 100.0,  0.0,  71.564,  55.928,  1.5    },
+    GeometrySpiral_Data{  0.0,  0.0,      M_PI_4, 100.0,  0.01,  0.02, 100.0,  0.0,  11.057,  90.151,  2.2854 },
+    GeometrySpiral_Data{  0.0,  0.0,     -M_PI_4, 100.0,  0.01,  0.02, 100.0,  0.0,  90.151, -11.057,  0.7146 },
+    GeometrySpiral_Data{  0.0,  0.0,  3 * M_PI_4, 100.0,  0.01,  0.02, 100.0,  0.0, -90.151,  11.057,  3.8562 },
+    GeometrySpiral_Data{  0.0,  0.0, -3 * M_PI_4, 100.0,  0.01,  0.02, 100.0,  0.0, -11.057, -90.151, -0.8562 },
+
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0, -0.01, -0.02, 100.0,  0.0,  71.564, -55.928, -1.5    },
+    GeometrySpiral_Data{  0.0,  0.0,      M_PI_4, 100.0, -0.01, -0.02, 100.0,  0.0,  90.151,  11.057, -0.7146 },
+    GeometrySpiral_Data{  0.0,  0.0,     -M_PI_4, 100.0, -0.01, -0.02, 100.0,  0.0,  11.057, -90.151, -2.2854 },
+    GeometrySpiral_Data{  0.0,  0.0,  3 * M_PI_4, 100.0, -0.01, -0.02, 100.0,  0.0, -11.057,  90.151,  0.8562 },
+    GeometrySpiral_Data{  0.0,  0.0, -3 * M_PI_4, 100.0, -0.01, -0.02, 100.0,  0.0, -90.151, -11.057, -3.8562 },
+
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0,  0.02,  0.01, 100.0,  0.0,  60.850,  67.429,  1.5    },
+    GeometrySpiral_Data{  0.0,  0.0,      M_PI_4, 100.0,  0.02,  0.01, 100.0,  0.0,  -4.652,  90.707,  2.2854 },
+    GeometrySpiral_Data{  0.0,  0.0,     -M_PI_4, 100.0,  0.02,  0.01, 100.0,  0.0,  90.707,   4.652,  0.7146 },
+    GeometrySpiral_Data{  0.0,  0.0,  3 * M_PI_4, 100.0,  0.02,  0.01, 100.0,  0.0, -90.707,  -4.652,  3.8562 },
+    GeometrySpiral_Data{  0.0,  0.0, -3 * M_PI_4, 100.0,  0.02,  0.01, 100.0,  0.0,   4.652, -90.707, -0.8562 },
+
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0, -0.02, -0.01, 100.0,  0.0,  60.850, -67.429, -1.5    },
+    GeometrySpiral_Data{  0.0,  0.0,      M_PI_4, 100.0, -0.02, -0.01, 100.0,  0.0,  90.707,  -4.652, -0.7146 },
+    GeometrySpiral_Data{  0.0,  0.0,     -M_PI_4, 100.0, -0.02, -0.01, 100.0,  0.0,  -4.652, -90.707, -2.2854 },
+    GeometrySpiral_Data{  0.0,  0.0,  3 * M_PI_4, 100.0, -0.02, -0.01, 100.0,  0.0,   4.652,  90.707,  0.8562 },
+    GeometrySpiral_Data{  0.0,  0.0, -3 * M_PI_4, 100.0, -0.02, -0.01, 100.0,  0.0, -90.707,   4.652, -3.8562 }
+));
+
+INSTANTIATE_TEST_SUITE_P(AtEndOfGeometryAndZeroTWithNonzeroStartAndEndCurvatureAndNonzeroOrigin, RoadGeometries_Spiral, ::testing::Values(
+    //                   |       origin          | spirial definition | query pos |   expected result        |
+    //                   | x     y           hdg | len c_start  c_end |   s     t |    x        y      hdg   |
+    GeometrySpiral_Data{  0.0,  1.0,         0.0, 100.0,  0.01,  0.02, 100.0,  0.0,  71.564,  56.928,  1.5    },
+    GeometrySpiral_Data{  1.0,  0.0,      M_PI_4, 100.0,  0.01,  0.02, 100.0,  0.0,  12.057,  90.151,  2.2854 },
+    GeometrySpiral_Data{  1.0,  0.0,     -M_PI_4, 100.0,  0.01,  0.02, 100.0,  0.0,  91.151, -11.057,  0.7146 },
+    GeometrySpiral_Data{  1.0,  0.0,  3 * M_PI_4, 100.0,  0.01,  0.02, 100.0,  0.0, -89.151,  11.057,  3.8562 },
+    GeometrySpiral_Data{  0.0,  1.0, -3 * M_PI_4, 100.0,  0.01,  0.02, 100.0,  0.0, -11.057, -89.151, -0.8562 },
+
+    GeometrySpiral_Data{  0.0,  1.0,         0.0, 100.0, -0.01, -0.02, 100.0,  0.0,  71.564, -54.928, -1.5    },
+    GeometrySpiral_Data{  1.0,  0.0,      M_PI_4, 100.0, -0.01, -0.02, 100.0,  0.0,  91.151,  11.057, -0.7146 },
+    GeometrySpiral_Data{  1.0,  0.0,     -M_PI_4, 100.0, -0.01, -0.02, 100.0,  0.0,  12.057, -90.151, -2.2854 },
+    GeometrySpiral_Data{  1.0,  0.0,  3 * M_PI_4, 100.0, -0.01, -0.02, 100.0,  0.0, -10.057,  90.151,  0.8562 },
+    GeometrySpiral_Data{  0.0,  1.0, -3 * M_PI_4, 100.0, -0.01, -0.02, 100.0,  0.0, -90.151, -10.057, -3.8562 },
+
+    GeometrySpiral_Data{  0.0,  1.0,         0.0, 100.0,  0.02,  0.01, 100.0,  0.0,  60.850,  68.429,  1.5    },
+    GeometrySpiral_Data{  1.0,  0.0,      M_PI_4, 100.0,  0.02,  0.01, 100.0,  0.0,  -3.652,  90.707,  2.2854 },
+    GeometrySpiral_Data{  1.0,  0.0,     -M_PI_4, 100.0,  0.02,  0.01, 100.0,  0.0,  91.707,   4.652,  0.7146 },
+    GeometrySpiral_Data{  1.0,  0.0,  3 * M_PI_4, 100.0,  0.02,  0.01, 100.0,  0.0, -89.707,  -4.652,  3.8562 },
+    GeometrySpiral_Data{  0.0,  1.0, -3 * M_PI_4, 100.0,  0.02,  0.01, 100.0,  0.0,   4.652, -89.707, -0.8562 },
+
+    GeometrySpiral_Data{  0.0,  1.0,         0.0, 100.0, -0.02, -0.01, 100.0,  0.0,  60.850, -66.429, -1.5    },
+    GeometrySpiral_Data{  1.0,  0.0,      M_PI_4, 100.0, -0.02, -0.01, 100.0,  0.0,  91.707,  -4.652, -0.7146 },
+    GeometrySpiral_Data{  1.0,  0.0,     -M_PI_4, 100.0, -0.02, -0.01, 100.0,  0.0,  -3.652, -90.707, -2.2854 },
+    GeometrySpiral_Data{  1.0,  0.0,  3 * M_PI_4, 100.0, -0.02, -0.01, 100.0,  0.0,   5.652,  90.707,  0.8562 },
+    GeometrySpiral_Data{  0.0,  1.0, -3 * M_PI_4, 100.0, -0.02, -0.01, 100.0,  0.0, -90.707,   5.652, -3.8562 }
+));
+
+INSTANTIATE_TEST_SUITE_P(AtEndOfGeometryAndNonzeroTWithNonzeroStartAndEndCurvatureAndNonzeroOrigin, RoadGeometries_Spiral, ::testing::Values(
+    //                   |       origin          | spirial definition | query pos |   expected result        |
+    //                   | x     y           hdg | len c_start  c_end |   s     t |    x        y      hdg   |
+    GeometrySpiral_Data{  0.0,  1.0,         0.0, 100.0,  0.01,  0.02, 100.0,  2.0,  69.569,  57.069,  1.5    },
+    GeometrySpiral_Data{  1.0,  0.0,      M_PI_4, 100.0,  0.01,  0.02, 100.0, -2.0,  13.568,  91.461,  2.2854 },
+    GeometrySpiral_Data{  1.0,  1.0,     -M_PI_4, 100.0,  0.01,  0.02, 100.0,  2.0,  89.840,  -8.546,  0.7146 },
+    GeometrySpiral_Data{  1.0,  0.0,  3 * M_PI_4, 100.0,  0.01,  0.02, 100.0, -2.0, -90.461,  12.568,  3.8562 },
+    GeometrySpiral_Data{  0.0,  1.0, -3 * M_PI_4, 100.0,  0.01,  0.02, 100.0,  2.0,  -9.546, -87.840, -0.8562 },
+
+    GeometrySpiral_Data{  0.0,  1.0,         0.0, 100.0, -0.01, -0.02, 100.0, -2.0,  69.569, -55.069, -1.5    },
+    GeometrySpiral_Data{  1.0,  0.0,      M_PI_4, 100.0, -0.01, -0.02, 100.0,  2.0,  92.461,  12.568, -0.7146 },
+    GeometrySpiral_Data{  1.0,  1.0,     -M_PI_4, 100.0, -0.01, -0.02, 100.0, -2.0,  10.546, -87.840, -2.2854 },
+    GeometrySpiral_Data{  1.0,  0.0,  3 * M_PI_4, 100.0, -0.01, -0.02, 100.0,  2.0, -11.568,  91.461,  0.8562 },
+    GeometrySpiral_Data{  0.0,  1.0, -3 * M_PI_4, 100.0, -0.01, -0.02, 100.0, -2.0, -88.840,  -8.546, -3.8562 },
+
+    GeometrySpiral_Data{  0.0,  1.0,         0.0, 100.0,  0.02,  0.01, 100.0,  2.0,  58.855,  68.570,  1.5    },
+    GeometrySpiral_Data{  1.0,  0.0,      M_PI_4, 100.0,  0.02,  0.01, 100.0,  2.0,  -5.163,  89.396,  2.2854 },
+    GeometrySpiral_Data{  1.0,  1.0,     -M_PI_4, 100.0,  0.02,  0.01, 100.0, -2.0,  93.017,   4.141,  0.7146 },
+    GeometrySpiral_Data{  1.0,  0.0,  3 * M_PI_4, 100.0,  0.02,  0.01, 100.0, -2.0, -91.017,  -3.141,  3.8562 },
+    GeometrySpiral_Data{  0.0,  1.0, -3 * M_PI_4, 100.0,  0.02,  0.01, 100.0, -2.0,   3.141, -91.017, -0.8562 },
+
+    GeometrySpiral_Data{  0.0,  1.0,         0.0, 100.0, -0.02, -0.01, 100.0, -2.0,  58.855, -66.570, -1.5    },
+    GeometrySpiral_Data{  1.0,  0.0,      M_PI_4, 100.0, -0.02, -0.01, 100.0, -2.0,  90.396,  -6.163, -0.7146 },
+    GeometrySpiral_Data{  1.0,  1.0,     -M_PI_4, 100.0, -0.02, -0.01, 100.0, -2.0,  -5.163, -88.396, -2.2854 },
+    GeometrySpiral_Data{  1.0,  0.0,  3 * M_PI_4, 100.0, -0.02, -0.01, 100.0,  2.0,   4.141,  92.017,  0.8562 },
+    GeometrySpiral_Data{  0.0,  1.0, -3 * M_PI_4, 100.0, -0.02, -0.01, 100.0,  2.0, -92.017,   4.141, -3.8562 }
+));
+
+INSTANTIATE_TEST_SUITE_P(AtCenterOfGeometryAndNonzeroTWithNonzeroStartAndEndCurvatureAndNonzeroOrigin, RoadGeometries_Spiral, ::testing::Values(
+    //                   |       origin          | spirial definition | query pos |   expected result        |
+    //                   | x     y           hdg | len c_start  c_end |   s     t |    x        y      hdg   |
+    GeometrySpiral_Data{  0.0,  1.0,         0.0, 100.0,  0.01,  0.02,  50.0,  2.0,  45.942,  16.759,  0.6250 },
+    GeometrySpiral_Data{  1.0,  0.0,      M_PI_4, 100.0,  0.01,  0.02,  50.0, -2.0,  26.291,  42.991,  1.4104 },
+    GeometrySpiral_Data{  1.0,  1.0,     -M_PI_4, 100.0,  0.01,  0.02,  50.0,  2.0,  44.630, -20.343, -0.1604 },
+    GeometrySpiral_Data{  1.0,  0.0,  3 * M_PI_4, 100.0,  0.01,  0.02,  50.0, -2.0, -41.991,  25.291,  2.9812 },
+    GeometrySpiral_Data{  0.0,  1.0, -3 * M_PI_4, 100.0,  0.01,  0.02,  50.0,  2.0, -21.343, -42.630, -1.7312 },
+
+    GeometrySpiral_Data{  0.0,  1.0,         0.0, 100.0, -0.01, -0.02,  50.0,  2.0,  48.283, -11.516, -0.6250 },
+    GeometrySpiral_Data{  1.0,  0.0,      M_PI_4, 100.0, -0.01, -0.02,  50.0, -2.0,  44.630,  21.343,  0.1604 },
+    GeometrySpiral_Data{  1.0,  1.0,     -M_PI_4, 100.0, -0.01, -0.02,  50.0,  2.0,  26.291, -41.991, -1.4104 },
+    GeometrySpiral_Data{  1.0,  0.0,  3 * M_PI_4, 100.0, -0.01, -0.02,  50.0, -2.0, -20.343,  43.630,  1.7312 },
+    GeometrySpiral_Data{  0.0,  1.0, -3 * M_PI_4, 100.0, -0.01, -0.02,  50.0,  2.0, -42.991, -24.291, -2.9812 },
+
+    GeometrySpiral_Data{  0.0,  1.0,         0.0, 100.0,  0.02,  0.01,  50.0,  2.0,  41.880,  23.716,  0.8750 },
+    GeometrySpiral_Data{  1.0,  0.0,      M_PI_4, 100.0,  0.02,  0.01,  50.0,  2.0,  14.551,  45.677,  1.6604 },
+    GeometrySpiral_Data{  1.0,  1.0,     -M_PI_4, 100.0,  0.02,  0.01,  50.0, -2.0,  47.035, -16.535,  0.0896 },
+    GeometrySpiral_Data{  1.0,  0.0,  3 * M_PI_4, 100.0,  0.02,  0.01,  50.0, -2.0, -45.035,  17.535,  3.2312 },
+    GeometrySpiral_Data{  0.0,  1.0, -3 * M_PI_4, 100.0,  0.02,  0.01,  50.0, -2.0, -17.535, -45.035, -1.4812 },
+
+    GeometrySpiral_Data{  0.0,  1.0,         0.0, 100.0, -0.02, -0.01,  50.0, -2.0,  41.880, -21.716, -0.8750 },
+    GeometrySpiral_Data{  1.0,  0.0,      M_PI_4, 100.0, -0.02, -0.01,  50.0, -2.0,  46.677,  13.551, -0.0896 },
+    GeometrySpiral_Data{  1.0,  1.0,     -M_PI_4, 100.0, -0.02, -0.01,  50.0, -2.0,  14.551, -44.677, -1.6604 },
+    GeometrySpiral_Data{  1.0,  0.0,  3 * M_PI_4, 100.0, -0.02, -0.01,  50.0,  2.0, -16.535,  46.035,  1.4812 },
+    GeometrySpiral_Data{  0.0,  1.0, -3 * M_PI_4, 100.0, -0.02, -0.01,  50.0,  2.0, -46.035, -16.535, -3.2312 }
+));
+
+INSTANTIATE_TEST_SUITE_P(AtEndOfGeometryAndZeroTWithAlternatingCurvatureSign, RoadGeometries_Spiral, ::testing::Values(
+    //                   |       origin          | spirial definition | query pos |   expected result        |
+    //                   | x     y           hdg | len c_start  c_end |   s     t |    x        y      hdg   |
+    GeometrySpiral_Data{ -49.688, -4.148,   0.25, 100.0, -0.01,  0.01,  50.0,  0.0,   0.000,   0.000,  0.0000 },
+    GeometrySpiral_Data{ -49.688,  4.148,  -0.25, 100.0,  0.01, -0.01,  50.0,  0.0,   0.000,   0.000,  0.0000 },
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0, -0.01,  0.01,  50.0,  0.0,  49.170,  -8.274, -0.2500 },
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0, -0.01,  0.01, 100.0,  0.0,  98.340, -16.548,  0.0000 },
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0,  0.01, -0.01,  50.0,  0.0,  49.170,   8.274,  0.2500 },
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0,  0.01, -0.01, 100.0,  0.0,  98.340,  16.548,  0.0000 },
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0, -0.02,  0.01, 100.0,  0.0,  86.252, -47.254, -0.5000 },
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0, -0.02,  0.01,  50.0,  0.0,  45.747, -18.029, -0.6250 },
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0,  0.02, -0.01, 100.0,  0.0,  86.252,  47.254,  0.5000 },
+    GeometrySpiral_Data{  0.0,  0.0,         0.0, 100.0,  0.02, -0.01,  50.0,  0.0,  45.747,  18.029,  0.6250 }
+));
diff --git a/sim/tests/unitTests/unitTests.pro b/sim/tests/unitTests/unitTests.pro
index ade3e5da1eeb7980f63b56d166a8e2f96071398d..fd38aee5703b95dbdfd1b428f3fa769c5f4173b4 100644
--- a/sim/tests/unitTests/unitTests.pro
+++ b/sim/tests/unitTests/unitTests.pro
@@ -30,7 +30,8 @@ SUBDIRS = \
     openScenarioActions_Tests \
     scheduler_Tests \
     sensorDriver_Tests \
-    sensorFusionOSI_Tests \
+    sensorAggregation_Tests \
+    sensorFusionErrorless_Tests \
     sensorOSI_Tests \
     signalPrioritizer_Tests \
     spawnPointScenario_Tests \
@@ -87,8 +88,11 @@ scheduler_Tests.file = \
 sensorDriver_Tests.file = \
     $$PWD/components/Sensor_Driver/sensorDriver_Tests.pro
 
-sensorFusionOSI_Tests.file = \
-    $$PWD/components/SensorFusion_OSI/sensorFusionOSI_Tests.pro
+sensorAggregation_Tests.file = \
+    $$PWD/components/SensorAggregation_OSI/sensorAggregationOSI_Tests.pro
+
+sensorFusionErrorless_Tests.file = \
+    $$PWD/components/SensorFusionErrorless_OSI/sensorFusionErrorless_Tests.pro
 
 sensorOSI_Tests.file = \
     $$PWD/components/Sensor_OSI/sensorOSI_Tests.pro