Skip to content

bassamlab/Contextual-DPC

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

271 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Trajectory-Following Controllers for Autonomous Vehicles

Research code for data-driven trajectory-following controllers in simulation. The repository is designed for:

  • Reproducible experiments
  • Easy onboarding for new students
  • Modular integration with simulation environments (e.g., F1TENTH Gym)

Table of Contents


Getting Started

Run your first experiment

  1. Collect data:

    python -m experiment.main +experiment=collect_data

    This configuration will:

    • Run for 50 seconds
    • Create column names for collected data
    • Apply default data collection settings

    Outputs are stored under:

    outputs/single/yyyy-mm-dd-HH-MM-SS_+experiment=collect_data
    
  2. Promote a run to the data directory:

    • If the run looks acceptable, move it to data (configured via experiment.data_dir) and give it a descriptive name:
      data/drone/your_run
      
  3. Train/run a DPC experiment:

    python -m experiment.main

    This uses the current Hydra config. You can customize configs and overrides as needed (see β€œHydra configuration” below).


πŸ“ Project Structure

First lets get you an outline of what this project contains, and

trajectory-following-framework/
β”œβ”€β”€ controllers/            # Controller implementations (MPC, DPC, etc.)
β”‚   β”œβ”€β”€ base/               # Base DPC controllers
β”‚   β”œβ”€β”€ data_processing/    # Data loading and preprocessing
β”‚   β”‚   β”œβ”€β”€ filtering/      # Data filtering
β”‚   β”œβ”€β”€ data_sampling/      # Offline/online sampling for DPC
β”‚   β”œβ”€β”€ drone_dpc/          # Drone base controller + DPC for drone model
β”‚   β”œβ”€β”€ drone_mpc/          # MPC for the drone model
β”‚   β”œβ”€β”€ online/             # Online controller (TBI)
β”‚   β”œβ”€β”€ vehicle/            # Vehicle controllers
β”œβ”€β”€ data/                   # Collected input-output data
β”œβ”€β”€ evaluation/             # Visualization for multi-runs
β”œβ”€β”€ experiment/             # Experiment scripts and configurations
β”‚   β”œβ”€β”€ config/             # Hydra configuration
β”‚   β”œβ”€β”€ drone/              # Drone experiments
β”‚   β”œβ”€β”€ vehicle/            # Vehicle experiments (not implemented)
β”‚   β”œβ”€β”€ base_drone_experiment.py  # Shared drone experiment
β”‚   β”œβ”€β”€ main.py             # Hydra entry point
β”œβ”€β”€ scenarios/              # Scenario definitions (e.g., tracks)
β”œβ”€β”€ test/                   # Pytest environment
β”œβ”€β”€ utils/                  # Helpers
β”‚   β”œβ”€β”€ paths/              # Path creation utilities
β”‚   β”œβ”€β”€ config_logger.py    # Logger configuration
β”œβ”€β”€ README.md
β”œβ”€β”€ requirements.txt

Hydra Configuration

Hydra controls all experiment settings via layered config files.

  • Main config: experiment/config/config.yaml
  • Defaults: define which sub-configs load and where they are mounted.
  • Example: Parameters in controller/default_drone_dpc_controller.yaml appear under config.controller.params.

You can re-run past configurations by pointing Hydra to a previous run’s .hydra folder:

python -m experiment.main --config-dir outputs/single/2025-12-05_11-02-06_/.hydra --config-name overwrite

Note: Rename the run’s config.yaml to overwrite.yaml (or any name you plan to use with --config-name).

Important: Configs are applied top-to-bottom. Later-loaded configs (e.g., via +experiment=name) override earlier parameters.

Loading values

When loading the configuration:

  • The top-level configuration is a standard dict.
  • Nested sections are DictConfig objects (from OmegaConf).

Recommended ways to retrieve values

  1. Error if missing (preferred for required values)

    • Dot access (compact):
      config.key
    • Key access (useful in scripts):
      config['key']
  2. Provide a default (for optional values)
    config.get('key', default_value)

Notes

  • The configuration is a Hydra/OmegaConf object, similar to a normal dictionary.
  • Some functions may require a plain dict. Convert with:
    from omegaconf import OmegaConf
    plain_dict = OmegaConf.to_container(cfg)

