Usage Examples
Below we provide two example scripts that display a typical usage of freneticlib.
The first one uses an executor featuring a bicycle model (BicycleExecutor
), while the second one
executes using the BeamNG.tech executor (BeamNGExecutor
).
Bicycle Executor Example
import logging
from freneticlib.core.core import FreneticCore
from freneticlib.core.mutation import exploiters, crossovers
from freneticlib.core.mutation.mutators import FreneticMutator
from freneticlib.core.objective import MaxObjective
from freneticlib.executors.bicycle.bicycleexecutor import BicycleExecutor
from freneticlib.executors.road_validator import RoadValidator
from freneticlib.frenetic import Frenetic
from freneticlib.representations.kappa_representation import FixStepKappaRepresentation
from freneticlib.stopcriteria.counter import CountingStop
# specify a logging format
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s %(message)s", datefmt="%H:%M:%S")
def run_example():
# We want a FixStep Kappa representation
representation = FixStepKappaRepresentation(length=30, variation=5, step=10.0)
# alternative:
# representation = CatmullRomRepresentation(control_nodes=30, variation=5)
# Setup an objective. Here: maximize the distance_from_center (i.e. push the vehicle off the road)
objective = MaxObjective(
feature="distance_from_center",
# every simulation produces 10 records per second, we extract the maximum value of the selected feature
per_simulation_aggregator="max",
)
# Define the Frenetic core using representation, objective and the mutation operators
core = FreneticCore(
representation=representation,
objective=objective,
mutator=FreneticMutator(),
crossover=crossovers.ChooseRandomCrossoverOperator(size=20),
)
# Define the Frenetic executor and the stop-criterion.
frenetic = Frenetic(
core,
executor=BicycleExecutor(
representation=representation,
objective=objective,
# results_path="./data/detailed"
),
stop_criterion=CountingStop(n_random=50, n_total=250),
)
# If we wanted to extend a previous run, we could load the history like so:
# frenetic.load_history("./data/dev.csv")
# run the search
frenetic.start()
# store the history for later use
frenetic.store_results("./data/history.csv")
# Display the progress
frenetic.plot("./data/plot.png")
if __name__ == "__main__":
run_example()
BeamNG.tech Executor Example
Our second example is rather similar to the first one, except that it uses a different simulator. However, to use the BeamNG.tech simulator, we first have to perform some extra steps.
First, request a free researcher license from https://register.beamng.tech.
Then, download and install the BeamNG.tech according to the instructions emailed to you.
Next, download or clone the SBFT 2023 CPS tool competition pipeline, which we use as an interface to BeamNG.tech.
Specify the required arguments
cps_pipeline_path
,beamng_home
andbeamng_user
in the initialisation of theBeamNGExecutor
, like so
BeamNGExecutor(
representation=...,
objective=...,
cps_pipeline_path="~/cps-tool-competition",
beamng_home="~/Downloads/BeamNG.tech.v0.26.2.0",
beamng_user="~/BeamNG.tech",
)
The rest of the code is exactly the same as in the BicycleExecutor
example.
Note
Currently, we tested frenetic-lib on Windows using BeamNG.tech v0.26.2.0 In case you use it on Linux and/or another version of BeamNG.tech, please share your experience with us.
import logging
from pathlib import Path
from freneticlib.core.core import FreneticCore
from freneticlib.core.mutation import exploiters, crossovers
from freneticlib.core.mutation.mutators import FreneticMutator
from freneticlib.core.objective import MaxObjective
from freneticlib.executors.beamng.beamng_executor import BeamNGExecutor
from freneticlib.executors.bicycle.bicycleexecutor import BicycleExecutor
from freneticlib.frenetic import Frenetic
from freneticlib.representations.kappa_representation import FixStepKappaRepresentation
from freneticlib.stopcriteria.counter import CountingStop
# specify a logging format
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s %(message)s", datefmt="%H:%M:%S")
def run_example():
# We want a FixStep Kappa representation
representation = FixStepKappaRepresentation(length=30, variation=5, step=10.0)
# Setup an objective. Here: maximize the distance_from_center (i.e. push the vehicle off the road)
objective = MaxObjective(
feature="oob_percentage", # BeamNG Executor
# every simulation produces many records per second, we extract the maximum of this
per_simulation_aggregator="max",
)
# Define the Frenetic core using representation, objective and the mutation operators
core = FreneticCore(
representation=representation,
objective=objective,
mutator=FreneticMutator(),
crossover=crossovers.ChooseRandomCrossoverOperator(size=20),
)
# Define the Frenetic executor and the stop-criterion.
frenetic = Frenetic(
core,
BeamNGExecutor(
representation=representation,
objective=objective,
cps_pipeline_path="~/cps-tool-competition",
beamng_home="~/Downloads/BeamNG.tech.v0.26.1.0",
beamng_user="~/BeamNG.tech",
results_path="./data/detailed",
),
CountingStop(n_random=5, n_total=15), # just a few, since simulation takes long
)
# run the search
frenetic.start()
# store the history for later use
frenetic.store_results("./data/dev.csv")
# Display the progress
frenetic.plot()
if __name__ == "__main__":
run_example()