This repository applies PLANTA to a robot self-adaptation scenario based on the paper "Software architecture and task plan co-adaptation for mobile service robots", and compares it with the solution proposed in that paper.
This repo contains the experimental setup used in the paper "Plan your Self-Adaptation! – Efficient Task and Architecture Co-adaptation Planning for Robots".
The remainder of this README explains how to reproduce the experiments.
experiment_runner.py: shared sweep orchestrationreporting.py: plotting, comparison figures, and summary reportsscenario_variants.py: corridor, mission, and combined scenario variantsmap_generator.py: facade over graph generation, map I/O, and PDDL constructiongraph_generation.py: graph generation and pathfindingmap_io.py: JSON loading, discretization, and map plottingpddl_builder.py: Unified Planning domain/problem construction and serializationutils.py: planner execution, CSV serialization, and plan parsingprism_model_generator.py: PRISM model generation and policy simulation
See docs/architecture.md for a developer-oriented overview.
The first step is to get the docker image used for the experiments.
You can either build it locally:
docker build -t navigation_planta .Or you can download it with:
docker pull ghcr.io/kas-lab/navigation_planta:mainRun the full experiment suite with the locally built image:
docker run --rm -it -v $PWD/results:/navigation_planta/results -v /etc/localtime:/etc/localtime:ro navigation_planta:latest python scripts/run_all_experiments.pyRun only the grid-map scalability experiment:
docker run --rm -it -v $PWD/results:/navigation_planta/results -v /etc/localtime:/etc/localtime:ro navigation_planta:latest python scripts/run_grid_map_scenario.pyOpen a shell inside the container image:
docker run --rm -it -v /etc/localtime:/etc/localtime:ro navigation_planta:latest bashOpen a shell with the local repository mounted inside the container:
docker run --rm -it --name navigation_planta -v $PWD/src/navigation_planta:/navigation_planta/ -v /etc/localtime:/etc/localtime:ro navigation_planta:latest bashRun the full experiment suite with the GitHub image:
docker run --rm -it -v $PWD/results:/navigation_planta/results -v /etc/localtime:/etc/localtime:ro ghcr.io/kas-lab/navigation_planta:main python scripts/run_all_experiments.pyNote: If you want to change the directory where the results are going to be saved in the host machine, replace PWD/results with the path of the directory where you want the results to be saved.
Docker is the recommended path for full reproducibility. The manual setup below covers the Python package dependencies, but the full experiment suite also needs Java 17, PRISM, Fast Downward, and the OWL-to-PDDL toolchain.
Install Python dependencies:
pip install psutil networkx numpy==1.26.4 matplotlib scipy
Install Unified Planning:
pip install unified-planningInstall fast-downward unified planning engine:
pip install unified-planning[fast-downward]Build:
colcon build --symlink-install --packages-skip plansys2_downward_plannerTo reproduce the grid-map experiment from the paper, use:
python scripts/run_grid_map_scenario.pyTo run the full experiment suite, including the Cámara-style PRISM and PDDL comparisons, use:
python scripts/run_all_experiments.pyTo benchmark search strategies on the combined scenario, use:
python scripts/benchmark_search_strategies.py --nodes 10,20,50 --runs 3 --timeout 60The supported standalone experiment entrypoints are:
scripts/run_grid_map_scenario.pyscripts/run_camara_scenario.pyscripts/run_camara_scenario_discretized.pyscripts/run_camara_prism_scenario.pyscripts/run_fd_scale_scenario.pyscripts/run_corridor_type_scale_scenario.pyscripts/run_mission_action_scale_scenario.pyscripts/run_combined_scenario.pyscripts/run_all_experiments.pyscripts/benchmark_search_strategies.py
Normal version:
export PATH=$HOME/navigation_planta_ws/src/owl_to_pddl:$PATH
Example matching the adaptive experiment flow:
OWLToPDDL.sh --owl=owl/navigation.owl --tBox --inDomain=pddl/domain_sas.pddl --outDomain=pddl/domain_sas_created.pddl --aBox --inProblem=problem.pddl --outProblem=problem_created.pddl --replace-output --add-num-comparisonsROS version:
ros2 run owl_to_pddl owl_to_pddl.py --ros-args -p owl_file:=owl/navigation.owl -p in_domain_file:=pddl/domain_sas.pddl -p out_domain_file:=pddl/domain_sas_created.pddl -p in_problem_file:=pddl/problem.pddl -p out_problem_file:=pddl/problem_created.pddlThe repository contains both owl/navigation.owl and owl/navigation_with_imports.owl. The current Python experiment scripts use owl/navigation.owl unless a scenario-specific OWL file is selected.
The current pattern is:
- add or extend a scenario generator in
navigation_planta/ - create a thin script in
scripts/with constants and CLI parsing - use
run_sweep_experiment()fromnavigation_planta.experiment_runner - use plotting and summary helpers from
navigation_planta.reporting - add focused tests in
tests/for new scenario or reporting behavior
export PATH=$HOME/navigation_planta_ws/src/downward:$PATH
fast-downward.py pddl/domain_sas_created.pddl pddl/problem_created.pddl --search "astar(blind())"
ros2 run downward_ros fast-downward.py --alias lama-first pddl/domain_sas_created.pddl pddl/problem_created.pddlThe exact values depend on the sampled map and the execution environment. The examples below are illustrative.
Parameters:
self.num_nodes = 30
self.nodes_skip = 0.1 # 10%
self.unconnected_amount = 0.15 # 10%
self.unsafe_amount = 0.25 # 10%
self.dark_amount = 0.25 # 10%time:
Solution found.
Peak memory: 45500 KB
Remove intermediate file output.sas
search exit code: 0
INFO Planner time: 0.15s
real 0m0,325s
user 0m0,270s
sys 0m0,054sParameters:
self.num_nodes = 300
self.nodes_skip = 0.1 # 10%
self.unconnected_amount = 0.15 # 10%
self.unsafe_amount = 0.25 # 10%
self.dark_amount = 0.25 # 10%time:
Solution found.
Peak memory: 50856 KB
Remove intermediate file output.sas
search exit code: 0
INFO Planner time: 8.33s
real 0m8,517s
user 0m8,230s
sys 0m0,287stime prism navigate_map_one_path.prism -pf 'R{"time"}min=? [ F stop ]' -exportstrat stdout -const INITIAL_BATTERY=5000,INITIAL_LOCATION=1,TARGET_LOCATION=5,INITIAL_CONFIGURATION=1time prism navigate_map_one_path.prism -pf 'R{"energy"}max=? [ F stop ]' -exportstrat stdout -const INITIAL_BATTERY=32560,INITIAL_LOCATION=0,TARGET_LOCATION=16,INITIAL_CONFIGURATION=1time prism test.prism -pf 'R{"energy"}min=? [ F stop ]' -exportstrat stdout -const INITIAL_BATTERY=32560,INITIAL_LOCATION=0,TARGET_LOCATION=7,INITIAL_CONFIGURATION=1
time prism l52_l24.prism -javamaxmem 16g -cuddmaxmem 16g -pf 'R{"energy"}max=? [ F stop ]' -exportstrat stdout -const INITIAL_BATTERY=32560,INITIAL_LOCATION=0,TARGET_LOCATION=16,INITIAL_CONFIGURATION=1
python scripts/run_camara_prism_scenario.pyRun with docker:
docker run --rm -it -v $PWD/results:/navigation_planta/results navigation_planta:latest python scripts/run_camara_prism_scenario.pydocker run --rm -it -v $PWD/results:/navigation_planta/results navigation_planta:latest python scripts/run_camara_prism_scenario.pydocker run --rm -it -v $PWD/results:/navigation_planta/results ghcr.io/kas-lab/navigation_planta:main python scripts/run_camara_prism_scenario.pydocker run --rm -it -v $PWD/results:/navigation_planta/results ghcr.io/kas-lab/navigation_planta:main python scripts/run_grid_map_scenario.pyscripts/run_grid_map_scenario.py reports planning time around the fast-downward.py call only. The total wall-clock runtime per case is larger because map generation, problem-file generation, plotting, and OWLToPDDL.sh happen before the timer starts.
Map example:
--search 'astar(blind())'
--search 'astar(ff())'
--search 'astar(lmcount(lm_merged([lm_rhw(),lm_hm(m=1)])))'
for experiment C, ff was much faster