Overrides

Above we have already used a bit of the overides. But bellow one can see how to add overrides to a run. It is very usefull to change a single parameter or a collection within the configuration. On top of that within the saving of the runs all of the overrides are included in the name of the folder. Like yyyy-mm-dd-HH-MM-SS_parameter=value

Overrides

Hydra supports fine-grained overrides. Overrides are also encoded in the output directory name for reproducibility (e.g., yyyy-mm-dd-HH-MM-SS_parameter=value).

  • Add (introduce) a parameter:
    python -m experiment.main +parameter.subparameter=value
    python -m experiment.main +parameter_collection=override_file
    
  • Replace (override) a parameter:
    python -m experiment.main parameter.subparameter=value
    python -m experiment.main parameter_collection=override_file
    

Multirun (Sweeps)

Launch sweeps to evaluate multiple settings:

python -m experiment.main --multirun +hydra=sweep_config

Recommendations:

  • Use a dedicated sweep file: +hydra=sweep_file for:
    • Consistent post-processing and visualization
    • Reproducibility
  • Sweep 1–2 parameters at a time for easier visualization.

Outputs

.hydra

Contains the full YAML configuration used for a run. This ensures the run is always traceable and reproducible.

Logging

Extensive logging keeps the console focused and preserves detailed traces:

  • Configured via utils/config_logger.py and config.logger in Hydra
  • Topics are defined under config.logger.topics; create with:
    log = logging.getLogger("desired_topic")
  • A levels folder aggregates high-severity logs for rapid triage; a clean run should have none.
  • main.log in the run’s parent folder contains a full log of all events.

Plots and Debug

  • Controlled via Hydra settings
  • Saved in run subfolders
  • Enable only what you need to keep runs clear and efficient

Stats

Structured run statistics are captured via the custom DataLogger. These stats are summarized (min, max, mean, spread) and used during post-processing.

  • Register stats keys before logging values:

    self.data_logger.add_tracked_stats(["new_stats_key"])

    If a key isn’t registered, it won’t be savedβ€”this safeguards against typos and name mismatches.

  • Log values during the run:

    self.data_logger.stats_log({"new_stats_key": value})
  • Summary metrics produced per key:

    • min: Minimum observed value
    • max: Maximum observed value
    • mean: Average value
    • spread: max - min
  • Typical usage pattern:

    # 1) Register once (e.g., in setup)
    self.data_logger.add_tracked_stats(["tracking_error", "control_effort"])
    
    # 2) Log on each step or event
    self.data_logger.stats_log({
        "tracking_error": current_error,
        "control_effort": np.linalg.norm(u),
    })
  • Downstream consumption:

    • These summaries are saved with the run artifacts
    • Post-processing scripts read the stats to aggregate results across runs/sweeps

Preprocessing

Loading and Saving

To accelerate large multiruns, preprocessed data is cached in .npy format.

  • The system compares the saved config.controller.preprocess against the current configuration to determine compatibility.
  • preprocess_options are ignored for compatibility checks.

Modes:

  1. Default: scan the data folder and load the most recent compatible dataset
  2. Manual (recommended): specify a target data folder in the config

Visualization

Preprocessing also generates comparison plots saved in a similarly named folder. These are created once per preprocessing step.


Modules

Experiment

A base experiment provides shared functionality for reusability, testability, and consistency. Individual experiments:

  • Implement their own controllers
  • Add experiment-specific features
  • Clearly separate functional differences

Evaluation

Example usage:

  • 2D sweep heatmap:

    python evaluation/sweep_2d_heatmap.py --n-before 0 --metric drone0.[LOG-TRAC].tracking.abs_tracking_error
    
  • Batched 2D sweep heatmap:

    python evaluation/sweep_2d_heatmap_batch.py --all -- --metric drone0.[LOG-TRAC].abs_tracking_error
    

Scenarios

Scenario definitions for vehicle experiments (e.g., race tracks).


Dependencies

Notable:

  • f1tenth_gym (installed via pip from GitHub)
  • dtaidistance (DTW-based trajectory comparison)

Install all dependencies:

pip install -r requirements.txt

License

Licensed under the MIT License. See LICENSE for details.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages