From 864a5547715aab95b82d2757cda8dd607ed3c6ff Mon Sep 17 00:00:00 2001 From: paulbourelly999 <77466294+paulbourelly999@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:36:52 -0500 Subject: [PATCH 01/12] Fix time sync message updates (#198) # PR Details ## Description CARMA Ambassador was sending timestep updates 100 ms ahead of time. This is because the CARMA Ambassador was using the value for the next time step requested instead of the value of the current time step for time sync messages. ## Related GitHub Issue ## Related Jira Key [CDAR-764 ](https://usdot-carma.atlassian.net/browse/CDAR-764) ## Motivation and Context Fix CARMA Time sync ## How Has This Been Tested? CDASim Deployment ## Types of changes - [x] Defect fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that cause existing functionality to change) ## Checklist: - [ ] I have added any new packages to the sonar-scanner.properties file - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [x] I have read the [**CONTRIBUTING**](https://github.com/usdot-fhwa-stol/carma-platform/blob/develop/Contributing.md) document. - [ ] I have added tests to cover my changes. - [x] All new and existing tests passed. --- .../carma/ambassador/CarmaMessageAmbassador.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaMessageAmbassador.java b/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaMessageAmbassador.java index b1f86475..eec5c94f 100644 --- a/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaMessageAmbassador.java +++ b/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaMessageAmbassador.java @@ -157,6 +157,7 @@ public synchronized void processTimeAdvanceGrant(long time) throws InternalFeder // simulation time step return; } + log.info("Carma message ambassador processing timestep to {}.", time); try { List newRegistrations = carmaRegistrationReceiver.getReceivedMessages(); @@ -164,25 +165,26 @@ public synchronized void processTimeAdvanceGrant(long time) throws InternalFeder carmaInstanceManager.onNewRegistration(reg); onDsrcRegistrationRequest(reg.getCarlaVehicleRole()); } - - + // Set current simulation time to most recent time update + currentSimulationTime = time; if (currentSimulationTime == 0) { // For the first timestep, clear the message receive queues. v2xMessageReceiver.getReceivedMessages(); // Automatically empties the queues. } else { List> newMessages = v2xMessageReceiver.getReceivedMessages(); for (Tuple msg : newMessages) { - V2xMessageTransmission msgInt = carmaInstanceManager.onV2XMessageTx(msg.getA(), msg.getB(), time); + V2xMessageTransmission msgInt = carmaInstanceManager.onV2XMessageTx(msg.getA(), msg.getB(), currentSimulationTime); SimulationKernel.SimulationKernel.getV2xMessageCache().putItem(currentSimulationTime, msgInt.getMessage()); rti.triggerInteraction(msgInt); } } - - currentSimulationTime += carmaConfiguration.updateInterval * TIME.MILLI_SECOND; - timeSyncSeq += 1; - // Timestep in nano seconds + // Time Syncmessage in nano seconds TimeSyncMessage timeSyncMessage = new TimeSyncMessage(currentSimulationTime, timeSyncSeq); carmaInstanceManager.onTimeStepUpdate(timeSyncMessage); + // Increment time + currentSimulationTime += carmaConfiguration.updateInterval * TIME.MILLI_SECOND; + timeSyncSeq += 1; + rti.requestAdvanceTime(currentSimulationTime, 0, (byte) 2); } catch (IllegalValueException e) { log.error("Error during advanceTime(" + time + ")", e); From a5010c08d61bb4662bf7293a4dbc94e915458781 Mon Sep 17 00:00:00 2001 From: Anish Date: Wed, 6 Mar 2024 09:28:37 -0500 Subject: [PATCH 02/12] update carla install url --- docker/install_dependencies.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/install_dependencies.sh b/docker/install_dependencies.sh index 8f7280c4..6866bc82 100755 --- a/docker/install_dependencies.sh +++ b/docker/install_dependencies.sh @@ -61,7 +61,7 @@ CARLA_TAR="CARLA_0.9.10.tar.gz" cd /home/carma/src/ if [[ ! -f "$CARLA_TAR" ]]; then echo "!!! $CARLA_TAR not present in the installation directory, downloading automatically instead. This could take a long time, consider downloading the file manually and placing it in the installation directory. !!!" - wget -q "https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/CARLA_0.9.10.tar.gz" + wget -q "https://carla-releases.s3.us-east-005.backblazeb2.com/Linux/CARLA_0.9.10.tar.gz" fi sudo mkdir -p /opt/carla From 78f1cbb35d594ac696ac95607581580ef9165421 Mon Sep 17 00:00:00 2001 From: paulbourelly999 <77466294+paulbourelly999@users.noreply.github.com> Date: Thu, 21 Mar 2024 14:04:22 -0400 Subject: [PATCH 03/12] Fix CI badges --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c4de76fa..3aa7f723 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -| CI Build Status | Docker Build | Docker Hub Push | Sonar Code Quality | +| Docker Image Build (develop) | Docker Image Build (release) | Sonar Code Quality | Sonar Workflow | |----------------------|---------------------|---------------------|---------------------| -|[![CI](https://github.com/usdot-fhwa-stol/carma-simulation/actions/workflows/ci.yml/badge.svg)](https://github.com/usdot-fhwa-stol/carma-simulation/actions/workflows/ci.yml) | [![Docker](https://github.com/usdot-fhwa-stol/carma-simulation/actions/workflows/docker.yml/badge.svg)](https://github.com/usdot-fhwa-stol/carma-simulation/actions/workflows/docker.yml) | [![Docker Hub](https://github.com/usdot-fhwa-stol/carma-simulation/actions/workflows/dockerhub.yml/badge.svg)](https://github.com/usdot-fhwa-stol/carma-simulation/actions/workflows/dockerhub.yml) | [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=usdot-fhwa-stol_carma-simulation&metric=alert_status)](https://sonarcloud.io/dashboard?id=usdot-fhwa-stol_carma-simulation)| +|[![Docker Hub build](https://github.com/usdot-fhwa-stol/cdasim/actions/workflows/dockerhub.yml/badge.svg?branch=develop)](https://github.com/usdot-fhwa-stol/cdasim/actions/workflows/dockerhub.yml) | [![Docker Hub build](https://github.com/usdot-fhwa-stol/cdasim/actions/workflows/dockerhub.yml/badge.svg?branch=master)](https://github.com/usdot-fhwa-stol/cdasim/actions/workflows/dockerhub.yml) | [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=usdot-fhwa-stol_carma-simulation&metric=alert_status)](https://sonarcloud.io/dashboard?id=usdot-fhwa-stol_carma-simulation)| [![CI: Run tests](https://github.com/usdot-fhwa-stol/cdasim/actions/workflows/ci.yml/badge.svg)](https://github.com/usdot-fhwa-stol/cdasim/actions/workflows/ci.yml)| # CARMASimulation This repository will host the CARMA Everything-in-the-Loop Co-Simulation tool. This XiL simulation platform will support CARLA and SUMO simulation environments as a co-simulation using the MOSAIC framework to facilitate coordination and data exchange. This co-simulation environment will also utilize NS-3 to simulate the communications used by the C-ADS systems. From fd6959de3343da2edef21a214498b3e761f39684 Mon Sep 17 00:00:00 2001 From: Saikrishna Bairamoni <84093461+SaikrishnaBairamoni@users.noreply.github.com> Date: Wed, 1 May 2024 11:17:33 -0400 Subject: [PATCH 04/12] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3aa7f723..517cdc43 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,9 @@ # CARMASimulation This repository will host the CARMA Everything-in-the-Loop Co-Simulation tool. This XiL simulation platform will support CARLA and SUMO simulation environments as a co-simulation using the MOSAIC framework to facilitate coordination and data exchange. This co-simulation environment will also utilize NS-3 to simulate the communications used by the C-ADS systems. -The current version and release history can be found here: [Release Notes]() +## Release Notes +The current version and release history of the CARMA software platform: [CARMA Release Notes]() + ## Contribution Welcome to the CARMA contributing guide. Please read this guide to learn about our development process, how to propose pull requests and improvements, and how to build and test your changes to this project. [CARMA Contributing Guide](https://github.com/usdot-fhwa-stol/carma-platform/blob/develop/Contributing.md) From 6aa703b88e6ebef7c1266f7c27255fb3436038ce Mon Sep 17 00:00:00 2001 From: Saikrishna Bairamoni <84093461+SaikrishnaBairamoni@users.noreply.github.com> Date: Wed, 1 May 2024 11:43:52 -0400 Subject: [PATCH 05/12] fix ref link --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 517cdc43..137678cf 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,7 @@ This repository will host the CARMA Everything-in-the-Loop Co-Simulation tool. This XiL simulation platform will support CARLA and SUMO simulation environments as a co-simulation using the MOSAIC framework to facilitate coordination and data exchange. This co-simulation environment will also utilize NS-3 to simulate the communications used by the C-ADS systems. ## Release Notes -The current version and release history of the CARMA software platform: [CARMA Release Notes]() - +The current version and release history of the CARMA software platform: [CARMA Release Notes](https://github.com/usdot-fhwa-stol/carma-platform/blob/master/docs/Release_notes.md) ## Contribution Welcome to the CARMA contributing guide. Please read this guide to learn about our development process, how to propose pull requests and improvements, and how to build and test your changes to this project. [CARMA Contributing Guide](https://github.com/usdot-fhwa-stol/carma-platform/blob/develop/Contributing.md) From 9053f4c89af4a7d02441e27b0ab5ae2cf58bdffb Mon Sep 17 00:00:00 2001 From: Saikrishna Bairamoni <84093461+SaikrishnaBairamoni@users.noreply.github.com> Date: Wed, 1 May 2024 11:57:32 -0400 Subject: [PATCH 06/12] address comment --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 137678cf..e456e888 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This repository will host the CARMA Everything-in-the-Loop Co-Simulation tool. This XiL simulation platform will support CARLA and SUMO simulation environments as a co-simulation using the MOSAIC framework to facilitate coordination and data exchange. This co-simulation environment will also utilize NS-3 to simulate the communications used by the C-ADS systems. ## Release Notes -The current version and release history of the CARMA software platform: [CARMA Release Notes](https://github.com/usdot-fhwa-stol/carma-platform/blob/master/docs/Release_notes.md) +The current version and release history can be found here:[CDA Release Notes](https://github.com/usdot-fhwa-stol/carma-platform/blob/master/docs/Release_notes.md) ## Contribution Welcome to the CARMA contributing guide. Please read this guide to learn about our development process, how to propose pull requests and improvements, and how to build and test your changes to this project. [CARMA Contributing Guide](https://github.com/usdot-fhwa-stol/carma-platform/blob/develop/Contributing.md) From 001c0c4a92076a71d49f1ac2bf879fb84fa5b7b0 Mon Sep 17 00:00:00 2001 From: Saikrishna Bairamoni <84093461+SaikrishnaBairamoni@users.noreply.github.com> Date: Wed, 1 May 2024 13:38:22 -0400 Subject: [PATCH 07/12] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e456e888..423087f9 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ This repository will host the CARMA Everything-in-the-Loop Co-Simulation tool. This XiL simulation platform will support CARLA and SUMO simulation environments as a co-simulation using the MOSAIC framework to facilitate coordination and data exchange. This co-simulation environment will also utilize NS-3 to simulate the communications used by the C-ADS systems. ## Release Notes -The current version and release history can be found here:[CDA Release Notes](https://github.com/usdot-fhwa-stol/carma-platform/blob/master/docs/Release_notes.md) +The current version and release history can be found here: [Release Notes](https://github.com/usdot-fhwa-stol/carma-platform/blob/master/docs/Release_notes.md) + ## Contribution Welcome to the CARMA contributing guide. Please read this guide to learn about our development process, how to propose pull requests and improvements, and how to build and test your changes to this project. [CARMA Contributing Guide](https://github.com/usdot-fhwa-stol/carma-platform/blob/develop/Contributing.md) From 9e6494c34594ab4d709692737c4d64eaeb6fe472 Mon Sep 17 00:00:00 2001 From: paulbourelly999 <77466294+paulbourelly999@users.noreply.github.com> Date: Thu, 2 May 2024 14:25:49 -0400 Subject: [PATCH 08/12] Remove unused checkout.sh script and set runner explicitly (#217) # PR Details ## Description Remove unused checkout script and explicitly define runner ## Related GitHub Issue ## Related Jira Key ## Motivation and Context Remove unused scripts ## How Has This Been Tested? CI ## Types of changes - [ ] Defect fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that cause existing functionality to change) ## Checklist: - [ ] I have added any new packages to the sonar-scanner.properties file - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [ ] I have read the [**CONTRIBUTING**](https://github.com/usdot-fhwa-stol/carma-platform/blob/develop/Contributing.md) document. - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. --- .github/workflows/docker.yml | 3 ++- .github/workflows/dockerhub.yml | 6 +++-- docker/checkout.sh | 44 --------------------------------- 3 files changed, 6 insertions(+), 47 deletions(-) delete mode 100755 docker/checkout.sh diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index fe5ecef7..ba3eb807 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,8 @@ name: Docker build on: pull_request: types: [opened, synchronize, reopened] - jobs: docker: uses: usdot-fhwa-stol/actions/.github/workflows/docker.yml@main + with: + runner: ubuntu-latest-16-cores diff --git a/.github/workflows/dockerhub.yml b/.github/workflows/dockerhub.yml index abdd8134..09bf8bbf 100644 --- a/.github/workflows/dockerhub.yml +++ b/.github/workflows/dockerhub.yml @@ -2,8 +2,8 @@ name: Docker Hub build on: push: branches: - - "develop" - - "master" + - develop + - master - "release/*" tags: - "carma-system-*" @@ -14,3 +14,5 @@ jobs: secrets: DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + with: + runner: ubuntu-latest-16-cores diff --git a/docker/checkout.sh b/docker/checkout.sh deleted file mode 100755 index 06391349..00000000 --- a/docker/checkout.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -# Copyright (C) 2018-2020 LEIDOS. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not -# use this file except in compliance with the License. You may obtain a copy of -# the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations under -# the License. - -# CARMA packages checkout script -# Optional argument to set the root checkout directory with no ending '/' default is '~' - -set -ex - -dir=~ -while [[ $# -gt 0 ]]; do - arg="$1" - case $arg in - -d|--develop) - BRANCH=develop - shift - ;; - -r|--root) - dir=$2 - shift - shift - ;; - esac -done - -if [[ "$BRANCH" = "develop" ]]; then - git clone https://github.com/usdot-fhwa-stol/carma-msgs.git ~/src/carma-msgs --branch $BRANCH --depth 1 - git clone https://github.com/usdot-fhwa-stol/carma-utils.git ~/src/carma-utils --branch $BRANCH --depth 1 -else - git clone https://github.com/usdot-fhwa-stol/carma-msgs.git ${dir}/src/carma-msgs --branch carma-system-4.5.0 --depth 1 - git clone https://github.com/usdot-fhwa-stol/carma-utils.git ${dir}/src/carma-utils --branch carma-system-4.5.0 --depth 1 -fi From caac2ffb421646c7daf7143d3b9b436ed97e0acf Mon Sep 17 00:00:00 2001 From: kruegersp Date: Fri, 3 May 2024 11:02:58 -0500 Subject: [PATCH 09/12] CARMA Cloud ambassador integration (#200) # PR Details ## Description This PR primarily focuses on merging a branch into develop, which encompasses the integration testing of CARMA Cloud with CDASim. The purpose of this integration test was to assess the communication between CARMA Cloud and CDASim, ensuring that: All components operate correctly within CDASim without encountering any significant problems. CARMA Cloud successfully registers with Ambassador. CARMA Cloud receives and processes time synchronization messages. ## Related GitHub Issue ## Related Jira Key [CXC-10](https://usdot-carma.atlassian.net/jira/software/c/projects/CXC/issues/CXC-10) ## Motivation and Context ## How Has This Been Tested? ## Types of changes - [ ] Defect fix (non-breaking change that fixes an issue) - [x] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that cause existing functionality to change) ## Checklist: - [ ] I have added any new packages to the sonar-scanner.properties file - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [x] I have read the [**CONTRIBUTING**](https://github.com/usdot-fhwa-stol/carma-platform/blob/develop/Contributing.md) document. - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. [CXC-10]: https://usdot-carma.atlassian.net/browse/CXC-10?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: Cheng Yuan Co-authored-by: Kyle Rush Co-authored-by: Cheng Yuan <84340069+chengyuan0124@users.noreply.github.com> --- co-simulation/bundle/pom.xml | 7 +- .../src/assembly/resources/etc/logback.xml | 11 + .../src/assembly/resources/etc/runtime.json | 14 ++ .../carma-cloud/carma-cloud_config.json} | 0 .../scenarios/Town04/scenario_config.json | 3 +- .../application/Town04.db | Bin .../carla/bridge.sh | 0 .../carla/carla_config.json | 2 +- .../carma-cloud/carma-cloud_config.json | 3 + .../carma/carma_config.json | 0 .../infrastructure/infrastructure_config.json | 3 + .../mapping/mapping_config.json | 0 .../ns3/ns3_config.json | 0 .../ns3/ns3_federate_config.xml | 0 .../output/output_config.xml | 0 .../scenario_config.json | 3 +- .../sumo/Town04.net.xml | 0 .../sumo/Town04.rou.xml | 0 .../sumo/Town04.sumocfg | 0 .../sumo/detector.xml | 0 .../sumo/sumo_config.json | 0 co-simulation/fed/mosaic-carma-cloud/pom.xml | 105 +++++++++ .../ambassador/CarmaCloudInstance.java | 93 ++++++++ .../ambassador/CarmaCloudInstanceManager.java | 99 +++++++++ .../CarmaCloudMessageAmbassador.java | 208 ++++++++++++++++++ .../CarmaCloudRegistrationMessage.java | 71 ++++++ .../CarmaCloudRegistrationReceiver.java | 139 ++++++++++++ .../CarmaCloudConfiguration.java | 31 +++ .../CarmaCloudInstanceManagerTest.java | 69 ++++++ .../ambassador/CarmaCloudInstanceTest.java | 92 ++++++++ .../CarmaCloudMessageAmbassadorTest.java | 125 +++++++++++ .../CarmaCloudRegistrationMessageTest.java | 33 +++ .../CarmaCloudRegistrationReceiverTest.java | 69 ++++++ co-simulation/pom.xml | 1 + 34 files changed, 1177 insertions(+), 4 deletions(-) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test/infrastructure/infrastructure_config.json => Town04/carma-cloud/carma-cloud_config.json} (100%) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/application/Town04.db (100%) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/carla/bridge.sh (100%) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/carla/carla_config.json (63%) create mode 100644 co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/carma-cloud/carma-cloud_config.json rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/carma/carma_config.json (100%) create mode 100644 co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/infrastructure/infrastructure_config.json rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/mapping/mapping_config.json (100%) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/ns3/ns3_config.json (100%) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/ns3/ns3_federate_config.xml (100%) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/output/output_config.xml (100%) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/scenario_config.json (93%) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/sumo/Town04.net.xml (100%) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/sumo/Town04.rou.xml (100%) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/sumo/Town04.sumocfg (100%) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/sumo/detector.xml (100%) rename co-simulation/bundle/src/assembly/resources/scenarios/{Town04_test => Town04_carma_cloud}/sumo/sumo_config.json (100%) create mode 100644 co-simulation/fed/mosaic-carma-cloud/pom.xml create mode 100644 co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstance.java create mode 100644 co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstanceManager.java create mode 100644 co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudMessageAmbassador.java create mode 100644 co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationMessage.java create mode 100644 co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationReceiver.java create mode 100644 co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/configuration/CarmaCloudConfiguration.java create mode 100644 co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstanceManagerTest.java create mode 100644 co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstanceTest.java create mode 100644 co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudMessageAmbassadorTest.java create mode 100644 co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationMessageTest.java create mode 100644 co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationReceiverTest.java diff --git a/co-simulation/bundle/pom.xml b/co-simulation/bundle/pom.xml index 024b663c..f83b3d30 100644 --- a/co-simulation/bundle/pom.xml +++ b/co-simulation/bundle/pom.xml @@ -144,6 +144,11 @@ mosaic-infrastructure ${mosaic.version} + + org.eclipse.mosaic + mosaic-carma-cloud + ${mosaic.version} + @@ -262,4 +267,4 @@ - \ No newline at end of file + diff --git a/co-simulation/bundle/src/assembly/resources/etc/logback.xml b/co-simulation/bundle/src/assembly/resources/etc/logback.xml index 4ab190bd..1cd6764d 100755 --- a/co-simulation/bundle/src/assembly/resources/etc/logback.xml +++ b/co-simulation/bundle/src/assembly/resources/etc/logback.xml @@ -98,6 +98,13 @@ %date %-5level %C{0}:%line - %msg%n + + UTF-8 + ${logDirectory}/CarmaCloud.log + + %date %-5level %C{0}:%line - %msg%n + + UTF-8 ${logDirectory}/Environment.log @@ -209,6 +216,10 @@ + + + + diff --git a/co-simulation/bundle/src/assembly/resources/etc/runtime.json b/co-simulation/bundle/src/assembly/resources/etc/runtime.json index 4350f1eb..28c175e1 100644 --- a/co-simulation/bundle/src/assembly/resources/etc/runtime.json +++ b/co-simulation/bundle/src/assembly/resources/etc/runtime.json @@ -121,6 +121,20 @@ ], "javaClasspathEntries": [] }, + { + "id": "carma-cloud", + "classname": "org.eclipse.mosaic.fed.carmacloud.ambassador.CarmaCloudMessageAmbassador", + "configuration": "carma-cloud_config.json", + "priority": 50, + "host": "local", + "port": 0, + "deploy": false, + "start": false, + "subscriptions": [ + "V2xMessageReception" + ], + "javaClasspathEntries": [] + }, { "id": "mapping", diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/infrastructure/infrastructure_config.json b/co-simulation/bundle/src/assembly/resources/scenarios/Town04/carma-cloud/carma-cloud_config.json similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/infrastructure/infrastructure_config.json rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04/carma-cloud/carma-cloud_config.json diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04/scenario_config.json b/co-simulation/bundle/src/assembly/resources/scenarios/Town04/scenario_config.json index 2103391b..03a52f54 100755 --- a/co-simulation/bundle/src/assembly/resources/scenarios/Town04/scenario_config.json +++ b/co-simulation/bundle/src/assembly/resources/scenarios/Town04/scenario_config.json @@ -34,7 +34,8 @@ "sumo": true, "carla": true, "carma": true, - "infrastructure": true + "infrastructure": true, + "carma-cloud": true } } diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/application/Town04.db b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/application/Town04.db similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/application/Town04.db rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/application/Town04.db diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/carla/bridge.sh b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/carla/bridge.sh similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/carla/bridge.sh rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/carla/bridge.sh diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/carla/carla_config.json b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/carla/carla_config.json similarity index 63% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/carla/carla_config.json rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/carla/carla_config.json index aff6f191..7f16c9ba 100644 --- a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/carla/carla_config.json +++ b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/carla/carla_config.json @@ -1,7 +1,7 @@ { "updateInterval": 100, "carlaUE4Path": "/opt/carla/", - "bridgePath": "/opt/carma-simulation/scenarios/Town04_test/carla; bridge.sh", + "bridgePath": "/opt/carma-simulation/scenarios/Town04_carma_cloud/carla; bridge.sh", "carlaConnectionPort": 8913, "carlaCDASimAdapterUrl":"http://127.0.0.1:8090/RPC2" } diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/carma-cloud/carma-cloud_config.json b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/carma-cloud/carma-cloud_config.json new file mode 100644 index 00000000..196145f7 --- /dev/null +++ b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/carma-cloud/carma-cloud_config.json @@ -0,0 +1,3 @@ +{ + "updateInterval": 100 +} diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/carma/carma_config.json b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/carma/carma_config.json similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/carma/carma_config.json rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/carma/carma_config.json diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/infrastructure/infrastructure_config.json b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/infrastructure/infrastructure_config.json new file mode 100644 index 00000000..196145f7 --- /dev/null +++ b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/infrastructure/infrastructure_config.json @@ -0,0 +1,3 @@ +{ + "updateInterval": 100 +} diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/mapping/mapping_config.json b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/mapping/mapping_config.json similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/mapping/mapping_config.json rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/mapping/mapping_config.json diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/ns3/ns3_config.json b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/ns3/ns3_config.json similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/ns3/ns3_config.json rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/ns3/ns3_config.json diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/ns3/ns3_federate_config.xml b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/ns3/ns3_federate_config.xml similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/ns3/ns3_federate_config.xml rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/ns3/ns3_federate_config.xml diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/output/output_config.xml b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/output/output_config.xml similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/output/output_config.xml rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/output/output_config.xml diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/scenario_config.json b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/scenario_config.json similarity index 93% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/scenario_config.json rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/scenario_config.json index 2103391b..03a52f54 100755 --- a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/scenario_config.json +++ b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/scenario_config.json @@ -34,7 +34,8 @@ "sumo": true, "carla": true, "carma": true, - "infrastructure": true + "infrastructure": true, + "carma-cloud": true } } diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/sumo/Town04.net.xml b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/sumo/Town04.net.xml similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/sumo/Town04.net.xml rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/sumo/Town04.net.xml diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/sumo/Town04.rou.xml b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/sumo/Town04.rou.xml similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/sumo/Town04.rou.xml rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/sumo/Town04.rou.xml diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/sumo/Town04.sumocfg b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/sumo/Town04.sumocfg similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/sumo/Town04.sumocfg rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/sumo/Town04.sumocfg diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/sumo/detector.xml b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/sumo/detector.xml similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/sumo/detector.xml rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/sumo/detector.xml diff --git a/co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/sumo/sumo_config.json b/co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/sumo/sumo_config.json similarity index 100% rename from co-simulation/bundle/src/assembly/resources/scenarios/Town04_test/sumo/sumo_config.json rename to co-simulation/bundle/src/assembly/resources/scenarios/Town04_carma_cloud/sumo/sumo_config.json diff --git a/co-simulation/fed/mosaic-carma-cloud/pom.xml b/co-simulation/fed/mosaic-carma-cloud/pom.xml new file mode 100644 index 00000000..4c71b10c --- /dev/null +++ b/co-simulation/fed/mosaic-carma-cloud/pom.xml @@ -0,0 +1,105 @@ + + + + 4.0.0 + + + org.eclipse.mosaic + mosaic-parent + 22.1-SNAPSHOT + ../../pom.xml + + + mosaic-carma-cloud + CARMA Cloud Ambassador + + + + org.eclipse.mosaic + mosaic-rti-api + ${mosaic.version} + + + org.eclipse.mosaic + mosaic-objects + ${mosaic.version} + + + org.eclipse.mosaic + mosaic-objects + ${mosaic.version} + test-jar + test + + + gov.dot.fhwa.saxton + mosaic-carma-utils + ${mosaic.version} + + + org.eclipse.mosaic + mosaic-interactions + ${mosaic.version} + + + org.eclipse.mosaic + mosaic-utils + ${mosaic.version} + test-jar + test + + + org.eclipse.mosaic + mosaic-geomath + ${mosaic.version} + test-jar + test + + + ch.qos.logback + logback-classic + + + junit + junit + 4.11 + test + + + org.eclipse.mosaic + mosaic-application + 22.1-SNAPSHOT + compile + + + jakarta.xml.bind + jakarta.xml.bind-api + 2.3.2 + + + org.glassfish.jaxb + jaxb-runtime + 2.3.2 + + + + + + skip-carma-cloud-tests + + + + + + maven-surefire-plugin + + true + + + + + + + + diff --git a/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstance.java b/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstance.java new file mode 100644 index 00000000..0dc5333e --- /dev/null +++ b/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstance.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2023 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.eclipse.mosaic.fed.carmacloud.ambassador; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.URL; +import java.net.HttpURLConnection; +import com.google.gson.Gson; +import gov.dot.fhwa.saxton.TimeSyncMessage; + + +/** + * CarmaCloudInstance class represents a physical instance of an + * CARMA Cloud in the simulated environment. + * It contains information about the instance such as its id and target address + */ +public class CarmaCloudInstance +{ + // unique simulation identifier for the CARMA Cloud instance + private final String carmaCloudId; + // URL endpoint where to send simulation time sync messages + private final String carmaCloudUrl; + + + /** + * Constructor for CarmaCloudInstance + * + * @param sId the ID of the CARMA Cloud instance. + * @param sUrl the receive time synchronization message port of the infrastructure. + */ + public CarmaCloudInstance(String sId, String sUrl) + { + carmaCloudId = sId; + carmaCloudUrl = sUrl; + } + + + /** + * Returns the URL endpoint of the CARMA Cloud instance + * + * @return String URL endpoint of the CARMA Cloud instance + */ + public String getCarmaCloudUrl() + { + return carmaCloudUrl; + } + + + /** + * Returns the ID of the CARMA Cloud instance + * + * @return String the ID of the CARMA Cloud instance + */ + public String getCarmaCloudId() + { + return carmaCloudId; + } + + + /** + * Sends time sync data to the CARMA Cloud Instance + * + * @param oMsg the JSON time sync state to transmit + * @throws IOException if there is an issue with the underlying URL connection + */ + public void sendTimeSyncMsg(TimeSyncMessage oMsg) + throws IOException + { + HttpURLConnection oHttp = (HttpURLConnection)new URL(carmaCloudUrl).openConnection(); + oHttp.setRequestMethod("POST"); + oHttp.setDoOutput(true); + try (DataOutputStream oOut = new DataOutputStream(oHttp.getOutputStream())) + { + oOut.write(new Gson().toJson(oMsg).getBytes()); + } + if (oHttp.getResponseCode() != 200) + throw new IOException(String.format("CARMA Cloud failure %d %s", oHttp.getResponseCode(), oHttp.getResponseMessage())); + } +} diff --git a/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstanceManager.java b/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstanceManager.java new file mode 100644 index 00000000..94e55253 --- /dev/null +++ b/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstanceManager.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2023 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package org.eclipse.mosaic.fed.carmacloud.ambassador; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import gov.dot.fhwa.saxton.TimeSyncMessage; + + +/** + * Session management class for Infrastructure instances communicating with + * MOSAIC. + * + * This class is responsible for managing instances of CARMA Cloud registered + * with the MOSAIC system. It provides methods for registering new instances, + * checking if instances are registered, and storing and retrieving instances + * from a map. + */ +public class CarmaCloudInstanceManager +{ + private final Map managedInstances = new HashMap<>(); + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + + /** + * Register a new CARMA Cloud instance with the MOSAIC system. + * + * This method takes a CarmaCloudRegistrationMessage, converts it to a + * CarmaCloudInstance, and adds it to the managedInstances map + * if it is not already present. + * + * @param registration The CarmaCloudRegistrationMessage to be registered. + * + */ + public void onNewRegistration(CarmaCloudRegistrationMessage registration) + { + if (!managedInstances.containsKey(registration.getId())) + { + CarmaCloudInstance tmp = new CarmaCloudInstance(registration.getId(), registration.getUrl()); + managedInstances.put(registration.getId(), tmp); + } + else + log.warn("Registration message received for already registered CARMA Cloud with ID: {}", registration.getId()); + } + + + /** + * This function is used to send out encoded time step update to all registered + * instances the manager has on the managed instances map + * + * @param message This time message is used to store current seq and time step + * from the ambassador side + * @throws IOException + */ + public void onTimeStepUpdate(TimeSyncMessage message) + throws IOException + { + if (managedInstances.isEmpty()) + log.debug("There are no registered instances"); + else + { + log.debug("onTimeStepUpdate instance count {}", managedInstances.size()); + for (CarmaCloudInstance currentInstance : managedInstances.values()) + { + currentInstance.sendTimeSyncMsg(message); + log.debug("Sent time message to CARMA-Cloud " + message.toString()); + } + } + } + + + /** + * Returns Map of managed CARMA Cloud instances with CARMA Cloud ID as the + * String Key. + * + * @return map of managed CARMA Cloud instances. + */ + public Map getManagedInstances() + { + return managedInstances; + } +} diff --git a/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudMessageAmbassador.java b/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudMessageAmbassador.java new file mode 100644 index 00000000..3bc42cc1 --- /dev/null +++ b/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudMessageAmbassador.java @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2023 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package org.eclipse.mosaic.fed.carmacloud.ambassador; + +import java.io.IOException; +import java.util.List; + +import org.eclipse.mosaic.fed.carmacloud.configuration.CarmaCloudConfiguration; +import org.eclipse.mosaic.interactions.communication.V2xMessageReception; +import org.eclipse.mosaic.lib.util.objects.ObjectInstantiation; +import org.eclipse.mosaic.rti.api.AbstractFederateAmbassador; +import org.eclipse.mosaic.rti.api.IllegalValueException; +import org.eclipse.mosaic.rti.api.Interaction; +import org.eclipse.mosaic.rti.api.InternalFederateException; +import org.eclipse.mosaic.rti.api.parameters.AmbassadorParameter; +import org.eclipse.mosaic.rti.TIME; + +import gov.dot.fhwa.saxton.TimeSyncMessage; + +/** + * Implementation of a {@link AbstractFederateAmbassador} for CarmaCloud + * message ambassador. + */ +public class CarmaCloudMessageAmbassador extends AbstractFederateAmbassador +{ + /** + * Simulation time. + */ + long currentSimulationTime; + + /** + * CarmaCloudMessageAmbassador configuration file. + */ + CarmaCloudConfiguration carmaCloudConfiguration; + + private CarmaCloudRegistrationReceiver carmaCloudRegistrationReceiver; + private final CarmaCloudInstanceManager carmaCloudInstanceManager = new CarmaCloudInstanceManager(); + private int timeSyncSeq; + + + /** + * Create a new {@link CarmaCloudMessageAmbassador} object. + * + * @param ambassadorParameter includes parameters for the + * CarmaCloudMessageAmbassador. + */ + public CarmaCloudMessageAmbassador(AmbassadorParameter ambassadorParameter) throws RuntimeException + { + super(ambassadorParameter); + try // load configuration file + { + carmaCloudConfiguration = new ObjectInstantiation<>(CarmaCloudConfiguration.class, log) + .readFile(ambassadorParameter.configuration); + } + catch (InstantiationException e) + { + log.error("Configuration object could not be instantiated: ", e); + } + + log.info("The update interval of CARMA Cloud message ambassador is {}.", carmaCloudConfiguration.updateInterval); + + if (carmaCloudConfiguration.updateInterval <= 0L) + { + throw new RuntimeException("Invalid update interval for CARMA Cloud message ambassador, should be > 0."); + } + log.info("CARMA Cloud message ambassador is generated."); + } + + + /** + * This method is called to tell the federate the start time and the end time. + * + * @param startTime Start time of the simulation run in nanoseconds. + * @param endTime End time of the simulation run in nanoseconds. + * @throws InternalFederateException Exception is thrown if an error is occurred + * while execute of a federate. + */ + @Override + public void initialize(long startTime, long endTime) + throws InternalFederateException + { + super.initialize(startTime, endTime); + currentSimulationTime = startTime; + + carmaCloudRegistrationReceiver = new CarmaCloudRegistrationReceiver(); + carmaCloudRegistrationReceiver.init(); + new Thread(carmaCloudRegistrationReceiver).start(); + + try + { + rti.requestAdvanceTime(currentSimulationTime, 0, (byte) 1); + } + catch (IllegalValueException e) + { + log.error("Error during advanceTime request", e); + throw new InternalFederateException(e); + } + } + + + /** + * This method is called by the AbstractFederateAmbassador when the RTI grants a + * time advance to the federate.Any unprocessed interactions are forwarded to + the federate using the processInteraction method before this call is made. + * + * @param time The timestamp (in nanoseconds) indicating the time to which the federate can + * advance its local time. + * @throws InternalFederateException + */ + @Override + public synchronized void processTimeAdvanceGrant(long time) + throws InternalFederateException + { + // Process the time advance only if the time is equal or greater than the next + // simulation time step + log.debug("Process time advance grant from {} to {}.", currentSimulationTime, time); + if (time < currentSimulationTime) + { + return; + } + + currentSimulationTime = time; + try + { + // Handle any new carmaCloud registration requests + List newRegistrations = carmaCloudRegistrationReceiver.getReceivedMessages(); + for (CarmaCloudRegistrationMessage reg : newRegistrations) + { + log.info("Processing new registration request for {}.", reg.getId()); + // Store new instance registration to carmaCloud instance manager + carmaCloudInstanceManager.onNewRegistration(reg); + } + + timeSyncSeq += 1; + // nanoseconds to milliseconds for CarmaCloudTimeMessage + TimeSyncMessage timeSyncMessage = new TimeSyncMessage(currentSimulationTime / 1000000L, timeSyncSeq); + carmaCloudInstanceManager.onTimeStepUpdate(timeSyncMessage); + + // Advance the simulation time + currentSimulationTime += carmaCloudConfiguration.updateInterval* TIME.MILLI_SECOND; + + // Request the next time advance from the RTI + log.debug("Requesting timestep updated to {}.", currentSimulationTime); + rti.requestAdvanceTime(currentSimulationTime, 0, (byte) 2); + } + catch (IllegalValueException e) + { + throw new InternalFederateException(e); + } + catch (IOException e) + { + log.error("Error during updating timestep :", e); + } + } + + + /** + * Return whether this federate is time constrained. Is set if the federate is + * sensitive towards the correct ordering of events. The federate ambassador + * will ensure that the message processing happens in time stamp order. If set + * to false, interactions will be processed in receive order. + * + * @return {@code true} if this federate is time constrained, else + * {@code false}. + */ + @Override + public boolean isTimeConstrained() + { + return true; + } + + + /** + * Return whether this federate is time regulating. Is set if the federate + * influences other federates and can prevent them from advancing their local + * time. + * + * @return {@code true} if this federate is time regulating, {@code false} else. + */ + @Override + public boolean isTimeRegulating() + { + return false; + } + + + /** + * Test helper function to cleanup sockets and threads. + */ + protected void close() + { + carmaCloudRegistrationReceiver.stop(); + } +} diff --git a/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationMessage.java b/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationMessage.java new file mode 100644 index 00000000..82c5c25a --- /dev/null +++ b/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationMessage.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2023 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.eclipse.mosaic.fed.carmacloud.ambassador; + + +/** + * A message to be sent by CARMA Cloud instance when it registers with the + * carmacloud-mosaic ambassador + */ +public class CarmaCloudRegistrationMessage +{ + // unique simulation identifier for the CARMA Cloud instance + private final String id; + // URL endpoint where to send simulation time sync messages + private final String url; + + + /** + * Constructor for a CarmaCloudRegistrationMessage + * + * @param sId the ID of the CARMA Cloud instance. + * @param sUrl the receive time synchronization message port of the infrastructure. + */ + public CarmaCloudRegistrationMessage(String sId, String sUrl) + { + id = sId; + url = sUrl; + } + + + /** + * Returns the URL endpoint of the CARMA Cloud instance + * + * @return String URL endpoint of the CARMA Cloud instance + */ + public String getUrl() + { + return url; + } + + + /** + * Returns the ID of the CARMA Cloud instance + * + * @return String the ID of the CARMA Cloud instance + */ + public String getId() + { + return id; + } + + + @Override + public String toString() + { + return String.format("CarmaCloudRegistrationMessage id %s url %s", id, url); + } +} diff --git a/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationReceiver.java b/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationReceiver.java new file mode 100644 index 00000000..1bc0834d --- /dev/null +++ b/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationReceiver.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2023 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package org.eclipse.mosaic.fed.carmacloud.ambassador; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.atomic.AtomicBoolean; + +import com.google.gson.Gson; +import java.io.DataInputStream; +import java.net.ServerSocket; +import java.net.Socket; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Worker thread Runnable for operating a listen socket to receive outbound + * CARMA Cloud Messages from CARMA Cloud instances + * This {@link Runnable} instance will operate a UDP socket to subscribe to + * packets from a CARMA Cloud adapter. + * Upon receiving a packet, it will be queued for the primary thread + * to process the data once it ticks to a simulation processing step + */ +public class CarmaCloudRegistrationReceiver implements Runnable +{ + private static final int LISTEN_PORT = 1617; + private final AtomicBoolean running = new AtomicBoolean(false); + private final Logger log = LoggerFactory.getLogger(this.getClass()); + private final Queue rxQueue = new LinkedList<>(); + private ServerSocket srvr; + + + /** + * Initialize the listen socket for messages from the CARMA Cloud instance adapter + * + * @throws RuntimeException if socket instantiation fails + */ + public void init() throws RuntimeException + { + try + { + srvr = new ServerSocket(LISTEN_PORT); + } + catch (Exception oEx) + { + throw new RuntimeException("server socket instantiation failure", oEx); + } + } + + + /** + * The main method of the worker thread. Listens for incoming messages and + * queues them for processing on the primary thread. + */ + @Override + public void run() + { + running.set(true); + try + { + while (running.get()) + { + Socket oSock = srvr.accept(); + DataInputStream oIn = new DataInputStream(oSock.getInputStream()); + + // parse message + CarmaCloudRegistrationMessage parsedMessage = + new Gson().fromJson(oIn.readUTF(), CarmaCloudRegistrationMessage.class); + + // Enqueue message for processing on main thread + synchronized (rxQueue) + { + rxQueue.add(parsedMessage); + } + log.info("New CARMA Cloud instance '{}' received with CARMA Cloud Registration Receiver.", parsedMessage.getId()); + } + } + catch (Exception oEx) + { + log.error("Error occurred", oEx); + } + } + + + /** + * Stop the runnable instance and close the listen socket. + */ + public void stop() + { + running.set(false); + if (srvr != null) + { + try + { + srvr.close(); + } + catch (Exception oEx) + { + log.error("Error occurred", oEx); + } + } + } + + + /** + * Query the current buffer of outbound messages. Clears the currently stored + * buffer once called. Thread-safe. + * + * @return The list of received outbound message from all Infrastructure Device + * instances since last call of this method + */ + public List getReceivedMessages() + { + List output = new ArrayList<>(); + synchronized (rxQueue) + { + output.addAll(rxQueue); + rxQueue.clear(); + } + return output; + } +} diff --git a/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/configuration/CarmaCloudConfiguration.java b/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/configuration/CarmaCloudConfiguration.java new file mode 100644 index 00000000..bbdaf761 --- /dev/null +++ b/co-simulation/fed/mosaic-carma-cloud/src/main/java/org/eclipse/mosaic/fed/carmacloud/configuration/CarmaCloudConfiguration.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 Old Dominion University. All rights reserved. + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.eclipse.mosaic.fed.carmacloud.configuration; + +import java.io.Serializable; +import com.google.gson.annotations.JsonAdapter; +import org.eclipse.mosaic.lib.util.gson.TimeFieldAdapter; + + +/** + * The CARMA Cloud Message Ambassador configuration class. + */ +public class CarmaCloudConfiguration implements Serializable +{ + private static final long serialVersionUID = 1705520136000000000L; + + + @JsonAdapter(TimeFieldAdapter.LegacyMilliSeconds.class) + public Long updateInterval = 100L; +} diff --git a/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstanceManagerTest.java b/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstanceManagerTest.java new file mode 100644 index 00000000..98300e91 --- /dev/null +++ b/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstanceManagerTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2023 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package org.eclipse.mosaic.fed.carmacloud.ambassador; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import java.io.IOException; +import java.util.Map; +import org.junit.Before; +import org.junit.Test; + +import gov.dot.fhwa.saxton.TimeSyncMessage; + + + +public class CarmaCloudInstanceManagerTest { + + private CarmaCloudInstanceManager manager; + private CarmaCloudInstance instance1; + private static final String carmacloudId = "carma-cloud"; + private static final String carmacloudUrl = "carma-cloud-url"; + + @Before + public void setUp() throws Exception { + manager = new CarmaCloudInstanceManager(); + instance1 = mock(CarmaCloudInstance.class); + } + + @Test + public void testOnNewRegistration() { + // Set up the registration object + CarmaCloudRegistrationMessage registration = new CarmaCloudRegistrationMessage(carmacloudId, carmacloudUrl); + + // Call the onNewRegistration method with the registration object + manager.onNewRegistration(registration); + + // Verify that the infrastructure instance was added to the manager + assertFalse(manager.getManagedInstances().isEmpty()); + assertNotNull(manager.getManagedInstances().get(carmacloudId)); + } + + @Test + public void testOnTimeStepUpdate() throws IOException { + // replace registered CARMA Cloud instance with mock instance + manager.getManagedInstances().put(carmacloudId, instance1); + + TimeSyncMessage message = new TimeSyncMessage(999L, 11); + manager.onTimeStepUpdate(message); + // Verify that all instances sendTimeSyncMsgs was called. + verify(instance1).sendTimeSyncMsg(message); + } +} diff --git a/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstanceTest.java b/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstanceTest.java new file mode 100644 index 00000000..5f6d74e5 --- /dev/null +++ b/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudInstanceTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2023 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.eclipse.mosaic.fed.carmacloud.ambassador; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedInputStream; +import java.net.InetSocketAddress; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + +import com.google.gson.Gson; +import java.io.IOException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + + + +import gov.dot.fhwa.saxton.TimeSyncMessage; + +public class CarmaCloudInstanceTest { + + private CarmaCloudInstance instance; + private StringBuilder messageBuf = new StringBuilder(); + private HttpServer oSrvr; + + class TimeSyncHandler implements HttpHandler { + @Override + public void handle(HttpExchange oExch) throws IOException { + int nChar; + BufferedInputStream oIn = new BufferedInputStream(oExch.getRequestBody()); + while ((nChar = oIn.read()) >= 0) + messageBuf.append((char)nChar); + + oExch.sendResponseHeaders(200, -1L); + oExch.close(); + } + } + + @Before + public void setUp() throws IOException { + instance = new CarmaCloudInstance("carma-cloud", "http://localhost:8080/carmacloud/simulation"); + oSrvr = HttpServer.create(new InetSocketAddress("localhost", 8080), 0); + HttpContext oCtx = oSrvr.createContext("/carmacloud/simulation"); + oCtx.setHandler(new TimeSyncHandler()); + oSrvr.start(); + } + + @After + public void tearDown() throws IOException { + oSrvr.stop(0); + } + + @Test + public void testGetterSetterConstructor() { + // Test getters and constructor for setting and retrieving class members + assertEquals("carma-cloud", instance.getCarmaCloudId()); + assertEquals("http://localhost:8080/carmacloud/simulation", instance.getCarmaCloudUrl()); + } + + @Test + public void testSendTimeSyncMsg() throws IOException { + // Test SendTimeSyncMsg method + TimeSyncMessage test_msg = new TimeSyncMessage(999L, 11); + instance.sendTimeSyncMsg(test_msg); + + assertTrue(messageBuf.length() > 0); + if (messageBuf.length() > 0) + { + TimeSyncMessage parsedMessage = new Gson().fromJson(messageBuf.toString(), TimeSyncMessage.class); + assertEquals(999L, parsedMessage.getTimestep()); + assertEquals(11, parsedMessage.getSeq()); + } + } +} diff --git a/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudMessageAmbassadorTest.java b/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudMessageAmbassadorTest.java new file mode 100644 index 00000000..bde0faa1 --- /dev/null +++ b/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudMessageAmbassadorTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2023 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package org.eclipse.mosaic.fed.carmacloud.ambassador; + +import org.eclipse.mosaic.lib.util.junit.TestFileRule; +import org.eclipse.mosaic.rti.api.IllegalValueException; +import org.eclipse.mosaic.rti.api.InternalFederateException; +import org.eclipse.mosaic.rti.api.Interaction; +import org.eclipse.mosaic.rti.api.RtiAmbassador; +import org.eclipse.mosaic.rti.api.parameters.AmbassadorParameter; +import org.eclipse.mosaic.rti.api.parameters.FederateDescriptor; +import org.eclipse.mosaic.rti.config.CLocalHost; +import org.eclipse.mosaic.rti.TIME; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import org.mockito.internal.util.reflection.FieldSetter; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.RuleChain; +import org.junit.rules.TemporaryFolder; + + +/** + * Tests for {@link CarmaCloudMessageAmbassador}. + */ +public class CarmaCloudMessageAmbassadorTest { + + private final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + private final TestFileRule testFileRule = new TestFileRule(temporaryFolder).basedir("carmacloud"); + + @Rule + public RuleChain chain = RuleChain.outerRule(temporaryFolder).around(testFileRule); + + /** + * {@link RtiAmbassador} mock. + */ + private RtiAmbassador rtiMock; + + private CarmaCloudMessageAmbassador ambassador; + /** + * {@link CarmaCloudInstanceManager} mock. + */ + private CarmaCloudInstanceManager instanceManagerMock; + /** + * {@link CarmaCloudRegistrationReceiver} mock. + */ + private CarmaCloudRegistrationReceiver receiverMock; + + private ArrayList registrationMessages; + + @Before + public void setUp() throws IOException, NoSuchFieldException, InternalFederateException, IllegalValueException { + // Initialize Mocks + rtiMock = mock(RtiAmbassador.class); + FederateDescriptor handleMock = mock(FederateDescriptor.class); + instanceManagerMock = mock(CarmaCloudInstanceManager.class); + receiverMock = mock(CarmaCloudRegistrationReceiver.class); + File workingDir = temporaryFolder.getRoot(); + CLocalHost testHostConfig = new CLocalHost(); + testHostConfig.workingDirectory = workingDir.getAbsolutePath(); + + // Mock methods + when(handleMock.getHost()).thenReturn(testHostConfig); + when(handleMock.getId()).thenReturn("carmacloud"); + CarmaCloudRegistrationMessage message = new CarmaCloudRegistrationMessage("carmacloud-id", "carmacloud-url"); + registrationMessages = new ArrayList<>(); + registrationMessages.add(message); + when(receiverMock.getReceivedMessages()).thenReturn(registrationMessages); + + // Set mocks as ambassador members through reflection or setters + ambassador = new CarmaCloudMessageAmbassador(new AmbassadorParameter("carmacloud", + temporaryFolder.newFile("carmacloud/carma-cloud_config.json"))); + + ambassador.setRtiAmbassador(rtiMock); + ambassador.setFederateDescriptor(handleMock); + FieldSetter.setField(ambassador, ambassador.getClass().getDeclaredField("carmaCloudRegistrationReceiver"), receiverMock); + FieldSetter.setField(ambassador, ambassador.getClass().getDeclaredField("carmaCloudInstanceManager"), instanceManagerMock); + } + + @Test + public void testInitialize() throws InternalFederateException, IllegalValueException { + // Test initialize method + ambassador.initialize(0, 100 * TIME.SECOND); + verify(rtiMock, times(1)).requestAdvanceTime(0L, 0L, ((byte) 1)); + // cleanup threads and sockets + ambassador.close(); + } + + @Test + public void testProcessTimeAdvanceGrant() throws InternalFederateException, IllegalValueException, NoSuchFieldException, SecurityException + { + //Test processTimeAdvanceGrant for CARMA Cloud Registration + ambassador.processTimeAdvanceGrant(100000000L); + // Verify received messages were attempted to be pulled from CARMA Cloud Registration Receiver mock + verify(receiverMock, times(1)).getReceivedMessages(); + verify(rtiMock, times(1)).requestAdvanceTime(200000000L, 0L, ((byte) 2)); + } +} diff --git a/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationMessageTest.java b/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationMessageTest.java new file mode 100644 index 00000000..b48449b4 --- /dev/null +++ b/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationMessageTest.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package org.eclipse.mosaic.fed.carmacloud.ambassador; + +import static org.junit.Assert.assertEquals; +import org.junit.Test; + +public class CarmaCloudRegistrationMessageTest { + @Test + public void testGetterSettersConstructor() { + // Test Constructor + CarmaCloudRegistrationMessage message = new CarmaCloudRegistrationMessage( + "carma-cloud", + "http://someaddress:8080/carmacloud/simulation"); + + // Test Getter + assertEquals("carma-cloud", message.getId()); + assertEquals("http://someaddress:8080/carmacloud/simulation", message.getUrl() ); + } +} diff --git a/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationReceiverTest.java b/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationReceiverTest.java new file mode 100644 index 00000000..2a0341a6 --- /dev/null +++ b/co-simulation/fed/mosaic-carma-cloud/src/test/java/org/eclipse/mosaic/fed/carmacloud/ambassador/CarmaCloudRegistrationReceiverTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2023 LEIDOS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + + package org.eclipse.mosaic.fed.carmacloud.ambassador; + + import static org.junit.Assert.assertEquals; + import static org.mockito.Mockito.mock; + import static org.mockito.Mockito.when; + import org.mockito.internal.util.reflection.FieldSetter; + + import java.io.ByteArrayInputStream; + import java.io.ByteArrayOutputStream; + import java.io.DataOutputStream; + import java.net.InetAddress; + import java.net.InetSocketAddress; + import java.net.ServerSocket; + import java.net.Socket; + import java.util.List; + + import org.junit.After; + import org.junit.Before; + import org.junit.Test; + + public class CarmaCloudRegistrationReceiverTest { + + @Test + public void testMessageReceive() throws Exception { + // Define a test message in JSON format + String json = "{\"id\":\"carma-cloud\",\"url\":\"http://someaddress:8080/carmacloud/simulation\"}"; + ByteArrayOutputStream oBytes = new ByteArrayOutputStream(); + DataOutputStream oOut = new DataOutputStream(oBytes); + oOut.writeUTF(json); + oOut.close(); // flush contents + + ServerSocket MockServer = mock(ServerSocket.class); + Socket MockSock = mock(Socket.class); + + // mock socket server, socket, and inputstream + when(MockServer.accept()).thenReturn(MockSock); + when(MockSock.getInputStream()).thenReturn(new ByteArrayInputStream(oBytes.toByteArray())); + + // Setup the registration receiver + CarmaCloudRegistrationReceiver receiver = new CarmaCloudRegistrationReceiver(); + FieldSetter.setField(receiver, receiver.getClass().getDeclaredField("srvr"), MockServer); + receiver.run(); // multi-threading not needed here + + // Verify that the message was received correctly + List msgs = receiver.getReceivedMessages(); + assertEquals(1, msgs.size()); + + CarmaCloudRegistrationMessage msg = msgs.get(0); + assertEquals("carma-cloud", msg.getId()); + assertEquals("http://someaddress:8080/carmacloud/simulation", msg.getUrl()); + } + } + diff --git a/co-simulation/pom.xml b/co-simulation/pom.xml index 8844c0c0..cb71b377 100644 --- a/co-simulation/pom.xml +++ b/co-simulation/pom.xml @@ -72,6 +72,7 @@ fed/mosaic-carla fed/mosaic-carma fed/mosaic-infrastructure + fed/mosaic-carma-cloud test/mosaic-integration-tests From a4d75088a44f88ff0ceda90448f653d6c0c26661 Mon Sep 17 00:00:00 2001 From: Cheng Yuan <84340069+chengyuan0124@users.noreply.github.com> Date: Sun, 5 May 2024 04:24:01 -0400 Subject: [PATCH 10/12] Update CarmaInstanceManager.java --- .../mosaic/fed/carma/ambassador/CarmaInstanceManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaInstanceManager.java b/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaInstanceManager.java index 59aaee9d..090f18c1 100644 --- a/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaInstanceManager.java +++ b/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaInstanceManager.java @@ -96,10 +96,11 @@ public V2xMessageTransmission onV2XMessageTx(InetAddress sourceAddr, CarmaV2xMes sender.getCarlaRoleName(), sender.getLocation()).viaChannel(AdHocChannel.CCH); // TODO: Get maximum broadcast radius from configuration file. MessageRouting routing = messageRoutingBuilder.geoBroadCast(new GeoCircle(sender.getLocation(), 300)); - log.debug("Generating V2XMessageTransmission interaction sim time: {}, sender id: {}, location: {}, payload: {}", + log.debug("Generating V2XMessageTransmission interaction sim time: {}, sender id: {}, location: {}, payload: {}, type: {}", time, sender.getCarmaVehicleId(), sender.getLocation(), + txMsg.getType(), txMsg.getPayload() ); return new V2xMessageTransmission( time, new ExternalV2xMessage(routing, From 6e1a3e24baca99233a8304b3934c3cec7d949f03 Mon Sep 17 00:00:00 2001 From: Cheng Yuan <84340069+chengyuan0124@users.noreply.github.com> Date: Sun, 5 May 2024 17:14:24 -0400 Subject: [PATCH 11/12] add log and change radius of rsu --- .../mosaic/fed/carma/ambassador/CarmaInstanceManager.java | 2 +- .../mosaic/fed/carma/ambassador/CarmaMessageAmbassador.java | 1 + .../ambassador/InfrastructureMessageAmbassador.java | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaInstanceManager.java b/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaInstanceManager.java index 090f18c1..e53d049b 100644 --- a/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaInstanceManager.java +++ b/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaInstanceManager.java @@ -96,7 +96,7 @@ public V2xMessageTransmission onV2XMessageTx(InetAddress sourceAddr, CarmaV2xMes sender.getCarlaRoleName(), sender.getLocation()).viaChannel(AdHocChannel.CCH); // TODO: Get maximum broadcast radius from configuration file. MessageRouting routing = messageRoutingBuilder.geoBroadCast(new GeoCircle(sender.getLocation(), 300)); - log.debug("Generating V2XMessageTransmission interaction sim time: {}, sender id: {}, location: {}, payload: {}, type: {}", + log.debug("Generating V2XMessageTransmission interaction sim time: {}, sender id: {}, location: {}, type: {}, payload: {}", time, sender.getCarmaVehicleId(), sender.getLocation(), diff --git a/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaMessageAmbassador.java b/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaMessageAmbassador.java index eec5c94f..5215000c 100644 --- a/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaMessageAmbassador.java +++ b/co-simulation/fed/mosaic-carma/src/main/java/org/eclipse/mosaic/fed/carma/ambassador/CarmaMessageAmbassador.java @@ -174,6 +174,7 @@ public synchronized void processTimeAdvanceGrant(long time) throws InternalFeder List> newMessages = v2xMessageReceiver.getReceivedMessages(); for (Tuple msg : newMessages) { V2xMessageTransmission msgInt = carmaInstanceManager.onV2XMessageTx(msg.getA(), msg.getB(), currentSimulationTime); + log.debug("Generated a message with ID: {}", msgInt.getMessageId()); SimulationKernel.SimulationKernel.getV2xMessageCache().putItem(currentSimulationTime, msgInt.getMessage()); rti.triggerInteraction(msgInt); } diff --git a/co-simulation/fed/mosaic-infrastructure/src/main/java/org/eclipse/mosaic/fed/infrastructure/ambassador/InfrastructureMessageAmbassador.java b/co-simulation/fed/mosaic-infrastructure/src/main/java/org/eclipse/mosaic/fed/infrastructure/ambassador/InfrastructureMessageAmbassador.java index 8cceabdb..3743748a 100644 --- a/co-simulation/fed/mosaic-infrastructure/src/main/java/org/eclipse/mosaic/fed/infrastructure/ambassador/InfrastructureMessageAmbassador.java +++ b/co-simulation/fed/mosaic-infrastructure/src/main/java/org/eclipse/mosaic/fed/infrastructure/ambassador/InfrastructureMessageAmbassador.java @@ -230,7 +230,7 @@ private void onDsrcRegistrationRequest(String infrastructureId) throws UnknownHo .ip(rsuAddress) .subnet(IpResolver.getSingleton().getNetMask()) .power(50) - .radius(300.0) + .radius(500.0) .create(); // Create an AdHocConfiguration object to associate the Ad-Hoc interface From 8ccaa7b01f14702909ae4c7b15838365016f5a78 Mon Sep 17 00:00:00 2001 From: Cheng Yuan <84340069+chengyuan0124@users.noreply.github.com> Date: Mon, 6 May 2024 14:53:29 -0400 Subject: [PATCH 12/12] reverse radius --- .../ambassador/InfrastructureMessageAmbassador.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/co-simulation/fed/mosaic-infrastructure/src/main/java/org/eclipse/mosaic/fed/infrastructure/ambassador/InfrastructureMessageAmbassador.java b/co-simulation/fed/mosaic-infrastructure/src/main/java/org/eclipse/mosaic/fed/infrastructure/ambassador/InfrastructureMessageAmbassador.java index 3743748a..8cceabdb 100644 --- a/co-simulation/fed/mosaic-infrastructure/src/main/java/org/eclipse/mosaic/fed/infrastructure/ambassador/InfrastructureMessageAmbassador.java +++ b/co-simulation/fed/mosaic-infrastructure/src/main/java/org/eclipse/mosaic/fed/infrastructure/ambassador/InfrastructureMessageAmbassador.java @@ -230,7 +230,7 @@ private void onDsrcRegistrationRequest(String infrastructureId) throws UnknownHo .ip(rsuAddress) .subnet(IpResolver.getSingleton().getNetMask()) .power(50) - .radius(500.0) + .radius(300.0) .create(); // Create an AdHocConfiguration object to associate the Ad-Hoc interface