Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions demo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@

## Choosing a Core Network

RoboSim5G supports **three 5G Core Network implementations**: OAI, free5GC, and Open5GS.
RoboSim5G supports **three 5G Core Network implementations**: OAI, free5GC, and Open5GS. It also supports connecting to an **external** core network that is already running elsewhere.

A single `launch.sh` and `kill.sh` script is provided. You select the core network using the `CORE_NETWORK` environment variable (defaults to `oai`):

```bash
CORE_NETWORK=oai ./launch.sh # OpenAirInterface (default)
CORE_NETWORK=free5gc ./launch.sh # free5GC
CORE_NETWORK=open5gs ./launch.sh # Open5GS
CORE_NETWORK=external ./launch.sh # External / pre-existing core network
```

The core network containers are launched from the `core_network_setup/` folder at the root of the repository. Each CN has its own subfolder (`core_network_setup/oai/`, `core_network_setup/free5gc/`, `core_network_setup/open5gs/`) containing the docker-compose file and related configuration.
Expand All @@ -38,9 +39,37 @@ Install the prerequisite:
sudo apt install mongodb-mongosh
```

### External Core Network

When `CORE_NETWORK=external`, the script **does not start any local core network containers**. Instead it reads the routing parameters from `external.env` (in the `demo/` directory):

| Variable | Description |
|---|---|
| `UE_ROUTE_SUBNET` | Subnet routed through the UPF (added as a host route via `phine-net`) |
| `UE_ROUTE_GW` | IP of the UPF interface used as the PDU session gateway |
| `UE_CARRIER_FREQ` | Downlink carrier frequency in Hz — must match the external gNB |

Edit `external.env` to match your external core network before launching:

```bash
# Edit the values in external.env, then:
CORE_NETWORK=external ./launch.sh
```

You can also point to a custom env file:

```bash
EXTERNAL_ENV_FILE=/path/to/my-network.env CORE_NETWORK=external ./launch.sh
```

> **⚠️ Important:** When using an external core network, you must ensure that:
> - The UE subscriber (IMSI, keys) is already registered in the external core network.
> - The `phine-net` Docker network (`192.168.70.0/24`) is reachable from the external AMF and UPF.
> - The values in `world_only_external.sdf` (located in `gazebo_launch/src/ign_turtlebot/worlds/`) match your external core network. Edit that file directly to adjust gNB/UE plugin parameters (IPs, IMSI, keys, PLMN, etc.).

### Automatic World Selection

The Gazebo world file is **automatically selected** based on the `CORE_NETWORK` environment variable. The launch file (`gazebo_launch/src/ign_turtlebot/launch/gazebo_launch.launch.py`) reads the `CORE_NETWORK` variable and loads the corresponding world file (`world_only_oai.sdf`, `world_only_free5gc.sdf`, or `world_only_open5gs.sdf`). No manual editing of the launch file or rebuilding is required when switching between core networks.
The Gazebo world file is **automatically selected** based on the `CORE_NETWORK` environment variable. The launch file (`gazebo_launch/src/ign_turtlebot/launch/gazebo_launch.launch.py`) reads the `CORE_NETWORK` variable and loads the corresponding world file (`world_only_oai.sdf`, `world_only_free5gc.sdf`, `world_only_open5gs.sdf`, or `world_only_external.sdf`). No manual editing of the launch file or rebuilding is required when switching between core networks.

### RAN Docker Compose Structure

Expand Down Expand Up @@ -201,4 +230,4 @@ If you change the container name in the gNB and UE declarations, you should matc
Located in `core_network_setup/oai/`, this script ensures that the OAI core network is fully operational before proceeding with the simulation. It waits for the MySQL database container to become healthy and checks that all critical OAI services (`oai-nrf`, `oai-amf`, `oai-smf`, `oai-upf`) are running. The script is called automatically during the simulation launch process to avoid race conditions and ensure a reliable startup sequence.

### `ros_gz_net` bridge creation
The `launch.sh` script creates a custom Docker bridge network (`ros_gz_net`) with a specified subnet. It is used to enable communication between simulation containers (such as Gazebo, robot-UE, and network components) on a dedicated network, ensuring proper connectivity and isolation for the simulation environment. This is executed as part of the launch process and typically does not require manual intervention.
The `launch.sh` script creates a custom Docker bridge network (`ros_gz_net`) with a specified subnet. It is used to enable communication between simulation containers (such as Gazebo, robot-UE, and network components) on a dedicated network, ensuring proper connectivity and isolation for the simulation environment. This is executed as part of the launch process and typically does not require manual intervention.
17 changes: 17 additions & 0 deletions demo/external.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# External Core Network Configuration
# Used when CORE_NETWORK=external to connect to an already-running 5G core network.
# Adjust the values below to match your external core network.
# SDF-level plugin variables (credentials, topology) are in external.sdf.env.

# Subnet routed through the UPF (the UE container adds a route to this subnet
# through the UPF gateway so that robot traffic is steered over 5G).
UE_ROUTE_SUBNET="10.0.0.0/24"

# IP address of the UPF container / interface that acts as the PDU session
# gateway. Traffic from the UE toward UE_ROUTE_SUBNET is routed via this IP.
UE_ROUTE_GW="192.168.70.135"

# Downlink carrier frequency in Hz used by both the gNB and the UE RF
# simulator. Must match the absoluteFrequencyPointA / carrier frequency
# configured in the external gNB.
UE_CARRIER_FREQ="3319680000"
126 changes: 126 additions & 0 deletions demo/gazebo_launch/src/ign_turtlebot/worlds/world_only_external.sdf
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?xml version="1.0" ?>
<sdf version="1.6">
<world name="empty">
<physics name="1ms" type="ignored">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
</physics>
<plugin
filename="ignition-gazebo-physics-system"
name="ignition::gazebo::systems::Physics">
</plugin>
<plugin
filename="ignition-gazebo-user-commands-system"
name="ignition::gazebo::systems::UserCommands">
</plugin>
<plugin
filename="ignition-gazebo-scene-broadcaster-system"
name="ignition::gazebo::systems::SceneBroadcaster">
</plugin>
<plugin
filename="ignition-gazebo-contact-system"
name="ignition::gazebo::systems::Contact">
</plugin>
<plugin
filename="libignition-gazebo-sensors-system.so"
name="ignition::gazebo::systems::Sensors">
<render_engine>ogre2</render_engine>
</plugin>
<plugin filename="libignition-gazebo-imu-system.so"
name="ignition::gazebo::systems::Imu">
</plugin>

<light name="Warehouse_CeilingLight_003" type="point">
<pose>0 0 8.5 0 0 0</pose>
<diffuse>0.5 0.5 0.5 1</diffuse>
<specular>0.2 0.2 0.2 1</specular>
<attenuation>
<range>80</range>
<constant>0.3</constant>
<linear>0.01</linear>
<quadratic>0.001</quadratic>
</attenuation>
<cast_shadows>1</cast_shadows>
<direction>0.1 0.1 -1</direction>
</light>

<gui fullscreen='0'>
<camera name='user_camera'>
<pose frame=''>-4.70385 10.895 16.2659 -0 0.921795 -1.12701</pose>
<view_controller>orbit</view_controller>
<projection_type>perspective</projection_type>
</camera>
</gui>


<plugin name="phine_plugins::UE_plugin" filename="UE_plugin">
<cn_type>free5gc</cn_type>
<robot_container_name>ue_turtlebot</robot_container_name>
<robot_id>1</robot_id>
<ip_robotUE>192.168.70.150</ip_robotUE>
<net_name>phine-net</net_name>
<ip_gnb>192.168.70.160</ip_gnb>
<debug>true</debug>
<subnet_5G>10.0.0.0/24</subnet_5G>
<imsi>208930000000001</imsi>
<key>8baf473f2f8fd09487cccbd7097c6862</key>
<opc>8e27b6af0e692e750f32667a3b14605d</opc>
<dnn>internet</dnn>
<nssai_sst>1</nssai_sst>
<nssai_sd>66051</nssai_sd>
<robot_project_path>${PROJECT_PATH}/nav_stack</robot_project_path>
<robot_project_name>nav_stack</robot_project_name>
<execute_robot_launch_file>true</execute_robot_launch_file>
<robot_package_name>ign_turtlebot</robot_package_name>
<ros_gz_bridge_name>ros_gz_bridge.launch.py</ros_gz_bridge_name>
<robot_launch_file_name>nav_stack.launch.py</robot_launch_file_name>
<ros_discovery_server>192.168.70.159:11811</ros_discovery_server>
</plugin>

<model name="ground_plane">
<static>true</static>
<link name="link">
<collision name="collision">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
</collision>
<visual name="visual">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>100 100</size>
</plane>
</geometry>
<material>
<ambient>0.8 0.8 0.8 1</ambient>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.8 0.8 0.8 1</specular>
</material>
</visual>
</link>
</model>

<include>
<uri>model://phine_gNB</uri>
<name>gNB1</name>
<pose>-6.8 1 7 0 0 0</pose>
<plugin name="phine_plugins::gNB_plugin" filename="gNB_plugin">
<cn_type>free5gc</cn_type>
<link_name>phine_cell</link_name>
<net_name>phine-net</net_name>
<n3_net_name>demo-oai-n3-net</n3_net_name>
<IP_GNB>192.168.70.160</IP_GNB>
<IP_GNB_N3>192.168.71.160</IP_GNB_N3>
<IP_AMF>192.168.70.132</IP_AMF>
<debug>false</debug>
<mobile_country_code>208</mobile_country_code>
<mobile_network_code>93</mobile_network_code>
</plugin>
</include>
</world>
</sdf>

71 changes: 52 additions & 19 deletions demo/launch.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#!/bin/bash
# Unified launch script for RoboSim5G native demo
# Usage: CORE_NETWORK=oai|free5gc|open5gs ./launch.sh
# Usage: CORE_NETWORK=oai|free5gc|open5gs|external ./launch.sh
#
# When CORE_NETWORK=external the script skips launching any local core network
# containers. Configuration is read from external.env (in this directory) or
# from the file pointed to by the EXTERNAL_ENV_FILE environment variable.

set -e

Expand All @@ -10,8 +14,8 @@ DEMO_DIR=$(cd "$(dirname "$0")" && pwd)
CN_DIR="$REPO_ROOT/core_network_setup/$CORE_NETWORK"

# Validate CORE_NETWORK
if [[ ! "$CORE_NETWORK" =~ ^(oai|free5gc|open5gs)$ ]]; then
echo "ERROR: CORE_NETWORK must be one of: oai, free5gc, open5gs (got: $CORE_NETWORK)"
if [[ ! "$CORE_NETWORK" =~ ^(oai|free5gc|open5gs|external)$ ]]; then
echo "ERROR: CORE_NETWORK must be one of: oai, free5gc, open5gs, external (got: $CORE_NETWORK)"
exit 1
fi

Expand Down Expand Up @@ -40,6 +44,33 @@ case $CORE_NETWORK in
HOST_ROUTE_SUBNET="10.0.0.0/24"
HOST_ROUTE_GW="192.168.70.134"
;;
external)
EXTERNAL_ENV_FILE="${EXTERNAL_ENV_FILE:-$DEMO_DIR/external.env}"
if [ ! -f "$EXTERNAL_ENV_FILE" ]; then
echo "ERROR: External env file not found: $EXTERNAL_ENV_FILE"
echo " Copy $DEMO_DIR/external.env and adjust the values for your core network."
exit 1
fi
echo "Loading external core network config from: $EXTERNAL_ENV_FILE"
set -a
# shellcheck source=/dev/null
source "$EXTERNAL_ENV_FILE"
set +a
# Validate routing variables
missing=()
[ -z "$UE_ROUTE_SUBNET" ] && missing+=("UE_ROUTE_SUBNET")
[ -z "$UE_ROUTE_GW" ] && missing+=("UE_ROUTE_GW")
[ -z "$UE_CARRIER_FREQ" ] && missing+=("UE_CARRIER_FREQ")
if [ ${#missing[@]} -gt 0 ]; then
echo "ERROR: The following required variables are not set in $EXTERNAL_ENV_FILE:"
printf ' %s\n' "${missing[@]}"
exit 1
fi
HOST_ROUTE_SUBNET="$UE_ROUTE_SUBNET"
HOST_ROUTE_GW="$UE_ROUTE_GW"
echo "WARNING: Using external core network — make sure your UE subscriber is"
echo " already registered in the external core network before continuing."
;;
esac

# Set common environment variables
Expand All @@ -54,24 +85,26 @@ source "$DEMO_DIR/gazebo_launch/install/setup.bash"
export FASTRTPS_DEFAULT_PROFILES_FILE="$DEMO_DIR/dds.xml"
export NAME_ROBOT_1=${NAME_ROBOT_1:-"ue_turtlebot"}

# 1. Start the core network
echo "Starting $CORE_NETWORK core network..."
cd "$CN_DIR"
docker compose up -d
# 1. Start the core network (skipped for external)
if [ "$CORE_NETWORK" != "external" ]; then
echo "Starting $CORE_NETWORK core network..."
cd "$CN_DIR"
docker compose up -d

# 2. Wait for core network readiness
if [ "$CORE_NETWORK" = "oai" ]; then
./wait_for_core_network.sh
else
sleep 10
fi
# 2. Wait for core network readiness
if [ "$CORE_NETWORK" = "oai" ]; then
./wait_for_core_network.sh
else
sleep 10
fi

# 3. Add UE subscriber (open5gs only, after DB is ready)
if [ "$CORE_NETWORK" = "open5gs" ]; then
echo "Adding UE subscriber to Open5GS database..."
cd "$CN_DIR/scripts"
./add_ue_subscriber.sh
cd "$CN_DIR"
# 3. Add UE subscriber (open5gs only, after DB is ready)
if [ "$CORE_NETWORK" = "open5gs" ]; then
echo "Adding UE subscriber to Open5GS database..."
cd "$CN_DIR/scripts"
./add_ue_subscriber.sh
cd "$CN_DIR"
fi
fi

# 3. Add host route (ignore if it already exists)
Expand Down
42 changes: 31 additions & 11 deletions demo_containerized/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@

## Choosing a Core Network

RoboSim5G supports **three 5G Core Network implementations**: OAI, free5GC, and Open5GS.
RoboSim5G supports **three 5G Core Network implementations**: OAI, free5GC, and Open5GS. It also supports connecting to an **external** core network that is already running elsewhere.

A single `launch.sh` and `kill.sh` script is provided. You select the core network using the `CORE_NETWORK` environment variable (defaults to `oai`):

```bash
CORE_NETWORK=oai ./launch.sh # OpenAirInterface (default)
CORE_NETWORK=free5gc ./launch.sh # free5GC
CORE_NETWORK=open5gs ./launch.sh # Open5GS
CORE_NETWORK=external ./launch.sh # External / pre-existing core network
```

The core network containers are launched from the `core_network_setup/` folder at the root of the repository. Each CN has its own subfolder (`core_network_setup/oai/`, `core_network_setup/free5gc/`, `core_network_setup/open5gs/`) containing the docker-compose file and related configuration.
Expand All @@ -36,9 +37,37 @@ Install the prerequisite:
sudo apt install mongodb-mongosh
```

