Skip to content

Commit

Permalink
Merge branch 'develop' into fix-MAP
Browse files Browse the repository at this point in the history
  • Loading branch information
jwillmartin committed Jun 27, 2024
2 parents 7bbf823 + cea762d commit bc83c6c
Show file tree
Hide file tree
Showing 12 changed files with 253 additions and 61 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{
// Docker Compose syntax from https://github.com/devcontainers/templates/blob/main/src/docker-existing-docker-compose/.devcontainer/devcontainer.json
// and https://github.com/microsoft/vscode-dev-containers/blob/main/container-templates/docker-compose/.devcontainer/devcontainer.json
"name": "V2XHUB Docker Compose Dev",
"name": "V2X Hub Docker Compose Dev",

// Update the 'dockerComposeFile' list if you have more compose files or use different names.
"dockerComposeFile": "docker-compose-vscode.yml",
Expand Down
6 changes: 2 additions & 4 deletions .devcontainer/docker-compose-vscode.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3.3'

services:
v2xhub:
build:
Expand Down Expand Up @@ -31,7 +29,7 @@ services:
- mysql_password

db:
image: mysql:5.7
image: mysql:8.0
container_name: mysql
restart: always
environment:
Expand All @@ -44,7 +42,7 @@ services:
- mysql_password
- mysql_root_password
volumes:
- ../configuration/amd64/mysql/localhost.sql:/docker-entrypoint-initdb.d/localhost.sql
- ../configuration/mysql/localhost.sql:/docker-entrypoint-initdb.d/localhost.sql
# include creation of a user (user/user) to be able to log in
- ./mysql_add_dev_user.sql:/docker-entrypoint-initdb.d/mysql_add_dev_user.sql
- mysql-datavolume:/var/lib/mysql
Expand Down
26 changes: 15 additions & 11 deletions configuration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,18 @@ Enter the login credentials you created in step 5b and login.
Installation complete!

### Simulation Setup
To support execution in a simulated environment, V2X-Hub is in the process of integrating with CDASim, a Co-Simulation tool built as an extension of Eclipse Mosiac. This extension will incorporate integration with several other platforms including CARMA-Platform and CARLA. The setup for this simply requires setting environment variables inside the V2X-Hub docker container.
* **SIMULATION_MODE** – Environment variable for enabling simulation components for V2X-Hub. If set to "true" or "TRUE" simulation components will be enable. Otherwise, simulation components will not be enabled.
* **KAFKA_BROKER_ADDRESS** – Environment variable for storing Kafka broker connection string (including port).
* **TIME_SYNC_TOPIC** – Environment variable for storing Kafka time sync topic.
* **SIMULATION_IP** – Environment variable for storing IP address of CDASim application.
* **SIMULATION_REGISTRATION_PORT** – Environment variable for storing port on CDASim that handles registration attempts.
* **TIME_SYNC_PORT** – Environment varaible for storing port for receiving time sync messages from CDASim.
* **V2X_PORT** – Environment variable for storing port for receiving v2x messages from CDASim
* **SIM_V2X_PORT** – Environment variable for storing port for sending v2x messages to CDASim
* **LOCAL_IP** – Environment variable for storing local IP of V2X Hub.
* **INFRASTRUCTURE_ID** – Environment variable for storing infrastructure id of V2X Hub..

To support execution in a simulated environment, V2X-Hub is in the process of integrating with CDASim, a Co-Simulation tool built as an extension of Eclipse Mosiac. This extension will incorporate integration with several other platforms including CARMA-Platform and CARLA. The setup for this simply requires setting environment variables for the V2X-Hub docker compose deployment. These can be set via the `initialization.sh` script and can be manually edited after.

* **V2XHUB_VERSION** – Version of V2X-Hub to deloy ( Docker Tag/ GitHub Tag )
* **SIMULATION_MODE** – Environment variable for enabling simulation components for V2X-Hub. If set to "true" or "TRUE" simulation components will be enable. Otherwise, simulation components will not be enabled.
* **KAFKA_BROKER_ADDRESS** – Environment variable for storing Kafka broker connection string (including port).
* **TIME_SYNC_TOPIC** – Environment variable for storing Kafka time sync topic.
* **SIMULATION_IP** – Environment variable for storing IP address of CDASim application.
* **SIMULATION_REGISTRATION_PORT** – Environment variable for storing port on CDASim that handles registration attempts.
* **TIME_SYNC_PORT** – Environment varaible for storing port for receiving time sync messages from CDASim.
* **V2X_PORT** – Environment variable for storing port for receiving v2x messages from CDASim
* **SIM_V2X_PORT** – Environment variable for storing port for sending v2x messages to CDASim
* **V2XHUB_IP** – Environment variable for storing IP address of V2X Hub.
* **INFRASTRUCTURE_ID** – Environment variable for storing infrastructure id of V2X Hub.
* **SENSOR_JSON_FILE_PATH** – Environment variable for storing path to sensor configuration file. This is an optional simulation environment variable that allows for setting up simulated sensor for a V2X-Hub instance. Example file can be found in the **CDASimAdapterPlugin** tests [here](../src/v2i-hub/CDASimAdapter/test/sensors.json).
2 changes: 0 additions & 2 deletions configuration/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3.7'

services:
db:
image: mysql:8.0
Expand Down
106 changes: 99 additions & 7 deletions configuration/initialization.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,88 @@
#!/bin/bash

# Default values for the variables
PORT_DRAYAGE_ENABLED_DEFAULT="FALSE"
INFRASTRUCTURE_ID_DEFAULT="rsu_1234"
INFRASTRUCTURE_NAME_DEFAULT="East Intersection"
V2XHUB_IP_DEFAULT="127.0.0.1"
SIMULATION_MODE_DEFAULT="FALSE"
SIMULATION_IP_DEFAULT="127.0.0.1"
SENSOR_JSON_FILE_PATH_DEFAULT="/var/www/plugins/MAP/sensors.json"

echo "Setting up the environment..."

# Repository URL
repo_url_latest="https://api.github.com/repos/usdot-fhwa-OPS/V2X-Hub/releases/latest"

# Getting the latest release information using curl
release_info=$(curl -sSL $repo_url_latest)

# Parsing the JSON response to get the tag_name (version) of the latest release
latest_version=$(echo "$release_info" | grep -o '"tag_name": *"[^"]*"' | cut -d '"' -f 4)

# Fetching all tags from Git repository
tags=$(git ls-remote --tags https://github.com/usdot-fhwa-OPS/V2X-Hub.git | awk -F/ '{print $3}' | sort -V)

# Displaying all available versions
echo "Available versions:"
echo "$tags"

# select a version or accept the latest version as default
read -r -p "Enter V2X-Hub Version (choose from the above, or press Enter to use latest version $latest_version): " chosen_version
V2XHUB_VERSION=${chosen_version:-$latest_version}

# Enable Port Drayage functionality
read -r -p "Enable Port Drayage functionality (TRUE/FALSE, or press Enter to use default as $PORT_DRAYAGE_ENABLED_DEFAULT): " PORT_DRAYAGE_ENABLED
PORT_DRAYAGE_ENABLED=${PORT_DRAYAGE_ENABLED:-$PORT_DRAYAGE_ENABLED_DEFAULT}

# Infrastructure id
read -r -p "Enter Infrastructure id (or press Enter to use default as $INFRASTRUCTURE_ID_DEFAULT): " INFRASTRUCTURE_ID
INFRASTRUCTURE_ID=${INFRASTRUCTURE_ID:-$INFRASTRUCTURE_ID_DEFAULT}

# Infrastructure name
read -r -p "Enter Infrastructure name (or press Enter to use default as $INFRASTRUCTURE_NAME_DEFAULT): " INFRASTRUCTURE_NAME
INFRASTRUCTURE_NAME=${INFRASTRUCTURE_NAME:-$INFRASTRUCTURE_NAME_DEFAULT}

# V2XHub IP
read -r -p "Enter V2XHub IP (or press Enter to use default as $V2XHUB_IP_DEFAULT): " V2XHUB_IP
V2XHUB_IP=${V2XHUB_IP:-$V2XHUB_IP_DEFAULT}

# Simulation Mode
read -r -p "Simulation Mode (TRUE/FALSE, or press Enter to use default as $SIMULATION_MODE_DEFAULT): " SIMULATION_MODE
SIMULATION_MODE=${SIMULATION_MODE:-$SIMULATION_MODE_DEFAULT}

# In Simulation Mode
if [[ $SIMULATION_MODE == "TRUE" ]]; then
# Simulation IP
read -r -p "Enter Simulation IP (or press Enter to use default is $SIMULATION_IP_DEFAULT): " SIMULATION_IP
SIMULATION_IP=${SIMULATION_IP:-$SIMULATION_IP_DEFAULT}

# Sensor Configuration File Path
read -r -p "Enter Sensor Configuration File Path (or press Enter to use default as $SENSOR_JSON_FILE_PATH_DEFAULT): " SENSOR_JSON_FILE_PATH
SENSOR_JSON_FILE_PATH=${SENSOR_JSON_FILE_PATH:-$SENSOR_JSON_FILE_PATH_DEFAULT}
fi

echo "WARNING: This will overwrite the existing .env file if it exists."
read -r -p "Are you sure you want to continue? (Y/N): " overwrite_confirm
if [[ "$overwrite_confirm" =~ [yY](es)* ]]; then
# Write to .env file
cat <<EOF > .env
V2XHUB_VERSION=$V2XHUB_VERSION
INFRASTRUCTURE_ID=$INFRASTRUCTURE_ID
INFRASTRUCTURE_NAME=$INFRASTRUCTURE_NAME
V2XHUB_IP=$V2XHUB_IP
SIMULATION_MODE=$SIMULATION_MODE
EOF

# Adding Simulation IP and Sensor Path if Simulation Mode is TRUE
if [[ $SIMULATION_MODE == "TRUE" ]]; then
echo "SIMULATION_IP=$SIMULATION_IP" >> .env
echo "SENSOR_JSON_FILE_PATH=$SENSOR_JSON_FILE_PATH" >> .env
fi
else
echo "Aborting. No changes were made to the .env file."
fi

directory=$(pwd)
mysqlDir="$directory/mysql"

Expand All @@ -9,15 +93,15 @@ sudo apt update -y && sudo apt upgrade -y
sudo apt-get install chromium-browser -y

# Make passwords for mysql
mkdir -p secrets && cd secrets
mkdir -p secrets && cd secrets || return # SC2164 - Use return in case cd fails

# Creates password files where user inputs password
FILE1=mysql_root_password.txt
FILE2=mysql_password.txt
if test -f "$FILE1"; then
echo "$FILE1 exists."
else
read -p "enter password for the mysql_root_password: " sql_root_pass
read -r -p "enter password for the mysql_root_password: " sql_root_pass # SC2162 - read without -r will mangle backslashes
echo "$sql_root_pass" > sql_root_pass.txt
# Remove endline characters from password files
tr -d '\n' <sql_root_pass.txt> mysql_root_password.txt && rm sql_root_pass.txt
Expand All @@ -26,15 +110,14 @@ fi
if test -f "$FILE2"; then
echo "$FILE2 exists."
else
read -p "enter password for mysql_password: " sql_pass
read -r -p "enter password for mysql_password: " sql_pass
echo "$sql_pass" > sql_pass.txt
# Remove endline characters from password files
tr -d '\n' <sql_pass.txt> mysql_password.txt && rm sql_pass.txt
fi
# TODO VH-1303 Allow for version and configuration selection in initialization script

# AMD64 initialization
cd $directory
cd "$directory" || return # return in case cd fails
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
# Add Docker's official GPG key:
sudo apt-get update
Expand All @@ -50,10 +133,19 @@ echo \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo docker compose up -d

# Check if Port Drayage functionality is enabled
if [[ $PORT_DRAYAGE_ENABLED == "TRUE" ]]; then
sudo docker compose up -d
elif [[ $PORT_DRAYAGE_ENABLED == "FALSE" ]]; then
sudo docker compose up php -d
else
echo "Invalid value for PORT_DRAYAGE_ENABLED. Please provide either TRUE or FALSE."
exit 1
fi

# Create V2X Hub user
cd $mysqlDir
cd "$mysqlDir" || return # return in case cd fails
./add_v2xhub_user.bash

chromium-browser "http://127.0.0.1" > /dev/null 2>&1 &
Expand Down
12 changes: 7 additions & 5 deletions src/tmx/TmxUtils/src/simulation/SimulationEnvUtils.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <simulation/SimulationEnvUtils.h>
#include "simulation/SimulationEnvUtils.h"

namespace tmx::utils::sim{
bool is_simulation_mode() {
Expand All @@ -13,15 +13,17 @@ namespace tmx::utils::sim{

}

std::string get_sim_config(const char *config_name) {
std::string get_sim_config(const char *config_name, bool required) {
if (is_simulation_mode() && config_name) {
try {
if ( std::getenv(config_name) != nullptr) {
std::string config = std::getenv(config_name);
return config;
}
catch(const std::logic_error &e) {
else {
std::string config_name_str = config_name;
throw TmxException("Simulation Config " + config_name_str + " not set!");
if ( required ) {
throw TmxException("Required simulation config " + config_name_str + " not set!");
}
}
} else {
throw TmxException("V2X-Hub not in sumulation mode or config param name is null pointer!");
Expand Down
10 changes: 8 additions & 2 deletions src/tmx/TmxUtils/src/simulation/SimulationEnvUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,13 @@ namespace tmx::utils::sim{
* @return true if SIMULATION_MODE is "true" or "TRUE" and false otherwise.
*/
bool is_simulation_mode();

std::string get_sim_config(const char *config_name);
/**
* @brief Get simulation configuration.
* @param config_name Name of configuration parameter
* @param required bool flag whether configuration paramter is required (Default: true)
* @throws tmx::TmxException if required configuration is unset or system not in simulation mode.
* @return string value of sim configuration
*/
std::string get_sim_config(const char *config_name, bool required = true);

}
71 changes: 71 additions & 0 deletions src/tmx/TmxUtils/test/TestSimulationEnvUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <simulation/SimulationEnvUtils.h>
#include <gtest/gtest.h>
#include <stdlib.h>


TEST(testSimulationEnvUtils, is_simulation_mode_unset)
{
// Unset any environment set SIMULATION_MODE
unsetenv(tmx::utils::sim::SIMULATION_MODE);
EXPECT_FALSE(tmx::utils::sim::is_simulation_mode());
}

TEST(testSimulationEnvUtils, is_simulation_mode_true) {
setenv(tmx::utils::sim::SIMULATION_MODE, "true", 1);
EXPECT_TRUE(tmx::utils::sim::is_simulation_mode());
setenv(tmx::utils::sim::SIMULATION_MODE, "TRUE", 1);
EXPECT_TRUE(tmx::utils::sim::is_simulation_mode());
}

TEST(testSimulationEnvUtils, is_simulation_mode_false) {
setenv(tmx::utils::sim::SIMULATION_MODE, "false", 1);
EXPECT_FALSE(tmx::utils::sim::is_simulation_mode());
setenv(tmx::utils::sim::SIMULATION_MODE, "FALSE", 1);
EXPECT_FALSE(tmx::utils::sim::is_simulation_mode());
}

TEST(testSimulationEnvUtils, get_sim_config_non_simulation_mode) {
// Precondition for test (ASSERT)
ASSERT_FALSE(tmx::utils::sim::is_simulation_mode());
EXPECT_THROW(tmx::utils::sim::get_sim_config(tmx::utils::sim::SIMULATION_IP), tmx::TmxException );

}

TEST(testSimulationEnvUtils, get_sim_config_unset) {
// Precondition for test (ASSERT)
setenv(tmx::utils::sim::SIMULATION_MODE, "true", 1);
unsetenv(tmx::utils::sim::SIMULATION_IP);
ASSERT_TRUE(tmx::utils::sim::is_simulation_mode());

EXPECT_THROW(tmx::utils::sim::get_sim_config(tmx::utils::sim::SIMULATION_IP), tmx::TmxException );
}

TEST(testSimulationEnvUtils, get_sim_config_set) {
// Precondition for test (ASSERT)
std::string simulation_ip = "127.0.0.1";
setenv(tmx::utils::sim::SIMULATION_MODE, "true", 1);
setenv(tmx::utils::sim::SIMULATION_IP, simulation_ip.c_str(), 1);
ASSERT_TRUE(tmx::utils::sim::is_simulation_mode());

EXPECT_EQ(tmx::utils::sim::get_sim_config(tmx::utils::sim::SIMULATION_IP), simulation_ip );
}

TEST(testSimulationEnvUtils, get_sim_config_optional_set) {
// Precondition for test (ASSERT)
std::string simulation_ip = "127.0.0.1";
setenv(tmx::utils::sim::SIMULATION_MODE, "true", 1);
setenv(tmx::utils::sim::SIMULATION_IP, simulation_ip.c_str(), 1);
ASSERT_TRUE(tmx::utils::sim::is_simulation_mode());

EXPECT_EQ(tmx::utils::sim::get_sim_config(tmx::utils::sim::SIMULATION_IP,false), simulation_ip );
}

TEST(testSimulationEnvUtils, get_sim_config_optional_unset) {
// Precondition for test (ASSERT)
std::string simulation_ip = "127.0.0.1";
setenv(tmx::utils::sim::SIMULATION_MODE, "true", 1);
unsetenv(tmx::utils::sim::SIMULATION_IP);
ASSERT_TRUE(tmx::utils::sim::is_simulation_mode());

EXPECT_TRUE(tmx::utils::sim::get_sim_config(tmx::utils::sim::SIMULATION_IP,false).empty());
}
5 changes: 4 additions & 1 deletion src/v2i-hub/CDASimAdapter/src/CDASimAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,10 @@ namespace CDASimAdapter{
uint v2x_port = std::stoul(sim::get_sim_config(sim::V2X_PORT));
uint sim_v2x_port = std::stoul(sim::get_sim_config(sim::SIM_V2X_PORT));
std::string infrastructure_id = sim::get_sim_config(sim::INFRASTRUCTURE_ID);
std::string sensor_json_file_path = sim::get_sim_config(sim::SENSOR_JSON_FILE_PATH);
// Sensor JSON file path is an optional environment variable that allows configuration of
// simulated sensor if provided.
std::string sensor_json_file_path = "";
sensor_json_file_path = sim::get_sim_config(sim::SENSOR_JSON_FILE_PATH, false);

PLOG(logINFO) << "CDASim connecting " << simulation_ip <<
"\nUsing Registration Port : " << std::to_string( simulation_registration_port) <<
Expand Down
22 changes: 13 additions & 9 deletions src/v2i-hub/CDASimAdapter/src/CDASimConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ using namespace tmx::utils;
namespace CDASimAdapter{
CDASimConnection::CDASimConnection(const std::string &simulation_ip, const std::string &infrastructure_id, const uint simulation_registration_port, const uint sim_v2x_port,
const std::string &local_ip, const uint time_sync_port,const uint simulated_interaction_port, const uint v2x_port,
const Point &location, const std::string &sensor_json_file_path) :
const Point &location, const std::string &sensor_json_file_path ) :
_simulation_ip(simulation_ip), _infrastructure_id(infrastructure_id), _simulation_registration_port(simulation_registration_port),
_simulation_v2x_port(sim_v2x_port), _local_ip(local_ip), _time_sync_port(time_sync_port), _simulated_interaction_port(simulated_interaction_port),_v2x_port(v2x_port),
_location(location) ,_sensor_json_file_path(sensor_json_file_path) {
Expand Down Expand Up @@ -52,12 +52,18 @@ namespace CDASimAdapter{

//Read local sensor file and populate the sensors JSON
//Sample sensors.json: https://raw.githubusercontent.com/usdot-fhwa-OPS/V2X-Hub/develop/src/v2i-hub/CDASimAdapter/test/sensors.json
auto sensors_json_v = read_json_file(_sensor_json_file_path);
if(sensors_json_v.empty())
{
PLOG(logWARNING) << "Sensors JSON is empty!" << std::endl;
}
message["sensors"] = sensors_json_v;
// Sensor configuration is an optional part of registration message.
if ( !_sensor_json_file_path.empty() ) {
auto sensors_json_v = read_json_file(_sensor_json_file_path);
if(sensors_json_v.empty())
{
PLOG(logWARNING) << "Sensors JSON is empty!" << std::endl;
}
message["sensors"] = sensors_json_v;
}
else {
PLOG(logWARNING) << "No sensors where configured for this V2X-Hub instance.";
}
Json::StyledWriter writer;
message_str = writer.write(message);
return message_str;
Expand Down Expand Up @@ -97,10 +103,8 @@ namespace CDASimAdapter{
// Initialize V2X-Hub UDP Server and Client to foward V2X messages between CARMA Simulation Infrastructure
// Adapter and V2X-Hub.
// TODO: Using TMX Utils get immediate forward port
// TODO: Replace 0 with immediate forward port
immediate_forward_listener = std::make_shared<UdpServer>( local_ip, 5678);
// TODO: Using TMX Utils get message receiver port
// TODO: Replace 0 with message receiver port
message_receiver_publisher = std::make_shared<UdpClient>( local_ip, 8765);
// Initialize UDP Server for listening for incoming CARMA-Simulation time synchronization.
PLOG(logDEBUG) << "Creating UDPServer for Time Sync Messages: " << local_ip << ":" << std::to_string(time_sync_port) << "\n"
Expand Down
Loading

0 comments on commit bc83c6c

Please sign in to comment.