The Maveric project is the source of the RIC Algorithm Development Platform (RADP). It enables the development and evaluation of dynamic control policies that optimize cellular network operation, before their deployment on the network. It is intended to serve the use-case of developing solutions that leverage the Radio Intelligent Controller (RIC) paradigm. It is a developer platform that leverages AI/ML approaches to provide realistic cellular network representations (known as digital twins), as well as examples of simple xApp/rApp algorithms, that demonstrate its use.
- RIC Algorithm Development Platform (RADP)
Please follow the development workflow here when making code changes.
If you haven't already, download or clone this repo on the machine where you'd like to run RADP.
To run the RADP service you will need to install Docker.
Once Docker is installed make sure to start the docker daemon.
Once Docker is running you just need to cd to the "radp" directory (if you're not already there) and run the following command
docker build -t radp radp
[Alternative] Using GPUs from host
Docker has native support for this.
Host must have Nvidia driver, Nvidia Container toolkit installed.
RADP Docker Compose files are already set to attach Nvidia GPUs if available.
You will need to specify a different base image for Docker Compose:
docker build -f radp/Dockerfile-cuda -t radp radp
Then you can start RADP in production mode:
docker compose -f dc.yml -f dc-prod.yml up -d --build
Or with Nvidia GPU support too:
docker compose -f dc.yml -f dc-prod.yml -f dc-cuda.yml up -d --build
This will do the following:
- Build the docker images using their local Docker files
- Calls docker run to build containers for each service
- Creates services, volumes, kafka topics, and other components of RADP architecture
The first time you run this command it may take a while since Docker will need to download container images. You'll see a lot of text appear on your terminal.
Once you can see the RADP API service expose a web address you'll know you're ready to call the system's APIs:
radp-init | Successfully created the following topics:
radp-init | jobs
radp-init | outputs
radp-init exited with code 0
RADP currently requires Python >= 3.8.x and < 3.11.x
The last remaining holdout to support Python 3.11 appears to be the Torch library, which should be resolved soon.
CD to the top level of the repo. Run the following command to install Python client dependencies:
python3 -m venv .venv
source .venv/bin/activate
pip3 install --upgrade pip
pip3 install -r radp/client/requirements.txt
Install example requirements:
pip3 install -r apps/requirements.txt
You can copy the sample Environment files and make changes to them if desired:
copy .env-prod .env
This package comes with an example script which you can call to see the RADP service in action:
python3 apps/example/example_app.py
If the simulation runs end-to-end successfully, you should see an outputted dataframe containing the example simulation output.
Likewise, a basic Coverage and Capacity Optimization (CCO) example can be run as follows:
python3 apps/coverage_capacity_optimization/cco_example_app.py
The app takes about 2 minutes to run and produce final results on the console.
To stop the services run:
docker compose -f dc.yml -f dc-prod.yml down
in a terminal tab.
If you encounter an error here or hit ctrl + c
you may kill your containers, possibly leaving them or their volumes in an unhealthy state. To clean your Docker containers and volumes, just run the following commands.
docker container prune
to remove stopped containersdocker volume prune
to remove unused volumes
IMPORTANT: Running volume prune will completely remove your RADP system data so only run during development
The Train API allows a user to train a new RF Digital Twin model.
radp_client.train(
model_id=model_id,
params={},
ue_training_data="ue_training_data.csv",
topology="topology.csv",
)
- model_id (str, required) - the model_id which will be used to reference this model in subsequent calls to the Simulation API.
- params (dict, required) - the training parameters to pass in for training, see Training Params
- ue_training_data (str or pandas dataframe object, required) - the file path of the UE Training Data File (or a training data pandas dataframe)
- topology (str or pandas dataframe object, required) - the file path of the cell Topology File (or a cell topology pandas dataframe), required to enable the model to preprocess the UE training data and create per-cell engineered features for training
See the example_app.py script for an example where pandas dataframes are provided directly to the client.
The following object shows all training params that can be specified.
{
"maxiter": 100
"lr": 0.05
"stopping_threshold": 0.0001
}
- maxiter (int, optional) - the max number of iterations to run in training
- lr (float, optional) - model learning rate
- stopping_threshold (float, optional) - stopping threshold for training
The UE training data file must be a CSV file with the following format:
cell_id | avg_rsrp | lon | lat | cell_el_deg |
---|---|---|---|---|
cell_1 | -80 | 139.699058 | 35.644327 | 0 |
cell_1 | -70 | 139.707889 | 35.647814 | 3 |
cell_1 | -75 | 139.700024 | 35.643857 | 6 |
... | ... | ... | ... | ... |
- cell_id (str, required) - the ID of the cell unit, the RF Digital Twin will run training/inference on a per-cell unit basis
- avg_rsrp (float, required) - the RSRP value for this cell, for the lon-lat pixel of data, this is the target value for supervised learning employed by the RF Digital Twin model
- lon (float, required) - the longitude of this pixel of data
- lat (float, required) - the latitude of this pixel of data
- cell_el_deg (float, required) - the electrical antenna tilt of the cell
For an example of a UE training data file, see apps/example/ue_training_data.csv
The topology file must be a CSV file with the following format:
cell_id | cell_name | cell_lat | cell_lon | cell_az_deg | cell_carrier_freq_mhz |
---|---|---|---|---|---|
cell_1 | Cell1 | 35.690556 | 139.691944 | 0 | 2100 |
cell_2 | Cell2 | 35.690556 | 139.691944 | 120 | 2100 |
cell_3 | Cell3 | 35.690556 | 139.691944 | 240 | 2100 |
... | ... | ... | ... | ... | ... |
- cell_id (str) - the cell identfier
- cell_name (str) - the name of the cell (optional)
- cell_lat (float) - the cell latitude
- cell_lon (str) - the cell longitute
- cell_az_deg (int) - the cell azimuth degree
- cell_carrier_freq_mhz (int) - the cell carrier frequency layer
For an example of a topology file, see apps/example/topology.csv
The Simulation API allows a user to run a RIC Simulation event. If called with a valid request, the simulation API will create a simulation event which can be described by calling the Describe Simulation API. Once the simulation has finished, the outputted results can be consumed by calling the Consume Simulation Output API
radp_client.simulation(
simulation_event=simulation_event,
ue_data=prediction_data,
config=prediction_config,
)
- simulation_event - the simulation event object
- ue_data - the file path of the UE Data file, see Passing in UE Tracks via UE Data File; this can also instead by a pandas dataframe
- config - the file path of the Cell Config file, see
{
"simulation_time_interval_seconds": 0.01,
"ue_tracks": <UE Tracks object>,
"rf_prediction": <RF Prediction Object>,
}
- simulation_time_interval_seconds (float) - the simulation time interval in seconds; the time between "ticks" within the simulation - the above example would be 10ms between each tick
- ue_tracks - the UE Tracks component to the simulation, see UE Tracks
- rf_prediction - the RF Prediction component to the simulation, see RF Prediction
cell_id | cell_el_deg |
---|---|
cell_1 | 10 |
cell_2 | 10 |
cell_3 | 12 |
- cell_id (str, required) - the cell identifier
- cell_el_deg (float, required) - the electrical antenna tilt of the cell
{
"simulation_id": 'c88e347c613d1727a1c6ce5b61bc0877'
}
- simulation_id - the simulation identifier used to describe or consume output from this simulation
The Describe Model API allows a user to describe the training status of a digital twin model. This allows the user to see if a model has finished training (and thus is ready to be used in simulation).
radp_client.describe_model(model_id)
- model_id - the identifier of the model to describe
TO BE COMPLETED
The Describe Simulation API allows a user to describe an existing simulation. The response will signal to the user whether the simulation has finished (and thus whether output results can be consumed).
radp_client.describe_simulation(simulation_id)
- simulation_id - the identifier of the simulation to describe
TO BE COMPLETED
The Consume Simulation Output API allows a user to consume the output data from a simulation. The API returns a pandas dataframe object pertaining to simulation output
Example:
rf_dataframe = radp_client.consume_simulation_output(simulation_id)
- simulation_id (str, required) - the ID for the simulation
UE track data must be either passed in or generated to run a RIC simulation. The ue_tracks
key must be present in a SimulationEvent object.
Users have the option of passing in their own UE track data to the simulation. To specify that you will pass UE Track data to a simulation you must include the ue_data_id
key in the ue_tracks
like the following:
"ue_tracks": {
"ue_data_id": "ue_data_1"
},
The value provided will be used to identify this UE data passed in. It does not need to be the name of the file.
IMPORTANT: If two sequential calls to the simulation API contain the same value for this field, the RADP system will assume the provided UE tracks data is the same. The system caches data using a hash of this value. If you wish to pass and run a RIC simulation on a different data set you MUST change the value provided here.
Along with adding the ue_data_id
key to the simulation object, the user must also pass the file path of the UE data to the RADP Client. See the example.py script for an example API call with UE data file path passed in. The UE data file must be a comma-separated csv file with the following case-sensitive columns. See ue_data.csv for an example.
mock_ue_id | lon | lat | tick | cell_id |
---|---|---|---|---|
1 | 139.699058 | 35.644327 | 0 | 1 |
2 | 139.707889 | 35.647814 | 0 | 1 |
3 | 139.700024 | 35.643857 | 0 | 1 |
1 | 139.699061 | 35.644322 | 1 | 2 |
2 | 139.707899 | 35.647813 | 1 | 2 |
... | ... | ... | ... | ... |
- lon (float) - the longitude of the pixel
- lat (float) - the latitude of the pixel
- mock_ue_id (str, optional) - a fake user equipment ID to associate with this pixel of data
- tick (int, optional) - the relative index of this position with respect to time; if a a certain mock_ue_id has a position (x1,y1) at tick=1, then has position (x2, y2) at tick=2, the simulation sees that this UE has moved from (x1,y1) to (x2,y2) across an interval of time equal to simulation_time_interval_seconds
- cell_id (str, optional) - the identifier of the cell to attach this data point to. If this column is present then RF prediction will only occur from this pixel to this cell. If this column is not provided then RF prediction will occur on a per-cell basis where RX power is outputted for this pixel for every cell in the topology
For an example of a UE Tracks data file, see apps/example/ue_data.csv
Users also have the option of generating UE tracks data using RADP's built-in UE Tracks Generation service. The service employs a gaussian markov-based mobility model to generate UE tracks data.
To include UE Tracks Generation in a RIC simulation, set up your UE tracks object as follows:
"ue_tracks": {
"ue_tracks_generation" : {
"ue_class_distribution": UEClassDistribution,
"lat_lon_boundaries": LatLonBoundaries,
"gauss_markov_params": GaussianMarkovParams,
}
},
This object specifies the distribution of UE classes as well as mobility parameters for each class. The following UE classes are supported (case-sensitive): - stationary - pedestrian - cyclist - car
To include a UE class in the generated UE tracks data, include the class as a key in the UETypes object, with a value of UEType. See below example which includes only pedestrians and cars:
"ue_class_distribution": {
"pedestrian": UEClassParams,
"car": UEClassParams,
},
The basic parameters of the UE Class
- count (int) - the number of UEs of this class to generate in the simulation
- velocity (float) - the average velocity of this UE class (float in meters/second)
- velocity_variance (float) - the average variance from the average velocity of this UE class (float)
An example UEClassDistribution with UEClassParams for pedestrian and car:
"ue_class_distribution": {
"pedestrian": {
"count": 5,
"velocity": 1,
"velocity_variance": 1
},
"car": {
"count": 5,
"velocity": 10,
"velocity_variance": 0.5
}
},
The latitude and longitude boundaries of the grid where the UE Tracks data will be generated. UE device tracks will not stray outside of these boundaries. See the following example:
"lat_lon_boundaries": {
"min_lat": -90,
"max_lat": 90,
"min_lon": -180,
"max_lon": 180
},
This object specifies the Gauss-Markov parameters to tune the randomness of the generated UEs. The params that can be specified are:
- alpha (float) - the tuning parameter used to vary the randomness. Totally random values are obtained by setting it to 0 and linear motion is obtained by setting it to 1
- variance (float) - the randomness variance for the UEs
- rng_seed (int) - the random generator seed to be used to generate the UE data. The seed is set manually for reproducibility
Below is an example of UE mobility generated using the UE Tracks Generation service.
As a component of a RIC Simulation, users can specify a previously trained RF Digital Twin model to run RF Prediction.
The input to RF prediction is a data set pertaining to UE Tracks, thus to run RF Prediction UE Tracks must first be specified in the SimulationEvent object. The only field required to run RF Prediction is the ID of the trained Digital Twin model to use in RF Prediction.
"rf_prediction": {
"model_id": "my_trained_digital_twin_1"
}
As output, the RF Prediction step will add predicted per-cell RX Power data to the UE Tracks data.
cell_id | rxpower_dbm | mock_ue_id | lon | lat | tick |
---|---|---|---|---|---|
cell_1 | -73.58406342082407 | 0 | -22.647772018547954 | 59.7818913169958 | 0 |
cell_1 | -73.58406342082407 | 1 | 119.78045195037765 | 54.86740569575272 | 0 |
cell_1 | -73.58406342082407 | 2 | 72.1170723329875 | -20.22066321601217 | 0 |
cell_1 | -73.58406342082407 | 0 | -23.17652796675165 | 59.49811644458839 | 1 |
cell_1 | -73.58406342082407 | 1 | 121.23118177561184 | 55.20488171003581 | 1 |
cell_1 | -73.58406342082407 | 2 | 70.39142709656107 | -21.780123291101106 | 1 |
cell_1 | -73.58406342082407 | 0 | -27.928272856142712 | 60.77581594854604 | 2 |
cell_1 | -73.58406342082407 | 1 | 126.61098550003226 | 58.21946030130971 | 2 |
cell_1 | -73.58406342082407 | 2 | 69.80139485065422 | -21.980885049368638 | 2 |
- cell_id (str) - the ID of the cell for which this RF prediction is made
- rxpower_dbm (float) - the predicted RSRP value (in dBm) for this cell, for the lat-lon position specified
This section lays out the known limitations of the service.
Below are the timeout thresholds for training and simulation jobs
- training - 12 hours
- simulation - 15 minutes for each stage in a simulation event
To explain, a training job can take up to 12 hours after which it will timeout. A simulation event can handle as much data as is possible without passing a 15 minute length of time for any single stage in the simulation pipeline. The developer team plans to implement batch processing, after which this will no longer be a limitation.
For all of these API's you should be able to see relevant output in your terminal tab in which you ran docker compose
. If you see error outputs for any command then something is wrong!
Please follow this guide for running notebooks.
See license