### External Core Network

When `CORE_NETWORK=external`, the script **does not start any local core network containers**. Instead it reads the routing parameters from `external.env` (in the `demo_containerized/` directory):

| Variable | Description |
|---|---|
| `UE_ROUTE_SUBNET` | Subnet routed through the UPF (added as a host route inside the UE container) |
| `UE_ROUTE_GW` | IP of the UPF interface used as the PDU session gateway |
| `UE_CARRIER_FREQ` | Downlink carrier frequency in Hz — must match the external gNB |

Edit `external.env` to match your external core network before launching:

```bash
# Edit the values in external.env, then:
CORE_NETWORK=external ./launch.sh
```

You can also point to a custom env file:

```bash
EXTERNAL_ENV_FILE=/path/to/my-network.env CORE_NETWORK=external ./launch.sh
```

> **⚠️ Important:** When using an external core network, you must ensure that:
> - The UE subscriber (IMSI, keys) is already registered in the external core network.
> - The `phine-net` Docker network (`192.168.70.0/24`) is reachable from the external AMF and UPF.
> - The values in `world_only_external.sdf` (located in `images/simulation/gazebo_launch/src/ign_turtlebot/worlds/`) match your external core network. Edit that file directly to adjust gNB/UE plugin parameters (IPs, IMSI, keys, PLMN, etc.), then rebuild the simulation image with `./build_images.sh`.

### Automatic World Selection

The Gazebo world file is **automatically selected** based on the `CORE_NETWORK` environment variable. The launch file (`gazebo_launch.launch.py`) inside the simulation container reads the `CORE_NETWORK` variable and loads the corresponding world file (`world_only_oai.sdf`, `world_only_free5gc.sdf`, or `world_only_open5gs.sdf`). No manual editing of the launch file or rebuilding of the simulation image is required when switching between core networks.
The Gazebo world file is **automatically selected** based on the `CORE_NETWORK` environment variable. The launch file (`gazebo_launch.launch.py`) inside the simulation container reads the `CORE_NETWORK` variable and loads the corresponding world file (`world_only_oai.sdf`, `world_only_free5gc.sdf`, `world_only_open5gs.sdf`, or `world_only_external.sdf`). No manual editing of the launch file is required when switching between core networks.

### RAN Docker Compose Structure

Expand Down Expand Up @@ -183,15 +212,6 @@ Inside the world file for your chosen CN (same files as above), change the UE pa

**Note:** The `cn_type` parameter specifies which 5G Core Network the plugin should connect to. Ensure it matches the CN you're using.

## Remove CN from launch file

If you want to manage the CN containers separately, you can comment out the CN launch section in `launch.sh`:

```sh
# cd "$CN_DIR"
# docker compose up -d
```

## Changing ROS DOMAIN (avoiding multi-user bugs)

Set the `ROS_DOMAIN_ID` environment variable before launching (each PC should have its own):
Expand Down
17 changes: 17 additions & 0 deletions demo_containerized/external.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# External Core Network Configuration
# Used when CORE_NETWORK=external to connect to an already-running 5G core network.
# Adjust the values below to match your external core network.
# SDF-level plugin variables (credentials, topology) are in external.sdf.env.

# Subnet routed through the UPF (the UE container adds a route to this subnet
# through the UPF gateway so that robot traffic is steered over 5G).
UE_ROUTE_SUBNET="10.0.0.0/24"

# IP address of the UPF container / interface that acts as the PDU session
# gateway. Traffic from the UE toward UE_ROUTE_SUBNET is routed via this IP.
UE_ROUTE_GW="192.168.70.135"

# Downlink carrier frequency in Hz used by both the gNB and the UE RF
# simulator. Must match the absoluteFrequencyPointA / carrier frequency
# configured in the external gNB.
UE_CARRIER_FREQ="3319680000"
Loading
Loading