diff --git a/.github/workflows/perf-ci.yml b/.github/workflows/perf-ci.yml index 083a97a827..fd6f76553a 100644 --- a/.github/workflows/perf-ci.yml +++ b/.github/workflows/perf-ci.yml @@ -2,7 +2,7 @@ name: perf-ci on: pull_request: - branches: [ 2.0 ] + branches: [ main ] jobs: test-performance: diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 0000000000..cb7b20e1bc --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,28 @@ +name: Pre-commit + +on: + pull_request: + types: + - opened + - reopened + - synchronize + - ready_for_review + +jobs: + pre-commit: + name: pre-commit + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install pre-commit + run: python -m pip install -U pip pre-commit + + - name: Run pre-commit + run: pre-commit run --all-files --show-diff-on-failure diff --git a/.github/workflows/render-ci.yml b/.github/workflows/render-ci.yml new file mode 100644 index 0000000000..9634af71d2 --- /dev/null +++ b/.github/workflows/render-ci.yml @@ -0,0 +1,59 @@ +name: render-ci + +on: + pull_request: + branches: [ main ] + push: + branches: [ main ] + +jobs: + test-render: + name: test-render - ubuntu-latest + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: "3.11" + + - name: Check disk space (before cleanup) + run: df -h + + - name: Free up disk space + run: | + echo "Before cleanup:" + df -h + sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc + sudo apt-get clean + sudo rm -rf ~/.cache/pip /tmp/* /var/tmp/* + echo "After cleanup:" + df -h + + - name: Install system dependencies for headless rendering + run: | + sudo apt update + sudo apt install -y ffmpeg xvfb build-essential + + - name: Upgrade pip + run: python -m pip install -U pip + + - name: Install pufferlib + run: | + pip install -e .[cpu] --no-cache-dir + env: + TMPDIR: ${{ runner.temp }}/build + PIP_NO_CACHE_DIR: 1 + + - name: Compile C extensions + run: python setup.py build_ext --inplace --force + + - name: Check disk space (after install) + run: df -h + + - name: Run render test + run: python tests/test_drive_render.py + timeout-minutes: 15 diff --git a/.github/workflows/train-ci.yml b/.github/workflows/train-ci.yml index cad2613d93..bd5b377766 100644 --- a/.github/workflows/train-ci.yml +++ b/.github/workflows/train-ci.yml @@ -2,9 +2,9 @@ name: train-ci on: pull_request: - branches: [ 2.0 ] + branches: [ main ] push: - branches: [ 2.0 ] + branches: [ main ] jobs: test-training: diff --git a/.github/workflows/training-test.yml b/.github/workflows/training-test.yml new file mode 100644 index 0000000000..deb4ad3882 --- /dev/null +++ b/.github/workflows/training-test.yml @@ -0,0 +1,37 @@ +name: Training Test + +on: + pull_request: + types: + - closed + branches: [ develop ] + +jobs: + run-training-test: + name: Run Training Test + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Authenticate to Google Cloud + uses: 'google-github-actions/auth@v2' + with: + credentials_json: '${{ secrets.GCP_CREDENTIALS }}' + + - name: Configure Docker for GCP Artifact Registry + run: gcloud auth configure-docker europe-west4-docker.pkg.dev + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: "3.11" + + - name: Install dependencies for mlops.py + run: pip install pyyaml google-cloud-aiplatform + + - name: Run training test + run: python mlops/mlops.py train-test --verbose + timeout-minutes: 40 diff --git a/.github/workflows/utest.yml b/.github/workflows/utest.yml index 5a0626a051..cfcbdda4b7 100644 --- a/.github/workflows/utest.yml +++ b/.github/workflows/utest.yml @@ -2,9 +2,9 @@ name: Unit tests on: pull_request: - branches: [ 2.0 ] + branches: [ main ] push: - branches: [ 2.0 ] + branches: [ main ] jobs: test: diff --git a/.gitignore b/.gitignore index 2bd9405687..aa3da57485 100644 --- a/.gitignore +++ b/.gitignore @@ -141,13 +141,13 @@ dmypy.json # Pyre type checker .pyre/ .pylintrc -.vscode/ # ROMs *.gb checkpoints/ experiments/ +benchmark*/ wandb/ .neptune/ raylib*/ @@ -163,14 +163,9 @@ pufferlib/ocean/impulse_wars/benchmark/ # Ignore data files data/ -pufferlib/resources/drive/binaries/ -pufferlib/resources/drive/binaries/training/ -pufferlib/resources/drive/binaries/validation/ - -# But keep map_000.bin for the training test -!pufferlib/resources/drive/binaries/map_000.bin -!pufferlib/resources/drive/binaries/training/map_000.bin -pufferlib/resources/drive/sanity/sanity_binaries/ +pufferlib/resources/drive/binaries/*/ +!pufferlib/resources/drive/binaries/carla/ +!pufferlib/resources/drive/binaries/carla/** # Compiled drive binary in root /drive @@ -187,6 +182,5 @@ pufferlib/resources/drive/output_agent.gif pufferlib/resources/drive/output.gif artifacts/ # Local drive renders pufferlib/resources/drive/output*.gif -emsdk/ -docs/book/* -!docs/book/assets/ +*.mp4 +.vscode/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 74e29d4620..dd233d3ae7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,4 +26,4 @@ repos: rev: 'v21.1.5' hooks: - id: clang-format - exclude: '\.(js|html)$|^build_web/|^docs/assets/' + types_or: [c, c++] diff --git a/README.md b/README.md index 0b431e7169..fdb7786288 100644 --- a/README.md +++ b/README.md @@ -1,218 +1,139 @@ # PufferDrive -[![Unit Tests](https://github.com/Emerge-Lab/PufferDrive/actions/workflows/utest.yml/badge.svg)](https://github.com/Emerge-Lab/PufferDrive/actions/workflows/utest.yml) +MARL autonomous driving RL environment. C simulation engine (GigaFlow/Waymo replay) + Python/PyTorch PPO training loop with V-trace and priority sampling. - +## Install -**PufferDrive is a fast and friendly driving simulator to train and test RL-based models.** - -
-
-
-
-
-
-
-
-
-
- ---- - -**Docs**: https://emerge-lab.github.io/PufferDrive - ---- - -### See our 2.0 release video - - - PufferDrive 2.0 - - -## Installation - -Clone the repo ```bash -https://github.com/Emerge-Lab/PufferDrive.git -``` - -Make a venv (`uv venv`), activate the venv -``` -source .venv/bin/activate -``` - -Inside the venv, install the dependencies -``` +# Python env +uv venv && source .venv/bin/activate uv pip install -e . -``` -Compile the C code -``` +# Build C extensions (required after any .h/.c change) python setup.py build_ext --inplace --force ``` -Run this while your virtual environment is active so the extension is built against the right interpreter. - -To test your setup, you can run -``` -puffer train puffer_drive -``` -See also the [puffer docs](https://puffer.ai/docs.html). - - -## Quick start - -Start a training run -``` -puffer train puffer_drive -``` - -## Dataset - -
-Downloading and using data - -### Data preparation - -To train with PufferDrive, you need to convert JSON files to map binaries. Run the following command with the path to your data folder: - -```bash -python pufferlib/ocean/drive/drive.py -``` - -### Downloading Waymo Data - -You can download the WOMD data from Hugging Face in two versions: - -- **Mini dataset**: [GPUDrive_mini](https://huggingface.co/datasets/EMERGE-lab/GPUDrive_mini) contains 1,000 training files and 300 test/validation files -- **Medium dataset**: [10,000 files from the training dataset](https://huggingface.co/datasets/daphne-cornelisse/pufferdrive_train) -- **Large dataset**: [GPUDrive](https://huggingface.co/datasets/EMERGE-lab/GPUDrive) contains 100,000 unique scenes - -**Note**: Replace 'GPUDrive_mini' with 'GPUDrive' in your download commands if you want to use the full dataset. - -### Additional Data Sources - -For more training data compatible with PufferDrive, see [ScenarioMax](https://github.com/valeoai/ScenarioMax). The GPUDrive data format is fully compatible with PufferDrive. -
- - -## Visualizer - -
-Dependencies and usage - -## Local rendering - -To launch an interactive renderer, first build: -``` -bash scripts/build_ocean.sh drive local -``` -then launch: -```bash -./drive -``` -this will run `demo()` with an existing model checkpoint. +## Data -## Headless server setup +Place binaries under `pufferlib/resources/drive/binaries/`. -Run the Raylib visualizer on a headless server and export as .mp4. This will rollout the pre-trained policy in the env. - -### Install dependencies +## Train ```bash -sudo apt update -sudo apt install ffmpeg xvfb -``` - -For HPC (There are no root privileges), so install into the conda environment -```bash -conda install -c conda-forge xorg-x11-server-xvfb-cos6-x86_64 -conda install -c conda-forge ffmpeg -``` - -- `ffmpeg`: Video processing and conversion -- `xvfb`: Virtual display for headless environments - -### Build and run +# Single node +puffer train puffer_drive -1. Build the application: -```bash -bash scripts/build_ocean.sh visualize local -``` +# Override config on the fly +puffer train puffer_drive --train.learning_rate 0.001 --env.num_agents 512 -2. Run with virtual display: -```bash -xvfb-run -s "-screen 0 1280x720x24" ./visualize +# Multi-GPU +torchrun --standalone --nnodes=1 --nproc-per-node=6 -m pufferlib.pufferl train puffer_drive ``` -The `-s` flag sets up a virtual screen at 1280x720 resolution with 24-bit color depth. - ---- - -> To force a rebuild, you can delete the cached compiled executable binary using `rm ./visualize`. - ---- - -
+## Eval - -## Benchmarks - -### Distributional realism - -We provide a PufferDrive implementation of the [Waymo Open Sim Agents Challenge (WOSAC)](https://waymo.com/open/challenges/2025/sim-agents/) for fast, easy evaluation of how well your trained agent matches distributional properties of human behavior. See documentation [here](https://emerge-lab.github.io/PufferDrive/wosac/). - -WOSAC evaluation with random policy: ```bash -puffer eval puffer_drive --eval.wosac-realism-eval True -``` - -WOSAC evaluation with your checkpoint (must be .pt file): +# Multi-scenario eval (replay mode) +puffer eval_multi_scenarios puffer_drive \ + --load-model-path experiments/puffer_drive_177193887946/models/model_puffer_drive_000001.pt \ + --num_scenarios 250 --eval_simulation replay + +# Multi-scenario eval (gigaflow mode) +puffer eval_multi_scenarios puffer_drive \ + --load-model-path experiments/puffer_drive_177193887946/models/model_puffer_drive_000001.pt \ + --num_scenarios 10 --eval_simulation gigaflow + +# Multi-scenario eval with rendering +puffer eval_multi_scenarios_render puffer_drive \ + --load-model-path experiments/puffer_drive_177193887946/models/model_puffer_drive_000001.pt \ + --num_scenarios 10 --eval_simulation gigaflow --render 1 --render_obs 0 + +# Save eval as GIF +puffer eval_multi_scenarios_render puffer_drive \ + --load-model-path experiments/puffer_drive_177193887946/models/model_puffer_drive_000001.pt \ + --num_scenarios 5 --eval_simulation gigaflow --save-frames 1 --gif-path eval.gif --fps 15 +``` + +## Key Configuration (`pufferlib/config/ocean/drive.ini`) + +### `[env]` — Simulation + +| Parameter | Default | Notes | +|-----------|---------|-------| +| `simulation_mode` | `"gigaflow"` | `"gigaflow"` (procedural) or `"replay"` (Data-driven) | +| `num_agents` | `1024` | Total agents across all workers | +| `min/max_agents_per_env` | `10 / 80` | Per-env agent count range | +| `action_type` | `"discrete"` | `"discrete"`, `"continuous"`, `"trajectory"`, `"trajectory_frenet"`, `"trajectory_jerk"` | +| `dynamics_model` | `"jerk"` | `"classic"` or `"jerk"` | +| `scenario_length` | `128` | Steps per episode (128 GF, 91 replay) | +| `collision_behavior` | `1` | `0` ignore, `1` stop, `2` remove | +| `offroad_behavior` | `1` | Same options | +| `traffic_light_behavior` | `1` | Same options | +| `control_mode` | `"control_vehicles"` | `"control_vehicles"`, `"control_agents"`, `"control_sdc_only"` | +| `reward_conditioning` | `True` | Condition policy on reward weights | +| `reward_randomization` | `True` | Randomize reward weights each episode | + +### `[env]` — Reward Shaping + +| Parameter | Default | Effect | +|-----------|---------|--------| +| `reward_goal` | `1.0` | Goal reaching (set 0 without reward conditioning) | +| `reward_vehicle_collision` | `1.0` | Collision penalty | +| `reward_comfort` | `0.05` | Smooth driving | +| `reward_lane_align` | `0.025` | Lane heading alignment | +| `reward_vel_align` | `1.0` | Speed matching road limit | +| `reward_lane_center` | `0.0038` | Lane centering | +| `reward_traffic_light_violation` | `1.0` | Red light penalty | +| `reward_overspeed` | `0.05` | Speeding penalty | + +### `[train]` — PPO + +| Parameter | Default | Notes | +|-----------|---------|-------| +| `learning_rate` | `0.001` | Adam LR | +| `bptt_horizon` | `64` | BPTT window (64 GF, 91 replay) | +| `minibatch_size` | `4096` | | +| `gamma` | `0.98` | Discount | +| `gae_lambda` | `0.95` | GAE lambda | +| `vf_coef` | `2` | Value loss weight | +| `ent_coef` | `0.001` | Entropy bonus | +| `vtrace_rho_clip` / `vtrace_c_clip` | `1` | V-trace IS ratio clipping | +| `prio_alpha` / `prio_beta0` | `0.85` | Priority sampling exponents | + +### `[policy]` — Network + +| Parameter | Default | Notes | +|-----------|---------|-------| +| `backbone_hidden_size` | `512` | | +| `split_network` | `False` | GigaFlow network vs LSTM | +| `encoder_gigaflow` | `False` | | +| `dropout` | `0.0` | | + +## Notebooks + +| Notebook | Purpose | +|----------|---------| +| `01_observations.ipynb` | Verify obs vector packing, normalization, interpretability | +| `02_rewards.ipynb` | Reward magnitudes, component breakdown, correlation with behavior | +| `03_metrics.ipynb` | Episode metrics, `vec_log` aggregation, episode boundary handling | +| `04_training.ipynb` | End-to-end data flow: env → policy → loss; encoding, sampling, advantages, gradients | +| `05_inference.ipynb` | Config loading, policy forward pass, rollouts (det. vs stochastic), value accuracy, LSTM state | +| `06_architecture.ipynb` | Model summary, per-encoder breakdown, forward pass shape tracing, weight distributions | + + +## Debug + +**C build issues** ```bash -puffer eval puffer_drive --eval.wosac-realism-eval True --load-model-path .pt -``` - -### Human-compatibility - -You may be interested in how compatible your agent is with human partners. For this purpose, we support an eval where your policy only controls the self-driving car (SDC). The rest of the agents in the scene are stepped using the logs. While it is not a perfect eval since the human partners here are static, it will still give you a sense of how closely aligned your agent's behavior is to how people drive. You can run it like this: -```bash -puffer eval puffer_drive --eval.human-replay-eval True --load-model-path .pt -``` - -## Development - -
Documentation and browser demo - -**Docs** - -A browsable documentation site now lives under `docs/` and is configured with mkbooks. To preview locally: -``` -brew install mdbook -mdbook serve --open docs -``` -Open the served URL to see a local version of the docs. - -**Interactive demo** - -To edit the browser demo, follow these steps: -- Download [emscripten](https://github.com/emscripten-core/emscripten) -- emscripten install latest -- Activate: `source emsdk/emsdk_env.sh` -- Run `bash scripts/build_ocean.sh drive web` -- This generates a number of `game*` files, move them to `assets/` to include them on the webpage - -
- +# Verbose build with AddressSanitizer +DEBUG=1 python setup.py build_ext --inplace --force -## Citation +# Skip unrelated extensions +NO_OCEAN=1 python setup.py build_ext --inplace --force +NO_TRAIN=1 python setup.py build_ext --inplace --force -If you use PufferDrive in your research, please cite: -```bibtex -@software{pufferdrive2025github, - author = {Daphne Cornelisse* and Spencer Cheng* and Pragnay Mandavilli and Julian Hunt and Kevin Joseph and Waël Doulazmi and Valentin Charraut and Aditya Gupta and Joseph Suarez and Eugene Vinitsky}, - title = {{PufferDrive}: A Fast and Friendly Driving Simulator for Training and Evaluating {RL} Agents}, - url = {https://github.com/Emerge-Lab/PufferDrive}, - version = {2.0.0}, - year = {2025}, -} +# Debug train +CUDA_VISIBLE_DEVICES=None LD_PRELOAD=$(gcc -print-file-name=libasan.so) python -m pufferlib.pufferl train puffer_drive --train.device cpu --vec.backend Serial +# or +gdb --args python -m pufferlib.pufferl train puffer_drive --train.device cpu --vec.backend Serial ``` diff --git a/data_utils/carla/carla/Town01_0.json b/data_utils/carla/carla/Town01_0.json new file mode 100644 index 0000000000..21b0fbec47 --- /dev/null +++ b/data_utils/carla/carla/Town01_0.json @@ -0,0 +1,107229 @@ +{ + "name": "Town01", + "scenario_id": "N0KHWCZZgZhX", + "objects": [ + { + "position": [ + { + "x": 92.37733991874609, + "y": -48.26687711506169, + "z": 1.0 + }, + { + "x": 92.37727862621773, + "y": -47.863670458684396, + "z": 1.0 + }, + { + "x": 92.37720201055727, + "y": -47.359662138212784, + "z": 1.0 + }, + { + "x": 92.37711007176472, + "y": -46.75485215364684, + "z": 1.0 + }, + { + "x": 92.37704877923635, + "y": -46.35164549726926, + "z": 1.0 + }, + { + "x": 92.37701813297217, + "y": -46.15004216908089, + "z": 1.0 + }, + { + "x": 92.37694183367158, + "y": -45.648114989838035, + "z": 1.0 + }, + { + "x": 92.37688083639642, + "y": -45.24685062665783, + "z": 1.0 + }, + { + "x": 92.3767893404837, + "y": -44.644954081888244, + "z": 1.0 + }, + { + "x": 92.37669784457097, + "y": -44.04305753711837, + "z": 1.0 + }, + { + "x": 92.37663684729581, + "y": -43.64179317393818, + "z": 1.0 + }, + { + "x": 92.37654535138309, + "y": -43.039896629168595, + "z": 1.0 + }, + { + "x": 92.37645385547036, + "y": -42.43800008439872, + "z": 1.0 + }, + { + "x": 92.3763928581952, + "y": -42.036735721218534, + "z": 1.0 + }, + { + "x": 92.37630136228248, + "y": -41.434839176448946, + "z": 1.0 + }, + { + "x": 92.37622511568853, + "y": -40.93325872247377, + "z": 1.0 + }, + { + "x": 92.37616411841337, + "y": -40.53199435929386, + "z": 1.0 + }, + { + "x": 92.37607262250064, + "y": -39.93009781452399, + "z": 1.0 + }, + { + "x": 92.3760116252255, + "y": -39.52883345134437, + "z": 1.0 + }, + { + "x": 92.37592012931276, + "y": -38.92693690657421, + "z": 1.0 + }, + { + "x": 92.37585913203762, + "y": -38.52567254339458, + "z": 1.0 + }, + { + "x": 92.37578288544367, + "y": -38.02409208941941, + "z": 1.0 + }, + { + "x": 92.37572188816851, + "y": -37.62282772623949, + "z": 1.0 + }, + { + "x": 92.37563039225579, + "y": -37.02093118146962, + "z": 1.0 + }, + { + "x": 92.37555414566185, + "y": -36.51935072749474, + "z": 1.0 + }, + { + "x": 92.3754931483867, + "y": -36.11808636431482, + "z": 1.0 + }, + { + "x": 92.37541690179276, + "y": -35.61650591034021, + "z": 1.0 + }, + { + "x": 92.37532540588003, + "y": -35.01460936557035, + "z": 1.0 + }, + { + "x": 92.37526440860488, + "y": -34.61334500239043, + "z": 1.0 + }, + { + "x": 92.37518816201093, + "y": -34.11176454841525, + "z": 1.0 + }, + { + "x": 92.37512716473579, + "y": -33.71050018523563, + "z": 1.0 + }, + { + "x": 92.37505091814184, + "y": -33.20891973126045, + "z": 1.0 + }, + { + "x": 92.37495942222911, + "y": -32.60702318649058, + "z": 1.0 + }, + { + "x": 92.37488317563518, + "y": -32.10544273251598, + "z": 1.0 + }, + { + "x": 92.37482217836002, + "y": -31.704178369336063, + "z": 1.0 + }, + { + "x": 92.37474593176607, + "y": -31.202597915360887, + "z": 1.0 + }, + { + "x": 92.37466968517214, + "y": -30.701017461385998, + "z": 1.0 + }, + { + "x": 92.37460868789698, + "y": -30.299753098206086, + "z": 1.0 + }, + { + "x": 92.37453244130305, + "y": -29.798172644231478, + "z": 1.0 + }, + { + "x": 92.37447144402789, + "y": -29.39690828105128, + "z": 1.0 + }, + { + "x": 92.37437994811516, + "y": -28.795011736281694, + "z": 1.0 + }, + { + "x": 92.37430370152121, + "y": -28.29343128230652, + "z": 1.0 + }, + { + "x": 92.37421220560849, + "y": -27.691534737536653, + "z": 1.0 + }, + { + "x": 92.37415120833333, + "y": -27.29027037435674, + "z": 1.0 + }, + { + "x": 92.3740749617394, + "y": -26.788689920381852, + "z": 1.0 + }, + { + "x": 92.37398346582667, + "y": -26.18679337561198, + "z": 1.0 + }, + { + "x": 92.37390721923272, + "y": -25.685212921637092, + "z": 1.0 + }, + { + "x": 92.37384622195758, + "y": -25.28394855845746, + "z": 1.0 + }, + { + "x": 92.37376997536363, + "y": -24.782368104482284, + "z": 1.0 + }, + { + "x": 92.37370897808847, + "y": -24.381103741302372, + "z": 1.0 + }, + { + "x": 92.37364798081333, + "y": -23.97983937812274, + "z": 1.0 + }, + { + "x": 92.37355648490059, + "y": -23.377942833352595, + "z": 1.0 + }, + { + "x": 92.37349548762545, + "y": -22.976678470172963, + "z": 1.0 + }, + { + "x": 92.37340399171272, + "y": -22.37478192540309, + "z": 1.0 + }, + { + "x": 92.37334299443756, + "y": -21.9735175622229, + "z": 1.0 + }, + { + "x": 92.37325149852484, + "y": -21.371621017453307, + "z": 1.0 + }, + { + "x": 92.37317525193089, + "y": -20.87004056347814, + "z": 1.0 + }, + { + "x": 92.37308375601816, + "y": -20.268144018708266, + "z": 1.0 + }, + { + "x": 92.37299226010543, + "y": -19.6662474739384, + "z": 1.0 + }, + { + "x": 92.3729007641927, + "y": -19.06435092916853, + "z": 1.0 + }, + { + "x": 92.37283976691755, + "y": -18.66308656598862, + "z": 1.0 + }, + { + "x": 92.37274827100482, + "y": -18.06119002121876, + "z": 1.0 + }, + { + "x": 92.37267202441087, + "y": -17.55960956724387, + "z": 1.0 + }, + { + "x": 92.37258052849815, + "y": -16.957713022474007, + "z": 1.0 + }, + { + "x": 92.372519531223, + "y": -16.556448659294382, + "z": 1.0 + }, + { + "x": 92.37244328462906, + "y": -16.054868205319213, + "z": 1.0 + }, + { + "x": 92.37236703803512, + "y": -15.553287751344609, + "z": 1.0 + }, + { + "x": 92.37230604075997, + "y": -15.152023388164416, + "z": 1.0 + }, + { + "x": 92.37224504348481, + "y": -14.750759024984504, + "z": 1.0 + }, + { + "x": 92.37218404620965, + "y": -14.349494661804595, + "z": 1.0 + }, + { + "x": 92.37210779961572, + "y": -13.847914207829707, + "z": 1.0 + }, + { + "x": 92.37204680234056, + "y": -13.446649844649794, + "z": 1.0 + }, + { + "x": 92.3719858050654, + "y": -13.045385481469882, + "z": 1.0 + }, + { + "x": 92.37189430915268, + "y": -12.443488936700017, + "z": 1.0 + }, + { + "x": 92.37180281323995, + "y": -11.841592391930153, + "z": 1.0 + }, + { + "x": 92.37172656664602, + "y": -11.340011937955548, + "z": 1.0 + }, + { + "x": 92.37171131732723, + "y": -11.239695847160288, + "z": 1.0 + }, + { + "x": 92.37165010369664, + "y": -10.837008211690133, + "z": 1.0 + }, + { + "x": 92.37157358665839, + "y": -10.333648667352328, + "z": 1.0 + }, + { + "x": 92.37149706962015, + "y": -9.830289123014808, + "z": 1.0 + }, + { + "x": 92.37142055258188, + "y": -9.326929578676726, + "z": 1.0 + }, + { + "x": 92.37135933895128, + "y": -8.924241943206486, + "z": 1.0 + }, + { + "x": 92.37128282191303, + "y": -8.420882398868397, + "z": 1.0 + }, + { + "x": 92.38387847983404, + "y": -7.926753944901536, + "z": 1.0 + }, + { + "x": 92.41037157599465, + "y": -7.620861084595008, + "z": 1.0 + }, + { + "x": 92.45147026774205, + "y": -7.316185300747591, + "z": 1.0 + }, + { + "x": 92.50702318936625, + "y": -7.013812440974701, + "z": 1.0 + }, + { + "x": 92.59659554589444, + "y": -6.640127905133789, + "z": 1.0 + }, + { + "x": 92.68416038829855, + "y": -6.345430981750049, + "z": 1.0 + }, + { + "x": 92.8415494737095, + "y": -5.9120333829588265, + "z": 1.0 + }, + { + "x": 93.02946380436408, + "y": -5.490972509787698, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 1, + "heading": [ + 1.5541722980230424, + 1.5709483394834673, + 1.570948339483483, + 1.5709483394834929, + 1.5709483394834955, + 1.5709483394834909, + 1.570948339483491, + 1.5709483394834989, + 1.5709483394834896, + 1.570948339483485, + 1.5709483394834896, + 1.5709483394834896, + 1.570948339483485, + 1.5709483394834896, + 1.5709483394834896, + 1.5709483394834933, + 1.5709483394835004, + 1.5709483394834896, + 1.5709483394834753, + 1.5709483394834896, + 1.5709483394834896, + 1.570948339483485, + 1.5709483394835004, + 1.5709483394834896, + 1.5709483394834804, + 1.570948339483485, + 1.570948339483485, + 1.5709483394834804, + 1.5709483394834896, + 1.5709483394835004, + 1.570948339483485, + 1.570948339483485, + 1.5709483394834933, + 1.5709483394834804, + 1.570948339483485, + 1.5709483394835004, + 1.5709483394834896, + 1.570948339483485, + 1.570948339483485, + 1.570948339483485, + 1.5709483394834896, + 1.5709483394834933, + 1.5709483394834933, + 1.5709483394834896, + 1.570948339483485, + 1.5709483394834804, + 1.5709483394834933, + 1.570948339483485, + 1.570948339483485, + 1.5709483394835004, + 1.570948339483479, + 1.5709483394834896, + 1.5709483394834896, + 1.5709483394834753, + 1.5709483394834896, + 1.5709483394834896, + 1.5709483394834933, + 1.5709483394834933, + 1.570948339483485, + 1.570948339483485, + 1.5709483394834896, + 1.5709483394834896, + 1.5709483394834933, + 1.5709483394834933, + 1.5709483394834753, + 1.570948339483485, + 1.5709483394834896, + 1.570948339483485, + 1.5709483394834967, + 1.5709483394834967, + 1.570948339483485, + 1.570948339483485, + 1.5709483394834967, + 1.5709483394834896, + 1.570948339483485, + 1.5709483394834804, + 1.570948339483485, + 1.5709483394834682, + 1.570948339483472, + 1.5709483394834736, + 1.5709483394834878, + 1.5709483394835033, + 1.5709483394834878, + 1.5582463175408183, + 1.5219755106522177, + 1.4605422460017705, + 1.4129059797025108, + 1.3593412115275172, + 1.3117280718770892, + 1.2462600242857522, + 1.1867436228401171 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -0.00061292528357626, + "y": 4.032066563772929 + }, + { + "x": -0.0013790818881886935, + "y": 9.072149768489055 + }, + { + "x": -0.001685544530118932, + "y": 11.08818305037559 + }, + { + "x": -0.001532313209224867, + "y": 10.080166409435236 + }, + { + "x": -0.0009193879255064985, + "y": 6.048099845659465 + }, + { + "x": -0.001069455647666473, + "y": 7.035305074312248 + }, + { + "x": -0.00137296575744017, + "y": 9.03191542423059 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079497912 + }, + { + "x": -0.0018299182545433723, + "y": 12.037930895394595 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079500612 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0018299182545433723, + "y": 12.037930895394595 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079500612 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.001677425066759497, + "y": 11.034769987447675 + }, + { + "x": -0.0013724386910496378, + "y": 9.028448171550849 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0015249318786914046, + "y": 10.031609079494928 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079497912 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171548007 + }, + { + "x": -0.0013724386910496378, + "y": 9.028448171550849 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079497912 + }, + { + "x": -0.0016774250666173884, + "y": 11.034769987447532 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171548007 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171545307 + }, + { + "x": -0.0016774250666173884, + "y": 11.03476998744469 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0013724386910496378, + "y": 9.028448171550991 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171548007 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171548007 + }, + { + "x": -0.001677425066759497, + "y": 11.034769987450517 + }, + { + "x": -0.0016774250666173884, + "y": 11.03476998744469 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171545165 + }, + { + "x": -0.0013724386910496378, + "y": 9.028448171550956 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079500647 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171548007 + }, + { + "x": -0.0013724386909075292, + "y": 9.0284481715452 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171548042 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949784 + }, + { + "x": -0.001677425066759497, + "y": 11.034769987447604 + }, + { + "x": -0.001677425066759497, + "y": 11.03476998745041 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079497805 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171548007 + }, + { + "x": -0.0016774250666173884, + "y": 11.034769987447604 + }, + { + "x": -0.001677425066759497, + "y": 11.034769987447604 + }, + { + "x": -0.0013724386909075292, + "y": 9.0284481715452 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171548078 + }, + { + "x": -0.0013724386910496378, + "y": 9.028448171550885 + }, + { + "x": -0.0012199455029815454, + "y": 8.025287263595438 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0015249318786914046, + "y": 10.031609079495034 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079500647 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949784 + }, + { + "x": -0.001677425066759497, + "y": 11.034769987447604 + }, + { + "x": -0.001677425066759497, + "y": 11.03476998745041 + }, + { + "x": -0.0018299182545433723, + "y": 12.037930895397366 + }, + { + "x": -0.0018299182545433723, + "y": 12.037930895397366 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079497805 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079497699 + }, + { + "x": -0.001677425066759497, + "y": 11.034769987447497 + }, + { + "x": -0.001677425066759497, + "y": 11.034769987447532 + }, + { + "x": -0.0015249318786914046, + "y": 10.031609079494892 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171547936 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079497734 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171547971 + }, + { + "x": -0.001219945503123654, + "y": 8.02528726360105 + }, + { + "x": -0.001219945503123654, + "y": 8.025287263598209 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171547971 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171548007 + }, + { + "x": -0.001219945503123654, + "y": 8.025287263598244 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0018299182545433723, + "y": 12.037930895397295 + }, + { + "x": -0.0016774250666173884, + "y": 11.03476998744469 + }, + { + "x": -0.0009149591272716862, + "y": 6.018965447698648 + }, + { + "x": -0.0007646294938012943, + "y": 5.0300372626541545 + }, + { + "x": -0.0013773066883970841, + "y": 9.060471798079597 + }, + { + "x": -0.0015303407649014389, + "y": 10.067190886753252 + }, + { + "x": -0.0015303407650435474, + "y": 10.067190886756023 + }, + { + "x": -0.0013773066886813012, + "y": 9.06047179808322 + }, + { + "x": -0.0013773066885391927, + "y": 9.060471798083292 + }, + { + "x": 0.1251914088275896, + "y": 9.974879983049494 + }, + { + "x": 0.3908875408161805, + "y": 8.000213142733887 + }, + { + "x": 0.6759178790801457, + "y": 6.105686441539451 + }, + { + "x": 0.9665161337160555, + "y": 6.070486436203071 + }, + { + "x": 1.4512527815239196, + "y": 6.760573956138023 + }, + { + "x": 1.7713719893230007, + "y": 6.683814592246522 + }, + { + "x": 2.44953927815061, + "y": 7.280945221749624 + }, + { + "x": 3.453034160655335, + "y": 8.544584719623511 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 93.02946380436408, + "y": -5.490972509787698, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 88.39124251873497, + "y": -139.72401945159578, + "z": 1.0 + }, + { + "x": 88.3913191036827, + "y": -140.22782573152114, + "z": 1.0 + }, + { + "x": 88.39141100561999, + "y": -140.83239326743148, + "z": 1.0 + }, + { + "x": 88.3914875905677, + "y": -141.33619954735684, + "z": 1.0 + }, + { + "x": 88.39156417551544, + "y": -141.84000582728214, + "z": 1.0 + }, + { + "x": 88.39156417551544, + "y": -141.84000582728214, + "z": 1.0 + }, + { + "x": 88.39162514892526, + "y": -142.2411131951493, + "z": 1.0 + }, + { + "x": 88.39168607725401, + "y": -142.6419240013292, + "z": 1.0 + }, + { + "x": 88.39176223766492, + "y": -143.14293750905404, + "z": 1.0 + }, + { + "x": 88.39185363015802, + "y": -143.74415371832356, + "z": 1.0 + }, + { + "x": 88.39191455848675, + "y": -144.14496452450373, + "z": 1.0 + }, + { + "x": 88.3919754868155, + "y": -144.54577533068306, + "z": 1.0 + }, + { + "x": 88.39203641514422, + "y": -144.94658613686346, + "z": 1.0 + }, + { + "x": 88.39209734347294, + "y": -145.34739694304335, + "z": 1.0 + }, + { + "x": 88.39217350388387, + "y": -145.84841045076791, + "z": 1.0 + }, + { + "x": 88.3922344322126, + "y": -146.2492212569481, + "z": 1.0 + }, + { + "x": 88.39229536054133, + "y": -146.65003206312798, + "z": 1.0 + }, + { + "x": 88.39235628887006, + "y": -147.05084286930781, + "z": 1.0 + }, + { + "x": 88.3924172171988, + "y": -147.4516536754877, + "z": 1.0 + }, + { + "x": 88.39249337760971, + "y": -147.95266718321255, + "z": 1.0 + }, + { + "x": 88.39258477010281, + "y": -148.55388339248236, + "z": 1.0 + }, + { + "x": 88.39266093051373, + "y": -149.0548969002072, + "z": 1.0 + }, + { + "x": 88.39273709092465, + "y": -149.55591040793178, + "z": 1.0 + }, + { + "x": 88.39281325133557, + "y": -150.05692391565663, + "z": 1.0 + }, + { + "x": 88.3928741796643, + "y": -150.45773472183646, + "z": 1.0 + }, + { + "x": 88.39293510799303, + "y": -150.85854552801663, + "z": 1.0 + }, + { + "x": 88.39299603632178, + "y": -151.25935633419624, + "z": 1.0 + }, + { + "x": 88.39308742881487, + "y": -151.86057254346605, + "z": 1.0 + }, + { + "x": 88.39316358922578, + "y": -152.36158605119118, + "z": 1.0 + }, + { + "x": 88.39322451755451, + "y": -152.76239685737107, + "z": 1.0 + }, + { + "x": 88.39328544588325, + "y": -153.16320766355062, + "z": 1.0 + }, + { + "x": 88.39337683837634, + "y": -153.76442387282077, + "z": 1.0 + }, + { + "x": 88.39346823086944, + "y": -154.36564008209058, + "z": 1.0 + }, + { + "x": 88.39352915919818, + "y": -154.7664508882704, + "z": 1.0 + }, + { + "x": 88.39362055169128, + "y": -155.36766709754022, + "z": 1.0 + }, + { + "x": 88.39371194418439, + "y": -155.9688833068098, + "z": 1.0 + }, + { + "x": 88.3937881045953, + "y": -156.4698968145346, + "z": 1.0 + }, + { + "x": 88.39386426500621, + "y": -156.97091032225944, + "z": 1.0 + }, + { + "x": 88.39392519333495, + "y": -157.37172112843933, + "z": 1.0 + }, + { + "x": 88.39401658582806, + "y": -157.97293733770914, + "z": 1.0 + }, + { + "x": 88.39409274623897, + "y": -158.47395084543427, + "z": 1.0 + }, + { + "x": 88.39418413873207, + "y": -159.0751670547038, + "z": 1.0 + }, + { + "x": 88.39426029914299, + "y": -159.57618056242865, + "z": 1.0 + }, + { + "x": 88.3943364595539, + "y": -160.0771940701535, + "z": 1.0 + }, + { + "x": 88.39439738788263, + "y": -160.4780048763334, + "z": 1.0 + }, + { + "x": 88.39445831621137, + "y": -160.87881568251328, + "z": 1.0 + }, + { + "x": 88.39454970870446, + "y": -161.48003189178337, + "z": 1.0 + }, + { + "x": 88.39462586911537, + "y": -161.98104539950816, + "z": 1.0 + }, + { + "x": 88.39471726160848, + "y": -162.58226160877803, + "z": 1.0 + }, + { + "x": 88.39480865410158, + "y": -163.18347781804755, + "z": 1.0 + }, + { + "x": 88.39490004659467, + "y": -163.78469402731764, + "z": 1.0 + }, + { + "x": 88.3949609749234, + "y": -164.18550483349753, + "z": 1.0 + }, + { + "x": 88.39502190325214, + "y": -164.58631563967737, + "z": 1.0 + }, + { + "x": 88.39509806366306, + "y": -165.08732914740222, + "z": 1.0 + }, + { + "x": 88.39517422407398, + "y": -165.58834265512678, + "z": 1.0 + }, + { + "x": 88.3952503844849, + "y": -166.0893561628519, + "z": 1.0 + }, + { + "x": 88.39532654489581, + "y": -166.59036967057676, + "z": 1.0 + }, + { + "x": 88.39540270530674, + "y": -167.09138317830133, + "z": 1.0 + }, + { + "x": 88.39547886571765, + "y": -167.59239668602618, + "z": 1.0 + }, + { + "x": 88.39555502612856, + "y": -168.09341019375103, + "z": 1.0 + }, + { + "x": 88.39563118653948, + "y": -168.59442370147616, + "z": 1.0 + }, + { + "x": 88.39570734695039, + "y": -169.09543720920095, + "z": 1.0 + }, + { + "x": 88.39579873944349, + "y": -169.69665341847082, + "z": 1.0 + }, + { + "x": 88.3958748998544, + "y": -170.19766692619567, + "z": 1.0 + }, + { + "x": 88.39595106026533, + "y": -170.69868043392017, + "z": 1.0 + }, + { + "x": 88.39602722067625, + "y": -171.1996939416453, + "z": 1.0 + }, + { + "x": 88.39611861316935, + "y": -171.80091015091483, + "z": 1.0 + }, + { + "x": 88.39619477358026, + "y": -172.30192365863996, + "z": 1.0 + }, + { + "x": 88.39625570190898, + "y": -172.70273446481986, + "z": 1.0 + }, + { + "x": 88.39634709440209, + "y": -173.30395067408966, + "z": 1.0 + }, + { + "x": 88.39643848689519, + "y": -173.9051668833592, + "z": 1.0 + }, + { + "x": 88.39651464730612, + "y": -174.40618039108404, + "z": 1.0 + }, + { + "x": 88.39657557563484, + "y": -174.80699119726415, + "z": 1.0 + }, + { + "x": 88.39665173604575, + "y": -175.308004704989, + "z": 1.0 + }, + { + "x": 88.39671266437449, + "y": -175.70881551116884, + "z": 1.0 + }, + { + "x": 88.3968040568676, + "y": -176.31003172043836, + "z": 1.0 + }, + { + "x": 88.39688021727851, + "y": -176.8110452281632, + "z": 1.0 + }, + { + "x": 88.39695637768943, + "y": -177.312058735888, + "z": 1.0 + }, + { + "x": 88.39701730601816, + "y": -177.71286954206818, + "z": 1.0 + }, + { + "x": 88.39710869851126, + "y": -178.3140857513377, + "z": 1.0 + }, + { + "x": 88.39720009100436, + "y": -178.91530196060745, + "z": 1.0 + }, + { + "x": 88.39729148349745, + "y": -179.51651816987754, + "z": 1.0 + }, + { + "x": 88.39738287599056, + "y": -180.11773437914735, + "z": 1.0 + }, + { + "x": 88.3974438043193, + "y": -180.5185451853269, + "z": 1.0 + }, + { + "x": 88.39750473264803, + "y": -180.9193559915068, + "z": 1.0 + }, + { + "x": 88.39756566097675, + "y": -181.3201667976869, + "z": 1.0 + }, + { + "x": 88.39764182138767, + "y": -181.82118030541176, + "z": 1.0 + }, + { + "x": 88.39770274971642, + "y": -182.2219911115913, + "z": 1.0 + }, + { + "x": 88.39776367804514, + "y": -182.62280191777148, + "z": 1.0 + }, + { + "x": 88.39782460637387, + "y": -183.02361272395103, + "z": 1.0 + }, + { + "x": 88.3979007667848, + "y": -183.5246262316756, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 2, + "heading": [ + -1.5706443141063071, + -1.5706443141062971, + -1.5706443141062971, + -1.57064431410631, + -1.5706443141063113, + -1.5706443141062971, + -1.5706443141064466, + -1.5706443141063546, + -1.5706443141062902, + -1.5706443141063045, + -1.5706443141063122, + -1.570644314106298, + -1.570644314106298, + -1.5706443141063335, + -1.570644314106306, + -1.5706443141062902, + -1.5706443141063158, + -1.5706443141063158, + -1.570644314106298, + -1.570644314106306, + -1.5706443141063045, + -1.5706443141063045, + -1.570644314106298, + -1.570644314106298, + -1.570644314106306, + -1.5706443141063158, + -1.570644314106298, + -1.570644314106298, + -1.5706443141063176, + -1.570644314106306, + -1.570644314106298, + -1.5706443141063122, + -1.57064431410631, + -1.570644314106298, + -1.570644314106298, + -1.570644314106298, + -1.5706443141063045, + -1.5706443141063122, + -1.570644314106306, + -1.570644314106298, + -1.5706443141063047, + -1.5706443141063045, + -1.5706443141063045, + -1.5706443141063122, + -1.570644314106306, + -1.570644314106298, + -1.5706443141063122, + -1.5706443141063176, + -1.5706443141063045, + -1.570644314106298, + -1.57064431410631, + -1.5706443141063122, + -1.570644314106298, + -1.570644314106306, + -1.570644314106298, + -1.570644314106298, + -1.5706443141063122, + -1.570644314106298, + -1.570644314106298, + -1.5706443141063122, + -1.5706443141063122, + -1.5706443141063122, + -1.5706443141063045, + -1.5706443141063045, + -1.570644314106298, + -1.570644314106298, + -1.5706443141063045, + -1.5706443141063045, + -1.5706443141063218, + -1.5706443141063122, + -1.570644314106298, + -1.5706443141062916, + -1.570644314106306, + -1.5706443141063218, + -1.570644314106306, + -1.570644314106298, + -1.5706443141063045, + -1.570644314106298, + -1.570644314106306, + -1.5706443141063122, + -1.570644314106298, + -1.57064431410631, + -1.57064431410631, + -1.570644314106298, + -1.570644314106298, + -1.5706443141063158, + -1.5706443141063218, + -1.5706443141062902, + -1.570644314106298, + -1.5706443141063158, + -1.57064431410629 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0007658494773465918, + "y": -5.0380627992535665 + }, + { + "x": 0.001684868850162502, + "y": -11.08373815835705 + }, + { + "x": 0.0016848688500203934, + "y": -11.08373815835705 + }, + { + "x": 0.001531698954551075, + "y": -10.076125598506565 + }, + { + "x": 0.0007658494773465918, + "y": -5.038062799252998 + }, + { + "x": 0.0006097340981625621, + "y": -4.011073678671551 + }, + { + "x": 0.001219017385665211, + "y": -8.019181740470458 + }, + { + "x": 0.0013708873966322699, + "y": -9.0182431390474 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169943727 + }, + { + "x": 0.0015232082182592421, + "y": -10.020270154496984 + }, + { + "x": 0.0012185665747210805, + "y": -8.016216123594972 + }, + { + "x": 0.0012185665747210805, + "y": -8.016216123597246 + }, + { + "x": 0.0012185665744368634, + "y": -8.01621612360293 + }, + { + "x": 0.0013708873964901613, + "y": -9.018243139044557 + }, + { + "x": 0.0013708873966322699, + "y": -9.0182431390474 + }, + { + "x": 0.001218566574578972, + "y": -8.016216123600657 + }, + { + "x": 0.001218566574578972, + "y": -8.016216123597246 + }, + { + "x": 0.0012185665747210805, + "y": -8.016216123597246 + }, + { + "x": 0.0013708873964901613, + "y": -9.0182431390474 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169946569 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169946569 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154494142 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154494142 + }, + { + "x": 0.0013708873964901613, + "y": -9.018243139046831 + }, + { + "x": 0.001218566574578972, + "y": -8.016216123600088 + }, + { + "x": 0.0012185665747210805, + "y": -8.016216123597815 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154494142 + }, + { + "x": 0.001675529040028323, + "y": -11.022297169949411 + }, + { + "x": 0.0013708873964901613, + "y": -9.018243139050242 + }, + { + "x": 0.0012185665747210805, + "y": -8.016216123594404 + }, + { + "x": 0.0015232082182592421, + "y": -10.020270154496984 + }, + { + "x": 0.0018278498619395123, + "y": -12.024324185399564 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154496416 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154496416 + }, + { + "x": 0.0018278498620816208, + "y": -12.02432418539388 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169943727 + }, + { + "x": 0.0015232082182592421, + "y": -10.020270154496416 + }, + { + "x": 0.0013708873964901613, + "y": -9.0182431390474 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154496984 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169949411 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169946569 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169943727 + }, + { + "x": 0.0015232082182592421, + "y": -10.020270154496984 + }, + { + "x": 0.0013708873964901613, + "y": -9.0182431390474 + }, + { + "x": 0.0012185665747210805, + "y": -8.016216123597815 + }, + { + "x": 0.0015232082182592421, + "y": -10.020270154499826 + }, + { + "x": 0.001675529040028323, + "y": -11.022297169948843 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169946569 + }, + { + "x": 0.0018278498620816208, + "y": -12.02432418539388 + }, + { + "x": 0.0018278498619395123, + "y": -12.024324185396154 + }, + { + "x": 0.0015232082182592421, + "y": -10.020270154499826 + }, + { + "x": 0.0012185665747210805, + "y": -8.016216123597246 + }, + { + "x": 0.0013708873964901613, + "y": -9.018243139046831 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154494142 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154496984 + }, + { + "x": 0.0015232082182592421, + "y": -10.020270154499826 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154494142 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154494142 + }, + { + "x": 0.0015232082182592421, + "y": -10.020270154496984 + }, + { + "x": 0.0015232082182592421, + "y": -10.020270154499826 + }, + { + "x": 0.0015232082182592421, + "y": -10.020270154499258 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169946569 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169947137 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154493574 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154496416 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169946569 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169946569 + }, + { + "x": 0.0013708873963480528, + "y": -9.018243139050242 + }, + { + "x": 0.0015232082182592421, + "y": -10.020270154496984 + }, + { + "x": 0.0018278498620816208, + "y": -12.024324185393311 + }, + { + "x": 0.00167552904031254, + "y": -11.022297169943727 + }, + { + "x": 0.0013708873964901613, + "y": -9.018243139049673 + }, + { + "x": 0.0013708873963480528, + "y": -9.018243139049673 + }, + { + "x": 0.0013708873964901613, + "y": -9.018243139046831 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154493574 + }, + { + "x": 0.0016755290401704315, + "y": -11.022297169943727 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154496416 + }, + { + "x": 0.0013708873964901613, + "y": -9.018243139049673 + }, + { + "x": 0.0015232082182592421, + "y": -10.020270154496984 + }, + { + "x": 0.0018278498620816208, + "y": -12.024324185392743 + }, + { + "x": 0.0018278498619395123, + "y": -12.024324185398427 + }, + { + "x": 0.0018278498619395123, + "y": -12.024324185398996 + }, + { + "x": 0.0015232082184013507, + "y": -10.020270154493574 + }, + { + "x": 0.0012185665747210805, + "y": -8.016216123594404 + }, + { + "x": 0.001218566574578972, + "y": -8.016216123600088 + }, + { + "x": 0.0013708873963480528, + "y": -9.018243139049673 + }, + { + "x": 0.0013708873966322699, + "y": -9.018243139043989 + }, + { + "x": 0.0012185665747210805, + "y": -8.016216123597246 + }, + { + "x": 0.001218566574578972, + "y": -8.016216123597246 + }, + { + "x": 0.0013708873966322699, + "y": -9.018243139041147 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 88.3979007667848, + "y": -183.5246262316756, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 92.17738470449606, + "y": -5.543033931552639, + "z": 1.0 + }, + { + "x": 92.02893835203474, + "y": -4.9254451369259495, + "z": 1.0 + }, + { + "x": 91.83953272702882, + "y": -4.319165007001053, + "z": 1.0 + }, + { + "x": 91.55938507168747, + "y": -3.6103693432412705, + "z": 1.0 + }, + { + "x": 91.2232886141611, + "y": -2.92632261465836, + "z": 1.0 + }, + { + "x": 90.90160151268881, + "y": -2.3777725998696635, + "z": 1.0 + }, + { + "x": 90.46849895465499, + "y": -1.750514037920517, + "z": 1.0 + }, + { + "x": 89.98654266873672, + "y": -1.1600946235224388, + "z": 1.0 + }, + { + "x": 89.54979571361987, + "y": -0.6989172678760334, + "z": 1.0 + }, + { + "x": 89.08343174905256, + "y": -0.2681208996727509, + "z": 1.0 + }, + { + "x": 88.58937810804395, + "y": 0.13059820714422288, + "z": 1.0 + }, + { + "x": 87.96305420654113, + "y": 0.5642434078047397, + "z": 1.0 + }, + { + "x": 87.30318887392193, + "y": 0.9465681376052837, + "z": 1.0 + }, + { + "x": 86.73196755078408, + "y": 1.2236474556272232, + "z": 1.0 + }, + { + "x": 86.0240164078902, + "y": 1.5049320036980738, + "z": 1.0 + }, + { + "x": 85.41840054260388, + "y": 1.6954362312776485, + "z": 1.0 + }, + { + "x": 84.67690593435475, + "y": 1.8700932166469466, + "z": 1.0 + }, + { + "x": 83.923806202719, + "y": 1.9848547149246605, + "z": 1.0 + }, + { + "x": 83.41683773555708, + "y": 2.027617963707917, + "z": 1.0 + }, + { + "x": 82.90914004207372, + "y": 2.043181161697282, + "z": 1.0 + }, + { + "x": 82.48887153292773, + "y": 2.0432892540786893, + "z": 1.0 + }, + { + "x": 81.88708783985336, + "y": 2.043093126861388, + "z": 1.0 + }, + { + "x": 81.28530414677901, + "y": 2.0428969996440856, + "z": 1.0 + }, + { + "x": 80.88411501806277, + "y": 2.0427662481658846, + "z": 1.0 + }, + { + "x": 80.38262860716748, + "y": 2.042602808818133, + "z": 1.0 + }, + { + "x": 79.88114219627218, + "y": 2.0424393694703813, + "z": 1.0 + }, + { + "x": 79.37965578537688, + "y": 2.0422759301226296, + "z": 1.0 + }, + { + "x": 78.8789939970618, + "y": 2.0421127595274697, + "z": 1.0 + }, + { + "x": 78.37862787552477, + "y": 2.0419496852930257, + "z": 1.0 + }, + { + "x": 77.77818852968032, + "y": 2.0417539962116917, + "z": 1.0 + }, + { + "x": 77.2778224081433, + "y": 2.0415909219772477, + "z": 1.0 + }, + { + "x": 76.77745628660625, + "y": 2.0414278477428027, + "z": 1.0 + }, + { + "x": 76.27709016506921, + "y": 2.0412647735083587, + "z": 1.0 + }, + { + "x": 75.77672404353218, + "y": 2.0411016992739137, + "z": 1.0 + }, + { + "x": 75.37643114630255, + "y": 2.0409712398863586, + "z": 1.0 + }, + { + "x": 74.97613824907293, + "y": 2.0408407804988027, + "z": 1.0 + }, + { + "x": 74.47577212753589, + "y": 2.0406777062643586, + "z": 1.0 + }, + { + "x": 73.97540600599886, + "y": 2.0405146320299137, + "z": 1.0 + }, + { + "x": 73.57511310876923, + "y": 2.0403841726423577, + "z": 1.0 + }, + { + "x": 73.1748202115396, + "y": 2.0402537132548026, + "z": 1.0 + }, + { + "x": 72.67445409000257, + "y": 2.0400906390203577, + "z": 1.0 + }, + { + "x": 72.27416119277294, + "y": 2.0399601796328026, + "z": 1.0 + }, + { + "x": 71.7737950712359, + "y": 2.039797105398358, + "z": 1.0 + }, + { + "x": 71.37350217400628, + "y": 2.0396666460108026, + "z": 1.0 + }, + { + "x": 70.87313605246923, + "y": 2.0395035717763577, + "z": 1.0 + }, + { + "x": 70.37276993093221, + "y": 2.0393404975419136, + "z": 1.0 + }, + { + "x": 69.77233058508776, + "y": 2.0391448084605797, + "z": 1.0 + }, + { + "x": 69.17189123924332, + "y": 2.0389491193792466, + "z": 1.0 + }, + { + "x": 68.57145189339887, + "y": 2.0387534302979127, + "z": 1.0 + }, + { + "x": 67.97101254755444, + "y": 2.0385577412165796, + "z": 1.0 + }, + { + "x": 67.4706464260174, + "y": 2.0383946669821356, + "z": 1.0 + }, + { + "x": 67.07035352878778, + "y": 2.0382642075945796, + "z": 1.0 + }, + { + "x": 66.46991418294333, + "y": 2.0380685185132466, + "z": 1.0 + }, + { + "x": 65.9695480614063, + "y": 2.0379054442788016, + "z": 1.0 + }, + { + "x": 65.36910871556185, + "y": 2.0377097551974686, + "z": 1.0 + }, + { + "x": 64.96881581833222, + "y": 2.037579295809913, + "z": 1.0 + }, + { + "x": 64.36837647248778, + "y": 2.0373836067285795, + "z": 1.0 + }, + { + "x": 63.96808357525816, + "y": 2.0372531473410236, + "z": 1.0 + }, + { + "x": 63.36764422941371, + "y": 2.0370574582596905, + "z": 1.0 + }, + { + "x": 62.76720488356926, + "y": 2.0368617691783566, + "z": 1.0 + }, + { + "x": 62.36691198633963, + "y": 2.0367313097908015, + "z": 1.0 + }, + { + "x": 61.96661908911, + "y": 2.0366008504032456, + "z": 1.0 + }, + { + "x": 61.56632619188035, + "y": 2.0364703910156896, + "z": 1.0 + }, + { + "x": 61.16603329465072, + "y": 2.0363399316281345, + "z": 1.0 + }, + { + "x": 60.665667173113675, + "y": 2.0361768573936896, + "z": 1.0 + }, + { + "x": 60.065227827269226, + "y": 2.0359811683123565, + "z": 1.0 + }, + { + "x": 59.464788481424776, + "y": 2.0357854792310235, + "z": 1.0 + }, + { + "x": 58.964422359887735, + "y": 2.0356224049965785, + "z": 1.0 + }, + { + "x": 58.36398301404327, + "y": 2.0354267159152455, + "z": 1.0 + }, + { + "x": 57.76354366819882, + "y": 2.0352310268339115, + "z": 1.0 + }, + { + "x": 57.26317754666178, + "y": 2.0350679525994675, + "z": 1.0 + }, + { + "x": 56.66273820081733, + "y": 2.0348722635181336, + "z": 1.0 + }, + { + "x": 56.062298854972866, + "y": 2.0346765744368005, + "z": 1.0 + }, + { + "x": 55.66200595774323, + "y": 2.0345461150492445, + "z": 1.0 + }, + { + "x": 55.06156661189878, + "y": 2.0343504259679115, + "z": 1.0 + }, + { + "x": 54.56120049036174, + "y": 2.0341873517334665, + "z": 1.0 + }, + { + "x": 53.96076114451729, + "y": 2.0339916626521335, + "z": 1.0 + }, + { + "x": 53.46039502298024, + "y": 2.0338285884176894, + "z": 1.0 + }, + { + "x": 53.0601021257506, + "y": 2.0336981290301335, + "z": 1.0 + }, + { + "x": 52.65980922852097, + "y": 2.0335676696425775, + "z": 1.0 + }, + { + "x": 52.25951633129134, + "y": 2.0334372102550224, + "z": 1.0 + }, + { + "x": 51.859223434061704, + "y": 2.0333067508674665, + "z": 1.0 + }, + { + "x": 51.258784088217254, + "y": 2.0331110617861334, + "z": 1.0 + }, + { + "x": 50.65834474237279, + "y": 2.0329153727047995, + "z": 1.0 + }, + { + "x": 50.25805184514316, + "y": 2.0327849133172444, + "z": 1.0 + }, + { + "x": 49.65761249929871, + "y": 2.0325892242359105, + "z": 1.0 + }, + { + "x": 49.257319602069074, + "y": 2.0324587648483554, + "z": 1.0 + }, + { + "x": 48.85702670483944, + "y": 2.0323283054607995, + "z": 1.0 + }, + { + "x": 48.25658735899499, + "y": 2.0321326163794664, + "z": 1.0 + }, + { + "x": 47.65614801315053, + "y": 2.0319369272981325, + "z": 1.0 + }, + { + "x": 47.155781891613486, + "y": 2.0317738530636884, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 3, + "heading": [ + -1.8948221592538605, + 1.8066858210761172, + 1.8401406999963243, + 1.913741599788107, + 1.9873425501355715, + 2.0610054059259815, + 2.1414792235087416, + 2.215243017273065, + 2.2888481200291793, + 2.362398683948051, + 2.4291969436707634, + 2.5026304445853182, + 2.5762559620189145, + 2.649850799449807, + 2.730018525577581, + 2.7967754706062085, + 2.8768838068652123, + 2.950316514123116, + 3.017224983051775, + 3.0841724570389077, + 3.124706477370499, + -3.141506518228522, + -3.141266743777655, + -3.1412667437776545, + -3.141266743777655, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776465, + -3.141266743777647, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776536, + -3.141266743777655, + -3.1412667437776545, + -3.1412667437776545, + -3.141266743777655, + -3.1412667437776545, + -3.141266743777654, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776554, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.141266743777655, + -3.1412667437776545, + -3.141266743777654, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.141266743777655, + -3.1412667437776536, + -3.141266743777655, + -3.1412667437776545, + -3.1412667437776545, + -3.141266743777655, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776554, + -3.1412667437776545, + -3.1412667437776536, + -3.141266743777655, + -3.141266743777655, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.141266743777655, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -1.4844635246132043, + "y": 6.175887946266894 + }, + { + "x": -3.378519774672384, + "y": 12.23868924551586 + }, + { + "x": -4.695532803472702, + "y": 13.15075793684679 + }, + { + "x": -6.162441128677187, + "y": 13.928423923426928 + }, + { + "x": -6.5778355899865915, + "y": 12.32596743371607 + }, + { + "x": -7.547896595061161, + "y": 11.758085767378429 + }, + { + "x": -9.15058843952096, + "y": 12.176779763472247 + }, + { + "x": -9.18703241035118, + "y": 10.515967700444836 + }, + { + "x": -9.031109196841527, + "y": 8.919737238496879 + }, + { + "x": -9.604176055759268, + "y": 8.295154750202562 + }, + { + "x": -11.203775425114344, + "y": 8.323643074774905 + }, + { + "x": -12.861892341220198, + "y": 8.159699304610607 + }, + { + "x": -12.310866557570534, + "y": 6.5940404782248345 + }, + { + "x": -12.791724660317243, + "y": 5.5836386609279005 + }, + { + "x": -13.135670081802004, + "y": 4.717887756504253 + }, + { + "x": -13.471104735354515, + "y": 3.6516121294887283 + }, + { + "x": -14.945943398848698, + "y": 2.8941848364701195 + }, + { + "x": -12.600681987976685, + "y": 1.575247470609702 + }, + { + "x": -10.14666160645291, + "y": 0.5832644677262144 + }, + { + "x": -9.279662026293494, + "y": 0.15671290370772528 + }, + { + "x": -10.220522022203511, + "y": -0.0008803483589403527 + }, + { + "x": -12.035673861487197, + "y": -0.003922544346037782 + }, + { + "x": -10.029728217905927, + "y": -0.003268786955032965 + }, + { + "x": -9.026755396115362, + "y": -0.002941908259526116 + }, + { + "x": -10.029728217905927, + "y": -0.003268786955032965 + }, + { + "x": -10.029728217905927, + "y": -0.003268786955032965 + }, + { + "x": -10.021481992103816, + "y": -0.0032660994291155987 + }, + { + "x": -10.010279098521124, + "y": -0.0032624482960397216 + }, + { + "x": -11.008054673814769, + "y": -0.0035876331577799903 + }, + { + "x": -11.008054673814769, + "y": -0.0035876331577799903 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -8.00585794459252, + "y": -0.002609187751110298 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -9.006590187666603, + "y": -0.002935336220009077 + }, + { + "x": -8.005857944592663, + "y": -0.002609187751110298 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -9.006590187666745, + "y": -0.0029353362199957544 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200046362 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673814769, + "y": -0.0035876331577799903 + }, + { + "x": -12.008786916888852, + "y": -0.003913781626669888 + }, + { + "x": -12.008786916888852, + "y": -0.003913781626669888 + }, + { + "x": -12.008786916888852, + "y": -0.003913781626669888 + }, + { + "x": -11.008054673814769, + "y": -0.0035876331577711085 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673814769, + "y": -0.0035876331577799903 + }, + { + "x": -11.008054673814769, + "y": -0.0035876331577799903 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688885652 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -10.007322430740544, + "y": -0.0032614846888945337 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -12.008786916888994, + "y": -0.003913781626669888 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -8.005857944592663, + "y": -0.002609187751110298 + }, + { + "x": -8.005857944592805, + "y": -0.0026091877511191797 + }, + { + "x": -8.005857944592805, + "y": -0.002609187751110298 + }, + { + "x": -9.006590187666745, + "y": -0.0029353362200001953 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -12.008786916888994, + "y": -0.003913781626661006 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -11.008054673815053, + "y": -0.0035876331577799903 + }, + { + "x": -12.008786916889136, + "y": -0.003913781626669888 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -12.008786916889136, + "y": -0.003913781626669888 + }, + { + "x": -10.00732243074097, + "y": -0.003261484688890093 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -11.008054673815053, + "y": -0.0035876331577711085 + }, + { + "x": -9.006590187666887, + "y": -0.0029353362200001953 + }, + { + "x": -8.005857944592663, + "y": -0.0026091877511191797 + }, + { + "x": -8.005857944592663, + "y": -0.002609187751110298 + }, + { + "x": -8.005857944592663, + "y": -0.002609187751110298 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -12.008786916889136, + "y": -0.003913781626669888 + }, + { + "x": -10.00732243074097, + "y": -0.003261484688890093 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -8.005857944592663, + "y": -0.002609187751110298 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -12.008786916889136, + "y": -0.003913781626669888 + }, + { + "x": -11.008054673815053, + "y": -0.0035876331577799903 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 47.155781891613486, + "y": 2.0317738530636884, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 161.64683250352334, + "y": 2.0437492128140557, + "z": 1.0 + }, + { + "x": 161.1442238107338, + "y": 2.0438028558703465, + "z": 1.0 + }, + { + "x": 160.64161511794427, + "y": 2.0438564989266377, + "z": 1.0 + }, + { + "x": 160.23952816371266, + "y": 2.0438994133716704, + "z": 1.0 + }, + { + "x": 159.63639773236523, + "y": 2.0439637850392196, + "z": 1.0 + }, + { + "x": 159.13378903957567, + "y": 2.0440174280955103, + "z": 1.0 + }, + { + "x": 158.53065860822824, + "y": 2.0440817997630596, + "z": 1.0 + }, + { + "x": 157.92752817688083, + "y": 2.0441461714306093, + "z": 1.0 + }, + { + "x": 157.5254412226492, + "y": 2.0441890858756424, + "z": 1.0 + }, + { + "x": 157.12335426841756, + "y": 2.044232000320675, + "z": 1.0 + }, + { + "x": 156.72126731418595, + "y": 2.0442749147657078, + "z": 1.0 + }, + { + "x": 156.2186586213964, + "y": 2.0443285578219985, + "z": 1.0 + }, + { + "x": 155.8165716671648, + "y": 2.044371472267032, + "z": 1.0 + }, + { + "x": 155.41448471293316, + "y": 2.0444143867120648, + "z": 1.0 + }, + { + "x": 154.91187602014364, + "y": 2.044468029768356, + "z": 1.0 + }, + { + "x": 154.40926732735412, + "y": 2.0445216728246467, + "z": 1.0 + }, + { + "x": 153.90665863456456, + "y": 2.0445753158809374, + "z": 1.0 + }, + { + "x": 153.50457168033296, + "y": 2.044618230325971, + "z": 1.0 + }, + { + "x": 152.90144124898552, + "y": 2.0446826019935203, + "z": 1.0 + }, + { + "x": 152.29831081763808, + "y": 2.0447469736610695, + "z": 1.0 + }, + { + "x": 151.89622386340645, + "y": 2.044789888106102, + "z": 1.0 + }, + { + "x": 151.293093432059, + "y": 2.0448542597736514, + "z": 1.0 + }, + { + "x": 150.79048473926946, + "y": 2.0449079028299426, + "z": 1.0 + }, + { + "x": 150.18735430792202, + "y": 2.044972274497492, + "z": 1.0 + }, + { + "x": 149.6847456151325, + "y": 2.045025917553783, + "z": 1.0 + }, + { + "x": 149.28265866090086, + "y": 2.0450688319988157, + "z": 1.0 + }, + { + "x": 148.6795282295534, + "y": 2.0451332036663645, + "z": 1.0 + }, + { + "x": 148.2774412753218, + "y": 2.045176118111398, + "z": 1.0 + }, + { + "x": 147.87535432109016, + "y": 2.045219032556431, + "z": 1.0 + }, + { + "x": 147.2722238897427, + "y": 2.04528340422398, + "z": 1.0 + }, + { + "x": 146.87013693551108, + "y": 2.0453263186690127, + "z": 1.0 + }, + { + "x": 146.36752824272153, + "y": 2.045379961725304, + "z": 1.0 + }, + { + "x": 145.9654412884899, + "y": 2.0454228761703366, + "z": 1.0 + }, + { + "x": 145.46283259570038, + "y": 2.0454765192266278, + "z": 1.0 + }, + { + "x": 145.06074564146874, + "y": 2.045519433671661, + "z": 1.0 + }, + { + "x": 144.96022390291083, + "y": 2.045530162282919, + "z": 1.0 + }, + { + "x": 144.5595603980998, + "y": 2.0455729248042416, + "z": 1.0 + }, + { + "x": 144.05873101708605, + "y": 2.045626377955895, + "z": 1.0 + }, + { + "x": 143.55790163607227, + "y": 2.045679831107548, + "z": 1.0 + }, + { + "x": 143.15723813126127, + "y": 2.0457225936288705, + "z": 1.0 + }, + { + "x": 142.75657462645026, + "y": 2.045765356150193, + "z": 1.0 + }, + { + "x": 142.25574524543651, + "y": 2.0458188093018466, + "z": 1.0 + }, + { + "x": 141.8550817406255, + "y": 2.045861571823169, + "z": 1.0 + }, + { + "x": 141.4544182358145, + "y": 2.045904334344492, + "z": 1.0 + }, + { + "x": 140.95358885480073, + "y": 2.045957787496145, + "z": 1.0 + }, + { + "x": 140.35259359758422, + "y": 2.0460219312781294, + "z": 1.0 + }, + { + "x": 139.85176421657047, + "y": 2.0460753844297823, + "z": 1.0 + }, + { + "x": 139.45110071175947, + "y": 2.046118146951105, + "z": 1.0 + }, + { + "x": 138.85010545454296, + "y": 2.046182290733089, + "z": 1.0 + }, + { + "x": 138.44944194973195, + "y": 2.0462250532544117, + "z": 1.0 + }, + { + "x": 138.04877844492094, + "y": 2.0462678157757344, + "z": 1.0 + }, + { + "x": 137.44778318770443, + "y": 2.046331959557718, + "z": 1.0 + }, + { + "x": 136.9469538066907, + "y": 2.0463854127093715, + "z": 1.0 + }, + { + "x": 136.54629030187968, + "y": 2.046428175230694, + "z": 1.0 + }, + { + "x": 136.14562679706867, + "y": 2.0464709377520167, + "z": 1.0 + }, + { + "x": 135.74496329225767, + "y": 2.0465137002733393, + "z": 1.0 + }, + { + "x": 135.34429978744666, + "y": 2.046556462794662, + "z": 1.0 + }, + { + "x": 134.94363628263565, + "y": 2.0465992253159846, + "z": 1.0 + }, + { + "x": 134.34264102541917, + "y": 2.0466633690979688, + "z": 1.0 + }, + { + "x": 133.74164576820266, + "y": 2.0467275128799525, + "z": 1.0 + }, + { + "x": 133.34098226339165, + "y": 2.046770275401275, + "z": 1.0 + }, + { + "x": 132.8401528823779, + "y": 2.0468237285529285, + "z": 1.0 + }, + { + "x": 132.2391576251614, + "y": 2.0468878723349127, + "z": 1.0 + }, + { + "x": 131.73832824414762, + "y": 2.0469413254865656, + "z": 1.0 + }, + { + "x": 131.23749886313388, + "y": 2.046994778638219, + "z": 1.0 + }, + { + "x": 130.73666948212013, + "y": 2.0470482317898724, + "z": 1.0 + }, + { + "x": 130.33600597730913, + "y": 2.047090994311195, + "z": 1.0 + }, + { + "x": 129.83517659629538, + "y": 2.0471444474628484, + "z": 1.0 + }, + { + "x": 129.43451309148438, + "y": 2.047187209984171, + "z": 1.0 + }, + { + "x": 129.03384958667337, + "y": 2.0472299725054937, + "z": 1.0 + }, + { + "x": 128.5330202056596, + "y": 2.0472834256571466, + "z": 1.0 + }, + { + "x": 128.1323567008486, + "y": 2.0473261881784692, + "z": 1.0 + }, + { + "x": 127.53136144363208, + "y": 2.0473903319604534, + "z": 1.0 + }, + { + "x": 127.13069793882107, + "y": 2.047433094481776, + "z": 1.0 + }, + { + "x": 126.73003443401007, + "y": 2.0474758570030986, + "z": 1.0 + }, + { + "x": 126.2292050529963, + "y": 2.047529310154752, + "z": 1.0 + }, + { + "x": 125.82854154818529, + "y": 2.0475720726760747, + "z": 1.0 + }, + { + "x": 125.32771216717153, + "y": 2.047625525827728, + "z": 1.0 + }, + { + "x": 124.82688278615777, + "y": 2.047678978979381, + "z": 1.0 + }, + { + "x": 124.42621928134676, + "y": 2.0477217415007036, + "z": 1.0 + }, + { + "x": 123.82522402413024, + "y": 2.047785885282688, + "z": 1.0 + }, + { + "x": 123.22422876691373, + "y": 2.0478500290646715, + "z": 1.0 + }, + { + "x": 122.72339938589997, + "y": 2.047903482216325, + "z": 1.0 + }, + { + "x": 122.12240412868344, + "y": 2.047967625998309, + "z": 1.0 + }, + { + "x": 121.72174062387244, + "y": 2.0480103885196317, + "z": 1.0 + }, + { + "x": 121.22091124285868, + "y": 2.0480638416712846, + "z": 1.0 + }, + { + "x": 120.61991598564217, + "y": 2.048127985453269, + "z": 1.0 + }, + { + "x": 120.21925248083116, + "y": 2.0481707479745914, + "z": 1.0 + }, + { + "x": 119.61825722361463, + "y": 2.048234891756575, + "z": 1.0 + }, + { + "x": 119.11742784260088, + "y": 2.0482883449082285, + "z": 1.0 + }, + { + "x": 118.51643258538436, + "y": 2.0483524886902127, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 4, + "heading": [ + 3.1414859243253446, + 3.141485924325344, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.141485924325344, + 3.141485924325344, + 3.1414859243253432, + 3.141485924325343, + 3.1414859243253437, + 3.141485924325344, + 3.141485924325344, + 3.1414859243253432, + 3.141485924325343, + 3.1414859243253437, + 3.1414859243253437, + 3.141485924325344, + 3.1414859243253432, + 3.141485924325343, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.141485924325344, + 3.1414859243253432, + 3.141485924325343, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253432, + 3.1414859243253432, + 3.141485924325344, + 3.1414859243253437, + 3.141485924325344, + 3.141485924325344, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253432, + 3.1414859243253437, + 3.141485924325344, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.141485924325344, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.141485924325344, + 3.1414859243253437, + 3.1414859243253432, + 3.1414859243253437, + 3.141485924325344, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.141485924325344, + 3.141485924325344, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.141485924325344, + 3.141485924325344, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253432, + 3.1414859243253437, + 3.141485924325344, + 3.1414859243253437, + 3.1414859243253437, + 3.141485924325344, + 3.1414859243253437, + 3.1414859243253432 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -5.026086927895506, + "y": 0.0005364305629074195 + }, + { + "x": -10.052173855790727, + "y": 0.00107286112581928 + }, + { + "x": -9.046956470211285, + "y": 0.0009655750132386842 + }, + { + "x": -10.052173855790443, + "y": 0.00107286112581928 + }, + { + "x": -11.057391241369885, + "y": 0.0011801472383998757 + }, + { + "x": -11.057391241369885, + "y": 0.0011801472383998757 + }, + { + "x": -12.062608626948474, + "y": 0.0012874333509893532 + }, + { + "x": -10.052173855790443, + "y": 0.0010728611258281617 + }, + { + "x": -8.041739084632695, + "y": 0.0008582889006580885 + }, + { + "x": -8.041739084632411, + "y": 0.0008582889006536476 + }, + { + "x": -9.046956470211569, + "y": 0.0009655750132342433 + }, + { + "x": -9.046956470211569, + "y": 0.0009655750132431251 + }, + { + "x": -8.041739084632411, + "y": 0.0008582889006625294 + }, + { + "x": -9.046956470211569, + "y": 0.0009655750132386842 + }, + { + "x": -10.052173855790443, + "y": 0.00107286112581928 + }, + { + "x": -10.052173855790727, + "y": 0.001072861125814839 + }, + { + "x": -9.046956470211569, + "y": 0.0009655750132431251 + }, + { + "x": -10.052173855790443, + "y": 0.0010728611258281617 + }, + { + "x": -12.062608626948759, + "y": 0.0012874333509849123 + }, + { + "x": -10.052173855790727, + "y": 0.00107286112581928 + }, + { + "x": -10.052173855790727, + "y": 0.00107286112581928 + }, + { + "x": -11.057391241369885, + "y": 0.0011801472384043166 + }, + { + "x": -11.057391241369885, + "y": 0.0011801472384043166 + }, + { + "x": -11.0573912413696, + "y": 0.0011801472384043166 + }, + { + "x": -9.046956470211569, + "y": 0.0009655750132386842 + }, + { + "x": -10.052173855791011, + "y": 0.001072861125814839 + }, + { + "x": -10.052173855790727, + "y": 0.0010728611258237208 + }, + { + "x": -8.041739084632411, + "y": 0.0008582889006625294 + }, + { + "x": -10.052173855791011, + "y": 0.00107286112581928 + }, + { + "x": -10.052173855790727, + "y": 0.00107286112581928 + }, + { + "x": -9.046956470211569, + "y": 0.0009655750132386842 + }, + { + "x": -9.046956470211853, + "y": 0.0009655750132386842 + }, + { + "x": -9.046956470211569, + "y": 0.0009655750132386842 + }, + { + "x": -9.046956470211569, + "y": 0.0009655750132431251 + }, + { + "x": -5.026086927895506, + "y": 0.0005364305629118604 + }, + { + "x": -5.011852433689512, + "y": 0.0005349113258068527 + }, + { + "x": -9.0149288582478, + "y": 0.0009621567297601885 + }, + { + "x": -10.016587620275175, + "y": 0.001069063033063422 + }, + { + "x": -9.0149288582478, + "y": 0.0009621567297557476 + }, + { + "x": -8.01327009622014, + "y": 0.000855250426452514 + }, + { + "x": -9.014928858247515, + "y": 0.0009621567297601885 + }, + { + "x": -9.014928858247515, + "y": 0.0009621567297601885 + }, + { + "x": -8.01327009622014, + "y": 0.000855250426452514 + }, + { + "x": -9.0149288582478, + "y": 0.0009621567297601885 + }, + { + "x": -11.018246382302834, + "y": 0.0011759693363755375 + }, + { + "x": -11.01824638230255, + "y": 0.0011759693363710966 + }, + { + "x": -9.014928858247515, + "y": 0.0009621567297557476 + }, + { + "x": -10.016587620275175, + "y": 0.001069063033067863 + }, + { + "x": -10.016587620275175, + "y": 0.001069063033067863 + }, + { + "x": -8.01327009622014, + "y": 0.000855250426452514 + }, + { + "x": -10.016587620275175, + "y": 0.001069063033063422 + }, + { + "x": -11.01824638230255, + "y": 0.0011759693363710966 + }, + { + "x": -9.014928858247515, + "y": 0.0009621567297601885 + }, + { + "x": -8.01327009622014, + "y": 0.000855250426452514 + }, + { + "x": -8.01327009622014, + "y": 0.000855250426452514 + }, + { + "x": -8.01327009622014, + "y": 0.000855250426452514 + }, + { + "x": -8.01327009622014, + "y": 0.000855250426452514 + }, + { + "x": -10.01658762027489, + "y": 0.001069063033067863 + }, + { + "x": -12.019905144329925, + "y": 0.001282875639678771 + }, + { + "x": -10.016587620275175, + "y": 0.001069063033063422 + }, + { + "x": -9.014928858247515, + "y": 0.0009621567297601885 + }, + { + "x": -11.01824638230255, + "y": 0.0011759693363755375 + }, + { + "x": -11.018246382302834, + "y": 0.0011759693363710966 + }, + { + "x": -10.016587620275175, + "y": 0.001069063033063422 + }, + { + "x": -10.01658762027489, + "y": 0.001069063033067863 + }, + { + "x": -9.014928858247515, + "y": 0.0009621567297601885 + }, + { + "x": -9.014928858247515, + "y": 0.0009621567297601885 + }, + { + "x": -9.014928858247515, + "y": 0.0009621567297601885 + }, + { + "x": -8.01327009622014, + "y": 0.000855250426452514 + }, + { + "x": -9.0149288582478, + "y": 0.0009621567297557476 + }, + { + "x": -9.0149288582478, + "y": 0.0009621567297557476 + }, + { + "x": -10.016587620275175, + "y": 0.001069063033067863 + }, + { + "x": -10.016587620275175, + "y": 0.001069063033067863 + }, + { + "x": -8.01327009622014, + "y": 0.000855250426452514 + }, + { + "x": -9.014928858247657, + "y": 0.0009621567297601885 + }, + { + "x": -9.0149288582478, + "y": 0.0009621567297601885 + }, + { + "x": -9.0149288582478, + "y": 0.0009621567297601885 + }, + { + "x": -10.016587620275175, + "y": 0.001069063033063422 + }, + { + "x": -9.014928858247657, + "y": 0.0009621567297557476 + }, + { + "x": -10.016587620275317, + "y": 0.001069063033067863 + }, + { + "x": -12.019905144330352, + "y": 0.001282875639678771 + }, + { + "x": -11.018246382302692, + "y": 0.0011759693363710966 + }, + { + "x": -11.018246382302834, + "y": 0.0011759693363755375 + }, + { + "x": -10.016587620275317, + "y": 0.001069063033067863 + }, + { + "x": -9.014928858247657, + "y": 0.0009621567297557476 + }, + { + "x": -11.018246382302692, + "y": 0.0011759693363710966 + }, + { + "x": -10.016587620275175, + "y": 0.001069063033067863 + }, + { + "x": -10.016587620275317, + "y": 0.001069063033063422 + }, + { + "x": -11.018246382302834, + "y": 0.0011759693363710966 + }, + { + "x": -11.018246382302692, + "y": 0.0011759693363755375 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 118.51643258538436, + "y": 2.0483524886902127, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 166.26698125656839, + "y": -59.490756629877396, + "z": 1.0 + }, + { + "x": 166.7687912075939, + "y": -59.49069548293693, + "z": 1.0 + }, + { + "x": 167.1702391684144, + "y": -59.49064656538455, + "z": 1.0 + }, + { + "x": 167.67052415520067, + "y": -59.490585604265235, + "z": 1.0 + }, + { + "x": 168.2708661393441, + "y": -59.49051245092204, + "z": 1.0 + }, + { + "x": 168.67109412877318, + "y": -59.490463682026586, + "z": 1.0 + }, + { + "x": 169.0713221182021, + "y": -59.49041491313112, + "z": 1.0 + }, + { + "x": 169.5716071049883, + "y": -59.49035395201179, + "z": 1.0 + }, + { + "x": 170.1719490891316, + "y": -59.49028079866859, + "z": 1.0 + }, + { + "x": 170.57217707856051, + "y": -59.49023202977314, + "z": 1.0 + }, + { + "x": 171.17251906270394, + "y": -59.490158876429945, + "z": 1.0 + }, + { + "x": 171.5727470521329, + "y": -59.49011010753449, + "z": 1.0 + }, + { + "x": 171.97297504156188, + "y": -59.49006133863902, + "z": 1.0 + }, + { + "x": 172.57331702570542, + "y": -59.48998818529584, + "z": 1.0 + }, + { + "x": 173.17365900984873, + "y": -59.48991503195265, + "z": 1.0 + }, + { + "x": 173.57388699927765, + "y": -59.48986626305718, + "z": 1.0 + }, + { + "x": 174.17422898342107, + "y": -59.489793109713986, + "z": 1.0 + }, + { + "x": 174.57445697285004, + "y": -59.48974434081853, + "z": 1.0 + }, + { + "x": 174.974684962279, + "y": -59.489695571923065, + "z": 1.0 + }, + { + "x": 175.57502694642244, + "y": -59.489622418579884, + "z": 1.0 + }, + { + "x": 176.07531193320875, + "y": -59.48956145746055, + "z": 1.0 + }, + { + "x": 176.67565391735207, + "y": -59.48948830411736, + "z": 1.0 + }, + { + "x": 177.1759389041382, + "y": -59.48942734299804, + "z": 1.0 + }, + { + "x": 177.57616689356718, + "y": -59.489378574102574, + "z": 1.0 + }, + { + "x": 178.1765088777106, + "y": -59.48930542075939, + "z": 1.0 + }, + { + "x": 178.57673686713957, + "y": -59.489256651863926, + "z": 1.0 + }, + { + "x": 178.9769648565685, + "y": -59.48920788296846, + "z": 1.0 + }, + { + "x": 179.47724984335468, + "y": -59.48914692184914, + "z": 1.0 + }, + { + "x": 180.07759182749828, + "y": -59.489073768505946, + "z": 1.0 + }, + { + "x": 180.5778768142843, + "y": -59.489012807386615, + "z": 1.0 + }, + { + "x": 181.0781618010705, + "y": -59.4889518462673, + "z": 1.0 + }, + { + "x": 181.67850378521393, + "y": -59.488878692924104, + "z": 1.0 + }, + { + "x": 182.27884576935747, + "y": -59.48880553958092, + "z": 1.0 + }, + { + "x": 182.8791877535008, + "y": -59.48873238623773, + "z": 1.0 + }, + { + "x": 183.3794727402871, + "y": -59.4886714251184, + "z": 1.0 + }, + { + "x": 183.97981472443053, + "y": -59.4885982717752, + "z": 1.0 + }, + { + "x": 184.38004271385938, + "y": -59.48854950287975, + "z": 1.0 + }, + { + "x": 184.9803846980028, + "y": -59.488476349536555, + "z": 1.0 + }, + { + "x": 185.58072668214623, + "y": -59.48840319619336, + "z": 1.0 + }, + { + "x": 186.08101166893238, + "y": -59.48834223507404, + "z": 1.0 + }, + { + "x": 186.48123965836135, + "y": -59.488293466178575, + "z": 1.0 + }, + { + "x": 187.08158164250494, + "y": -59.488220312835395, + "z": 1.0 + }, + { + "x": 187.6819236266482, + "y": -59.4881471594922, + "z": 1.0 + }, + { + "x": 188.08215161607728, + "y": -59.48809839059673, + "z": 1.0 + }, + { + "x": 188.6824936002206, + "y": -59.48802523725354, + "z": 1.0 + }, + { + "x": 189.0827215896495, + "y": -59.487976468358085, + "z": 1.0 + }, + { + "x": 189.48294957907848, + "y": -59.48792769946262, + "z": 1.0 + }, + { + "x": 190.0832915632219, + "y": -59.487854546119436, + "z": 1.0 + }, + { + "x": 190.68363354736533, + "y": -59.48778139277624, + "z": 1.0 + }, + { + "x": 191.18391853415153, + "y": -59.48772043165691, + "z": 1.0 + }, + { + "x": 191.78426051829496, + "y": -59.48764727831373, + "z": 1.0 + }, + { + "x": 192.18448850772393, + "y": -59.48759850941826, + "z": 1.0 + }, + { + "x": 192.68477349451007, + "y": -59.48753754829893, + "z": 1.0 + }, + { + "x": 193.28511547865367, + "y": -59.48746439495575, + "z": 1.0 + }, + { + "x": 193.7854004654397, + "y": -59.48740343383642, + "z": 1.0 + }, + { + "x": 194.2856854522259, + "y": -59.48734247271709, + "z": 1.0 + }, + { + "x": 194.68591344165486, + "y": -59.487293703821635, + "z": 1.0 + }, + { + "x": 195.2862554257983, + "y": -59.48722055047844, + "z": 1.0 + }, + { + "x": 195.7865404125845, + "y": -59.48715958935912, + "z": 1.0 + }, + { + "x": 196.3868823967279, + "y": -59.48708643601593, + "z": 1.0 + }, + { + "x": 196.88716738351405, + "y": -59.4870254748966, + "z": 1.0 + }, + { + "x": 197.48750936765748, + "y": -59.4869523215534, + "z": 1.0 + }, + { + "x": 197.88773735708645, + "y": -59.48690355265795, + "z": 1.0 + }, + { + "x": 198.38802234387265, + "y": -59.48684259153862, + "z": 1.0 + }, + { + "x": 198.78825033330162, + "y": -59.486793822643165, + "z": 1.0 + }, + { + "x": 199.38859231744516, + "y": -59.48672066929997, + "z": 1.0 + }, + { + "x": 199.98893430158847, + "y": -59.486647515956776, + "z": 1.0 + }, + { + "x": 200.5892762857319, + "y": -59.486574362613595, + "z": 1.0 + }, + { + "x": 200.9895042751608, + "y": -59.48652559371813, + "z": 1.0 + }, + { + "x": 201.38973226458978, + "y": -59.486476824822674, + "z": 1.0 + }, + { + "x": 201.78996025401875, + "y": -59.486428055927206, + "z": 1.0 + }, + { + "x": 202.29024524080495, + "y": -59.486367094807875, + "z": 1.0 + }, + { + "x": 202.89058722494838, + "y": -59.486293941464695, + "z": 1.0 + }, + { + "x": 203.39087221173452, + "y": -59.48623298034536, + "z": 1.0 + }, + { + "x": 203.89115719852072, + "y": -59.48617201922603, + "z": 1.0 + }, + { + "x": 204.2913851879497, + "y": -59.48612325033058, + "z": 1.0 + }, + { + "x": 204.79167017473588, + "y": -59.48606228921125, + "z": 1.0 + }, + { + "x": 205.1918981641648, + "y": -59.486013520315794, + "z": 1.0 + }, + { + "x": 205.692183150951, + "y": -59.48595255919646, + "z": 1.0 + }, + { + "x": 206.09241114037997, + "y": -59.48590379030101, + "z": 1.0 + }, + { + "x": 206.49263912980905, + "y": -59.48585502140554, + "z": 1.0 + }, + { + "x": 207.09298111395236, + "y": -59.48578186806235, + "z": 1.0 + }, + { + "x": 207.6933230980959, + "y": -59.485708714719166, + "z": 1.0 + }, + { + "x": 208.29366508223922, + "y": -59.48563556137597, + "z": 1.0 + }, + { + "x": 208.79395006902536, + "y": -59.48557460025664, + "z": 1.0 + }, + { + "x": 209.19417805845433, + "y": -59.48552583136119, + "z": 1.0 + }, + { + "x": 209.79452004259775, + "y": -59.48545267801799, + "z": 1.0 + }, + { + "x": 210.29480502938395, + "y": -59.485391716898675, + "z": 1.0 + }, + { + "x": 210.89514701352738, + "y": -59.48531856355548, + "z": 1.0 + }, + { + "x": 211.4954889976708, + "y": -59.485245410212286, + "z": 1.0 + }, + { + "x": 211.995773984457, + "y": -59.485184449092955, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 5, + "heading": [ + 0.00012185278518115317, + 0.0001218527851825946, + 0.00012185278518572584, + 0.00012185278517498467, + 0.00012185278517614517, + 0.00012185278517742751, + 0.00012185278518097994, + 0.00012185278519480644, + 0.00012185278518907564, + 0.00012185278517746212, + 0.00012185278517744829, + 0.00012185278517744136, + 0.00012185278518098858, + 0.00012185278517742751, + 0.00012185278517507654, + 0.00012185278519166489, + 0.00012185278519165104, + 0.00012185278517744136, + 0.00012185278518098858, + 0.00012185278517744136, + 0.00012185278517613887, + 0.00012185278518906306, + 0.00012185278517617034, + 0.0001218527851790256, + 0.00012185278517744136, + 0.00012185278517744136, + 0.00012185278519875069, + 0.0001218527851790256, + 0.00012185278517613258, + 0.00012185278518906306, + 0.00012185278517746212, + 0.00012185278517615146, + 0.000121852785175065, + 0.00012185278517507654, + 0.00012185278518906306, + 0.00012185278518905047, + 0.0001218527851774552, + 0.0001218527851774552, + 0.00012185278518691218, + 0.00012185278517615775, + 0.0001218527851790256, + 0.00012185278517742058, + 0.00012185278517507654, + 0.00012185278519165104, + 0.00012185278519164411, + 0.00012185278517746212, + 0.00012185278518099724, + 0.00012185278517744136, + 0.00012185278517507654, + 0.00012185278518906306, + 0.00012185278517615146, + 0.00012185278517744136, + 0.00012185278519480644, + 0.00012185278517613887, + 0.00012185278517615146, + 0.00012185278519166489, + 0.0001218527851790179, + 0.00012185278517744136, + 0.00012185278517615146, + 0.00012185278517615146, + 0.00012185278518906935, + 0.00012185278518906935, + 0.00012185278517744136, + 0.0001218527851790179, + 0.0001218527851790179, + 0.00012185278517742751, + 0.00012185278518691218, + 0.00012185278517508807, + 0.00012185278517744829, + 0.00012185278518099724, + 0.00012185278518098858, + 0.00012185278519479875, + 0.00012185278517615146, + 0.00012185278517615775, + 0.00012185278519165104, + 0.0001218527851790179, + 0.0001218527851790179, + 0.0001218527851790256, + 0.0001218527851790256, + 0.0001218527851790179, + 0.00012185278518097128, + 0.00012185278519164411, + 0.00012185278517507654, + 0.00012185278517507654, + 0.00012185278518908194, + 0.0001218527851790256, + 0.00012185278517744136, + 0.00012185278517615146, + 0.00012185278517615146, + 0.00012185278518691218, + 0.00012185278518906306 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 5.01809951025507, + "y": 0.0006114694046743807 + }, + { + "x": 9.032579118460262, + "y": 0.001100644928442307 + }, + { + "x": 9.017329476067744, + "y": 0.0010987867169376386 + }, + { + "x": 11.006269709296816, + "y": 0.0013411446251154757 + }, + { + "x": 10.005699735725102, + "y": 0.0012192223864815332 + }, + { + "x": 8.004559788579968, + "y": 0.0009753779092136483 + }, + { + "x": 9.005129762151114, + "y": 0.0010973001479896993 + }, + { + "x": 11.006269709295111, + "y": 0.0013411446252575843 + }, + { + "x": 10.00569973572226, + "y": 0.0012192223864815332 + }, + { + "x": 10.005699735723397, + "y": 0.0012192223864815332 + }, + { + "x": 10.005699735723965, + "y": 0.0012192223864815332 + }, + { + "x": 8.0045597885794, + "y": 0.0009753779092136483 + }, + { + "x": 10.005699735725102, + "y": 0.0012192223864815332 + }, + { + "x": 12.00683968286853, + "y": 0.0014630668637494182 + }, + { + "x": 10.00569973572226, + "y": 0.0012192223866236418 + }, + { + "x": 10.005699735723397, + "y": 0.0012192223866236418 + }, + { + "x": 10.005699735723965, + "y": 0.0012192223864815332 + }, + { + "x": 8.0045597885794, + "y": 0.0009753779092136483 + }, + { + "x": 10.005699735723965, + "y": 0.0012192223864815332 + }, + { + "x": 11.006269709297385, + "y": 0.0013411446251154757 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446252575843 + }, + { + "x": 11.006269709294543, + "y": 0.0013411446251154757 + }, + { + "x": 9.005129762151114, + "y": 0.0010973001478475908 + }, + { + "x": 10.005699735723965, + "y": 0.0012192223864815332 + }, + { + "x": 10.005699735723965, + "y": 0.0012192223864815332 + }, + { + "x": 8.004559788578831, + "y": 0.0009753779093557569 + }, + { + "x": 9.005129762151114, + "y": 0.0010973001478475908 + }, + { + "x": 11.006269709297953, + "y": 0.0013411446251154757 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446252575843 + }, + { + "x": 10.00569973572226, + "y": 0.0012192223864815332 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446251154757 + }, + { + "x": 12.006839682869668, + "y": 0.0014630668637494182 + }, + { + "x": 12.00683968286853, + "y": 0.0014630668637494182 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446252575843 + }, + { + "x": 11.006269709297385, + "y": 0.0013411446252575843 + }, + { + "x": 10.005699735722828, + "y": 0.0012192223864815332 + }, + { + "x": 10.005699735722828, + "y": 0.0012192223864815332 + }, + { + "x": 12.00683968286853, + "y": 0.0014630668638915267 + }, + { + "x": 11.00626970929568, + "y": 0.0013411446251154757 + }, + { + "x": 9.005129762151114, + "y": 0.0010973001478475908 + }, + { + "x": 10.00569973572567, + "y": 0.0012192223864815332 + }, + { + "x": 12.00683968286853, + "y": 0.0014630668637494182 + }, + { + "x": 10.005699735723397, + "y": 0.0012192223866236418 + }, + { + "x": 10.005699735723965, + "y": 0.0012192223866236418 + }, + { + "x": 10.00569973572226, + "y": 0.0012192223864815332 + }, + { + "x": 8.004559788578831, + "y": 0.0009753779092136483 + }, + { + "x": 10.005699735723965, + "y": 0.0012192223864815332 + }, + { + "x": 12.00683968286853, + "y": 0.0014630668637494182 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446252575843 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446251154757 + }, + { + "x": 10.005699735723965, + "y": 0.0012192223864815332 + }, + { + "x": 9.005129762151114, + "y": 0.0010973001479896993 + }, + { + "x": 11.006269709297385, + "y": 0.0013411446251154757 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446251154757 + }, + { + "x": 10.00569973572226, + "y": 0.0012192223866236418 + }, + { + "x": 9.005129762151682, + "y": 0.0010973001478475908 + }, + { + "x": 10.005699735723965, + "y": 0.0012192223864815332 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446251154757 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446251154757 + }, + { + "x": 11.00626970929568, + "y": 0.0013411446252575843 + }, + { + "x": 11.00626970929568, + "y": 0.0013411446252575843 + }, + { + "x": 10.005699735723965, + "y": 0.0012192223864815332 + }, + { + "x": 9.005129762151682, + "y": 0.0010973001478475908 + }, + { + "x": 9.005129762151682, + "y": 0.0010973001478475908 + }, + { + "x": 10.005699735725102, + "y": 0.0012192223864815332 + }, + { + "x": 12.00683968286853, + "y": 0.0014630668638915267 + }, + { + "x": 12.006839682867394, + "y": 0.0014630668637494182 + }, + { + "x": 10.005699735723397, + "y": 0.0012192223864815332 + }, + { + "x": 8.004559788578831, + "y": 0.0009753779092136483 + }, + { + "x": 8.0045597885794, + "y": 0.0009753779092136483 + }, + { + "x": 9.005129762151682, + "y": 0.0010973001479896993 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446251154757 + }, + { + "x": 11.00626970929568, + "y": 0.0013411446251154757 + }, + { + "x": 10.005699735723397, + "y": 0.0012192223866236418 + }, + { + "x": 9.005129762151682, + "y": 0.0010973001478475908 + }, + { + "x": 9.005129762151682, + "y": 0.0010973001478475908 + }, + { + "x": 9.005129762151114, + "y": 0.0010973001478475908 + }, + { + "x": 9.005129762151114, + "y": 0.0010973001478475908 + }, + { + "x": 9.005129762151682, + "y": 0.0010973001478475908 + }, + { + "x": 8.004559788580536, + "y": 0.0009753779092136483 + }, + { + "x": 10.005699735723965, + "y": 0.0012192223866236418 + }, + { + "x": 12.00683968286853, + "y": 0.0014630668637494182 + }, + { + "x": 12.00683968286853, + "y": 0.0014630668637494182 + }, + { + "x": 11.006269709294543, + "y": 0.0013411446252575843 + }, + { + "x": 9.005129762151114, + "y": 0.0010973001478475908 + }, + { + "x": 10.005699735723965, + "y": 0.0012192223864815332 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446251154757 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446251154757 + }, + { + "x": 12.00683968286853, + "y": 0.0014630668638915267 + }, + { + "x": 11.006269709296248, + "y": 0.0013411446252575843 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 211.995773984457, + "y": -59.485184449092955, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 336.87871837455714, + "y": -1.9946542982485806, + "z": 1.0 + }, + { + "x": 337.48138495618383, + "y": -1.9949744568755592, + "z": 1.0 + }, + { + "x": 338.08405153781047, + "y": -1.995294615502536, + "z": 1.0 + }, + { + "x": 338.58627368916603, + "y": -1.9955614143583502, + "z": 1.0 + }, + { + "x": 339.0884958405216, + "y": -1.995828213214164, + "z": 1.0 + }, + { + "x": 339.49027356160605, + "y": -1.9960416522988154, + "z": 1.0 + }, + { + "x": 339.8920512826905, + "y": -1.9962550913834662, + "z": 1.0 + }, + { + "x": 340.394273434046, + "y": -1.9965218902392805, + "z": 1.0 + }, + { + "x": 340.9969400156727, + "y": -1.9968420488662573, + "z": 1.0 + }, + { + "x": 341.4991621670282, + "y": -1.997108847722071, + "z": 1.0 + }, + { + "x": 341.90093988811265, + "y": -1.9973222868067224, + "z": 1.0 + }, + { + "x": 342.3027176091971, + "y": -1.9975357258913733, + "z": 1.0 + }, + { + "x": 342.70449533028153, + "y": -1.9977491649760246, + "z": 1.0 + }, + { + "x": 343.106273051366, + "y": -1.997962604060676, + "z": 1.0 + }, + { + "x": 343.5080507724504, + "y": -1.9981760431453273, + "z": 1.0 + }, + { + "x": 344.1107173540771, + "y": -1.998496201772304, + "z": 1.0 + }, + { + "x": 344.6129395054326, + "y": -1.9987630006281178, + "z": 1.0 + }, + { + "x": 345.01471722651706, + "y": -1.9989764397127692, + "z": 1.0 + }, + { + "x": 345.4164949476015, + "y": -1.99918987879742, + "z": 1.0 + }, + { + "x": 346.0191615292282, + "y": -1.9995100374243995, + "z": 1.0 + }, + { + "x": 346.42093925031264, + "y": -1.9997234765090504, + "z": 1.0 + }, + { + "x": 346.92316140166815, + "y": -1.9999902753648646, + "z": 1.0 + }, + { + "x": 347.3249391227526, + "y": -2.000203714449516, + "z": 1.0 + }, + { + "x": 347.72671684383704, + "y": -2.0004171535341677, + "z": 1.0 + }, + { + "x": 348.2289389951926, + "y": -2.000683952389981, + "z": 1.0 + }, + { + "x": 348.82993064592614, + "y": -2.0010032212321396, + "z": 1.0 + }, + { + "x": 349.3307570215374, + "y": -2.001269278600605, + "z": 1.0 + }, + { + "x": 349.9317486722709, + "y": -2.0015885474427635, + "z": 1.0 + }, + { + "x": 350.43257504788215, + "y": -2.001854604811229, + "z": 1.0 + }, + { + "x": 350.9334014234934, + "y": -2.0021206621796934, + "z": 1.0 + }, + { + "x": 351.53439307422695, + "y": -2.002439931021852, + "z": 1.0 + }, + { + "x": 352.13538472496043, + "y": -2.0027591998640104, + "z": 1.0 + }, + { + "x": 352.53604582544943, + "y": -2.0029720457587827, + "z": 1.0 + }, + { + "x": 353.13703747618297, + "y": -2.0032913146009403, + "z": 1.0 + }, + { + "x": 353.537698576672, + "y": -2.0035041604957127, + "z": 1.0 + }, + { + "x": 354.13869022740556, + "y": -2.003823429337871, + "z": 1.0 + }, + { + "x": 354.53935132789456, + "y": -2.0040362752326435, + "z": 1.0 + }, + { + "x": 355.1403429786281, + "y": -2.004355544074802, + "z": 1.0 + }, + { + "x": 355.74133462936163, + "y": -2.0046748129169596, + "z": 1.0 + }, + { + "x": 356.2421610049729, + "y": -2.004940870285425, + "z": 1.0 + }, + { + "x": 356.84315265570643, + "y": -2.0052601391275835, + "z": 1.0 + }, + { + "x": 357.3439790313177, + "y": -2.005526196496049, + "z": 1.0 + }, + { + "x": 357.74464013180676, + "y": -2.0057390423908212, + "z": 1.0 + }, + { + "x": 358.14530123229576, + "y": -2.0059518882855927, + "z": 1.0 + }, + { + "x": 358.7462928830293, + "y": -2.006271157127751, + "z": 1.0 + }, + { + "x": 359.1469539835183, + "y": -2.0064840030225235, + "z": 1.0 + }, + { + "x": 359.74794563425183, + "y": -2.006803271864682, + "z": 1.0 + }, + { + "x": 360.34893728498537, + "y": -2.0071225407068396, + "z": 1.0 + }, + { + "x": 360.8497636605967, + "y": -2.007388598075305, + "z": 1.0 + }, + { + "x": 361.4507553113302, + "y": -2.0077078669174635, + "z": 1.0 + }, + { + "x": 361.9515816869415, + "y": -2.007973924285929, + "z": 1.0 + }, + { + "x": 362.552573337675, + "y": -2.0082931931280865, + "z": 1.0 + }, + { + "x": 363.0533997132863, + "y": -2.008559250496552, + "z": 1.0 + }, + { + "x": 363.65439136401983, + "y": -2.0088785193387104, + "z": 1.0 + }, + { + "x": 364.1552177396311, + "y": -2.009144576707176, + "z": 1.0 + }, + { + "x": 364.65604411524237, + "y": -2.0094106340756412, + "z": 1.0 + }, + { + "x": 365.0567052157314, + "y": -2.0096234799704127, + "z": 1.0 + }, + { + "x": 365.45736631622043, + "y": -2.009836325865185, + "z": 1.0 + }, + { + "x": 365.9581926918317, + "y": -2.0101023832336504, + "z": 1.0 + }, + { + "x": 366.35885379232076, + "y": -2.0103152291284228, + "z": 1.0 + }, + { + "x": 366.9598454430543, + "y": -2.0106344979705812, + "z": 1.0 + }, + { + "x": 367.5608370937878, + "y": -2.010953766812739, + "z": 1.0 + }, + { + "x": 368.0616634693991, + "y": -2.0112198241812043, + "z": 1.0 + }, + { + "x": 368.6626551201326, + "y": -2.0115390930233628, + "z": 1.0 + }, + { + "x": 369.1634814957439, + "y": -2.011805150391828, + "z": 1.0 + }, + { + "x": 369.66430787135516, + "y": -2.0120712077602927, + "z": 1.0 + }, + { + "x": 370.16513424696643, + "y": -2.012337265128758, + "z": 1.0 + }, + { + "x": 370.6659606225777, + "y": -2.0126033224972235, + "z": 1.0 + }, + { + "x": 371.16678699818897, + "y": -2.012869379865689, + "z": 1.0 + }, + { + "x": 371.66761337380024, + "y": -2.0131354372341543, + "z": 1.0 + }, + { + "x": 372.1684397494115, + "y": -2.013401494602619, + "z": 1.0 + }, + { + "x": 372.6692661250228, + "y": -2.0136675519710843, + "z": 1.0 + }, + { + "x": 373.17009250063404, + "y": -2.0139336093395497, + "z": 1.0 + }, + { + "x": 373.6709188762453, + "y": -2.014199666708015, + "z": 1.0 + }, + { + "x": 374.1717452518566, + "y": -2.0144657240764805, + "z": 1.0 + }, + { + "x": 374.5724063523456, + "y": -2.014678569971252, + "z": 1.0 + }, + { + "x": 375.1733980030791, + "y": -2.0149978388134104, + "z": 1.0 + }, + { + "x": 375.77438965381265, + "y": -2.015317107655569, + "z": 1.0 + }, + { + "x": 376.3753813045462, + "y": -2.0156363764977274, + "z": 1.0 + }, + { + "x": 376.7760424050352, + "y": -2.015849222392499, + "z": 1.0 + }, + { + "x": 377.27686878064645, + "y": -2.0161152797609643, + "z": 1.0 + }, + { + "x": 377.7776951562577, + "y": -2.0163813371294297, + "z": 1.0 + }, + { + "x": 378.1783562567467, + "y": -2.016594183024202, + "z": 1.0 + }, + { + "x": 378.5790173572357, + "y": -2.0168070289189743, + "z": 1.0 + }, + { + "x": 379.079843732847, + "y": -2.017073086287439, + "z": 1.0 + }, + { + "x": 379.68083538358053, + "y": -2.0173923551295974, + "z": 1.0 + }, + { + "x": 380.28182703431406, + "y": -2.017711623971756, + "z": 1.0 + }, + { + "x": 380.8828186850476, + "y": -2.0180308928139143, + "z": 1.0 + }, + { + "x": 381.38364506065886, + "y": -2.018296950182379, + "z": 1.0 + }, + { + "x": 381.9846367113924, + "y": -2.0186162190245374, + "z": 1.0 + }, + { + "x": 382.3852978118814, + "y": -2.0188290649193097, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 6, + "heading": [ + -0.0005312366847937874, + -0.0005312366847964263, + -0.0005312366847949776, + -0.0005312366847937787, + -0.0005312366847936362, + -0.0005312366847934955, + -0.0005312366847933196, + -0.000531236684793529, + -0.0005312366847937787, + -0.0005312366847933768, + -0.000531236684793529, + -0.0005312366847933196, + -0.0005312366847933196, + -0.0005312366847938724, + -0.0005312366847938724, + -0.0005312366847936362, + -0.0005312366847933768, + -0.000531236684793529, + -0.0005312366847933196, + -0.0005312366847958469, + -0.0005312366847958469, + -0.000531236684793529, + -0.0005312366847940202, + -0.000531236684794425, + -0.0005312366847934955, + -0.0005312366847932849, + -0.0005312366847941043, + -0.0005312366847941316, + -0.0005312366847941316, + -0.000531236684793223, + -0.0005312366847932982, + -0.0005312366847941248, + -0.0005312366847941398, + -0.000531236684793223, + -0.0005312366847931929, + -0.0005312366847940795, + -0.0005312366847941097, + -0.0005312366847941097, + -0.0005312366847933607, + -0.0005312366847932982, + -0.0005312366847941043, + -0.0005312366847941043, + -0.0005312366847940829, + -0.0005312366847929788, + -0.000531236684793223, + -0.0005312366847941097, + -0.0005312366847941097, + -0.0005312366847933607, + -0.0005312366847932707, + -0.0005312366847940768, + -0.0005312366847941043, + -0.0005312366847932982, + -0.0005312366847932982, + -0.0005312366847941043, + -0.0005312366847941043, + -0.0005312366847941097, + -0.0005312366847930977, + -0.0005312366847929788, + -0.0005312366847941164, + -0.0005312366847940829, + -0.0005312366847940795, + -0.0005312366847933607, + -0.0005312366847932982, + -0.0005312366847941043, + -0.0005312366847941043, + -0.000531236684793223, + -0.000531236684793223, + -0.0005312366847941097, + -0.0005312366847941097, + -0.0005312366847941097, + -0.000531236684793223, + -0.000531236684793223, + -0.0005312366847941097, + -0.0005312366847941097, + -0.0005312366847941097, + -0.0005312366847931312, + -0.000531236684793223, + -0.0005312366847940997, + -0.0005312366847940997, + -0.000531236684793223, + -0.0005312366847931312, + -0.0005312366847941097, + -0.0005312366847941164, + -0.0005312366847941248, + -0.0005312366847931312, + -0.0005312366847932982, + -0.0005312366847940997, + -0.0005312366847940997, + -0.0005312366847932982, + -0.0005312366847932982, + -0.0005312366847941097 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 6.026665816266927, + "y": -0.0032015862697853947 + }, + { + "x": 12.053331632533286, + "y": -0.006403172539553026 + }, + { + "x": 11.048887329822037, + "y": -0.005869574827910284 + }, + { + "x": 10.044443027111356, + "y": -0.005335977116280866 + }, + { + "x": 9.039998724400107, + "y": -0.004802379404651447 + }, + { + "x": 8.035554421688857, + "y": -0.004268781693022028 + }, + { + "x": 9.039998724399538, + "y": -0.004802379404651447 + }, + { + "x": 11.048887329822037, + "y": -0.005869574827910284 + }, + { + "x": 11.048887329822037, + "y": -0.0058695748279058435 + }, + { + "x": 9.039998724399538, + "y": -0.004802379404651447 + }, + { + "x": 8.035554421688857, + "y": -0.004268781693022028 + }, + { + "x": 8.035554421688857, + "y": -0.004268781693022028 + }, + { + "x": 8.035554421688857, + "y": -0.004268781693026469 + }, + { + "x": 8.035554421688857, + "y": -0.004268781693026469 + }, + { + "x": 10.044443027111356, + "y": -0.005335977116280866 + }, + { + "x": 11.048887329822037, + "y": -0.0058695748279058435 + }, + { + "x": 9.039998724399538, + "y": -0.004802379404651447 + }, + { + "x": 8.035554421688857, + "y": -0.004268781693022028 + }, + { + "x": 10.044443027111356, + "y": -0.00533597711630307 + }, + { + "x": 10.044443027111356, + "y": -0.00533597711630307 + }, + { + "x": 9.039998724399538, + "y": -0.004802379404651447 + }, + { + "x": 9.039998724399538, + "y": -0.004802379404655888 + }, + { + "x": 8.035554421688857, + "y": -0.00426878169303091 + }, + { + "x": 9.039998724400107, + "y": -0.004802379404651447 + }, + { + "x": 11.032138020891011, + "y": -0.005860676979718704 + }, + { + "x": 11.018180263448016, + "y": -0.005853262106239043 + }, + { + "x": 11.018180263447448, + "y": -0.005853262106239043 + }, + { + "x": 11.018180263447448, + "y": -0.005853262106239043 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369299339 + }, + { + "x": 11.018180263448016, + "y": -0.0058532621062301615 + }, + { + "x": 12.019833014670098, + "y": -0.006385376843169865 + }, + { + "x": 10.016527512224798, + "y": -0.005321147369308221 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369299339 + }, + { + "x": 10.016527512225935, + "y": -0.005321147369299339 + }, + { + "x": 10.016527512225935, + "y": -0.005321147369308221 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + }, + { + "x": 12.019833014670667, + "y": -0.006385376843160984 + }, + { + "x": 11.018180263448016, + "y": -0.0058532621062301615 + }, + { + "x": 11.018180263448016, + "y": -0.005853262106239043 + }, + { + "x": 11.018180263448016, + "y": -0.005853262106239043 + }, + { + "x": 9.014874761003284, + "y": -0.004789032632377399 + }, + { + "x": 8.013222009780634, + "y": -0.004256917895437695 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369299339 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + }, + { + "x": 12.019833014670667, + "y": -0.006385376843160984 + }, + { + "x": 11.018180263448585, + "y": -0.0058532621062301615 + }, + { + "x": 11.018180263448585, + "y": -0.005853262106239043 + }, + { + "x": 11.018180263448016, + "y": -0.005853262106239043 + }, + { + "x": 11.018180263448016, + "y": -0.0058532621062301615 + }, + { + "x": 11.018180263448016, + "y": -0.0058532621062301615 + }, + { + "x": 11.018180263448016, + "y": -0.005853262106239043 + }, + { + "x": 11.018180263448016, + "y": -0.005853262106239043 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + }, + { + "x": 9.014874761003284, + "y": -0.004789032632368517 + }, + { + "x": 8.013222009780634, + "y": -0.004256917895437695 + }, + { + "x": 9.014874761002716, + "y": -0.004789032632377399 + }, + { + "x": 9.014874761003284, + "y": -0.004789032632377399 + }, + { + "x": 10.016527512225935, + "y": -0.005321147369308221 + }, + { + "x": 12.019833014670667, + "y": -0.006385376843160984 + }, + { + "x": 11.018180263448016, + "y": -0.0058532621062301615 + }, + { + "x": 11.018180263448016, + "y": -0.005853262106239043 + }, + { + "x": 11.018180263448016, + "y": -0.005853262106239043 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369299339 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369299339 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369299339 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369299339 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + }, + { + "x": 9.014874761002716, + "y": -0.004789032632368517 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369299339 + }, + { + "x": 12.019833014670667, + "y": -0.006385376843169865 + }, + { + "x": 12.019833014670667, + "y": -0.006385376843169865 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369299339 + }, + { + "x": 9.014874761002716, + "y": -0.004789032632368517 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + }, + { + "x": 9.014874761002716, + "y": -0.004789032632377399 + }, + { + "x": 8.013222009780065, + "y": -0.004256917895446577 + }, + { + "x": 9.014874761002716, + "y": -0.004789032632368517 + }, + { + "x": 11.018180263448016, + "y": -0.0058532621062301615 + }, + { + "x": 12.019833014670667, + "y": -0.006385376843169865 + }, + { + "x": 12.019833014670667, + "y": -0.006385376843169865 + }, + { + "x": 11.018180263448016, + "y": -0.0058532621062301615 + }, + { + "x": 11.018180263448016, + "y": -0.0058532621062301615 + }, + { + "x": 10.016527512225366, + "y": -0.005321147369308221 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 382.3852978118814, + "y": -2.0188290649193097, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 396.3472344367284, + "y": -37.160345373104796, + "z": 1.0 + }, + { + "x": 396.34783460167466, + "y": -36.660199843302536, + "z": 1.0 + }, + { + "x": 396.3484347666208, + "y": -36.16005431350368, + "z": 1.0 + }, + { + "x": 396.3491549645562, + "y": -35.55987967774118, + "z": 1.0 + }, + { + "x": 396.3496350965132, + "y": -35.15976325390029, + "z": 1.0 + }, + { + "x": 396.3503552944486, + "y": -34.559588618138925, + "z": 1.0 + }, + { + "x": 396.351075492384, + "y": -33.959413982377555, + "z": 1.0 + }, + { + "x": 396.351555624341, + "y": -33.559297558536606, + "z": 1.0 + }, + { + "x": 396.35203575629794, + "y": -33.15918113469572, + "z": 1.0 + }, + { + "x": 396.35251588825486, + "y": -32.75906471085483, + "z": 1.0 + }, + { + "x": 396.3531160532011, + "y": -32.258919181052505, + "z": 1.0 + }, + { + "x": 396.35359618515804, + "y": -31.85880275721275, + "z": 1.0 + }, + { + "x": 396.3543163830934, + "y": -31.258628121451384, + "z": 1.0 + }, + { + "x": 396.3550365810288, + "y": -30.65845348569116, + "z": 1.0 + }, + { + "x": 396.35551671298583, + "y": -30.25833706184913, + "z": 1.0 + }, + { + "x": 396.35599684494275, + "y": -29.858220638008184, + "z": 1.0 + }, + { + "x": 396.35671704287813, + "y": -29.25804600224796, + "z": 1.0 + }, + { + "x": 396.3574372408136, + "y": -28.657871366485452, + "z": 1.0 + }, + { + "x": 396.358157438749, + "y": -28.05769673072409, + "z": 1.0 + }, + { + "x": 396.3588776366844, + "y": -27.457522094963863, + "z": 1.0 + }, + { + "x": 396.3593577686414, + "y": -27.057405671122968, + "z": 1.0 + }, + { + "x": 396.35983790059834, + "y": -26.65728924728094, + "z": 1.0 + }, + { + "x": 396.3605580985337, + "y": -26.057114611520714, + "z": 1.0 + }, + { + "x": 396.36115826348, + "y": -25.556969081718446, + "z": 1.0 + }, + { + "x": 396.3617584284261, + "y": -25.05682355191732, + "z": 1.0 + }, + { + "x": 396.3624786263615, + "y": -24.456648916155956, + "z": 1.0 + }, + { + "x": 396.36295875831854, + "y": -24.056532492315007, + "z": 1.0 + }, + { + "x": 396.3636789562539, + "y": -23.456357856552508, + "z": 1.0 + }, + { + "x": 396.3643991541893, + "y": -22.856183220793415, + "z": 1.0 + }, + { + "x": 396.36487928614633, + "y": -22.456066796951387, + "z": 1.0 + }, + { + "x": 396.36535941810325, + "y": -22.055950373110495, + "z": 1.0 + }, + { + "x": 396.36607961603875, + "y": -21.45577573734913, + "z": 1.0 + }, + { + "x": 396.36655974799555, + "y": -21.055659313509317, + "z": 1.0 + }, + { + "x": 396.3671599129418, + "y": -20.555513783707056, + "z": 1.0 + }, + { + "x": 396.3678801108772, + "y": -19.95533914794569, + "z": 1.0 + }, + { + "x": 396.3683602428342, + "y": -19.555222724104787, + "z": 1.0 + }, + { + "x": 396.36884037479115, + "y": -19.155106300262716, + "z": 1.0 + }, + { + "x": 396.36932050674807, + "y": -18.754989876424098, + "z": 1.0 + }, + { + "x": 396.36992067169433, + "y": -18.25484434662183, + "z": 1.0 + }, + { + "x": 396.3706408696297, + "y": -17.654669710860468, + "z": 1.0 + }, + { + "x": 396.37124103457586, + "y": -17.15452418105934, + "z": 1.0 + }, + { + "x": 396.37196123251124, + "y": -16.55434954529911, + "z": 1.0 + }, + { + "x": 396.37268143044673, + "y": -15.954174909536611, + "z": 1.0 + }, + { + "x": 396.37316156240365, + "y": -15.55405848569572, + "z": 1.0 + }, + { + "x": 396.3737617273499, + "y": -15.053912955894535, + "z": 1.0 + }, + { + "x": 396.3744819252853, + "y": -14.453738320133171, + "z": 1.0 + }, + { + "x": 396.3749620572422, + "y": -14.053621896292277, + "z": 1.0 + }, + { + "x": 396.3756822551776, + "y": -13.453447260530915, + "z": 1.0 + }, + { + "x": 396.3761623871346, + "y": -13.053330836690023, + "z": 1.0 + }, + { + "x": 396.37664251909155, + "y": -12.653214412849076, + "z": 1.0 + }, + { + "x": 396.3772426840377, + "y": -12.153068883047947, + "z": 1.0 + }, + { + "x": 396.37772281599473, + "y": -11.752952459207044, + "z": 1.0 + }, + { + "x": 396.37820294795165, + "y": -11.352836035366167, + "z": 1.0 + }, + { + "x": 396.37892314588703, + "y": -10.7526613996048, + "z": 1.0 + }, + { + "x": 396.3796433438224, + "y": -10.152486763844573, + "z": 1.0 + }, + { + "x": 396.3800034427902, + "y": -9.852399445962725, + "z": 1.0 + }, + { + "x": 396.38072947083594, + "y": -9.24736630647071, + "z": 1.0 + }, + { + "x": 396.38018884440146, + "y": -8.827697833519784, + "z": 1.0 + }, + { + "x": 396.3559542057511, + "y": -8.213198337464048, + "z": 1.0 + }, + { + "x": 396.31200879560265, + "y": -7.723158864023834, + "z": 1.0 + }, + { + "x": 396.20527536482757, + "y": -6.992592214704764, + "z": 1.0 + }, + { + "x": 396.0500718257525, + "y": -6.271164008187339, + "z": 1.0 + }, + { + "x": 395.8842368704714, + "y": -5.678967931305309, + "z": 1.0 + }, + { + "x": 395.6857622060334, + "y": -5.096899880584985, + "z": 1.0 + }, + { + "x": 395.455260748745, + "y": -4.526756868425108, + "z": 1.0 + }, + { + "x": 395.2482753165647, + "y": -4.0804127215268355, + "z": 1.0 + }, + { + "x": 394.9011210530243, + "y": -3.4292445540602023, + "z": 1.0 + }, + { + "x": 394.57919369521915, + "y": -2.905263665688727, + "z": 1.0 + }, + { + "x": 394.2286560290763, + "y": -2.3999741932397383, + "z": 1.0 + }, + { + "x": 393.85059020493986, + "y": -1.9149362194119146, + "z": 1.0 + }, + { + "x": 393.4461633242467, + "y": -1.4516473413939093, + "z": 1.0 + }, + { + "x": 393.10315414617816, + "y": -1.0964914090564002, + "z": 1.0 + }, + { + "x": 392.5556607414593, + "y": -0.5917147279677624, + "z": 1.0 + }, + { + "x": 391.97441258430604, + "y": -0.12667220556926106, + "z": 1.0 + }, + { + "x": 391.5694707284134, + "y": 0.16029339798120468, + "z": 1.0 + }, + { + "x": 391.1515965517793, + "y": 0.42807561936125904, + "z": 1.0 + }, + { + "x": 390.6124534574134, + "y": 0.7349446250181975, + "z": 1.0 + }, + { + "x": 389.9432649415583, + "y": 1.060967210825062, + "z": 1.0 + }, + { + "x": 389.3693148975709, + "y": 1.296387251222732, + "z": 1.0 + }, + { + "x": 388.90088974534075, + "y": 1.4604024328109124, + "z": 1.0 + }, + { + "x": 388.3054464689899, + "y": 1.6344358076569507, + "z": 1.0 + }, + { + "x": 387.82242371460416, + "y": 1.748505382053843, + "z": 1.0 + }, + { + "x": 387.3346097798446, + "y": 1.8399412798968666, + "z": 1.0 + }, + { + "x": 386.84306450454335, + "y": 1.9085448273143313, + "z": 1.0 + }, + { + "x": 386.2250132455845, + "y": 1.961968903319451, + "z": 1.0 + }, + { + "x": 385.4980846920273, + "y": 1.979517872767351, + "z": 1.0 + }, + { + "x": 384.8934007714826, + "y": 1.9798391030788676, + "z": 1.0 + }, + { + "x": 384.59105881121025, + "y": 1.979999718234626, + "z": 1.0 + }, + { + "x": 383.9900671604767, + "y": 1.9803189870767843, + "z": 1.0 + }, + { + "x": 383.48924078486544, + "y": 1.9805850444452497, + "z": 1.0 + }, + { + "x": 383.08857968437644, + "y": 1.980797890340022, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 7, + "heading": [ + 1.8979433016187948, + 1.5695963467442284, + 1.569596346744338, + 1.5695963467444518, + 1.5695963467443406, + 1.5695963467443392, + 1.569596346744453, + 1.5695963467443395, + 1.5695963467443108, + 1.569596346744453, + 1.5695963467443281, + 1.5695963467443268, + 1.5695963467444516, + 1.5695963467444518, + 1.5695963467443392, + 1.5695963467443126, + 1.5695963467444516, + 1.5695963467443583, + 1.5695963467443594, + 1.5695963467444518, + 1.569596346744338, + 1.5695963467443126, + 1.569596346744453, + 1.5695963467443497, + 1.5695963467443406, + 1.569596346744453, + 1.5695963467443395, + 1.5695963467443408, + 1.5695963467444518, + 1.569596346744338, + 1.5695963467443126, + 1.5695963467443392, + 1.5695963467444516, + 1.569596346744453, + 1.5695963467443508, + 1.5695963467443392, + 1.5695963467443126, + 1.5695963467444514, + 1.569596346744325, + 1.5695963467443508, + 1.569596346744453, + 1.5695963467444518, + 1.5695963467443583, + 1.5695963467443406, + 1.5695963467443268, + 1.5695963467443497, + 1.569596346744453, + 1.569596346744453, + 1.5695963467443392, + 1.569596346744311, + 1.569596346744453, + 1.5695963467443266, + 1.5695963467443108, + 1.569596346744453, + 1.5695963467444518, + 1.5695963467443268, + 1.569596346744325, + 1.5706153945049763, + 1.5947484581231608, + 1.6324452626433934, + 1.6936208548054112, + 1.7492747489820462, + 1.8104893934341382, + 1.8716255364061702, + 1.9272038296191953, + 1.9772242945495098, + 2.0383604066772216, + 2.0883808667884334, + 2.1495169833593275, + 2.2050952761025653, + 2.260673574203252, + 2.3108780558633866, + 2.373656925855639, + 2.4317794339744916, + 2.4901149063298034, + 2.548388391437845, + 2.600834497835706, + 2.659107941869012, + 2.7173814004965506, + 2.775654864224719, + 2.8339283163605002, + 2.880547077762562, + 2.932993183603905, + 2.9796119446485148, + 3.0320580554517327, + 3.0888726955741186, + 3.1281734888993147, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.141061416904999 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.006001649462632486, + "y": 5.001455298022606 + }, + { + "x": 0.012003298924128103, + "y": 10.002910596011176 + }, + { + "x": 0.013203628815290358, + "y": 11.003201655613566 + }, + { + "x": 0.012003298924128103, + "y": 10.002910596033914 + }, + { + "x": 0.012003298924128103, + "y": 10.002910596022545 + }, + { + "x": 0.014403958707589481, + "y": 12.003492715227324 + }, + { + "x": 0.012003298924128103, + "y": 10.002910596023185 + }, + { + "x": 0.009602639139529856, + "y": 8.002328476818334 + }, + { + "x": 0.009602639138392988, + "y": 8.002328476817766 + }, + { + "x": 0.01080296903182898, + "y": 9.002619536432164 + }, + { + "x": 0.01080296903182898, + "y": 9.002619536420795 + }, + { + "x": 0.012003298922991235, + "y": 10.002910596011212 + }, + { + "x": 0.014403958707589481, + "y": 12.003492715215884 + }, + { + "x": 0.012003298924128103, + "y": 10.002910596022545 + }, + { + "x": 0.009602639139529856, + "y": 8.002328476829774 + }, + { + "x": 0.012003298922991235, + "y": 10.00291059601171 + }, + { + "x": 0.01440395870872635, + "y": 12.003492715227324 + }, + { + "x": 0.01440395870872635, + "y": 12.003492715238693 + }, + { + "x": 0.014403958707589481, + "y": 12.003492715215884 + }, + { + "x": 0.012003298924128103, + "y": 10.002910596011212 + }, + { + "x": 0.009602639139529856, + "y": 8.002328476829241 + }, + { + "x": 0.012003298922991235, + "y": 10.002910596022545 + }, + { + "x": 0.013203628816427226, + "y": 11.003201655624935 + }, + { + "x": 0.012003298924128103, + "y": 10.00291059603395 + }, + { + "x": 0.013203628815290358, + "y": 11.003201655624899 + }, + { + "x": 0.012003298924128103, + "y": 10.002910596023113 + }, + { + "x": 0.012003298924128103, + "y": 10.002910596034482 + }, + { + "x": 0.014403958707589481, + "y": 12.00349271521592 + }, + { + "x": 0.012003298924128103, + "y": 10.002910596011212 + }, + { + "x": 0.009602639139529856, + "y": 8.002328476829206 + }, + { + "x": 0.012003298924128103, + "y": 10.00291059602258 + }, + { + "x": 0.012003298922991235, + "y": 10.00291059601178 + }, + { + "x": 0.010802969030692111, + "y": 9.002619536420724 + }, + { + "x": 0.013203628816427226, + "y": 11.003201655636268 + }, + { + "x": 0.012003298924128103, + "y": 10.002910596022687 + }, + { + "x": 0.009602639139529856, + "y": 8.002328476829739 + }, + { + "x": 0.009602639138392988, + "y": 8.002328476806895 + }, + { + "x": 0.01080296903182898, + "y": 9.002619536408858 + }, + { + "x": 0.013203628816427226, + "y": 11.003201655636303 + }, + { + "x": 0.013203628815290358, + "y": 11.003201655624899 + }, + { + "x": 0.013203628815290358, + "y": 11.003201655613566 + }, + { + "x": 0.01440395870872635, + "y": 12.003492715227289 + }, + { + "x": 0.012003298924128103, + "y": 10.002910596033914 + }, + { + "x": 0.01080296903182898, + "y": 9.00261953642076 + }, + { + "x": 0.013203628816427226, + "y": 11.003201655625485 + }, + { + "x": 0.012003298922991235, + "y": 10.00291059602258 + }, + { + "x": 0.012003298922991235, + "y": 10.002910596022563 + }, + { + "x": 0.012003298924128103, + "y": 10.002910596022545 + }, + { + "x": 0.009602639139529856, + "y": 8.002328476818388 + }, + { + "x": 0.010802969030692111, + "y": 9.00261953642076 + }, + { + "x": 0.01080296903182898, + "y": 9.002619536420315 + }, + { + "x": 0.009602639139529856, + "y": 8.002328476817802 + }, + { + "x": 0.012003298922991235, + "y": 10.002910596022438 + }, + { + "x": 0.014403958707589481, + "y": 12.003492715215938 + }, + { + "x": 0.01080296903182898, + "y": 9.00261953642076 + }, + { + "x": 0.010861270135364975, + "y": 9.051204573738634 + }, + { + "x": 0.00185401611247471, + "y": 10.247016124429411 + }, + { + "x": -0.2477526508482697, + "y": 10.341679690066616 + }, + { + "x": -0.6818004879880846, + "y": 11.0453896949595 + }, + { + "x": -1.5067884092354689, + "y": 12.206061227592837 + }, + { + "x": -2.6193696985012593, + "y": 14.519948558364941 + }, + { + "x": -3.210384943561735, + "y": 13.13624283399455 + }, + { + "x": -3.6430961971910847, + "y": 11.742641276023544 + }, + { + "x": -4.289761217264072, + "y": 11.522110628802018 + }, + { + "x": -4.374868894687438, + "y": 10.164871590581495 + }, + { + "x": -5.5413969572066435, + "y": 10.975123143649052 + }, + { + "x": -6.690816213455264, + "y": 11.751490558381086 + }, + { + "x": -6.72465023948007, + "y": 10.29270360820464 + }, + { + "x": -7.286034902792835, + "y": 9.903274462768122 + }, + { + "x": -7.824927048296217, + "y": 9.483268518458289 + }, + { + "x": -7.4743605876170705, + "y": 8.184448103555143 + }, + { + "x": -8.905025827874056, + "y": 8.599326134261469 + }, + { + "x": -11.287415618721184, + "y": 9.69819203487139 + }, + { + "x": -9.861900130458707, + "y": 7.52008125948967 + }, + { + "x": -8.228160325267595, + "y": 5.5474782493052 + }, + { + "x": -9.570172710000406, + "y": 5.746512270369927 + }, + { + "x": -12.083316102209665, + "y": 6.32891591463803 + }, + { + "x": -12.43138559842464, + "y": 5.6144262620453445 + }, + { + "x": -10.42375196217563, + "y": 3.9943522198585035 + }, + { + "x": -10.638684285810314, + "y": 3.3804855643421883 + }, + { + "x": -10.784660307365925, + "y": 2.8810294924293056 + }, + { + "x": -9.70836689145301, + "y": 2.055054722399159 + }, + { + "x": -9.793592100608066, + "y": 1.600394452604883 + }, + { + "x": -11.095965342601062, + "y": 1.2202762342258433 + }, + { + "x": -13.449798125160441, + "y": 0.7097304545301975 + }, + { + "x": -13.316124741018598, + "y": 0.17870199759416616 + }, + { + "x": -9.070258808170593, + "y": 0.0048184546727503275 + }, + { + "x": -9.033336110059054, + "y": 0.004798839979167635 + }, + { + "x": -11.018180263448016, + "y": 0.005853262106236823 + }, + { + "x": -9.014874761002716, + "y": 0.004789032632377399 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 383.08857968437644, + "y": 1.980797890340022, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 92.38854030013255, + "y": -121.94744551989223, + "z": 1.0 + }, + { + "x": 92.38846402549676, + "y": -121.44568059549218, + "z": 1.0 + }, + { + "x": 92.38840300578813, + "y": -121.04426865597216, + "z": 1.0 + }, + { + "x": 92.38834198607951, + "y": -120.64285671645214, + "z": 1.0 + }, + { + "x": 92.38828096637087, + "y": -120.2414447769321, + "z": 1.0 + }, + { + "x": 92.38821994666225, + "y": -119.84003283741208, + "z": 1.0 + }, + { + "x": 92.38821994666225, + "y": -119.84003283741208, + "z": 1.0 + }, + { + "x": 92.38815898411413, + "y": -119.43899692261479, + "z": 1.0 + }, + { + "x": 92.38808284520091, + "y": -118.93812483537857, + "z": 1.0 + }, + { + "x": 92.38799147850507, + "y": -118.33707833069512, + "z": 1.0 + }, + { + "x": 92.38790011180922, + "y": -117.73603182601165, + "z": 1.0 + }, + { + "x": 92.38780874511338, + "y": -117.1349853213282, + "z": 1.0 + }, + { + "x": 92.3877478339828, + "y": -116.73428765153922, + "z": 1.0 + }, + { + "x": 92.38768692285224, + "y": -116.33358998175025, + "z": 1.0 + }, + { + "x": 92.3875955561564, + "y": -115.7325434770668, + "z": 1.0 + }, + { + "x": 92.38753464502582, + "y": -115.33184580727782, + "z": 1.0 + }, + { + "x": 92.38747373389526, + "y": -114.93114813748885, + "z": 1.0 + }, + { + "x": 92.38741282276469, + "y": -114.5304504676996, + "z": 1.0 + }, + { + "x": 92.38732145606885, + "y": -113.92940396301641, + "z": 1.0 + }, + { + "x": 92.38726054493829, + "y": -113.52870629322744, + "z": 1.0 + }, + { + "x": 92.38718440602507, + "y": -113.02783420599124, + "z": 1.0 + }, + { + "x": 92.38709303932922, + "y": -112.42678770130777, + "z": 1.0 + }, + { + "x": 92.38700167263336, + "y": -111.82574119662432, + "z": 1.0 + }, + { + "x": 92.38692553372016, + "y": -111.3248691093881, + "z": 1.0 + }, + { + "x": 92.3868341670243, + "y": -110.72382260470464, + "z": 1.0 + }, + { + "x": 92.38677325589374, + "y": -110.32312493491567, + "z": 1.0 + }, + { + "x": 92.38671234476318, + "y": -109.9224272651267, + "z": 1.0 + }, + { + "x": 92.38662097806733, + "y": -109.32138076044323, + "z": 1.0 + }, + { + "x": 92.38652961137149, + "y": -108.72033425575978, + "z": 1.0 + }, + { + "x": 92.38643824467563, + "y": -108.11928775107631, + "z": 1.0 + }, + { + "x": 92.38637733354507, + "y": -107.71859008128735, + "z": 1.0 + }, + { + "x": 92.38628596684921, + "y": -107.1175435766039, + "z": 1.0 + }, + { + "x": 92.38620982793601, + "y": -106.61667148936768, + "z": 1.0 + }, + { + "x": 92.3861336890228, + "y": -106.11579940213146, + "z": 1.0 + }, + { + "x": 92.38604232232696, + "y": -105.514752897448, + "z": 1.0 + }, + { + "x": 92.3859509556311, + "y": -104.91370639276454, + "z": 1.0 + }, + { + "x": 92.38589004450054, + "y": -104.51300872297557, + "z": 1.0 + }, + { + "x": 92.38579867780469, + "y": -103.91196221829183, + "z": 1.0 + }, + { + "x": 92.38573776667413, + "y": -103.51126454850314, + "z": 1.0 + }, + { + "x": 92.38566162776092, + "y": -103.01039246126692, + "z": 1.0 + }, + { + "x": 92.3855854888477, + "y": -102.50952037403071, + "z": 1.0 + }, + { + "x": 92.3855093499345, + "y": -102.0086482867945, + "z": 1.0 + }, + { + "x": 92.38544843880392, + "y": -101.60795061700523, + "z": 1.0 + }, + { + "x": 92.38538752767336, + "y": -101.20725294721655, + "z": 1.0 + }, + { + "x": 92.38531138876016, + "y": -100.70638085998033, + "z": 1.0 + }, + { + "x": 92.38523524984694, + "y": -100.20550877274411, + "z": 1.0 + }, + { + "x": 92.3851438831511, + "y": -99.60446226806066, + "z": 1.0 + }, + { + "x": 92.38508297202053, + "y": -99.2037645982714, + "z": 1.0 + }, + { + "x": 92.38502206088997, + "y": -98.80306692848272, + "z": 1.0 + }, + { + "x": 92.38493069419413, + "y": -98.20202042379925, + "z": 1.0 + }, + { + "x": 92.38486978306355, + "y": -97.80132275401029, + "z": 1.0 + }, + { + "x": 92.38479364415035, + "y": -97.30045066677407, + "z": 1.0 + }, + { + "x": 92.38471750523713, + "y": -96.79957857953785, + "z": 1.0 + }, + { + "x": 92.38465659410657, + "y": -96.39888090974888, + "z": 1.0 + }, + { + "x": 92.38456522741073, + "y": -95.79783440506542, + "z": 1.0 + }, + { + "x": 92.38450431628016, + "y": -95.39713673527645, + "z": 1.0 + }, + { + "x": 92.3844434051496, + "y": -94.99643906548748, + "z": 1.0 + }, + { + "x": 92.38438249401904, + "y": -94.59574139569851, + "z": 1.0 + }, + { + "x": 92.38432158288846, + "y": -94.19504372590953, + "z": 1.0 + }, + { + "x": 92.38423021619262, + "y": -93.59399722122608, + "z": 1.0 + }, + { + "x": 92.38416930506204, + "y": -93.19329955143711, + "z": 1.0 + }, + { + "x": 92.38407793836619, + "y": -92.59225304675364, + "z": 1.0 + }, + { + "x": 92.38401702723561, + "y": -92.19155537696439, + "z": 1.0 + }, + { + "x": 92.38394088832241, + "y": -91.69068328972845, + "z": 1.0 + }, + { + "x": 92.38387997719185, + "y": -91.28998561993949, + "z": 1.0 + }, + { + "x": 92.383788610496, + "y": -90.68893911525602, + "z": 1.0 + }, + { + "x": 92.3837124715828, + "y": -90.1880670280198, + "z": 1.0 + }, + { + "x": 92.38365156045222, + "y": -89.78736935823055, + "z": 1.0 + }, + { + "x": 92.38356019375638, + "y": -89.18632285354738, + "z": 1.0 + }, + { + "x": 92.38349928262582, + "y": -88.7856251837584, + "z": 1.0 + }, + { + "x": 92.38343837149525, + "y": -88.38492751396943, + "z": 1.0 + }, + { + "x": 92.38337746036468, + "y": -87.98422984418046, + "z": 1.0 + }, + { + "x": 92.38331654923412, + "y": -87.5835321743915, + "z": 1.0 + }, + { + "x": 92.38324041032091, + "y": -87.08266008715528, + "z": 1.0 + }, + { + "x": 92.38317949919035, + "y": -86.68196241736631, + "z": 1.0 + }, + { + "x": 92.38311858805977, + "y": -86.28126474757704, + "z": 1.0 + }, + { + "x": 92.38302722136393, + "y": -85.68021824289387, + "z": 1.0 + }, + { + "x": 92.38296631023337, + "y": -85.2795205731049, + "z": 1.0 + }, + { + "x": 92.38287494353752, + "y": -84.67847406842144, + "z": 1.0 + }, + { + "x": 92.38278357684167, + "y": -84.07742756373798, + "z": 1.0 + }, + { + "x": 92.3827226657111, + "y": -83.676729893949, + "z": 1.0 + }, + { + "x": 92.38263129901524, + "y": -83.07568338926527, + "z": 1.0 + }, + { + "x": 92.38255516010203, + "y": -82.57481130202933, + "z": 1.0 + }, + { + "x": 92.38246379340619, + "y": -81.97376479734588, + "z": 1.0 + }, + { + "x": 92.38240288227561, + "y": -81.57306712755661, + "z": 1.0 + }, + { + "x": 92.38232674336241, + "y": -81.07219504032068, + "z": 1.0 + }, + { + "x": 92.38225060444921, + "y": -80.57132295308448, + "z": 1.0 + }, + { + "x": 92.38218969331864, + "y": -80.1706252832955, + "z": 1.0 + }, + { + "x": 92.3820983266228, + "y": -79.56957877861204, + "z": 1.0 + }, + { + "x": 92.38203741549222, + "y": -79.16888110882307, + "z": 1.0 + }, + { + "x": 92.38194604879638, + "y": -78.5678346041396, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 8, + "heading": [ + 1.5709483394834889, + 1.5709483394834909, + 1.5709483394834847, + 1.5709483394834767, + 1.5709483394834944, + 1.5709483394834944, + 1.5709483394834767, + 1.5709483394835362, + 1.5709483394835178, + 1.5709483394834876, + 1.5709483394834864, + 1.5709483394834864, + 1.5709483394834889, + 1.5709483394834922, + 1.5709483394834747, + 1.5709483394834889, + 1.5709483394834922, + 1.5709483394834922, + 1.5709483394834889, + 1.5709483394834747, + 1.5709483394834904, + 1.5709483394835004, + 1.5709483394834982, + 1.5709483394834876, + 1.5709483394834876, + 1.5709483394834889, + 1.5709483394834747, + 1.5709483394834889, + 1.5709483394834864, + 1.5709483394834864, + 1.5709483394834889, + 1.5709483394834889, + 1.5709483394834876, + 1.5709483394834889, + 1.5709483394834876, + 1.5709483394834864, + 1.5709483394834889, + 1.5709483394834887, + 1.5709483394834889, + 1.5709483394834747, + 1.5709483394835029, + 1.5709483394835029, + 1.5709483394834902, + 1.5709483394834922, + 1.5709483394834747, + 1.5709483394834889, + 1.5709483394834876, + 1.5709483394834887, + 1.5709483394834922, + 1.5709483394834747, + 1.5709483394834889, + 1.5709483394834904, + 1.5709483394834889, + 1.5709483394834904, + 1.5709483394834747, + 1.5709483394834889, + 1.5709483394834922, + 1.5709483394834747, + 1.5709483394834922, + 1.5709483394834889, + 1.5709483394834889, + 1.5709483394835029, + 1.5709483394835029, + 1.5709483394834904, + 1.5709483394834747, + 1.5709483394834889, + 1.5709483394834876, + 1.5709483394834902, + 1.5709483394834889, + 1.5709483394834747, + 1.5709483394834922, + 1.5709483394834922, + 1.5709483394834747, + 1.5709483394834904, + 1.5709483394834904, + 1.5709483394834922, + 1.5709483394834889, + 1.5709483394834747, + 1.5709483394834889, + 1.5709483394834864, + 1.5709483394834889, + 1.5709483394835029, + 1.5709483394835004, + 1.5709483394834876, + 1.5709483394834887, + 1.5709483394834904, + 1.5709483394834747, + 1.5709483394834904, + 1.5709483394834889, + 1.5709483394834889, + 1.5709483394834889 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -0.000762746357878541, + "y": 5.017649244000495 + }, + { + "x": -0.0013729434441245303, + "y": 9.031768639200664 + }, + { + "x": -0.0012203941724919787, + "y": 8.028238790400337 + }, + { + "x": -0.0012203941726340872, + "y": 8.028238790400621 + }, + { + "x": -0.0012203941726340872, + "y": 8.028238790400621 + }, + { + "x": -0.0006101970862459893, + "y": 4.014119395200169 + }, + { + "x": -0.0006096254811893687, + "y": 4.010359147972906 + }, + { + "x": -0.0013710146133405487, + "y": 9.019080020335082 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.0018273339169638803, + "y": 12.020930093669193 + }, + { + "x": -0.0018273339169638803, + "y": 12.020930093669193 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.001218222611356623, + "y": 8.01395339577951 + }, + { + "x": -0.001522778264018143, + "y": 10.01744174472421 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.001218222611356623, + "y": 8.01395339577951 + }, + { + "x": -0.001218222611356623, + "y": 8.01395339578221 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.001522778264018143, + "y": 10.01744174472151 + }, + { + "x": -0.0013705004377584373, + "y": 9.015697570251717 + }, + { + "x": -0.0016750560907041745, + "y": 11.019185919196701 + }, + { + "x": -0.0018273339171059888, + "y": 12.020930093669193 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196843 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0012182226112145145, + "y": 8.013953395779367 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0018273339169638803, + "y": 12.020930093669193 + }, + { + "x": -0.0018273339169638803, + "y": 12.020930093669193 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0015227782641602516, + "y": 10.01744174472421 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.0018273339169638803, + "y": 12.020930093669193 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744727051 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0013705004376163288, + "y": 9.01569757024916 + }, + { + "x": -0.0015227782643023602, + "y": 10.01744174472421 + }, + { + "x": -0.0015227782643023602, + "y": 10.01744174472421 + }, + { + "x": -0.0013705004377584373, + "y": 9.015697570254844 + }, + { + "x": -0.001218222611356623, + "y": 8.01395339577951 + }, + { + "x": -0.0013705004376163288, + "y": 9.015697570249017 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744727051 + }, + { + "x": -0.001218222611356623, + "y": 8.013953395779367 + }, + { + "x": -0.001522778264018143, + "y": 10.01744174472151 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0013705004377584373, + "y": 9.01569757025186 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0013705004377584373, + "y": 9.01569757025186 + }, + { + "x": -0.001522778264018143, + "y": 10.017441744724351 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.001218222611356623, + "y": 8.013953395779367 + }, + { + "x": -0.0012182226112145145, + "y": 8.013953395779367 + }, + { + "x": -0.001218222611356623, + "y": 8.01395339577951 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0015227782641602516, + "y": 10.01744174472421 + }, + { + "x": -0.0015227782643023602, + "y": 10.017441744724351 + }, + { + "x": -0.0015227782643023602, + "y": 10.017441744727194 + }, + { + "x": -0.0013705004377584373, + "y": 9.01569757025186 + }, + { + "x": -0.0013705004376163288, + "y": 9.015697570249017 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196843 + }, + { + "x": -0.0013705004377584373, + "y": 9.015697570254702 + }, + { + "x": -0.0015227782641602516, + "y": 10.01744174472421 + }, + { + "x": -0.001522778264018143, + "y": 10.01744174472151 + }, + { + "x": -0.001218222611356623, + "y": 8.01395339577951 + }, + { + "x": -0.001218222611356623, + "y": 8.013953395779367 + }, + { + "x": -0.0012182226112145145, + "y": 8.013953395779367 + }, + { + "x": -0.0013705004377584373, + "y": 9.01569757025186 + }, + { + "x": -0.0013705004377584373, + "y": 9.01569757025186 + }, + { + "x": -0.001218222611356623, + "y": 8.013953395782352 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.001522778264018143, + "y": 10.017441744721367 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0018273339169638803, + "y": 12.020930093669193 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0015227782643023602, + "y": 10.017441744727194 + }, + { + "x": -0.0016750560907041745, + "y": 11.019185919196701 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919193859 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744727194 + }, + { + "x": -0.0013705004377584373, + "y": 9.015697570252001 + }, + { + "x": -0.001522778264018143, + "y": 10.017441744721367 + }, + { + "x": -0.0013705004377584373, + "y": 9.01569757025186 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0015227782641602516, + "y": 10.01744174472421 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 92.38194604879638, + "y": -78.5678346041396, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 336.1489057852639, + "y": -325.05033162122857, + "z": 1.0 + }, + { + "x": 336.5229456022105, + "y": -325.67646946787795, + "z": 1.0 + }, + { + "x": 336.7939565516582, + "y": -326.0799650034013, + "z": 1.0 + }, + { + "x": 337.15633618498657, + "y": -326.5676097729596, + "z": 1.0 + }, + { + "x": 337.5440052274156, + "y": -327.03539979664663, + "z": 1.0 + }, + { + "x": 337.9622085454788, + "y": -327.4877505784889, + "z": 1.0 + }, + { + "x": 338.3183308810072, + "y": -327.8342538022563, + "z": 1.0 + }, + { + "x": 338.8825055067306, + "y": -328.3211543814014, + "z": 1.0 + }, + { + "x": 339.378296205565, + "y": -328.69520423560505, + "z": 1.0 + }, + { + "x": 340.0013780611089, + "y": -329.10403038474396, + "z": 1.0 + }, + { + "x": 340.5418874628223, + "y": -329.4099335158296, + "z": 1.0 + }, + { + "x": 340.9871585419557, + "y": -329.63124209683366, + "z": 1.0 + }, + { + "x": 341.5575350479918, + "y": -329.8773357090277, + "z": 1.0 + }, + { + "x": 342.141456730006, + "y": -330.0889067021541, + "z": 1.0 + }, + { + "x": 342.8572627989721, + "y": -330.29624980319954, + "z": 1.0 + }, + { + "x": 343.5860716295812, + "y": -330.45182618187255, + "z": 1.0 + }, + { + "x": 344.07732448992476, + "y": -330.52637956177955, + "z": 1.0 + }, + { + "x": 344.57157639307513, + "y": -330.5773955476963, + "z": 1.0 + }, + { + "x": 345.31253722029027, + "y": -330.6095350149743, + "z": 1.0 + }, + { + "x": 345.82291093398845, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 346.2243261579756, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 346.6257413819628, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 347.02715660595004, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 347.528925635934, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 347.7296332479276, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 348.1305367405361, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 348.73136320009144, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 349.23205191638755, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 349.73274063268366, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 350.1332916057205, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 350.6339803220166, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 351.0345312950535, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 351.5352200113496, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 351.93577098438647, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 352.33632195742337, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 352.8370106737195, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 353.2375616467564, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 353.6381126197932, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 354.23893907934854, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 354.8397655389039, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 355.24031651194076, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 355.8411429714961, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 356.4419694310514, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 357.0427958906067, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 357.4433468636436, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 357.8438978366805, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 358.44472429623585, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 358.94541301253196, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 359.3459639855688, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 359.9467904451242, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 360.44747916142023, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 360.94816787771634, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 361.44885659401245, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 361.94954531030857, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 362.4502340266047, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 362.9509227429008, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 363.4516114591969, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 364.0524379187522, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 364.45298889178906, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 365.0538153513444, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 365.5545040676405, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 366.0551927839366, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 366.5558815002327, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 367.0565702165288, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 367.65739667608415, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 368.15808539238026, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 368.65877410867637, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 369.1594628249725, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 369.5600137980093, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 369.9605647710462, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 370.3611157440831, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 370.76166671712, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 371.16221769015687, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 371.662906406453, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 372.1635951227491, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 372.6642838390452, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 373.1649725553413, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 373.6656612716374, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 374.26648773119274, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 374.76717644748885, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 375.2678651637849, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 375.768553880081, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 376.36938033963634, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 376.76993131267324, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 377.17048228571014, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 377.571033258747, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 378.17185971830236, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 378.7726861778577, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 379.1732371508945, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 379.5737881239314, + "y": -330.6099853515625, + "z": 1.0 + }, + { + "x": 380.17461458348674, + "y": -330.6099853515625, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 9, + "heading": [ + -0.11553553829427615, + -1.0323083606255987, + -1.0111292333148185, + -0.9528825726285378, + -0.9052479255653736, + -0.8515053875159617, + -0.8009884773025137, + -0.7358901996185394, + -0.6821623094798233, + -0.6105251199603642, + -0.5508274551632518, + -0.4911113655175353, + -0.4313047534661909, + -0.3774745492893383, + -0.3117961589325643, + -0.24612873318359238, + -0.18643105564388768, + -0.1267334041301747, + -0.067219329230323, + -0.026038151534696963, + -0.0004939043817662466, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 3.7403981694660615, + "y": -6.261378466493852 + }, + { + "x": 6.450507663943199, + "y": -10.29633382172733 + }, + { + "x": 6.333905827760873, + "y": -8.911403050816489 + }, + { + "x": 7.500486757573981, + "y": -9.554347932453311 + }, + { + "x": 8.058723604922307, + "y": -9.201408055292859 + }, + { + "x": 7.743256535916316, + "y": -7.988540056096554 + }, + { + "x": 9.20296961251779, + "y": -8.334038029125281 + }, + { + "x": 10.599653245577656, + "y": -8.609504333487621 + }, + { + "x": 11.188725543782994, + "y": -7.82876003342551 + }, + { + "x": 11.635912572572806, + "y": -7.147292802245602 + }, + { + "x": 9.857804808468131, + "y": -5.272117120896951 + }, + { + "x": 10.156475851695177, + "y": -4.674021931980974 + }, + { + "x": 11.542981880502907, + "y": -4.576646053204172 + }, + { + "x": 12.997277509803098, + "y": -4.189140941718392 + }, + { + "x": 14.446148995752424, + "y": -3.6291947971847094 + }, + { + "x": 12.200616909526616, + "y": -2.3012975858000573 + }, + { + "x": 9.85504763493907, + "y": -1.2556936582376466 + }, + { + "x": 12.352127303655038, + "y": -0.8315545319476314 + }, + { + "x": 12.513345409133194, + "y": -0.32589803866187594 + }, + { + "x": 9.11788937685344, + "y": -0.004503365881873833 + }, + { + "x": 8.028304479743724, + "y": 0.0 + }, + { + "x": 8.028304479744293, + "y": 0.0 + }, + { + "x": 9.03184253971176, + "y": 0.0 + }, + { + "x": 7.024766419775688, + "y": 0.0 + }, + { + "x": 6.0161110460211376, + "y": 0.0 + }, + { + "x": 10.017299521638279, + "y": 0.0 + }, + { + "x": 11.015151758514321, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 9.012396893329537, + "y": 0.0 + }, + { + "x": 9.012396893329537, + "y": 0.0 + }, + { + "x": 9.012396893330106, + "y": 0.0 + }, + { + "x": 9.012396893330106, + "y": 0.0 + }, + { + "x": 9.012396893329537, + "y": 0.0 + }, + { + "x": 8.01101946073743, + "y": 0.0 + }, + { + "x": 9.012396893330106, + "y": 0.0 + }, + { + "x": 9.012396893330106, + "y": 0.0 + }, + { + "x": 8.01101946073743, + "y": 0.0 + }, + { + "x": 10.013774325921645, + "y": 0.0 + }, + { + "x": 12.016529191106997, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 10.013774325921645, + "y": 0.0 + }, + { + "x": 12.016529191106429, + "y": 0.0 + }, + { + "x": 12.016529191106429, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 8.011019460737998, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 11.015151758514321, + "y": 0.0 + }, + { + "x": 9.012396893329537, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 11.015151758514321, + "y": 0.0 + }, + { + "x": 10.013774325921645, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 11.015151758514321, + "y": 0.0 + }, + { + "x": 10.013774325921645, + "y": 0.0 + }, + { + "x": 10.013774325921645, + "y": 0.0 + }, + { + "x": 11.015151758514321, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 11.015151758514321, + "y": 0.0 + }, + { + "x": 11.015151758514321, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 9.012396893329537, + "y": 0.0 + }, + { + "x": 8.01101946073743, + "y": 0.0 + }, + { + "x": 8.011019460737998, + "y": 0.0 + }, + { + "x": 8.011019460737998, + "y": 0.0 + }, + { + "x": 8.01101946073743, + "y": 0.0 + }, + { + "x": 9.012396893329537, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 11.015151758514321, + "y": 0.0 + }, + { + "x": 11.015151758514321, + "y": 0.0 + }, + { + "x": 10.013774325921645, + "y": 0.0 + }, + { + "x": 10.013774325921645, + "y": 0.0 + }, + { + "x": 11.015151758514321, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 8.011019460737998, + "y": 0.0 + }, + { + "x": 8.01101946073743, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + }, + { + "x": 12.016529191106997, + "y": 0.0 + }, + { + "x": 10.013774325921645, + "y": 0.0 + }, + { + "x": 8.01101946073743, + "y": 0.0 + }, + { + "x": 10.013774325922213, + "y": 0.0 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 380.17461458348674, + "y": -330.6099853515625, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 334.75466558785854, + "y": -240.4847832109267, + "z": 1.0 + }, + { + "x": 334.7543028798573, + "y": -241.0852821771714, + "z": 1.0 + }, + { + "x": 334.75406107452307, + "y": -241.48561482133636, + "z": 1.0 + }, + { + "x": 334.75381926918885, + "y": -241.88594746550024, + "z": 1.0 + }, + { + "x": 334.75357746385475, + "y": -242.28628010966406, + "z": 1.0 + }, + { + "x": 334.75333565852054, + "y": -242.68661275382675, + "z": 1.0 + }, + { + "x": 334.7530334018528, + "y": -243.18702855903274, + "z": 1.0 + }, + { + "x": 334.75273114518507, + "y": -243.68744436423754, + "z": 1.0 + }, + { + "x": 334.7523684371838, + "y": -244.28794333048216, + "z": 1.0 + }, + { + "x": 334.75206618051607, + "y": -244.7883591356881, + "z": 1.0 + }, + { + "x": 334.75182437518185, + "y": -245.18869177985084, + "z": 1.0 + }, + { + "x": 334.7514616671806, + "y": -245.78919074609774, + "z": 1.0 + }, + { + "x": 334.75109895917933, + "y": -246.3896897123435, + "z": 1.0 + }, + { + "x": 334.7508571538451, + "y": -246.7900223565062, + "z": 1.0 + }, + { + "x": 334.7505548971774, + "y": -247.2904381617122, + "z": 1.0 + }, + { + "x": 334.7501921891761, + "y": -247.89093712795682, + "z": 1.0 + }, + { + "x": 334.7499503838419, + "y": -248.29126977212064, + "z": 1.0 + }, + { + "x": 334.74958767584064, + "y": -248.89176873836755, + "z": 1.0 + }, + { + "x": 334.7492249678394, + "y": -249.49226770461217, + "z": 1.0 + }, + { + "x": 334.74898316250517, + "y": -249.89260034877606, + "z": 1.0 + }, + { + "x": 334.74868090583743, + "y": -250.39301615398085, + "z": 1.0 + }, + { + "x": 334.7483786491697, + "y": -250.89343195918678, + "z": 1.0 + }, + { + "x": 334.74801594116843, + "y": -251.4939309254314, + "z": 1.0 + }, + { + "x": 334.74765323316717, + "y": -252.09442989167837, + "z": 1.0 + }, + { + "x": 334.74735097649943, + "y": -252.59484569688203, + "z": 1.0 + }, + { + "x": 334.74698826849806, + "y": -253.19534466312894, + "z": 1.0 + }, + { + "x": 334.7466860118303, + "y": -253.69576046833373, + "z": 1.0 + }, + { + "x": 334.7464442064962, + "y": -254.0960931124976, + "z": 1.0 + }, + { + "x": 334.7461419498285, + "y": -254.5965089177024, + "z": 1.0 + }, + { + "x": 334.7457792418271, + "y": -255.19700788394817, + "z": 1.0 + }, + { + "x": 334.74541653382585, + "y": -255.7975068501928, + "z": 1.0 + }, + { + "x": 334.7451142771581, + "y": -256.2979226553988, + "z": 1.0 + }, + { + "x": 334.7448120204904, + "y": -256.79833846060353, + "z": 1.0 + }, + { + "x": 334.74450976382263, + "y": -257.2987542658084, + "z": 1.0 + }, + { + "x": 334.7442075071549, + "y": -257.7991700710121, + "z": 1.0 + }, + { + "x": 334.7439657018208, + "y": -258.199502715177, + "z": 1.0 + }, + { + "x": 334.74366344515306, + "y": -258.6999185203807, + "z": 1.0 + }, + { + "x": 334.7433007371517, + "y": -259.3004174866277, + "z": 1.0 + }, + { + "x": 334.7430589318175, + "y": -259.70075013079145, + "z": 1.0 + }, + { + "x": 334.7428171264834, + "y": -260.1010827749542, + "z": 1.0 + }, + { + "x": 334.74251486981564, + "y": -260.6014985801602, + "z": 1.0 + }, + { + "x": 334.7421521618144, + "y": -261.20199754640475, + "z": 1.0 + }, + { + "x": 334.74184990514664, + "y": -261.7024133516096, + "z": 1.0 + }, + { + "x": 334.7415476484789, + "y": -262.2028291568156, + "z": 1.0 + }, + { + "x": 334.74118494047764, + "y": -262.80332812306017, + "z": 1.0 + }, + { + "x": 334.7409431351434, + "y": -263.20366076722405, + "z": 1.0 + }, + { + "x": 334.74058042714205, + "y": -263.8041597334709, + "z": 1.0 + }, + { + "x": 334.7402781704744, + "y": -264.30457553867575, + "z": 1.0 + }, + { + "x": 334.7400363651402, + "y": -264.70490818283963, + "z": 1.0 + }, + { + "x": 334.739794559806, + "y": -265.10524082700226, + "z": 1.0 + }, + { + "x": 334.73943185180474, + "y": -265.7057397932481, + "z": 1.0 + }, + { + "x": 334.7390691438035, + "y": -266.30623875949505, + "z": 1.0 + }, + { + "x": 334.73876688713574, + "y": -266.8066545646998, + "z": 1.0 + }, + { + "x": 334.73840417913436, + "y": -267.4071535309456, + "z": 1.0 + }, + { + "x": 334.7380414711331, + "y": -268.0076524971913, + "z": 1.0 + }, + { + "x": 334.73767876313184, + "y": -268.60815146343714, + "z": 1.0 + }, + { + "x": 334.7373160551306, + "y": -269.20865042968285, + "z": 1.0 + }, + { + "x": 334.73701379846284, + "y": -269.7090662348877, + "z": 1.0 + }, + { + "x": 334.7367719931286, + "y": -270.1093988790516, + "z": 1.0 + }, + { + "x": 334.7364697364609, + "y": -270.6098146842563, + "z": 1.0 + }, + { + "x": 334.7361070284596, + "y": -271.210313650501, + "z": 1.0 + }, + { + "x": 334.7358047717919, + "y": -271.710729455707, + "z": 1.0 + }, + { + "x": 334.7355629664578, + "y": -272.1110620998696, + "z": 1.0 + }, + { + "x": 334.73526070978994, + "y": -272.6114779050756, + "z": 1.0 + }, + { + "x": 334.7349584531222, + "y": -273.11189371028047, + "z": 1.0 + }, + { + "x": 334.73459574512094, + "y": -273.7123926765262, + "z": 1.0 + }, + { + "x": 334.73435393978684, + "y": -274.1127253206889, + "z": 1.0 + }, + { + "x": 334.73411213445263, + "y": -274.5130579648528, + "z": 1.0 + }, + { + "x": 334.7338098777849, + "y": -275.01347377005754, + "z": 1.0 + }, + { + "x": 334.7335680724507, + "y": -275.4138064142214, + "z": 1.0 + }, + { + "x": 334.73332626711647, + "y": -275.81413905838644, + "z": 1.0 + }, + { + "x": 334.73308446178225, + "y": -276.2144717025502, + "z": 1.0 + }, + { + "x": 334.7327822051145, + "y": -276.71488750775507, + "z": 1.0 + }, + { + "x": 334.7324799484468, + "y": -277.2153033129599, + "z": 1.0 + }, + { + "x": 334.7321172404455, + "y": -277.8158022792056, + "z": 1.0 + }, + { + "x": 334.7318754351114, + "y": -278.2161349233684, + "z": 1.0 + }, + { + "x": 334.7316336297772, + "y": -278.61646756753225, + "z": 1.0 + }, + { + "x": 334.73133137310947, + "y": -279.116883372737, + "z": 1.0 + }, + { + "x": 334.7309686651081, + "y": -279.7173823389828, + "z": 1.0 + }, + { + "x": 334.73060595710683, + "y": -280.31788130522966, + "z": 1.0 + }, + { + "x": 334.73024324910557, + "y": -280.91838027147435, + "z": 1.0 + }, + { + "x": 334.72994099243783, + "y": -281.4187960766802, + "z": 1.0 + }, + { + "x": 334.7296387357701, + "y": -281.9192118818862, + "z": 1.0 + }, + { + "x": 334.72927602776883, + "y": -282.51971084812976, + "z": 1.0 + }, + { + "x": 334.72891331976757, + "y": -283.12020981437547, + "z": 1.0 + }, + { + "x": 334.72867151443336, + "y": -283.5205424585405, + "z": 1.0 + }, + { + "x": 334.72842970909915, + "y": -283.9208751027044, + "z": 1.0 + }, + { + "x": 334.7281274524314, + "y": -284.4212909079091, + "z": 1.0 + }, + { + "x": 334.7278856470972, + "y": -284.821623552073, + "z": 1.0 + }, + { + "x": 334.72752293909593, + "y": -285.4221225183177, + "z": 1.0 + }, + { + "x": 334.7272811337617, + "y": -285.8224551624826, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 10, + "heading": [ + -1.5714003377550492, + -1.5714003377550179, + -1.5714003377550545, + -1.5714003377551105, + -1.5714003377549692, + -1.5714003377549701, + -1.5714003377550798, + -1.5714003377550538, + -1.5714003377550345, + -1.5714003377550338, + -1.5714003377550798, + -1.5714003377550545, + -1.571400337755016, + -1.5714003377550552, + -1.5714003377550798, + -1.5714003377550338, + -1.5714003377550552, + -1.5714003377550538, + -1.5714003377550168, + -1.5714003377550552, + -1.5714003377550798, + -1.5714003377550538, + -1.5714003377550338, + -1.5714003377550168, + -1.5714003377550338, + -1.571400337755137, + -1.5714003377551364, + -1.5714003377549535, + -1.5714003377549535, + -1.571400337755137, + -1.571400337755112, + -1.5714003377550338, + -1.5714003377550538, + -1.5714003377550545, + -1.5714003377550552, + -1.5714003377549537, + -1.5714003377549537, + -1.571400337755137, + -1.5714003377551675, + -1.5714003377549701, + -1.5714003377549535, + -1.5714003377550338, + -1.5714003377550345, + -1.5714003377550538, + -1.5714003377550338, + -1.5714003377550552, + -1.5714003377551675, + -1.5714003377550332, + -1.5714003377549535, + -1.5714003377551122, + -1.5714003377550552, + -1.571400337755016, + -1.5714003377550332, + -1.571400337755137, + -1.5714003377551113, + -1.5714003377550168, + -1.5714003377550168, + -1.5714003377550338, + -1.5714003377550798, + -1.5714003377550798, + -1.5714003377550345, + -1.5714003377550338, + -1.5714003377549537, + -1.5714003377550798, + -1.5714003377551673, + -1.5714003377550338, + -1.5714003377549417, + -1.5714003377549701, + -1.5714003377550798, + -1.5714003377550798, + -1.5714003377551105, + -1.5714003377551105, + -1.5714003377550798, + -1.5714003377550545, + -1.5714003377550338, + -1.5714003377549417, + -1.5714003377549701, + -1.5714003377550798, + -1.571400337755137, + -1.5714003377551107, + -1.5714003377550168, + -1.5714003377550338, + -1.5714003377550532, + -1.5714003377550345, + -1.5714003377550179, + -1.5714003377550538, + -1.5714003377551105, + -1.5714003377550798, + -1.5714003377550798, + -1.5714003377550552, + -1.5714003377550545 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -0.003627080012620354, + "y": -6.00498966244686 + }, + { + "x": -0.006045133354746213, + "y": -10.00831610409648 + }, + { + "x": -0.0048361066842517175, + "y": -8.006652883288439 + }, + { + "x": -0.004836106683114849, + "y": -8.00665288327707 + }, + { + "x": -0.004836106683114849, + "y": -8.006652883265133 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686775 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104107848 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714494247 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714505616 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686775 + }, + { + "x": -0.006045133354746213, + "y": -10.00831610409648 + }, + { + "x": -0.007254160025240708, + "y": -12.00997932492669 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104084543 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686775 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714506184 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104084543 + }, + { + "x": -0.006045133354746213, + "y": -10.00831610410728 + }, + { + "x": -0.007254160025240708, + "y": -12.00997932491532 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104085111 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686775 + }, + { + "x": -0.006045133354746213, + "y": -10.00831610410728 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714505616 + }, + { + "x": -0.007254160025240708, + "y": -12.00997932491589 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714506184 + }, + { + "x": -0.006649646691130329, + "y": -11.009147714505616 + }, + { + "x": -0.006649646691130329, + "y": -11.009147714516985 + }, + { + "x": -0.005440620018362097, + "y": -9.007484493686775 + }, + { + "x": -0.005440620018362097, + "y": -9.007484493686775 + }, + { + "x": -0.006649646691130329, + "y": -11.009147714505616 + }, + { + "x": -0.007254160026377576, + "y": -12.009979324903952 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714506184 + }, + { + "x": -0.006045133354746213, + "y": -10.00831610410728 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104095911 + }, + { + "x": -0.006045133354746213, + "y": -10.00831610408568 + }, + { + "x": -0.005440620018362097, + "y": -9.007484493686206 + }, + { + "x": -0.005440620018362097, + "y": -9.007484493686206 + }, + { + "x": -0.006649646691130329, + "y": -11.009147714506753 + }, + { + "x": -0.006045133355883081, + "y": -10.00831610410728 + }, + { + "x": -0.004836106683114849, + "y": -8.006652883265133 + }, + { + "x": -0.005440620018362097, + "y": -9.007484493687343 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714505616 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714494247 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104108417 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714505616 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104084543 + }, + { + "x": -0.006045133355883081, + "y": -10.00831610410728 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714516985 + }, + { + "x": -0.005440620018362097, + "y": -9.007484493687343 + }, + { + "x": -0.0048361066842517175, + "y": -8.006652883265133 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104084543 + }, + { + "x": -0.007254160025240708, + "y": -12.009979324927826 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714516985 + }, + { + "x": -0.006649646691130329, + "y": -11.009147714505616 + }, + { + "x": -0.007254160026377576, + "y": -12.00997932491532 + }, + { + "x": -0.007254160025240708, + "y": -12.00997932491532 + }, + { + "x": -0.007254160025240708, + "y": -12.00997932491532 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714505616 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493687343 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686206 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714494247 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714506753 + }, + { + "x": -0.005440620018362097, + "y": -9.007484493686206 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686206 + }, + { + "x": -0.006045133355883081, + "y": -10.008316104108417 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714505616 + }, + { + "x": -0.006045133353609344, + "y": -10.008316104084543 + }, + { + "x": -0.004836106683114849, + "y": -8.00665288326627 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686206 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686206 + }, + { + "x": -0.0048361066842517175, + "y": -8.006652883289007 + }, + { + "x": -0.0048361066842517175, + "y": -8.00665288328787 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686206 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104097048 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714505616 + }, + { + "x": -0.006045133353609344, + "y": -10.008316104084543 + }, + { + "x": -0.004836106683114849, + "y": -8.00665288326627 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686206 + }, + { + "x": -0.006649646691130329, + "y": -11.009147714505616 + }, + { + "x": -0.007254160026377576, + "y": -12.00997932492669 + }, + { + "x": -0.007254160025240708, + "y": -12.00997932491532 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714505616 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104118649 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714495384 + }, + { + "x": -0.007254160025240708, + "y": -12.009979324892583 + }, + { + "x": -0.006045133354746213, + "y": -10.00831610410728 + }, + { + "x": -0.0048361066842517175, + "y": -8.006652883289007 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686206 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686206 + }, + { + "x": -0.006045133354746213, + "y": -10.00831610408568 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104095911 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 334.7272811337617, + "y": -285.8224551624826, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 158.0791310994979, + "y": -7.179605138451363, + "z": 1.0 + }, + { + "x": 158.11097082453202, + "y": -6.804332927747964, + "z": 1.0 + }, + { + "x": 158.15356090357636, + "y": -6.506044877657019, + "z": 1.0 + }, + { + "x": 158.24571299169025, + "y": -6.06363223592093, + "z": 1.0 + }, + { + "x": 158.37129529979165, + "y": -5.629523240288274, + "z": 1.0 + }, + { + "x": 158.52957898435005, + "y": -5.206238236024314, + "z": 1.0 + }, + { + "x": 158.68580526464018, + "y": -4.863544334243314, + "z": 1.0 + }, + { + "x": 158.82599564588895, + "y": -4.597510743033778, + "z": 1.0 + }, + { + "x": 159.02040646680712, + "y": -4.274940885637076, + "z": 1.0 + }, + { + "x": 159.19043770232992, + "y": -4.026182441576452, + "z": 1.0 + }, + { + "x": 159.3728867448101, + "y": -3.7863852726082063, + "z": 1.0 + }, + { + "x": 159.66581715772864, + "y": -3.4485299588337934, + "z": 1.0 + }, + { + "x": 159.86664884961996, + "y": -3.248066137378774, + "z": 1.0 + }, + { + "x": 160.07906496134046, + "y": -3.059920311173475, + "z": 1.0 + }, + { + "x": 160.4177510798241, + "y": -2.8022456274618905, + "z": 1.0 + }, + { + "x": 160.77809586609953, + "y": -2.575834518513972, + "z": 1.0 + }, + { + "x": 161.09221276714152, + "y": -2.4128186939734793, + "z": 1.0 + }, + { + "x": 161.41831692152203, + "y": -2.273349780093421, + "z": 1.0 + }, + { + "x": 161.75389318218015, + "y": -2.1585414349510534, + "z": 1.0 + }, + { + "x": 162.16646585430743, + "y": -2.054208769202902, + "z": 1.0 + }, + { + "x": 162.5867055330603, + "y": -1.9871276453476843, + "z": 1.0 + }, + { + "x": 162.94034406743444, + "y": -1.960078107492641, + "z": 1.0 + }, + { + "x": 163.44525098561672, + "y": -1.9564427538507048, + "z": 1.0 + }, + { + "x": 163.94900597132929, + "y": -1.956496519249997, + "z": 1.0 + }, + { + "x": 164.45276095704185, + "y": -1.9565502846492888, + "z": 1.0 + }, + { + "x": 165.05726693989692, + "y": -1.9566148031284396, + "z": 1.0 + }, + { + "x": 165.66177292275202, + "y": -1.95667932160759, + "z": 1.0 + }, + { + "x": 166.06477691132207, + "y": -1.9567223339270237, + "z": 1.0 + }, + { + "x": 166.66928289417714, + "y": -1.956786852406174, + "z": 1.0 + }, + { + "x": 167.17303787988973, + "y": -1.9568406178054727, + "z": 1.0 + }, + { + "x": 167.7775438627448, + "y": -1.9569051362846233, + "z": 1.0 + }, + { + "x": 168.07979685417234, + "y": -1.9569373955241984, + "z": 1.0 + }, + { + "x": 168.480178046297, + "y": -1.9569801279145151, + "z": 1.0 + }, + { + "x": 169.080749834484, + "y": -1.9570442264999608, + "z": 1.0 + }, + { + "x": 169.58122632463983, + "y": -1.9570976419878323, + "z": 1.0 + }, + { + "x": 170.18179811282684, + "y": -1.957161740573278, + "z": 1.0 + }, + { + "x": 170.5821793049515, + "y": -1.957204472963575, + "z": 1.0 + }, + { + "x": 171.18275109313848, + "y": -1.957268571549021, + "z": 1.0 + }, + { + "x": 171.68322758329433, + "y": -1.9573219870368925, + "z": 1.0 + }, + { + "x": 172.08360877541898, + "y": -1.9573647194271895, + "z": 1.0 + }, + { + "x": 172.58408526557483, + "y": -1.957418134915061, + "z": 1.0 + }, + { + "x": 173.08456175573065, + "y": -1.9574715504029325, + "z": 1.0 + }, + { + "x": 173.58503824588647, + "y": -1.957524965890804, + "z": 1.0 + }, + { + "x": 174.0855147360423, + "y": -1.9575783813786751, + "z": 1.0 + }, + { + "x": 174.48589592816697, + "y": -1.9576211137689725, + "z": 1.0 + }, + { + "x": 174.9863724183228, + "y": -1.957674529256844, + "z": 1.0 + }, + { + "x": 175.5869442065098, + "y": -1.9577386278422897, + "z": 1.0 + }, + { + "x": 175.98732539863445, + "y": -1.9577813602325866, + "z": 1.0 + }, + { + "x": 176.58789718682146, + "y": -1.9578454588180327, + "z": 1.0 + }, + { + "x": 177.18846897500845, + "y": -1.9579095574034784, + "z": 1.0 + }, + { + "x": 177.6889454651643, + "y": -1.95796297289135, + "z": 1.0 + }, + { + "x": 178.28951725335128, + "y": -1.9580270714767956, + "z": 1.0 + }, + { + "x": 178.7899937435071, + "y": -1.958080486964667, + "z": 1.0 + }, + { + "x": 179.3905655316941, + "y": -1.9581445855501127, + "z": 1.0 + }, + { + "x": 179.9911373198811, + "y": -1.9582086841355584, + "z": 1.0 + }, + { + "x": 180.49161381003694, + "y": -1.95826209962343, + "z": 1.0 + }, + { + "x": 181.09218559822392, + "y": -1.9583261982088755, + "z": 1.0 + }, + { + "x": 181.69275738641093, + "y": -1.9583902967943212, + "z": 1.0 + }, + { + "x": 182.19323387656675, + "y": -1.9584437122821927, + "z": 1.0 + }, + { + "x": 182.59361506869143, + "y": -1.9584864446724901, + "z": 1.0 + }, + { + "x": 183.19418685687842, + "y": -1.9585505432579358, + "z": 1.0 + }, + { + "x": 183.7947586450654, + "y": -1.9586146418433814, + "z": 1.0 + }, + { + "x": 184.3953304332524, + "y": -1.958678740428827, + "z": 1.0 + }, + { + "x": 184.79571162537707, + "y": -1.9587214728191245, + "z": 1.0 + }, + { + "x": 185.2961881155329, + "y": -1.9587748883069955, + "z": 1.0 + }, + { + "x": 185.8967599037199, + "y": -1.9588389868924416, + "z": 1.0 + }, + { + "x": 186.39723639387574, + "y": -1.9588924023803127, + "z": 1.0 + }, + { + "x": 186.7976175860004, + "y": -1.95893513477061, + "z": 1.0 + }, + { + "x": 187.39818937418738, + "y": -1.9589992333560557, + "z": 1.0 + }, + { + "x": 187.9987611623744, + "y": -1.9590633319415014, + "z": 1.0 + }, + { + "x": 188.4992376525302, + "y": -1.959116747429373, + "z": 1.0 + }, + { + "x": 189.09980944071722, + "y": -1.9591808460148186, + "z": 1.0 + }, + { + "x": 189.50019063284188, + "y": -1.959223578405116, + "z": 1.0 + }, + { + "x": 190.0006671229977, + "y": -1.9592769938929875, + "z": 1.0 + }, + { + "x": 190.40104831512238, + "y": -1.9593197262832844, + "z": 1.0 + }, + { + "x": 190.9015248052782, + "y": -1.959373141771156, + "z": 1.0 + }, + { + "x": 191.30190599740286, + "y": -1.959415874161453, + "z": 1.0 + }, + { + "x": 191.8023824875587, + "y": -1.9594692896493244, + "z": 1.0 + }, + { + "x": 192.30285897771452, + "y": -1.959522705137196, + "z": 1.0 + }, + { + "x": 192.80333546787037, + "y": -1.9595761206250675, + "z": 1.0 + }, + { + "x": 193.3038119580262, + "y": -1.959629536112939, + "z": 1.0 + }, + { + "x": 193.90438374621317, + "y": -1.9596936346983846, + "z": 1.0 + }, + { + "x": 194.40486023636902, + "y": -1.9597470501862562, + "z": 1.0 + }, + { + "x": 194.90533672652484, + "y": -1.9598004656741277, + "z": 1.0 + }, + { + "x": 195.50590851471185, + "y": -1.9598645642595733, + "z": 1.0 + }, + { + "x": 195.9062897068365, + "y": -1.9599072966498703, + "z": 1.0 + }, + { + "x": 196.50686149502351, + "y": -1.9599713952353164, + "z": 1.0 + }, + { + "x": 197.00733798517933, + "y": -1.9600248107231875, + "z": 1.0 + }, + { + "x": 197.60790977336632, + "y": -1.9600889093086336, + "z": 1.0 + }, + { + "x": 198.00829096549103, + "y": -1.9601316416989305, + "z": 1.0 + }, + { + "x": 198.60886275367812, + "y": -1.9601957402843762, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 11, + "heading": [ + 0.19935498835074622, + 1.4861546924418993, + 1.4607407580935998, + 1.3908522439327338, + 1.3273172116869896, + 1.2510751549492403, + 1.1811866373806958, + 1.1176473528504982, + 1.053886187741048, + 1.0029846256276123, + 0.9458030512447957, + 0.8822169386900508, + 0.828543390212532, + 0.7546814735401104, + 0.6801814600203556, + 0.6056813147480384, + 0.5236280170446252, + 0.44138141729989416, + 0.3668904708916304, + 0.2849404521945748, + 0.20299041185484692, + 0.12104038438677348, + 0.035725349092794956, + 0.0035508163599969026, + -0.00010672926444951508, + -0.00010672926444963529, + -0.00010672926444973295, + -0.00010672926444951205, + -0.00010672926444951508, + -0.00010672926445544282, + -0.00010672926445564316, + -0.00010672926444961302, + -0.00010672926447730693, + -0.00010672926446900236, + -0.00010672926444954181, + -0.00010672926444954181, + -0.0001067292644492592, + -0.0001067292644497059, + -0.00010672926444994514, + -0.00010672926444940675, + -0.00010672926444940675, + -0.00010672926444970287, + -0.0001067292644497059, + -0.0001067292644492592, + -0.00010672926444940675, + -0.00010672926444990308, + -0.00010672926444954181, + -0.0001067292644492592, + -0.00010672926444970287, + -0.00010672926444977732, + -0.00010672926444954181, + -0.00010672926444954181, + -0.00010672926444954457, + -0.00010672926444954181, + -0.00010672926444940759, + -0.00010672926444954181, + -0.00010672926444954181, + -0.00010672926444940759, + -0.00010672926444954181, + -0.00010672926444989972, + -0.00010672926444970287, + -0.00010672926444941012, + -0.00010672926444940759, + -0.00010672926444970287, + -0.00010672926444940675, + -0.00010672926444954181, + -0.00010672926444954181, + -0.00010672926444940675, + -0.0001067292644497059, + -0.00010672926444940759, + -0.00010672926444954181, + -0.00010672926444954181, + -0.00010672926444970287, + -0.00010672926444990308, + -0.00010672926444940675, + -0.00010672926444940675, + -0.00010672926444941012, + -0.00010672926444940675, + -0.00010672926444970287, + -0.00010672926444970287, + -0.00010672926444970287, + -0.00010672926444954457, + -0.00010672926444954181, + -0.00010672926444970287, + -0.00010672926444954181, + -0.0001067292644492592, + -0.00010672926444970287, + -0.00010672926444954181, + -0.00010672926444954457, + -0.00010672926444969984, + -0.00010672926444924405 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.31839725034103594, + "y": 3.7527221070339856 + }, + { + "x": 0.7442980407844857, + "y": 6.735602607943436 + }, + { + "x": 1.3474216715823673, + "y": 7.407006918270342 + }, + { + "x": 2.177343962152918, + "y": 8.765216373687448 + }, + { + "x": 2.838659926597984, + "y": 8.573939998966162 + }, + { + "x": 3.1450996484852567, + "y": 7.659789060449604 + }, + { + "x": 2.96416661538899, + "y": 6.087274929905355 + }, + { + "x": 3.3460120216693667, + "y": 5.886034486062384 + }, + { + "x": 3.644420564409643, + "y": 5.7132830145732605 + }, + { + "x": 3.5248027800298587, + "y": 4.885556130288693 + }, + { + "x": 4.753794553987234, + "y": 5.776524827426588 + }, + { + "x": 4.937621048098606, + "y": 5.383191352294325 + }, + { + "x": 4.132478036118243, + "y": 3.8860964766031847 + }, + { + "x": 5.511022302041226, + "y": 4.458205099168833 + }, + { + "x": 6.990309047590699, + "y": 4.840857926595028 + }, + { + "x": 6.744616873174323, + "y": 3.894269334884113 + }, + { + "x": 6.402210554225007, + "y": 3.0248473842055112 + }, + { + "x": 6.616804150386315, + "y": 2.542772590224258 + }, + { + "x": 7.4814893278539785, + "y": 2.191410108905192 + }, + { + "x": 8.328123508801468, + "y": 1.7141378960336917 + }, + { + "x": 7.738782131270057, + "y": 0.9413066171026085 + }, + { + "x": 8.585454525564273, + "y": 0.30684891496979505 + }, + { + "x": 10.08661903894847, + "y": 0.03581588242643985 + }, + { + "x": 10.075099714251223, + "y": -0.0010753079858405457 + }, + { + "x": 11.082609685676346, + "y": -0.0011828387844259325 + }, + { + "x": 12.090119657101752, + "y": -0.0012903695830113193 + }, + { + "x": 10.075099714251508, + "y": -0.0010753079858405457 + }, + { + "x": 10.075099714251223, + "y": -0.0010753079858405457 + }, + { + "x": 11.08260968567663, + "y": -0.0011828387844903254 + }, + { + "x": 11.08260968567663, + "y": -0.0011828387844925459 + }, + { + "x": 9.067589742826101, + "y": -0.0009677771872573793 + }, + { + "x": 7.026341835521919, + "y": -0.0007499162989188513 + }, + { + "x": 10.009529803116664, + "y": -0.00106830975762362 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574260003 + }, + { + "x": 10.00952980311638, + "y": -0.0010683097574304412 + }, + { + "x": 11.010482783428301, + "y": -0.0011751407331761499 + }, + { + "x": 9.008576822805026, + "y": -0.0009614787816847326 + }, + { + "x": 9.008576822805026, + "y": -0.0009614787816847326 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574304412 + }, + { + "x": 10.00952980311638, + "y": -0.0010683097574304412 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574260003 + }, + { + "x": 9.008576822805026, + "y": -0.0009614787816847326 + }, + { + "x": 9.008576822804741, + "y": -0.0009614787816891734 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574260003 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574304412 + }, + { + "x": 12.01143576373994, + "y": -0.0012819717089174176 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 11.010482783428017, + "y": -0.001175140733171709 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 12.01143576373994, + "y": -0.0012819717089129767 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 12.01143576373994, + "y": -0.0012819717089129767 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 9.008576822805026, + "y": -0.0009614787816891734 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574304412 + }, + { + "x": 12.011435763739655, + "y": -0.0012819717089129767 + }, + { + "x": 12.01143576373994, + "y": -0.0012819717089129767 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574304412 + }, + { + "x": 9.008576822805026, + "y": -0.0009614787816847326 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 9.008576822805026, + "y": -0.0009614787816847326 + }, + { + "x": 10.00952980311638, + "y": -0.0010683097574304412 + }, + { + "x": 12.01143576373994, + "y": -0.0012819717089129767 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574304412 + }, + { + "x": 9.008576822804741, + "y": -0.0009614787816891734 + }, + { + "x": 9.008576822805026, + "y": -0.0009614787816847326 + }, + { + "x": 9.008576822805026, + "y": -0.0009614787816847326 + }, + { + "x": 9.008576822804741, + "y": -0.0009614787816847326 + }, + { + "x": 9.008576822805026, + "y": -0.0009614787816847326 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574304412 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574304412 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574304412 + }, + { + "x": 11.010482783428017, + "y": -0.001175140733171709 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574304412 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574260003 + }, + { + "x": 10.009529803116664, + "y": -0.0010683097574304412 + }, + { + "x": 11.010482783428301, + "y": -0.001175140733171709 + }, + { + "x": 11.010482783428017, + "y": -0.001175140733171709 + }, + { + "x": 10.009529803116948, + "y": -0.0010683097574304412 + }, + { + "x": 10.009529803118085, + "y": -0.0010683097574260003 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 198.60886275367812, + "y": -1.9601957402843762, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": -2.0249086705307424, + "y": -8.280471528793488, + "z": 1.0 + }, + { + "x": -2.029612009939554, + "y": -8.952394399315889, + "z": 1.0 + }, + { + "x": -2.0297671463414297, + "y": -9.355128488453571, + "z": 1.0 + }, + { + "x": -2.029922282743306, + "y": -9.757862577591254, + "z": 1.0 + }, + { + "x": -2.029999850944244, + "y": -9.959229622160095, + "z": 1.0 + }, + { + "x": -2.030231080992902, + "y": -10.5595028133723, + "z": 1.0 + }, + { + "x": -2.0304623110415596, + "y": -11.159776004584504, + "z": 1.0 + }, + { + "x": -2.0306164644073315, + "y": -11.559958132059307, + "z": 1.0 + }, + { + "x": -2.0308476944559883, + "y": -12.160231323271512, + "z": 1.0 + }, + { + "x": -2.0310403861632036, + "y": -12.660458982615017, + "z": 1.0 + }, + { + "x": -2.031233077870418, + "y": -13.16068664195852, + "z": 1.0 + }, + { + "x": -2.03138723123619, + "y": -13.560868769433325, + "z": 1.0 + }, + { + "x": -2.0316184612848476, + "y": -14.16114196064553, + "z": 1.0 + }, + { + "x": -2.0317726146506194, + "y": -14.561324088120333, + "z": 1.0 + }, + { + "x": -2.0319267680163913, + "y": -14.961506215595136, + "z": 1.0 + }, + { + "x": -2.032157998065049, + "y": -15.561779406807341, + "z": 1.0 + }, + { + "x": -2.032312151430821, + "y": -15.961961534282144, + "z": 1.0 + }, + { + "x": -2.032466304796592, + "y": -16.36214366175695, + "z": 1.0 + }, + { + "x": -2.0326975348452496, + "y": -16.962416852969152, + "z": 1.0 + }, + { + "x": -2.0329287648939074, + "y": -17.56269004418136, + "z": 1.0 + }, + { + "x": -2.033159994942565, + "y": -18.162963235393562, + "z": 1.0 + }, + { + "x": -2.0333526866497795, + "y": -18.66319089473706, + "z": 1.0 + }, + { + "x": -2.033545378356995, + "y": -19.16341855408056, + "z": 1.0 + }, + { + "x": -2.033738070064209, + "y": -19.66364621342406, + "z": 1.0 + }, + { + "x": -2.0339307617714244, + "y": -20.16387387276756, + "z": 1.0 + }, + { + "x": -2.0341619918200813, + "y": -20.76414706397976, + "z": 1.0 + }, + { + "x": -2.034393221868739, + "y": -21.36442025519196, + "z": 1.0 + }, + { + "x": -2.034624451917397, + "y": -21.96469344640416, + "z": 1.0 + }, + { + "x": -2.0348556819660546, + "y": -22.56496663761636, + "z": 1.0 + }, + { + "x": -2.0350869120147124, + "y": -23.16523982882856, + "z": 1.0 + }, + { + "x": -2.035241065380484, + "y": -23.56542195630336, + "z": 1.0 + }, + { + "x": -2.0354337570876986, + "y": -24.06564961564686, + "z": 1.0 + }, + { + "x": -2.035626448794913, + "y": -24.56587727499036, + "z": 1.0 + }, + { + "x": -2.035780602160685, + "y": -24.96605940246516, + "z": 1.0 + }, + { + "x": -2.0359732938679, + "y": -25.466287061808657, + "z": 1.0 + }, + { + "x": -2.036204523916558, + "y": -26.06656025302086, + "z": 1.0 + }, + { + "x": -2.0364357539652147, + "y": -26.666833444233074, + "z": 1.0 + }, + { + "x": -2.03662844567243, + "y": -27.167061103576582, + "z": 1.0 + }, + { + "x": -2.036782599038202, + "y": -27.567243231051386, + "z": 1.0 + }, + { + "x": -2.0369367524039736, + "y": -27.967425358526196, + "z": 1.0 + }, + { + "x": -2.037129444111188, + "y": -28.467653017869704, + "z": 1.0 + }, + { + "x": -2.03728359747696, + "y": -28.867835145344507, + "z": 1.0 + }, + { + "x": -2.0374377508427317, + "y": -29.268017272819318, + "z": 1.0 + }, + { + "x": -2.037630442549946, + "y": -29.768244932162826, + "z": 1.0 + }, + { + "x": -2.0378231342571613, + "y": -30.268472591506335, + "z": 1.0 + }, + { + "x": -2.0380158259643757, + "y": -30.768700250849843, + "z": 1.0 + }, + { + "x": -2.0381699793301475, + "y": -31.16888237832465, + "z": 1.0 + }, + { + "x": -2.0383241326959194, + "y": -31.569064505799457, + "z": 1.0 + }, + { + "x": -2.038555362744577, + "y": -32.16933769701166, + "z": 1.0 + }, + { + "x": -2.038709516110349, + "y": -32.56951982448648, + "z": 1.0 + }, + { + "x": -2.038940746159006, + "y": -33.16979301569869, + "z": 1.0 + }, + { + "x": -2.039133437866221, + "y": -33.670020675042196, + "z": 1.0 + }, + { + "x": -2.0393261295734355, + "y": -34.170248334385704, + "z": 1.0 + }, + { + "x": -2.0394802829392074, + "y": -34.57043046186051, + "z": 1.0 + }, + { + "x": -2.039634436304979, + "y": -34.97061258933532, + "z": 1.0 + }, + { + "x": -2.039865666353637, + "y": -35.57088578054753, + "z": 1.0 + }, + { + "x": -2.040019819719409, + "y": -35.971067908022334, + "z": 1.0 + }, + { + "x": -2.0401739730851807, + "y": -36.37125003549714, + "z": 1.0 + }, + { + "x": -2.0403281264509525, + "y": -36.77143216297195, + "z": 1.0 + }, + { + "x": -2.0405593564996094, + "y": -37.37170535418416, + "z": 1.0 + }, + { + "x": -2.0407520482068247, + "y": -37.871933013527666, + "z": 1.0 + }, + { + "x": -2.0409062015725965, + "y": -38.27211514100247, + "z": 1.0 + }, + { + "x": -2.041098893279811, + "y": -38.77234280034598, + "z": 1.0 + }, + { + "x": -2.0412915849870252, + "y": -39.27257045968949, + "z": 1.0 + }, + { + "x": -2.0414842766942405, + "y": -39.772798119033, + "z": 1.0 + }, + { + "x": -2.041676968401455, + "y": -40.27302577837651, + "z": 1.0 + }, + { + "x": -2.04186966010867, + "y": -40.773253437720015, + "z": 1.0 + }, + { + "x": -2.042100890157327, + "y": -41.373526628932225, + "z": 1.0 + }, + { + "x": -2.0422935818645422, + "y": -41.873754288275734, + "z": 1.0 + }, + { + "x": -2.042486273571757, + "y": -42.37398194761924, + "z": 1.0 + }, + { + "x": -2.042678965278972, + "y": -42.87420960696275, + "z": 1.0 + }, + { + "x": -2.0428331186447437, + "y": -43.27439173443756, + "z": 1.0 + }, + { + "x": -2.043025810351958, + "y": -43.774619393781066, + "z": 1.0 + }, + { + "x": -2.04317996371773, + "y": -44.17480152125587, + "z": 1.0 + }, + { + "x": -2.0434111937663877, + "y": -44.77507471246808, + "z": 1.0 + }, + { + "x": -2.0436424238150455, + "y": -45.37534790368029, + "z": 1.0 + }, + { + "x": -2.0438736538637023, + "y": -45.97562109489251, + "z": 1.0 + }, + { + "x": -2.0440278072294746, + "y": -46.37580322236731, + "z": 1.0 + }, + { + "x": -2.0441819605952465, + "y": -46.775985349842124, + "z": 1.0 + }, + { + "x": -2.044336113961018, + "y": -47.17616747731693, + "z": 1.0 + }, + { + "x": -2.0445288056682327, + "y": -47.67639513666044, + "z": 1.0 + }, + { + "x": -2.0447214973754475, + "y": -48.17662279600395, + "z": 1.0 + }, + { + "x": -2.0449527274241053, + "y": -48.77689598721615, + "z": 1.0 + }, + { + "x": -2.045183957472763, + "y": -49.37716917842837, + "z": 1.0 + }, + { + "x": -2.0453766491799774, + "y": -49.877396837771876, + "z": 1.0 + }, + { + "x": -2.045569340887192, + "y": -50.377624497115384, + "z": 1.0 + }, + { + "x": -2.045762032594407, + "y": -50.87785215645889, + "z": 1.0 + }, + { + "x": -2.045954724301622, + "y": -51.378079815802394, + "z": 1.0 + }, + { + "x": -2.0461474160088358, + "y": -51.87830747514591, + "z": 1.0 + }, + { + "x": -2.0463786460574935, + "y": -52.47858066635812, + "z": 1.0 + }, + { + "x": -2.0466098761061513, + "y": -53.07885385757033, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 12, + "heading": [ + -1.5713009816235572, + -1.577796032862566, + -1.5753172510457183, + -1.5711815347978622, + -1.5711815347978622, + -1.5711815347978622, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978615, + -1.571181534797862, + -1.5711815347978624, + -1.571181534797862, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978613, + -1.5711815347978615, + -1.5711815347978624, + -1.5711815347978624, + -1.571181534797862, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978624, + -1.571181534797862, + -1.5711815347978617, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978624, + -1.571181534797862, + -1.5711815347978615, + -1.571181534797862, + -1.5711815347978628, + -1.5711815347978628, + -1.5711815347978617, + -1.571181534797862, + -1.5711815347978628, + -1.5711815347978624, + -1.571181534797862, + -1.571181534797862, + -1.5711815347978624, + -1.571181534797862, + -1.5711815347978624, + -1.5711815347978624, + -1.571181534797862, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978615, + -1.571181534797862, + -1.5711815347978624, + -1.571181534797862, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978615, + -1.571181534797862, + -1.5711815347978628, + -1.571181534797862, + -1.5711815347978615, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978624, + -1.571181534797862, + -1.571181534797862, + -1.5711815347978628, + -1.5711815347978624, + -1.5711815347978624, + -1.571181534797862, + -1.571181534797862, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978617, + -1.571181534797862, + -1.5711815347978628, + -1.5711815347978617, + -1.571181534797862, + -1.5711815347978624, + -1.5711815347978624, + -1.5711815347978624, + -1.571181534797862, + -1.5711815347978615, + -1.5711815347978624, + -1.5711815347978628, + -1.5711815347978615, + -1.5711815347978615, + -1.5711815347978624 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -0.04703339408811402, + "y": -6.719228705224012 + }, + { + "x": -0.04858475810687324, + "y": -10.746569596600839 + }, + { + "x": -0.0031027280375228727, + "y": -8.054681782753654 + }, + { + "x": -0.0023270460281432648, + "y": -6.041011337065232 + }, + { + "x": -0.00308798249595732, + "y": -8.016402357810453 + }, + { + "x": -0.004624600973155424, + "y": -12.005463824244096 + }, + { + "x": -0.0038538341442961865, + "y": -10.00455318687008 + }, + { + "x": -0.0038538341442873048, + "y": -10.00455318687008 + }, + { + "x": -0.004239217558721364, + "y": -11.005008505557097 + }, + { + "x": -0.0038538341442961865, + "y": -10.00455318687008 + }, + { + "x": -0.003468450729862127, + "y": -9.00409786818308 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870098 + }, + { + "x": -0.0038538341442961865, + "y": -10.00455318687008 + }, + { + "x": -0.0030830673154369492, + "y": -8.003642549496064 + }, + { + "x": -0.0038538341442961865, + "y": -10.00455318687008 + }, + { + "x": -0.0038538341442961865, + "y": -10.00455318687008 + }, + { + "x": -0.0030830673154280674, + "y": -8.003642549496082 + }, + { + "x": -0.0038538341442873048, + "y": -10.00455318687008 + }, + { + "x": -0.004624600973155424, + "y": -12.005463824244096 + }, + { + "x": -0.004624600973155424, + "y": -12.005463824244096 + }, + { + "x": -0.004239217558721364, + "y": -11.005008505557008 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186869991 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186869991 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186869991 + }, + { + "x": -0.004239217558721364, + "y": -11.005008505557008 + }, + { + "x": -0.004624600973146542, + "y": -12.00546382424399 + }, + { + "x": -0.004624600973155424, + "y": -12.00546382424399 + }, + { + "x": -0.004624600973155424, + "y": -12.005463824244025 + }, + { + "x": -0.004624600973155424, + "y": -12.005463824244025 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186869991 + }, + { + "x": -0.003468450729862127, + "y": -9.004097868182974 + }, + { + "x": -0.0038538341442873048, + "y": -10.004553186869991 + }, + { + "x": -0.003468450729862127, + "y": -9.00409786818301 + }, + { + "x": -0.0034684507298710088, + "y": -9.004097868182974 + }, + { + "x": -0.004239217558730246, + "y": -11.005008505557008 + }, + { + "x": -0.004624600973146542, + "y": -12.005463824244167 + }, + { + "x": -0.004239217558721364, + "y": -11.005008505557221 + }, + { + "x": -0.0034684507298710088, + "y": -9.004097868183116 + }, + { + "x": -0.0030830673154369492, + "y": -8.003642549496135 + }, + { + "x": -0.003468450729862127, + "y": -9.004097868183187 + }, + { + "x": -0.003468450729862127, + "y": -9.004097868183116 + }, + { + "x": -0.0030830673154369492, + "y": -8.003642549496135 + }, + { + "x": -0.003468450729862127, + "y": -9.004097868183187 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870169 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870169 + }, + { + "x": -0.003468450729862127, + "y": -9.004097868183152 + }, + { + "x": -0.0030830673154369492, + "y": -8.003642549496135 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870133 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870204 + }, + { + "x": -0.0038538341442873048, + "y": -10.00455318687024 + }, + { + "x": -0.004239217558721364, + "y": -11.005008505557186 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870169 + }, + { + "x": -0.003468450729862127, + "y": -9.004097868183152 + }, + { + "x": -0.0030830673154369492, + "y": -8.003642549496135 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870169 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870169 + }, + { + "x": -0.0030830673154369492, + "y": -8.003642549496135 + }, + { + "x": -0.0030830673154369492, + "y": -8.003642549496135 + }, + { + "x": -0.0038538341442873048, + "y": -10.004553186870169 + }, + { + "x": -0.004239217558721364, + "y": -11.005008505557186 + }, + { + "x": -0.0034684507298710088, + "y": -9.004097868183152 + }, + { + "x": -0.003468450729862127, + "y": -9.004097868183152 + }, + { + "x": -0.0038538341442873048, + "y": -10.004553186870169 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870169 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870169 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870169 + }, + { + "x": -0.004239217558721364, + "y": -11.005008505557186 + }, + { + "x": -0.004239217558721364, + "y": -11.005008505557186 + }, + { + "x": -0.0038538341443006274, + "y": -10.004553186870169 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870169 + }, + { + "x": -0.003468450729866568, + "y": -9.004097868183152 + }, + { + "x": -0.003468450729862127, + "y": -9.004097868183152 + }, + { + "x": -0.003468450729862127, + "y": -9.004097868183152 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870169 + }, + { + "x": -0.004624600973155424, + "y": -12.005463824244202 + }, + { + "x": -0.004624600973146542, + "y": -12.005463824244273 + }, + { + "x": -0.0038538341442917456, + "y": -10.004553186870169 + }, + { + "x": -0.00308306731544139, + "y": -8.003642549496135 + }, + { + "x": -0.0030830673154325083, + "y": -8.003642549496206 + }, + { + "x": -0.003468450729862127, + "y": -9.004097868183152 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870169 + }, + { + "x": -0.004239217558725805, + "y": -11.005008505557115 + }, + { + "x": -0.004624600973155424, + "y": -12.005463824244202 + }, + { + "x": -0.004239217558721364, + "y": -11.005008505557257 + }, + { + "x": -0.0038538341442873048, + "y": -10.004553186870169 + }, + { + "x": -0.0038538341442961865, + "y": -10.004553186870169 + }, + { + "x": -0.0038538341443006274, + "y": -10.004553186870098 + }, + { + "x": -0.0038538341442873048, + "y": -10.004553186870169 + }, + { + "x": -0.004239217558716923, + "y": -11.005008505557257 + }, + { + "x": -0.004624600973155424, + "y": -12.005463824244202 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": -2.0466098761061513, + "y": -53.07885385757033, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 338.85713578381797, + "y": -70.83644799954263, + "z": 1.0 + }, + { + "x": 338.85743867061865, + "y": -70.33498894704724, + "z": 1.0 + }, + { + "x": 338.8578021347794, + "y": -69.73323808405277, + "z": 1.0 + }, + { + "x": 338.8580444442198, + "y": -69.33207084205532, + "z": 1.0 + }, + { + "x": 338.85822617630015, + "y": -69.03119541055808, + "z": 1.0 + }, + { + "x": 338.8584689618465, + "y": -68.62923992832572, + "z": 1.0 + }, + { + "x": 338.8587117473928, + "y": -68.22728444609271, + "z": 1.0 + }, + { + "x": 338.85895453293904, + "y": -67.82532896385973, + "z": 1.0 + }, + { + "x": 338.85931871125854, + "y": -67.22239574051028, + "z": 1.0 + }, + { + "x": 338.85956149680476, + "y": -66.82044025827727, + "z": 1.0 + }, + { + "x": 338.85992567512415, + "y": -66.21750703492668, + "z": 1.0 + }, + { + "x": 338.86028985344365, + "y": -65.61457381157831, + "z": 1.0 + }, + { + "x": 338.8605933353765, + "y": -65.11212945878708, + "z": 1.0 + }, + { + "x": 338.86089681730937, + "y": -64.60968510599582, + "z": 1.0 + }, + { + "x": 338.86126099562875, + "y": -64.00675188264634, + "z": 1.0 + }, + { + "x": 338.8615037811751, + "y": -63.604796400412226, + "z": 1.0 + }, + { + "x": 338.8617465667213, + "y": -63.202840918180364, + "z": 1.0 + }, + { + "x": 338.86205004865417, + "y": -62.70039656538912, + "z": 1.0 + }, + { + "x": 338.86235353058703, + "y": -62.197952212596746, + "z": 1.0 + }, + { + "x": 338.8626570125199, + "y": -61.69550785980665, + "z": 1.0 + }, + { + "x": 338.86296049445286, + "y": -61.19306350701542, + "z": 1.0 + }, + { + "x": 338.86332467277225, + "y": -60.59013028366594, + "z": 1.0 + }, + { + "x": 338.8636281547051, + "y": -60.087685930874706, + "z": 1.0 + }, + { + "x": 338.863931636638, + "y": -59.585241578083476, + "z": 1.0 + }, + { + "x": 338.86429581495736, + "y": -58.982308354733995, + "z": 1.0 + }, + { + "x": 338.8645992968902, + "y": -58.479864001942765, + "z": 1.0 + }, + { + "x": 338.86484208243655, + "y": -58.07790851970978, + "z": 1.0 + }, + { + "x": 338.8650848679828, + "y": -57.67595303747565, + "z": 1.0 + }, + { + "x": 338.86538834991563, + "y": -57.17350868468442, + "z": 1.0 + }, + { + "x": 338.86563113546197, + "y": -56.77155320245143, + "z": 1.0 + }, + { + "x": 338.86599531378135, + "y": -56.16861997910308, + "z": 1.0 + }, + { + "x": 338.8662987957142, + "y": -55.66617562631184, + "z": 1.0 + }, + { + "x": 338.86654158126055, + "y": -55.26422014407885, + "z": 1.0 + }, + { + "x": 338.86690575957994, + "y": -54.66128692072936, + "z": 1.0 + }, + { + "x": 338.86726993789944, + "y": -54.05835369737988, + "z": 1.0 + }, + { + "x": 338.86751272344566, + "y": -53.65639821514689, + "z": 1.0 + }, + { + "x": 338.867755508992, + "y": -53.25444273291391, + "z": 1.0 + }, + { + "x": 338.8681196873114, + "y": -52.65150950956443, + "z": 1.0 + }, + { + "x": 338.8683624728577, + "y": -52.24955402733144, + "z": 1.0 + }, + { + "x": 338.86860525840405, + "y": -51.84759854509846, + "z": 1.0 + }, + { + "x": 338.86896943672343, + "y": -51.244665321747846, + "z": 1.0 + }, + { + "x": 338.8692729186563, + "y": -50.74222096895887, + "z": 1.0 + }, + { + "x": 338.86957640058915, + "y": -50.23977661616764, + "z": 1.0 + }, + { + "x": 338.869879882522, + "y": -49.73733226337527, + "z": 1.0 + }, + { + "x": 338.8701833644549, + "y": -49.2348879105829, + "z": 1.0 + }, + { + "x": 338.8704261500012, + "y": -48.83293242835218, + "z": 1.0 + }, + { + "x": 338.8707903283206, + "y": -48.22999920500157, + "z": 1.0 + }, + { + "x": 338.87103311386693, + "y": -47.828043722768584, + "z": 1.0 + }, + { + "x": 338.8713365957998, + "y": -47.32559936997735, + "z": 1.0 + }, + { + "x": 338.871579381346, + "y": -46.92364388774436, + "z": 1.0 + }, + { + "x": 338.87182216689234, + "y": -46.52168840551025, + "z": 1.0 + }, + { + "x": 338.87188286327887, + "y": -46.42119953495314, + "z": 1.0 + }, + { + "x": 338.8722465969555, + "y": -45.81900246170348, + "z": 1.0 + }, + { + "x": 338.87261033063214, + "y": -45.21680538845446, + "z": 1.0 + }, + { + "x": 338.8729740643088, + "y": -44.61460831520546, + "z": 1.0 + }, + { + "x": 338.8733377979855, + "y": -44.01241124195758, + "z": 1.0 + }, + { + "x": 338.87364090938263, + "y": -43.51058034758226, + "z": 1.0 + }, + { + "x": 338.87394402077985, + "y": -43.0087494532081, + "z": 1.0 + }, + { + "x": 338.87418650989764, + "y": -42.607284737709875, + "z": 1.0 + }, + { + "x": 338.8745502435743, + "y": -42.00508766445971, + "z": 1.0 + }, + { + "x": 338.8747927326921, + "y": -41.603622948960364, + "z": 1.0 + }, + { + "x": 338.87503522180987, + "y": -41.202158233461006, + "z": 1.0 + }, + { + "x": 338.8753989554865, + "y": -40.599961160211976, + "z": 1.0 + }, + { + "x": 338.8757020668837, + "y": -40.09813026583778, + "z": 1.0 + }, + { + "x": 338.87600517828093, + "y": -39.59629937146359, + "z": 1.0 + }, + { + "x": 338.8762476673986, + "y": -39.19483465596423, + "z": 1.0 + }, + { + "x": 338.87661140107537, + "y": -38.592637582716335, + "z": 1.0 + }, + { + "x": 338.87685389019305, + "y": -38.191172867215855, + "z": 1.0 + }, + { + "x": 338.87715700159026, + "y": -37.68934197284166, + "z": 1.0 + }, + { + "x": 338.8775207352669, + "y": -37.08714489959263, + "z": 1.0 + }, + { + "x": 338.87788446894353, + "y": -36.4849478263436, + "z": 1.0 + }, + { + "x": 338.8782482026203, + "y": -35.8827507530957, + "z": 1.0 + }, + { + "x": 338.87849069173797, + "y": -35.48128603759521, + "z": 1.0 + }, + { + "x": 338.8788544254146, + "y": -34.87908896434618, + "z": 1.0 + }, + { + "x": 338.87921815909124, + "y": -34.27689189109715, + "z": 1.0 + }, + { + "x": 338.87952127048845, + "y": -33.77506099672296, + "z": 1.0 + }, + { + "x": 338.8798850041652, + "y": -33.172863923475056, + "z": 1.0 + }, + { + "x": 338.8801881155623, + "y": -32.67103302909973, + "z": 1.0 + }, + { + "x": 338.88055184923905, + "y": -32.06883595585183, + "z": 1.0 + }, + { + "x": 338.8809155829157, + "y": -31.466638882602805, + "z": 1.0 + }, + { + "x": 338.8812186943129, + "y": -30.96480798822861, + "z": 1.0 + }, + { + "x": 338.8815218057101, + "y": -30.46297709385442, + "z": 1.0 + }, + { + "x": 338.88188553938676, + "y": -29.860780020605386, + "z": 1.0 + }, + { + "x": 338.882188650784, + "y": -29.358949126231195, + "z": 1.0 + }, + { + "x": 338.8825523844606, + "y": -28.756752052982165, + "z": 1.0 + }, + { + "x": 338.88291611813725, + "y": -28.154554979731998, + "z": 1.0 + }, + { + "x": 338.8832798518139, + "y": -27.552357906482968, + "z": 1.0 + }, + { + "x": 338.8836435854905, + "y": -26.950160833233937, + "z": 1.0 + }, + { + "x": 338.88394669688773, + "y": -26.44832993885975, + "z": 1.0 + }, + { + "x": 338.88431043056437, + "y": -25.846132865611864, + "z": 1.0 + }, + { + "x": 338.8846135419616, + "y": -25.344301971236543, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 13, + "heading": [ + 1.570192315834742, + 1.5701923158345978, + 1.5701923158346802, + 1.5701923158348252, + 1.5701923158348579, + 1.5701923158346793, + 1.5701923158346276, + 1.5701923158347695, + 1.5701923158347413, + 1.5701923158347413, + 1.570192315834855, + 1.5701923158347224, + 1.5701923158346789, + 1.5701923158347413, + 1.5701923158347824, + 1.570192315834742, + 1.5701923158347695, + 1.5701923158348159, + 1.570192315834742, + 1.5701923158347413, + 1.5701923158346274, + 1.5701923158346796, + 1.5701923158347824, + 1.5701923158347413, + 1.5701923158347824, + 1.5701923158347824, + 1.5701923158346909, + 1.5701923158347704, + 1.5701923158348174, + 1.5701923158346909, + 1.5701923158347406, + 1.5701923158347817, + 1.5701923158346909, + 1.5701923158347413, + 1.5701923158347224, + 1.5701923158347413, + 1.5701923158347695, + 1.5701923158347413, + 1.5701923158347413, + 1.570192315834628, + 1.570192315834742, + 1.5701923158347817, + 1.57019231583474, + 1.570192315834742, + 1.5701923158347426, + 1.5701923158346902, + 1.5701923158347406, + 1.570192315834742, + 1.5701923158346909, + 1.5701923158348166, + 1.5701923158347704, + 1.5701923158347413, + 1.5701923158348248, + 1.570192315834764, + 1.5701923158347635, + 1.5701923158346687, + 1.5701923158347464, + 1.5701923158348399, + 1.5701923158347, + 1.5701923158347257, + 1.5701923158347266, + 1.5701923158346691, + 1.5701923158347257, + 1.5701923158347464, + 1.5701923158347257, + 1.5701923158348265, + 1.570192315834725, + 1.5701923158347257, + 1.5701923158348272, + 1.5701923158347464, + 1.5701923158347637, + 1.5701923158346687, + 1.5701923158347257, + 1.5701923158348399, + 1.5701923158347637, + 1.5701923158347464, + 1.570192315834643, + 1.5701923158347464, + 1.5701923158347464, + 1.5701923158346687, + 1.5701923158347464, + 1.5701923158347257, + 1.5701923158347464, + 1.5701923158347464, + 1.5701923158347464, + 1.5701923158347642, + 1.5701923158347642, + 1.5701923158347637, + 1.5701923158347464, + 1.5701923158347457, + 1.5701923158347464 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0030288680068224494, + "y": 5.014590524953917 + }, + { + "x": 0.006663509614099894, + "y": 11.03209915489856 + }, + { + "x": 0.006057736011371162, + "y": 10.029181049919202 + }, + { + "x": 0.00424041520773244, + "y": 7.020426734946881 + }, + { + "x": 0.004245176266977069, + "y": 7.028309137295992 + }, + { + "x": 0.004855710926676693, + "y": 8.039109644653735 + }, + { + "x": 0.0048557109255398245, + "y": 8.039109644659845 + }, + { + "x": 0.006069638657208998, + "y": 10.04888705582431 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055824594 + }, + { + "x": 0.006069638656072129, + "y": 10.048887055835962 + }, + { + "x": 0.007283566388878171, + "y": 12.058664466989626 + }, + { + "x": 0.0066766025236120186, + "y": 11.053775761396025 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055824878 + }, + { + "x": 0.00667660252247515, + "y": 11.053775761407394 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055835962 + }, + { + "x": 0.0048557109255398245, + "y": 8.039109644659774 + }, + { + "x": 0.005462674790805977, + "y": 9.043998350231064 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055836175 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055824665 + }, + { + "x": 0.006069638658345866, + "y": 10.048887055813296 + }, + { + "x": 0.0066766025236120186, + "y": 11.05377576140711 + }, + { + "x": 0.00667660252247515, + "y": 11.05377576140711 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055824665 + }, + { + "x": 0.00667660252247515, + "y": 11.05377576140711 + }, + { + "x": 0.00667660252247515, + "y": 11.05377576140711 + }, + { + "x": 0.005462674791942845, + "y": 9.043998350242148 + }, + { + "x": 0.0048557109255398245, + "y": 8.039109644671143 + }, + { + "x": 0.005462674790805977, + "y": 9.043998350253588 + }, + { + "x": 0.005462674791942845, + "y": 9.04399835024222 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055813438 + }, + { + "x": 0.00667660252247515, + "y": 11.053775761395883 + }, + { + "x": 0.005462674791942845, + "y": 9.04399835024229 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055824807 + }, + { + "x": 0.007283566388878171, + "y": 12.058664466989697 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055824665 + }, + { + "x": 0.0048557109255398245, + "y": 8.039109644659703 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055824665 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055824665 + }, + { + "x": 0.004855710926676693, + "y": 8.039109644659703 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055835962 + }, + { + "x": 0.00667660252247515, + "y": 11.053775761395883 + }, + { + "x": 0.006069638657208998, + "y": 10.04888705580207 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055835962 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055847402 + }, + { + "x": 0.005462674791942845, + "y": 9.043998350230922 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055813296 + }, + { + "x": 0.006069638657208998, + "y": 10.048887055835962 + }, + { + "x": 0.005462674791942845, + "y": 9.04399835024222 + }, + { + "x": 0.005462674790805977, + "y": 9.04399835024222 + }, + { + "x": 0.0048557109255398245, + "y": 8.039109644671 + }, + { + "x": 0.003034819328604499, + "y": 5.024443527912226 + }, + { + "x": 0.0042443006316261744, + "y": 7.026859438067703 + }, + { + "x": 0.007274673532720044, + "y": 12.043941464986787 + }, + { + "x": 0.007274673532720044, + "y": 12.043941464980179 + }, + { + "x": 0.007274673533856912, + "y": 12.04394146496881 + }, + { + "x": 0.006668450738516185, + "y": 11.040279676231961 + }, + { + "x": 0.006062227943175458, + "y": 10.036617887494828 + }, + { + "x": 0.005456005150108467, + "y": 9.032956098723872 + }, + { + "x": 0.006062227944312326, + "y": 10.036617887483885 + }, + { + "x": 0.006062227944312326, + "y": 10.036617887495112 + }, + { + "x": 0.004849782355904608, + "y": 8.029294309987023 + }, + { + "x": 0.006062227944312326, + "y": 10.036617887483885 + }, + { + "x": 0.006668450738516185, + "y": 11.040279676232245 + }, + { + "x": 0.006062227944312326, + "y": 10.036617887483885 + }, + { + "x": 0.005456005148971599, + "y": 9.032956098735525 + }, + { + "x": 0.006062227944312326, + "y": 10.036617887472516 + }, + { + "x": 0.006062227944312326, + "y": 10.036617887483743 + }, + { + "x": 0.005456005148971599, + "y": 9.032956098746752 + }, + { + "x": 0.006668450738516185, + "y": 11.040279676232245 + }, + { + "x": 0.007274673532720044, + "y": 12.043941464980605 + }, + { + "x": 0.007274673533856912, + "y": 12.043941464969308 + }, + { + "x": 0.006062227944312326, + "y": 10.036617887483885 + }, + { + "x": 0.006062227943175458, + "y": 10.036617887495183 + }, + { + "x": 0.007274673532720044, + "y": 12.043941464980605 + }, + { + "x": 0.006668450738516185, + "y": 11.040279676232245 + }, + { + "x": 0.0066684507396530535, + "y": 11.040279676220948 + }, + { + "x": 0.006668450738516185, + "y": 11.040279676232245 + }, + { + "x": 0.006668450738516185, + "y": 11.040279676232245 + }, + { + "x": 0.007274673533856912, + "y": 12.043941464969272 + }, + { + "x": 0.006668450738516185, + "y": 11.04027967623221 + }, + { + "x": 0.006062227944312326, + "y": 10.03661788748385 + }, + { + "x": 0.006668450738516185, + "y": 11.040279676232245 + }, + { + "x": 0.006668450738516185, + "y": 11.040279676232245 + }, + { + "x": 0.006668450738516185, + "y": 11.04027967623221 + }, + { + "x": 0.007274673532720044, + "y": 12.043941464991974 + }, + { + "x": 0.007274673532720044, + "y": 12.043941464991974 + }, + { + "x": 0.007274673532720044, + "y": 12.043941464980605 + }, + { + "x": 0.006668450738516185, + "y": 11.040279676232174 + }, + { + "x": 0.006668450738516185, + "y": 11.040279676220734 + }, + { + "x": 0.006668450738516185, + "y": 11.040279676232068 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 338.8846135419616, + "y": -25.344301971236543, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 393.3504725840923, + "y": -327.0485015111582, + "z": 1.0 + }, + { + "x": 393.69005141079685, + "y": -326.6858281969275, + "z": 1.0 + }, + { + "x": 394.16622838247656, + "y": -326.11265285187653, + "z": 1.0 + }, + { + "x": 394.46051050493213, + "y": -325.7123460897148, + "z": 1.0 + }, + { + "x": 394.8011293029479, + "y": -325.1930784805868, + "z": 1.0 + }, + { + "x": 395.1103756129993, + "y": -324.6545354059099, + "z": 1.0 + }, + { + "x": 395.438600971734, + "y": -323.9852775888519, + "z": 1.0 + }, + { + "x": 395.67509170223576, + "y": -323.4110529176839, + "z": 1.0 + }, + { + "x": 395.8395177444637, + "y": -322.9422111616245, + "z": 1.0 + }, + { + "x": 396.0440198204258, + "y": -322.2256531197213, + "z": 1.0 + }, + { + "x": 396.19705673814303, + "y": -321.4963701042684, + "z": 1.0 + }, + { + "x": 396.2847072711144, + "y": -320.88157522525205, + "z": 1.0 + }, + { + "x": 396.32849329031455, + "y": -320.38667352672815, + "z": 1.0 + }, + { + "x": 396.34876069791414, + "y": -319.89025260019343, + "z": 1.0 + }, + { + "x": 396.3502793922545, + "y": -319.2427121151802, + "z": 1.0 + }, + { + "x": 396.3500450152746, + "y": -318.6397023052805, + "z": 1.0 + }, + { + "x": 396.35000595244463, + "y": -318.53920067029856, + "z": 1.0 + }, + { + "x": 396.349811556479, + "y": -318.03905481818254, + "z": 1.0 + }, + { + "x": 396.3496171605133, + "y": -317.5389089660682, + "z": 1.0 + }, + { + "x": 396.34946164374077, + "y": -317.13879228437474, + "z": 1.0 + }, + { + "x": 396.3493061269682, + "y": -316.73867560268235, + "z": 1.0 + }, + { + "x": 396.3490728518094, + "y": -316.13850058014384, + "z": 1.0 + }, + { + "x": 396.3488784558437, + "y": -315.6383547280295, + "z": 1.0 + }, + { + "x": 396.34868405987805, + "y": -315.13820887591294, + "z": 1.0 + }, + { + "x": 396.34845078471926, + "y": -314.53803385337324, + "z": 1.0 + }, + { + "x": 396.3482952679467, + "y": -314.13791717168203, + "z": 1.0 + }, + { + "x": 396.3480619927879, + "y": -313.53774214914233, + "z": 1.0 + }, + { + "x": 396.34782871762906, + "y": -312.9375671266049, + "z": 1.0 + }, + { + "x": 396.3476732008565, + "y": -312.5374504449137, + "z": 1.0 + }, + { + "x": 396.34747880489084, + "y": -312.0373045927971, + "z": 1.0 + }, + { + "x": 396.34732328811833, + "y": -311.6371879111048, + "z": 1.0 + }, + { + "x": 396.3471288921526, + "y": -311.1370420589893, + "z": 1.0 + }, + { + "x": 396.34689561699383, + "y": -310.53686703645076, + "z": 1.0 + }, + { + "x": 396.3467012210281, + "y": -310.03672118433644, + "z": 1.0 + }, + { + "x": 396.3465457042556, + "y": -309.63660450264297, + "z": 1.0 + }, + { + "x": 396.3463513082899, + "y": -309.13645865052865, + "z": 1.0 + }, + { + "x": 396.3461957915174, + "y": -308.7363419688351, + "z": 1.0 + }, + { + "x": 396.3460402747449, + "y": -308.33622528714164, + "z": 1.0 + }, + { + "x": 396.34580699958605, + "y": -307.7360502646042, + "z": 1.0 + }, + { + "x": 396.34561260362034, + "y": -307.2359044124899, + "z": 1.0 + }, + { + "x": 396.34545708684783, + "y": -306.8357877307964, + "z": 1.0 + }, + { + "x": 396.34522381168904, + "y": -306.23561270825786, + "z": 1.0 + }, + { + "x": 396.3449905365302, + "y": -305.6354376857205, + "z": 1.0 + }, + { + "x": 396.3448350197577, + "y": -305.23532100402696, + "z": 1.0 + }, + { + "x": 396.3446017445989, + "y": -304.63514598148845, + "z": 1.0 + }, + { + "x": 396.3444073486332, + "y": -304.135000129373, + "z": 1.0 + }, + { + "x": 396.3441740734744, + "y": -303.53482510683443, + "z": 1.0 + }, + { + "x": 396.3440185567019, + "y": -303.1347084251421, + "z": 1.0 + }, + { + "x": 396.34378528154303, + "y": -302.53453340260353, + "z": 1.0 + }, + { + "x": 396.34362976477047, + "y": -302.1344167209112, + "z": 1.0 + }, + { + "x": 396.34347424799796, + "y": -301.7343000392188, + "z": 1.0 + }, + { + "x": 396.34324097283917, + "y": -301.13412501667915, + "z": 1.0 + }, + { + "x": 396.3430854560666, + "y": -300.7340083349879, + "z": 1.0 + }, + { + "x": 396.3429299392941, + "y": -300.33389165329555, + "z": 1.0 + }, + { + "x": 396.34277442252153, + "y": -299.93377497160316, + "z": 1.0 + }, + { + "x": 396.34261890574896, + "y": -299.5336582899108, + "z": 1.0 + }, + { + "x": 396.3424245097833, + "y": -299.0335124377953, + "z": 1.0 + }, + { + "x": 396.3422301138176, + "y": -298.533366585681, + "z": 1.0 + }, + { + "x": 396.3419968386588, + "y": -297.93319156314135, + "z": 1.0 + }, + { + "x": 396.34180244269317, + "y": -297.43304571102584, + "z": 1.0 + }, + { + "x": 396.3416469259206, + "y": -297.0329290293335, + "z": 1.0 + }, + { + "x": 396.3414136507618, + "y": -296.43275400679494, + "z": 1.0 + }, + { + "x": 396.34118037560296, + "y": -295.8325789842564, + "z": 1.0 + }, + { + "x": 396.34102485883045, + "y": -295.43246230256403, + "z": 1.0 + }, + { + "x": 396.34086934205794, + "y": -295.03234562087164, + "z": 1.0 + }, + { + "x": 396.3407138252854, + "y": -294.6322289391793, + "z": 1.0 + }, + { + "x": 396.34051942931967, + "y": -294.13208308706385, + "z": 1.0 + }, + { + "x": 396.340325033354, + "y": -293.6319372349484, + "z": 1.0 + }, + { + "x": 396.34016951658145, + "y": -293.23182055325714, + "z": 1.0 + }, + { + "x": 396.33993624142266, + "y": -292.63164553071744, + "z": 1.0 + }, + { + "x": 396.33970296626387, + "y": -292.0314705081789, + "z": 1.0 + }, + { + "x": 396.33950857029816, + "y": -291.5313246560635, + "z": 1.0 + }, + { + "x": 396.3392752951394, + "y": -290.9311496335249, + "z": 1.0 + }, + { + "x": 396.3391197783668, + "y": -290.5310329518325, + "z": 1.0 + }, + { + "x": 396.3389642615943, + "y": -290.1309162701402, + "z": 1.0 + }, + { + "x": 396.3387698656286, + "y": -289.6307704180247, + "z": 1.0 + }, + { + "x": 396.3385365904698, + "y": -289.03059539548616, + "z": 1.0 + }, + { + "x": 396.338303315311, + "y": -288.4304203729476, + "z": 1.0 + }, + { + "x": 396.3381089193453, + "y": -287.93027452083214, + "z": 1.0 + }, + { + "x": 396.3378756441865, + "y": -287.3300994982936, + "z": 1.0 + }, + { + "x": 396.33768124822086, + "y": -286.829953646177, + "z": 1.0 + }, + { + "x": 396.3375257314483, + "y": -286.4298369644858, + "z": 1.0 + }, + { + "x": 396.3373702146758, + "y": -286.0297202827934, + "z": 1.0 + }, + { + "x": 396.3372146979032, + "y": -285.62960360110105, + "z": 1.0 + }, + { + "x": 396.3369814227444, + "y": -285.0294285785636, + "z": 1.0 + }, + { + "x": 396.3367481475856, + "y": -284.4292535560239, + "z": 1.0 + }, + { + "x": 396.3365926308131, + "y": -284.0291368743316, + "z": 1.0 + }, + { + "x": 396.33639823484737, + "y": -283.5289910222172, + "z": 1.0 + }, + { + "x": 396.3361649596885, + "y": -282.9288159996787, + "z": 1.0 + }, + { + "x": 396.3359316845297, + "y": -282.32864097714014, + "z": 1.0 + }, + { + "x": 396.3357372885641, + "y": -281.82849512502355, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 14, + "heading": [ + 1.5100439818715332, + 0.8182726338896165, + 0.8538526685934247, + 0.9012926828937182, + 0.9665226973987117, + 1.019892727772154, + 1.085160506298573, + 1.1445042776719234, + 1.2038418448434116, + 1.2690718565066614, + 1.3283718560986324, + 1.3936018810754445, + 1.4529019040221436, + 1.5062719155068656, + 1.5517541909138082, + 1.5697693253906897, + 1.5711850053275338, + 1.5711850053274206, + 1.571185005327503, + 1.5711850053274965, + 1.571185005327488, + 1.5711850053275027, + 1.5711850053275083, + 1.5711850053275027, + 1.5711850053274554, + 1.5711850053275027, + 1.5711850053275027, + 1.5711850053275123, + 1.5711850053275604, + 1.5711850053274965, + 1.5711850053274328, + 1.5711850053274965, + 1.571185005327508, + 1.5711850053275083, + 1.5711850053274965, + 1.5711850053274965, + 1.5711850053274965, + 1.5711850053274163, + 1.5711850053275027, + 1.5711850053275604, + 1.5711850053274965, + 1.5711850053274454, + 1.5711850053275127, + 1.5711850053275027, + 1.5711850053274454, + 1.571185005327508, + 1.571185005327508, + 1.5711850053274459, + 1.5711850053275027, + 1.5711850053275596, + 1.5711850053274885, + 1.5711850053274454, + 1.5711850053275027, + 1.5711850053274892, + 1.5711850053274885, + 1.5711850053275596, + 1.5711850053274965, + 1.5711850053275032, + 1.571185005327508, + 1.5711850053274559, + 1.5711850053274965, + 1.5711850053275027, + 1.5711850053275123, + 1.5711850053275027, + 1.5711850053274174, + 1.5711850053274885, + 1.5711850053275596, + 1.5711850053275027, + 1.571185005327497, + 1.5711850053275027, + 1.5711850053274645, + 1.571185005327508, + 1.571185005327508, + 1.5711850053275027, + 1.5711850053274885, + 1.5711850053274965, + 1.571185005327508, + 1.571185005327465, + 1.571185005327508, + 1.571185005327508, + 1.5711850053274559, + 1.5711850053274965, + 1.5711850053274892, + 1.5711850053274885, + 1.57118500532756, + 1.5711850053275123, + 1.5711850053274454, + 1.571185005327497, + 1.57118500532756, + 1.5711850053275123, + 1.5711850053274559 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 3.395788267045532, + "y": 3.6267331423067617 + }, + { + "x": 8.157557983842594, + "y": 9.358486592816462 + }, + { + "x": 7.7045909413527625, + "y": 9.734821072127033 + }, + { + "x": 6.349009204713525, + "y": 9.19574371289741 + }, + { + "x": 6.498651080671607, + "y": 10.578106838049166 + }, + { + "x": 6.374716687860769, + "y": 12.078008917349052 + }, + { + "x": 5.647160892364695, + "y": 12.434824882259932 + }, + { + "x": 4.009167727297154, + "y": 10.430664272273589 + }, + { + "x": 3.689281181900128, + "y": 11.853997979625888 + }, + { + "x": 3.5753899367932718, + "y": 14.458410573561196 + }, + { + "x": 2.4068745068865383, + "y": 13.44077894469251 + }, + { + "x": 1.3143655217152173, + "y": 11.096965775402623 + }, + { + "x": 0.6405342679971682, + "y": 9.913226250586149 + }, + { + "x": 0.21786101939937907, + "y": 11.439614115479344 + }, + { + "x": 0.012843173604437652, + "y": 12.50550294912955 + }, + { + "x": -0.0027343980985961025, + "y": 7.035114448816557 + }, + { + "x": -0.0023345879560565663, + "y": 6.006474870979446 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042303352 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338077905 + }, + { + "x": -0.003110335450742241, + "y": 8.002333633858711 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309036 + }, + { + "x": -0.004276711244983744, + "y": 11.00320874652823 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309036 + }, + { + "x": -0.00427671124441531, + "y": 11.003208746562905 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309036 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309036 + }, + { + "x": -0.0046655031763975785, + "y": 12.003500450771298 + }, + { + "x": -0.003887919314138344, + "y": 10.002917042286299 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338077905 + }, + { + "x": -0.003499127381587641, + "y": 9.002625338089274 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338077905 + }, + { + "x": -0.004276711244983744, + "y": 11.003208746540167 + }, + { + "x": -0.004276711244983744, + "y": 11.003208746528799 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338077905 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338077905 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338078474 + }, + { + "x": -0.0031103354501738067, + "y": 8.00233363387008 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309036 + }, + { + "x": -0.004276711245552178, + "y": 11.00320874651743 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338077905 + }, + { + "x": -0.0038879193130014755, + "y": 10.002917042320405 + }, + { + "x": -0.0046655031763975785, + "y": 12.003500450759361 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309036 + }, + { + "x": -0.0038879193130014755, + "y": 10.002917042320405 + }, + { + "x": -0.004276711244983744, + "y": 11.003208746539599 + }, + { + "x": -0.004276711244983744, + "y": 11.003208746540167 + }, + { + "x": -0.0038879193130014755, + "y": 10.002917042309036 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309036 + }, + { + "x": -0.003887919314138344, + "y": 10.002917042309036 + }, + { + "x": -0.003110335450742241, + "y": 8.002333633847343 + }, + { + "x": -0.0038879193130014755, + "y": 10.002917042320405 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309036 + }, + { + "x": -0.003110335450742241, + "y": 8.002333633835974 + }, + { + "x": -0.003110335450742241, + "y": 8.002333633847343 + }, + { + "x": -0.003110335451310675, + "y": 8.002333633847343 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338078474 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042298236 + }, + { + "x": -0.004276711244983744, + "y": 11.003208746539599 + }, + { + "x": -0.00427671124441531, + "y": 11.003208746551536 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338078474 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309036 + }, + { + "x": -0.0046655031763975785, + "y": 12.003500450771298 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309036 + }, + { + "x": -0.0031103354501738067, + "y": 8.002333633847343 + }, + { + "x": -0.003110335450742241, + "y": 8.002333633847343 + }, + { + "x": -0.0034991273827245095, + "y": 9.002625338077905 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309036 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338067105 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309605 + }, + { + "x": -0.004665503175829144, + "y": 12.003500450782099 + }, + { + "x": -0.004276711244983744, + "y": 11.003208746539599 + }, + { + "x": -0.004276711244983744, + "y": 11.003208746540167 + }, + { + "x": -0.0038879193135699097, + "y": 10.002917042309605 + }, + { + "x": -0.003110335450742241, + "y": 8.002333633847343 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338077905 + }, + { + "x": -0.004276711244983744, + "y": 11.003208746540167 + }, + { + "x": -0.004665503175829144, + "y": 12.003500450771298 + }, + { + "x": -0.004276711244983744, + "y": 11.003208746540167 + }, + { + "x": -0.004276711244983744, + "y": 11.003208746540167 + }, + { + "x": -0.00427671124441531, + "y": 11.003208746551536 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338077905 + }, + { + "x": -0.003110335450742241, + "y": 8.002333633835974 + }, + { + "x": -0.003110335450742241, + "y": 8.002333633847343 + }, + { + "x": -0.003887919314138344, + "y": 10.002917042297668 + }, + { + "x": -0.0046655031763975785, + "y": 12.003500450771298 + }, + { + "x": -0.0038879193130014755, + "y": 10.002917042320405 + }, + { + "x": -0.0034991273821560753, + "y": 9.002625338067105 + }, + { + "x": -0.004276711245552178, + "y": 11.003208746528799 + }, + { + "x": -0.0046655031763975785, + "y": 12.00350045077073 + }, + { + "x": -0.00427671124441531, + "y": 11.003208746551536 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 396.3357372885641, + "y": -281.82849512502355, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 83.3983254223986, + "y": 2.043585654035443, + "z": 1.0 + }, + { + "x": 82.89595475942362, + "y": 2.043421926501252, + "z": 1.0 + }, + { + "x": 82.29310996385367, + "y": 2.0432254534602228, + "z": 1.0 + }, + { + "x": 81.8912134334737, + "y": 2.0430944714328696, + "z": 1.0 + }, + { + "x": 81.48931690309372, + "y": 2.0429634894055173, + "z": 1.0 + }, + { + "x": 80.98694624011875, + "y": 2.0427997618713256, + "z": 1.0 + }, + { + "x": 80.48457557714379, + "y": 2.042636034337135, + "z": 1.0 + }, + { + "x": 80.0826790467638, + "y": 2.0425050523097816, + "z": 1.0 + }, + { + "x": 79.58030838378885, + "y": 2.042341324775591, + "z": 1.0 + }, + { + "x": 79.37936011859885, + "y": 2.0422758337619147, + "z": 1.0 + }, + { + "x": 78.77892077275439, + "y": 2.042080144680581, + "z": 1.0 + }, + { + "x": 78.27855465121736, + "y": 2.0419170704461367, + "z": 1.0 + }, + { + "x": 77.87826175398773, + "y": 2.0417866110585807, + "z": 1.0 + }, + { + "x": 77.3778956324507, + "y": 2.0416235368241367, + "z": 1.0 + }, + { + "x": 76.87752951091366, + "y": 2.0414604625896917, + "z": 1.0 + }, + { + "x": 76.27709016506921, + "y": 2.0412647735083587, + "z": 1.0 + }, + { + "x": 75.67665081922478, + "y": 2.0410690844270247, + "z": 1.0 + }, + { + "x": 75.17628469768773, + "y": 2.0409060101925807, + "z": 1.0 + }, + { + "x": 74.77599180045812, + "y": 2.0407755508050247, + "z": 1.0 + }, + { + "x": 74.17555245461367, + "y": 2.0405798617236917, + "z": 1.0 + }, + { + "x": 73.57511310876923, + "y": 2.0403841726423577, + "z": 1.0 + }, + { + "x": 73.07474698723219, + "y": 2.0402210984079137, + "z": 1.0 + }, + { + "x": 72.67445409000257, + "y": 2.0400906390203577, + "z": 1.0 + }, + { + "x": 72.17408796846553, + "y": 2.0399275647859136, + "z": 1.0 + }, + { + "x": 71.7737950712359, + "y": 2.039797105398358, + "z": 1.0 + }, + { + "x": 71.17335572539146, + "y": 2.0396014163170246, + "z": 1.0 + }, + { + "x": 70.77306282816183, + "y": 2.0394709569294687, + "z": 1.0 + }, + { + "x": 70.37276993093221, + "y": 2.0393404975419136, + "z": 1.0 + }, + { + "x": 69.77233058508776, + "y": 2.0391448084605797, + "z": 1.0 + }, + { + "x": 69.27196446355073, + "y": 2.0389817342261356, + "z": 1.0 + }, + { + "x": 68.8716715663211, + "y": 2.0388512748385796, + "z": 1.0 + }, + { + "x": 68.27123222047666, + "y": 2.0386555857572466, + "z": 1.0 + }, + { + "x": 67.77086609893962, + "y": 2.0384925115228016, + "z": 1.0 + }, + { + "x": 67.27049997740258, + "y": 2.0383294372883576, + "z": 1.0 + }, + { + "x": 66.87020708017296, + "y": 2.0381989779008016, + "z": 1.0 + }, + { + "x": 66.36984095863592, + "y": 2.0380359036663576, + "z": 1.0 + }, + { + "x": 65.9695480614063, + "y": 2.0379054442788016, + "z": 1.0 + }, + { + "x": 65.36910871556185, + "y": 2.0377097551974686, + "z": 1.0 + }, + { + "x": 64.86874259402482, + "y": 2.0375466809630236, + "z": 1.0 + }, + { + "x": 64.46844969679519, + "y": 2.0374162215754685, + "z": 1.0 + }, + { + "x": 63.96808357525816, + "y": 2.0372531473410236, + "z": 1.0 + }, + { + "x": 63.36764422941371, + "y": 2.0370574582596905, + "z": 1.0 + }, + { + "x": 62.96735133218408, + "y": 2.0369269988721346, + "z": 1.0 + }, + { + "x": 62.36691198633963, + "y": 2.0367313097908015, + "z": 1.0 + }, + { + "x": 61.86654586480259, + "y": 2.0365682355563566, + "z": 1.0 + }, + { + "x": 61.36617974326553, + "y": 2.0364051613219125, + "z": 1.0 + }, + { + "x": 60.765740397421084, + "y": 2.0362094722405786, + "z": 1.0 + }, + { + "x": 60.26537427588404, + "y": 2.0360463980061345, + "z": 1.0 + }, + { + "x": 59.66493493003959, + "y": 2.0358507089248006, + "z": 1.0 + }, + { + "x": 59.26464203280996, + "y": 2.0357202495372455, + "z": 1.0 + }, + { + "x": 58.764275911272904, + "y": 2.0355571753028006, + "z": 1.0 + }, + { + "x": 58.26390978973586, + "y": 2.0353941010683565, + "z": 1.0 + }, + { + "x": 57.86361689250623, + "y": 2.0352636416808005, + "z": 1.0 + }, + { + "x": 57.26317754666178, + "y": 2.0350679525994675, + "z": 1.0 + }, + { + "x": 56.66273820081733, + "y": 2.0348722635181336, + "z": 1.0 + }, + { + "x": 56.162372079280274, + "y": 2.0347091892836895, + "z": 1.0 + }, + { + "x": 55.66200595774323, + "y": 2.0345461150492445, + "z": 1.0 + }, + { + "x": 55.06156661189878, + "y": 2.0343504259679115, + "z": 1.0 + }, + { + "x": 54.46112726605433, + "y": 2.0341547368865784, + "z": 1.0 + }, + { + "x": 54.0608343688247, + "y": 2.0340242774990225, + "z": 1.0 + }, + { + "x": 53.46039502298024, + "y": 2.0338285884176894, + "z": 1.0 + }, + { + "x": 52.960028901443195, + "y": 2.0336655141832445, + "z": 1.0 + }, + { + "x": 52.359589555598745, + "y": 2.0334698251019114, + "z": 1.0 + }, + { + "x": 51.859223434061704, + "y": 2.0333067508674665, + "z": 1.0 + }, + { + "x": 51.45893053683207, + "y": 2.0331762914799114, + "z": 1.0 + }, + { + "x": 51.05863763960244, + "y": 2.0330458320923555, + "z": 1.0 + }, + { + "x": 50.55827151806538, + "y": 2.0328827578579105, + "z": 1.0 + }, + { + "x": 50.15797862083575, + "y": 2.0327522984703554, + "z": 1.0 + }, + { + "x": 49.757685723606116, + "y": 2.0326218390827995, + "z": 1.0 + }, + { + "x": 49.157246377761666, + "y": 2.0324261500014664, + "z": 1.0 + }, + { + "x": 48.656880256224625, + "y": 2.0322630757670215, + "z": 1.0 + }, + { + "x": 48.25658735899499, + "y": 2.0321326163794664, + "z": 1.0 + }, + { + "x": 47.756221237457936, + "y": 2.0319695421450215, + "z": 1.0 + }, + { + "x": 47.3559283402283, + "y": 2.0318390827574664, + "z": 1.0 + }, + { + "x": 46.85556221869126, + "y": 2.0316760085230214, + "z": 1.0 + }, + { + "x": 46.25512287284681, + "y": 2.0314803194416884, + "z": 1.0 + }, + { + "x": 45.65468352700236, + "y": 2.0312846303603544, + "z": 1.0 + }, + { + "x": 45.15431740546532, + "y": 2.0311215561259104, + "z": 1.0 + }, + { + "x": 44.75402450823567, + "y": 2.0309910967383544, + "z": 1.0 + }, + { + "x": 44.25365838669863, + "y": 2.0308280225039104, + "z": 1.0 + }, + { + "x": 43.75329226516159, + "y": 2.0306649482694654, + "z": 1.0 + }, + { + "x": 43.15285291931714, + "y": 2.0304692591881324, + "z": 1.0 + }, + { + "x": 42.75256002208751, + "y": 2.0303387998005764, + "z": 1.0 + }, + { + "x": 42.352267124857875, + "y": 2.0302083404130213, + "z": 1.0 + }, + { + "x": 41.95197422762823, + "y": 2.0300778810254654, + "z": 1.0 + }, + { + "x": 41.551681330398594, + "y": 2.0299474216379094, + "z": 1.0 + }, + { + "x": 41.15138843316896, + "y": 2.0298169622503544, + "z": 1.0 + }, + { + "x": 40.65102231163192, + "y": 2.0296538880159094, + "z": 1.0 + }, + { + "x": 40.05058296578747, + "y": 2.0294581989345764, + "z": 1.0 + }, + { + "x": 39.450143619943006, + "y": 2.0292625098532433, + "z": 1.0 + }, + { + "x": 38.94977749840598, + "y": 2.0290994356187984, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 15, + "heading": [ + -3.1412667437776554, + -3.141266743777655, + -3.141266743777655, + -3.141266743777654, + -3.141266743777655, + -3.1412667437776545, + -3.141266743777654, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776554, + -3.141266743777655, + -3.1412667437776545, + -3.141266743777654, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.141266743777655, + -3.1412667437776545, + -3.141266743777654, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.141266743777655, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.141266743777655, + -3.1412667437776536, + -3.1412667437776545, + -3.141266743777655, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.1412667437776545, + -3.141266743777655, + -3.141266743777655, + -3.1412667437776536, + -3.141266743777655, + -3.1412667437776545, + -3.1412667437776545, + -3.141266743777655, + -3.1412667437776545 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -5.0237066297498245, + "y": -0.001637275341908051 + }, + { + "x": -11.05215458544933, + "y": -0.003602005752201265 + }, + { + "x": -10.047413259499223, + "y": -0.003274550683824984 + }, + { + "x": -8.037930607599435, + "y": -0.002619640547054658 + }, + { + "x": -9.0426719335494, + "y": -0.002947095615439821 + }, + { + "x": -10.047413259499365, + "y": -0.003274550683824984 + }, + { + "x": -9.042671933549542, + "y": -0.002947095615439821 + }, + { + "x": -9.0426719335494, + "y": -0.002947095615439821 + }, + { + "x": -7.03318928164947, + "y": -0.002292185478669495 + }, + { + "x": -8.013876110344569, + "y": -0.002611800950096388 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200046362 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -12.008786916888852, + "y": -0.003913781626669888 + }, + { + "x": -11.008054673814769, + "y": -0.0035876331577799903 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -12.008786916888852, + "y": -0.003913781626669888 + }, + { + "x": -11.008054673814769, + "y": -0.0035876331577799903 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -9.006590187666745, + "y": -0.0029353362199957544 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -10.007322430740686, + "y": -0.0032614846888945337 + }, + { + "x": -8.00585794459252, + "y": -0.002609187751110298 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673814769, + "y": -0.0035876331577799903 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673814769, + "y": -0.0035876331577799903 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -10.007322430740686, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673814769, + "y": -0.0035876331577799903 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -9.006590187666603, + "y": -0.0029353362200001953 + }, + { + "x": -11.008054673814769, + "y": -0.0035876331577799903 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -10.00732243074097, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673815053, + "y": -0.0035876331577799903 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -9.006590187666887, + "y": -0.0029353362200001953 + }, + { + "x": -10.00732243074097, + "y": -0.003261484688890093 + }, + { + "x": -9.006590187666745, + "y": -0.0029353362200001953 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -12.008786916888994, + "y": -0.003913781626669888 + }, + { + "x": -11.008054673815053, + "y": -0.0035876331577799903 + }, + { + "x": -10.00732243074097, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -12.008786916888994, + "y": -0.003913781626661006 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -10.00732243074097, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673815053, + "y": -0.0035876331577799903 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -9.006590187666745, + "y": -0.0029353362200001953 + }, + { + "x": -8.005857944592663, + "y": -0.002609187751110298 + }, + { + "x": -9.006590187666887, + "y": -0.002935336220009077 + }, + { + "x": -9.006590187666887, + "y": -0.0029353362200001953 + }, + { + "x": -8.005857944592663, + "y": -0.002609187751110298 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -9.006590187666745, + "y": -0.0029353362200001953 + }, + { + "x": -9.006590187666887, + "y": -0.0029353362200001953 + }, + { + "x": -9.006590187666887, + "y": -0.0029353362200001953 + }, + { + "x": -9.006590187666745, + "y": -0.0029353362200001953 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -12.008786916888994, + "y": -0.003913781626669888 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -9.006590187666887, + "y": -0.0029353362200001953 + }, + { + "x": -9.006590187666887, + "y": -0.0029353362200001953 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -10.007322430740828, + "y": -0.003261484688890093 + }, + { + "x": -8.005857944592663, + "y": -0.002609187751110298 + }, + { + "x": -8.005857944592805, + "y": -0.002609187751110298 + }, + { + "x": -8.005857944592805, + "y": -0.0026091877511191797 + }, + { + "x": -8.005857944592663, + "y": -0.002609187751110298 + }, + { + "x": -9.006590187666745, + "y": -0.0029353362200001953 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + }, + { + "x": -12.008786916889136, + "y": -0.003913781626661006 + }, + { + "x": -11.008054673814911, + "y": -0.0035876331577799903 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 38.94977749840598, + "y": 2.0290994356187984, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 92.40138135506758, + "y": -206.4210177929624, + "z": 1.0 + }, + { + "x": 92.40132027234365, + "y": -206.01919131358682, + "z": 1.0 + }, + { + "x": 92.40125918961971, + "y": -205.61736483421123, + "z": 1.0 + }, + { + "x": 92.40119810689576, + "y": -205.21553835483564, + "z": 1.0 + }, + { + "x": 92.40113702417182, + "y": -204.81371187546003, + "z": 1.0 + }, + { + "x": 92.40107594144787, + "y": -204.41188539608444, + "z": 1.0 + }, + { + "x": 92.40101485872391, + "y": -204.01005891670857, + "z": 1.0 + }, + { + "x": 92.40093850531899, + "y": -203.50777581748966, + "z": 1.0 + }, + { + "x": 92.40087742259504, + "y": -203.10594933811376, + "z": 1.0 + }, + { + "x": 92.40081633987108, + "y": -202.7041228587379, + "z": 1.0 + }, + { + "x": 92.40075525714714, + "y": -202.3022963793626, + "z": 1.0 + }, + { + "x": 92.40067890374222, + "y": -201.8000132801434, + "z": 1.0 + }, + { + "x": 92.40061782101826, + "y": -201.39818680076752, + "z": 1.0 + }, + { + "x": 92.40055673829431, + "y": -200.99636032139193, + "z": 1.0 + }, + { + "x": 92.40046511420839, + "y": -200.39362060232827, + "z": 1.0 + }, + { + "x": 92.40040403148444, + "y": -199.99179412295297, + "z": 1.0 + }, + { + "x": 92.4003429487605, + "y": -199.58996764357738, + "z": 1.0 + }, + { + "x": 92.40025132467457, + "y": -198.98722792451397, + "z": 1.0 + }, + { + "x": 92.40015970058866, + "y": -198.38448820545088, + "z": 1.0 + }, + { + "x": 92.40006807650273, + "y": -197.78174848638722, + "z": 1.0 + }, + { + "x": 92.39997645241681, + "y": -197.17900876732415, + "z": 1.0 + }, + { + "x": 92.39988482833088, + "y": -196.57626904826049, + "z": 1.0 + }, + { + "x": 92.39980847492595, + "y": -196.073985949041, + "z": 1.0 + }, + { + "x": 92.39971685084004, + "y": -195.4712462299779, + "z": 1.0 + }, + { + "x": 92.39965576811608, + "y": -195.06941975060204, + "z": 1.0 + }, + { + "x": 92.39956414403017, + "y": -194.46668003153894, + "z": 1.0 + }, + { + "x": 92.39948779062522, + "y": -193.96439693231886, + "z": 1.0 + }, + { + "x": 92.3994114372203, + "y": -193.46211383309966, + "z": 1.0 + }, + { + "x": 92.39933508381536, + "y": -192.95983073388047, + "z": 1.0 + }, + { + "x": 92.39927400109141, + "y": -192.55800425450488, + "z": 1.0 + }, + { + "x": 92.39918237700549, + "y": -191.9552645354415, + "z": 1.0 + }, + { + "x": 92.39909075291956, + "y": -191.3525248163778, + "z": 1.0 + }, + { + "x": 92.39901439951464, + "y": -190.8502417171586, + "z": 1.0 + }, + { + "x": 92.39892277542872, + "y": -190.24750199809523, + "z": 1.0 + }, + { + "x": 92.39886169270477, + "y": -189.84567551871964, + "z": 1.0 + }, + { + "x": 92.39878533929982, + "y": -189.34339241949988, + "z": 1.0 + }, + { + "x": 92.39872425657587, + "y": -188.9415659401243, + "z": 1.0 + }, + { + "x": 92.39866317385194, + "y": -188.53973946074896, + "z": 1.0 + }, + { + "x": 92.39858682044698, + "y": -188.03745636152922, + "z": 1.0 + }, + { + "x": 92.39852573772303, + "y": -187.6356298821536, + "z": 1.0 + }, + { + "x": 92.39846465499909, + "y": -187.23380340277802, + "z": 1.0 + }, + { + "x": 92.39837303091316, + "y": -186.63106368371464, + "z": 1.0 + }, + { + "x": 92.39832721887021, + "y": -186.32969382418295, + "z": 1.0 + }, + { + "x": 92.39826629054149, + "y": -185.92888301800355, + "z": 1.0 + }, + { + "x": 92.39819013013054, + "y": -185.42786951027819, + "z": 1.0 + }, + { + "x": 92.39809873763745, + "y": -184.82665330100866, + "z": 1.0 + }, + { + "x": 92.39800734514435, + "y": -184.22543709173857, + "z": 1.0 + }, + { + "x": 92.39793118473344, + "y": -183.72442358401378, + "z": 1.0 + }, + { + "x": 92.39785502432252, + "y": -183.22341007628893, + "z": 1.0 + }, + { + "x": 92.39776363182942, + "y": -182.62219386701912, + "z": 1.0 + }, + { + "x": 92.39768747141851, + "y": -182.12118035929433, + "z": 1.0 + }, + { + "x": 92.39762654308977, + "y": -181.72036955311472, + "z": 1.0 + }, + { + "x": 92.39755038267886, + "y": -181.21935604538993, + "z": 1.0 + }, + { + "x": 92.39748945435012, + "y": -180.81854523920975, + "z": 1.0 + }, + { + "x": 92.3974285260214, + "y": -180.4177344330302, + "z": 1.0 + }, + { + "x": 92.3973371335283, + "y": -179.8165182237604, + "z": 1.0 + }, + { + "x": 92.39724574103519, + "y": -179.2153020144903, + "z": 1.0 + }, + { + "x": 92.39716958062426, + "y": -178.7142885067655, + "z": 1.0 + }, + { + "x": 92.39710865229554, + "y": -178.3134777005859, + "z": 1.0 + }, + { + "x": 92.3970477239668, + "y": -177.9126668944058, + "z": 1.0 + }, + { + "x": 92.39695633147372, + "y": -177.31145068513626, + "z": 1.0 + }, + { + "x": 92.39689540314497, + "y": -176.9106398789561, + "z": 1.0 + }, + { + "x": 92.39680401065188, + "y": -176.30942366968662, + "z": 1.0 + }, + { + "x": 92.39674308232314, + "y": -175.90861286350645, + "z": 1.0 + }, + { + "x": 92.39668215399442, + "y": -175.5078020573269, + "z": 1.0 + }, + { + "x": 92.39659076150132, + "y": -174.9065858480571, + "z": 1.0 + }, + { + "x": 92.39649936900821, + "y": -174.305369638787, + "z": 1.0 + }, + { + "x": 92.39643844067947, + "y": -173.90455883260745, + "z": 1.0 + }, + { + "x": 92.39636228026856, + "y": -173.4035453248826, + "z": 1.0 + }, + { + "x": 92.39628611985765, + "y": -172.90253181715775, + "z": 1.0 + }, + { + "x": 92.39622519152891, + "y": -172.50172101097786, + "z": 1.0 + }, + { + "x": 92.39616426320018, + "y": -172.10091020479797, + "z": 1.0 + }, + { + "x": 92.39607287070707, + "y": -171.49969399552788, + "z": 1.0 + }, + { + "x": 92.39598147821397, + "y": -170.89847778625807, + "z": 1.0 + }, + { + "x": 92.39592054988525, + "y": -170.49766698007852, + "z": 1.0 + }, + { + "x": 92.39584438947433, + "y": -169.99665347235367, + "z": 1.0 + }, + { + "x": 92.3957682290634, + "y": -169.49563996462882, + "z": 1.0 + }, + { + "x": 92.39567683657032, + "y": -168.894423755359, + "z": 1.0 + }, + { + "x": 92.39560067615939, + "y": -168.39341024763388, + "z": 1.0 + }, + { + "x": 92.39553974783067, + "y": -167.99259944145427, + "z": 1.0 + }, + { + "x": 92.39547881950193, + "y": -167.59178863527438, + "z": 1.0 + }, + { + "x": 92.39538742700883, + "y": -166.9905724260043, + "z": 1.0 + }, + { + "x": 92.39532649868009, + "y": -166.5897616198244, + "z": 1.0 + }, + { + "x": 92.39523510618699, + "y": -165.9885454105546, + "z": 1.0 + }, + { + "x": 92.39517417785827, + "y": -165.58773460437504, + "z": 1.0 + }, + { + "x": 92.39509801744734, + "y": -165.0867210966499, + "z": 1.0 + }, + { + "x": 92.39503708911862, + "y": -164.6859102904703, + "z": 1.0 + }, + { + "x": 92.39494569662551, + "y": -164.0846940812005, + "z": 1.0 + }, + { + "x": 92.39488476829678, + "y": -163.6838832750206, + "z": 1.0 + }, + { + "x": 92.39479337580369, + "y": -163.0826670657508, + "z": 1.0 + }, + { + "x": 92.39471721539276, + "y": -162.58165355802566, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 16, + "heading": [ + 1.5709483394834876, + 1.5709483394834476, + 1.5709483394834654, + 1.570948339483483, + 1.570948339483483, + 1.570948339483483, + 1.5709483394835007, + 1.5709483394834869, + 1.5709483394834711, + 1.5709483394835004, + 1.5709483394835007, + 1.5709483394834713, + 1.5709483394834869, + 1.5709483394835007, + 1.57094833948349, + 1.57094833948349, + 1.5709483394834831, + 1.57094833948349, + 1.570948339483483, + 1.570948339483483, + 1.5709483394834947, + 1.5709483394834947, + 1.5709483394834927, + 1.5709483394834798, + 1.57094833948349, + 1.57094833948349, + 1.5709483394834927, + 1.57094833948349, + 1.570948339483476, + 1.5709483394834869, + 1.57094833948349, + 1.5709483394834947, + 1.5709483394834798, + 1.5709483394834798, + 1.57094833948349, + 1.5709483394835027, + 1.5709483394835027, + 1.5709483394834654, + 1.5709483394835027, + 1.5709483394835182, + 1.570948339483483, + 1.57094833948349, + 1.5709483394834869, + 1.5709483394834647, + 1.570948339483503, + 1.5709483394835015, + 1.5709483394834833, + 1.5709483394834887, + 1.570948339483481, + 1.5709483394834887, + 1.5709483394834887, + 1.5709483394834873, + 1.5709483394834873, + 1.5709483394834873, + 1.5709483394834773, + 1.5709483394834811, + 1.570948339483495, + 1.5709483394835015, + 1.5709483394834873, + 1.5709483394834773, + 1.570948339483481, + 1.570948339483495, + 1.570948339483495, + 1.570948339483481, + 1.5709483394834773, + 1.5709483394834811, + 1.570948339483495, + 1.570948339483495, + 1.5709483394834873, + 1.570948339483481, + 1.5709483394834873, + 1.570948339483495, + 1.570948339483495, + 1.570948339483495, + 1.5709483394834811, + 1.5709483394834716, + 1.570948339483495, + 1.5709483394834887, + 1.5709483394834887, + 1.5709483394834873, + 1.5709483394834776, + 1.570948339483495, + 1.570948339483495, + 1.570948339483495, + 1.5709483394834811, + 1.5709483394834873, + 1.5709483394834873, + 1.5709483394834811, + 1.570948339483495, + 1.570948339483481, + 1.5709483394834887 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -0.0006108272393134939, + "y": 4.018264793755861 + }, + { + "x": -0.0012216544787690964, + "y": 8.036529587511723 + }, + { + "x": -0.001221654478911205, + "y": 8.036529587511723 + }, + { + "x": -0.001221654478911205, + "y": 8.036529587512007 + }, + { + "x": -0.001221654478911205, + "y": 8.036529587512007 + }, + { + "x": -0.0012216544790533135, + "y": 8.036529587514565 + }, + { + "x": -0.0013743612888106327, + "y": 9.041095785947846 + }, + { + "x": -0.0013743612886685241, + "y": 9.04109578594813 + }, + { + "x": -0.0012216544790533135, + "y": 8.036529587517691 + }, + { + "x": -0.0012216544790533135, + "y": 8.036529587511723 + }, + { + "x": -0.0013743612886685241, + "y": 9.041095785945004 + }, + { + "x": -0.0013743612888106327, + "y": 9.041095785950688 + }, + { + "x": -0.0012216544790533135, + "y": 8.036529587514565 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984392495 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389653 + }, + { + "x": -0.001221654478911205, + "y": 8.03652958750888 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389938 + }, + { + "x": -0.0018324817183668074, + "y": 12.054794381265026 + }, + { + "x": -0.0018324817183668074, + "y": 12.054794381267584 + }, + { + "x": -0.001832481718508916, + "y": 12.0547943812673 + }, + { + "x": -0.001832481718508916, + "y": 12.0547943812673 + }, + { + "x": -0.0016797749086094882, + "y": 11.05022818283146 + }, + { + "x": -0.0016797749084673796, + "y": 11.050228182825776 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389653 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389653 + }, + { + "x": -0.0016797749086094882, + "y": 11.050228182831745 + }, + { + "x": -0.0015270680987100604, + "y": 10.04566198439278 + }, + { + "x": -0.001527068098567952, + "y": 10.045661984383969 + }, + { + "x": -0.0013743612888106327, + "y": 9.041095785947846 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389653 + }, + { + "x": -0.001832481718508916, + "y": 12.05479438127071 + }, + { + "x": -0.0016797749084673796, + "y": 11.050228182828903 + }, + { + "x": -0.0016797749084673796, + "y": 11.050228182825776 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389653 + }, + { + "x": -0.0013743612889527412, + "y": 9.04109578595353 + }, + { + "x": -0.0013743612889527412, + "y": 9.04109578595353 + }, + { + "x": -0.0012216544787690964, + "y": 8.036529587509165 + }, + { + "x": -0.0013743612889527412, + "y": 9.041095785950688 + }, + { + "x": -0.0013743612890948498, + "y": 9.04109578595353 + }, + { + "x": -0.001221654478911205, + "y": 8.036529587512007 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389653 + }, + { + "x": -0.0013743612888106327, + "y": 9.041095785950688 + }, + { + "x": -0.0010674037167746064, + "y": 7.021806657110972 + }, + { + "x": -0.0013708873966322699, + "y": 9.018243139047684 + }, + { + "x": -0.00167552904031254, + "y": 11.022297169948843 + }, + { + "x": -0.0018278498619395123, + "y": 12.024324185396154 + }, + { + "x": -0.0016755290401704315, + "y": 11.022297169948843 + }, + { + "x": -0.0015232082182592421, + "y": 10.020270154496416 + }, + { + "x": -0.0016755290401704315, + "y": 11.022297169946569 + }, + { + "x": -0.0016755290401704315, + "y": 11.022297169946 + }, + { + "x": -0.0013708873964901613, + "y": 9.018243139043989 + }, + { + "x": -0.0013708873964901613, + "y": 9.018243139043989 + }, + { + "x": -0.0013708873964901613, + "y": 9.018243139049673 + }, + { + "x": -0.001218566574578972, + "y": 8.016216123597246 + }, + { + "x": -0.0015232082182592421, + "y": 10.020270154493574 + }, + { + "x": -0.0018278498620816208, + "y": 12.024324185398996 + }, + { + "x": -0.00167552904031254, + "y": 11.022297169948843 + }, + { + "x": -0.0013708873964901613, + "y": 9.018243139043989 + }, + { + "x": -0.001218566574578972, + "y": 8.016216123597246 + }, + { + "x": -0.0015232082182592421, + "y": 10.020270154496416 + }, + { + "x": -0.0015232082184013507, + "y": 10.020270154496984 + }, + { + "x": -0.0015232082184013507, + "y": 10.020270154496416 + }, + { + "x": -0.0015232082182592421, + "y": 10.020270154496416 + }, + { + "x": -0.001218566574578972, + "y": 8.016216123597246 + }, + { + "x": -0.0015232082182592421, + "y": 10.020270154493574 + }, + { + "x": -0.0018278498620816208, + "y": 12.024324185398996 + }, + { + "x": -0.0015232082184013507, + "y": 10.020270154496416 + }, + { + "x": -0.0013708873964901613, + "y": 9.018243139043989 + }, + { + "x": -0.0015232082182592421, + "y": 10.020270154496984 + }, + { + "x": -0.0013708873964901613, + "y": 9.0182431390474 + }, + { + "x": -0.0012185665747210805, + "y": 8.016216123597815 + }, + { + "x": -0.0015232082184013507, + "y": 10.020270154499826 + }, + { + "x": -0.0018278498620816208, + "y": 12.024324185398996 + }, + { + "x": -0.0015232082182592421, + "y": 10.020270154493574 + }, + { + "x": -0.0013708873963480528, + "y": 9.018243139043989 + }, + { + "x": -0.0015232082184013507, + "y": 10.020270154496984 + }, + { + "x": -0.0016755290401704315, + "y": 11.022297169946569 + }, + { + "x": -0.0016755290401704315, + "y": 11.022297169949411 + }, + { + "x": -0.0013708873964901613, + "y": 9.0182431390474 + }, + { + "x": -0.001218566574578972, + "y": 8.016216123594972 + }, + { + "x": -0.0015232082184013507, + "y": 10.020270154499826 + }, + { + "x": -0.0015232082184013507, + "y": 10.020270154499826 + }, + { + "x": -0.0015232082184013507, + "y": 10.020270154496984 + }, + { + "x": -0.0015232082182592421, + "y": 10.020270154493574 + }, + { + "x": -0.0013708873964901613, + "y": 9.018243139046831 + }, + { + "x": -0.0013708873964901613, + "y": 9.0182431390474 + }, + { + "x": -0.0015232082182592421, + "y": 10.020270154494142 + }, + { + "x": -0.0015232082184013507, + "y": 10.020270154496984 + }, + { + "x": -0.0015232082182592421, + "y": 10.020270154496984 + }, + { + "x": -0.0016755290401704315, + "y": 11.022297169949411 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 92.39471721539276, + "y": -162.58165355802566, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 98.51810306057145, + "y": -55.50484681194324, + "z": 1.0 + }, + { + "x": 97.90210763219395, + "y": -55.54275923928253, + "z": 1.0 + }, + { + "x": 97.1672865624749, + "y": -55.63466477552653, + "z": 1.0 + }, + { + "x": 96.68166077772335, + "y": -55.72386663030572, + "z": 1.0 + }, + { + "x": 96.20062722226538, + "y": -55.835202363034306, + "z": 1.0 + }, + { + "x": 95.72519384633145, + "y": -55.96843865514556, + "z": 1.0 + }, + { + "x": 95.25635687268348, + "y": -56.123296327664626, + "z": 1.0 + }, + { + "x": 94.56761440630069, + "y": -56.395400963932104, + "z": 1.0 + }, + { + "x": 94.00903059441187, + "y": -56.65783241733771, + "z": 1.0 + }, + { + "x": 93.35990744115566, + "y": -57.01427844825002, + "z": 1.0 + }, + { + "x": 92.73644077798586, + "y": -57.414744385709014, + "z": 1.0 + }, + { + "x": 92.33698122798639, + "y": -57.70496070084755, + "z": 1.0 + }, + { + "x": 91.85702245212593, + "y": -58.09293837455154, + "z": 1.0 + }, + { + "x": 91.39786416293066, + "y": -58.51010636110452, + "z": 1.0 + }, + { + "x": 91.04411377147096, + "y": -58.869432796682446, + "z": 1.0 + }, + { + "x": 90.70915520760263, + "y": -59.246337381510976, + "z": 1.0 + }, + { + "x": 90.24384526998537, + "y": -59.84249537269999, + "z": 1.0 + }, + { + "x": 89.89184851897855, + "y": -60.3653002596416, + "z": 1.0 + }, + { + "x": 89.63469918666868, + "y": -60.799042668986026, + "z": 1.0 + }, + { + "x": 89.2910951948812, + "y": -61.47329534779308, + "z": 1.0 + }, + { + "x": 89.00037913616302, + "y": -62.171598554025486, + "z": 1.0 + }, + { + "x": 88.83665481370848, + "y": -62.64851758812371, + "z": 1.0 + }, + { + "x": 88.69747394854923, + "y": -63.13316632318826, + "z": 1.0 + }, + { + "x": 88.53549611385694, + "y": -63.871868352028564, + "z": 1.0 + }, + { + "x": 88.44400352070429, + "y": -64.49544921231548, + "z": 1.0 + }, + { + "x": 88.39955449165987, + "y": -64.99772352931295, + "z": 1.0 + }, + { + "x": 88.37999549573044, + "y": -65.73662391198296, + "z": 1.0 + }, + { + "x": 88.38005663906475, + "y": -66.13884911037657, + "z": 1.0 + }, + { + "x": 88.3801483540662, + "y": -66.74218690796627, + "z": 1.0 + }, + { + "x": 88.38020949740049, + "y": -67.1444121063596, + "z": 1.0 + }, + { + "x": 88.38028592656836, + "y": -67.64719360435126, + "z": 1.0 + }, + { + "x": 88.38036235573624, + "y": -68.1499751023429, + "z": 1.0 + }, + { + "x": 88.38042331674794, + "y": -68.55100091016726, + "z": 1.0 + }, + { + "x": 88.38051468344379, + "y": -69.15204741485073, + "z": 1.0 + }, + { + "x": 88.380590822357, + "y": -69.65291950208695, + "z": 1.0 + }, + { + "x": 88.38065173348757, + "y": -70.05361717187591, + "z": 1.0 + }, + { + "x": 88.38072787240077, + "y": -70.55448925911213, + "z": 1.0 + }, + { + "x": 88.38081923909662, + "y": -71.15553576379558, + "z": 1.0 + }, + { + "x": 88.38091060579247, + "y": -71.75658226847905, + "z": 1.0 + }, + { + "x": 88.38098674470567, + "y": -72.25745435571554, + "z": 1.0 + }, + { + "x": 88.38107811140152, + "y": -72.85850086039872, + "z": 1.0 + }, + { + "x": 88.38115425031474, + "y": -73.35937294763522, + "z": 1.0 + }, + { + "x": 88.38121516144531, + "y": -73.7600706174239, + "z": 1.0 + }, + { + "x": 88.38130652814115, + "y": -74.36111712210736, + "z": 1.0 + }, + { + "x": 88.38139789483701, + "y": -74.96216362679083, + "z": 1.0 + }, + { + "x": 88.38148926153285, + "y": -75.56321013147428, + "z": 1.0 + }, + { + "x": 88.3815806282287, + "y": -76.16425663615775, + "z": 1.0 + }, + { + "x": 88.38164153935926, + "y": -76.56495430594671, + "z": 1.0 + }, + { + "x": 88.38171767827248, + "y": -77.06582639318293, + "z": 1.0 + }, + { + "x": 88.38177858940304, + "y": -77.4665240629719, + "z": 1.0 + }, + { + "x": 88.38185472831624, + "y": -77.96739615020812, + "z": 1.0 + }, + { + "x": 88.3819460950121, + "y": -78.56844265489157, + "z": 1.0 + }, + { + "x": 88.3820222339253, + "y": -79.06931474212779, + "z": 1.0 + }, + { + "x": 88.38208314505587, + "y": -79.47001241191676, + "z": 1.0 + }, + { + "x": 88.38214405618643, + "y": -79.87071008170574, + "z": 1.0 + }, + { + "x": 88.38222019509963, + "y": -80.37158216894196, + "z": 1.0 + }, + { + "x": 88.38231156179549, + "y": -80.97262867362541, + "z": 1.0 + }, + { + "x": 88.38237247292605, + "y": -81.37332634341438, + "z": 1.0 + }, + { + "x": 88.38243338405663, + "y": -81.77402401320336, + "z": 1.0 + }, + { + "x": 88.38252475075247, + "y": -82.37507051788681, + "z": 1.0 + }, + { + "x": 88.38260088966568, + "y": -82.87594260512303, + "z": 1.0 + }, + { + "x": 88.38269225636154, + "y": -83.47698910980648, + "z": 1.0 + }, + { + "x": 88.3827531674921, + "y": -83.87768677959545, + "z": 1.0 + }, + { + "x": 88.38282930640531, + "y": -84.37855886683167, + "z": 1.0 + }, + { + "x": 88.38292067310115, + "y": -84.97960537151513, + "z": 1.0 + }, + { + "x": 88.38301203979701, + "y": -85.58065187619859, + "z": 1.0 + }, + { + "x": 88.38310340649285, + "y": -86.18169838088205, + "z": 1.0 + }, + { + "x": 88.38316431762343, + "y": -86.58239605067102, + "z": 1.0 + }, + { + "x": 88.38324045653663, + "y": -87.08326813790724, + "z": 1.0 + }, + { + "x": 88.38331659544984, + "y": -87.58414022514346, + "z": 1.0 + }, + { + "x": 88.3833775065804, + "y": -87.98483789493243, + "z": 1.0 + }, + { + "x": 88.38346887327624, + "y": -88.58588439961588, + "z": 1.0 + }, + { + "x": 88.38354501218946, + "y": -89.0867564868521, + "z": 1.0 + }, + { + "x": 88.3836363788853, + "y": -89.68780299153555, + "z": 1.0 + }, + { + "x": 88.38372774558115, + "y": -90.28884949621902, + "z": 1.0 + }, + { + "x": 88.383819112277, + "y": -90.88989600090247, + "z": 1.0 + }, + { + "x": 88.38391047897285, + "y": -91.49094250558593, + "z": 1.0 + }, + { + "x": 88.38398661788605, + "y": -91.99181459282215, + "z": 1.0 + }, + { + "x": 88.38407798458191, + "y": -92.5928610975056, + "z": 1.0 + }, + { + "x": 88.38413889571248, + "y": -92.99355876729457, + "z": 1.0 + }, + { + "x": 88.38419980684304, + "y": -93.39425643708384, + "z": 1.0 + }, + { + "x": 88.38427594575626, + "y": -93.89512852431977, + "z": 1.0 + }, + { + "x": 88.38435208466946, + "y": -94.39600061155598, + "z": 1.0 + }, + { + "x": 88.38442822358267, + "y": -94.8968726987922, + "z": 1.0 + }, + { + "x": 88.38448913471323, + "y": -95.29757036858116, + "z": 1.0 + }, + { + "x": 88.38456527362645, + "y": -95.79844245581738, + "z": 1.0 + }, + { + "x": 88.38464141253965, + "y": -96.2993145430536, + "z": 1.0 + }, + { + "x": 88.38471755145285, + "y": -96.80018663028982, + "z": 1.0 + }, + { + "x": 88.3848089181487, + "y": -97.40123313497327, + "z": 1.0 + }, + { + "x": 88.38488505706191, + "y": -97.90210522220949, + "z": 1.0 + }, + { + "x": 88.38496119597512, + "y": -98.4029773094457, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 17, + "heading": [ + -1.8073716690550956, + -3.0801235849284487, + -3.045783560178179, + -2.9942734138791116, + -2.937039928828713, + -2.891253154713288, + -2.8454663805070655, + -2.7882328993815464, + -2.736722755012727, + -2.6680425608727507, + -2.605019650346343, + -2.547703940744266, + -2.484670601444463, + -2.4328508823942907, + -2.3791011330762006, + -2.322856624015015, + -2.259060740481147, + -2.2016444200165335, + -2.1378485409691073, + -2.0676302122575954, + -2.0037041380264404, + -1.9397715028023987, + -1.8759678803709683, + -1.81217201350278, + -1.7547557105582061, + -1.6909598213230572, + -1.6223212022660787, + -1.587881173364619, + -1.5706443141062976, + -1.5706443141063116, + -1.570644314106307, + -1.5706443141062976, + -1.5706443141063156, + -1.5706443141063124, + -1.5706443141063058, + -1.570644314106303, + -1.570644314106303, + -1.5706443141063058, + -1.570644314106307, + -1.5706443141063187, + -1.5706443141063058, + -1.570644314106293, + -1.5706443141062871, + -1.5706443141063045, + -1.570644314106307, + -1.570644314106307, + -1.570644314106307, + -1.5706443141063045, + -1.570644314106303, + -1.570644314106303, + -1.5706443141063187, + -1.5706443141063058, + -1.5706443141063058, + -1.570644314106303, + -1.570644314106301, + -1.5706443141063187, + -1.5706443141063058, + -1.5706443141063045, + -1.570644314106301, + -1.5706443141063045, + -1.5706443141063058, + -1.570644314106293, + -1.5706443141063045, + -1.570644314106303, + -1.5706443141063058, + -1.570644314106307, + -1.570644314106307, + -1.5706443141063045, + -1.570644314106303, + -1.5706443141063045, + -1.570644314106303, + -1.5706443141063187, + -1.5706443141063058, + -1.5706443141063058, + -1.570644314106307, + -1.570644314106307, + -1.570644314106307, + -1.5706443141063058, + -1.5706443141063058, + -1.5706443141062902, + -1.570644314106301, + -1.570644314106303, + -1.5706443141063045, + -1.5706443141063045, + -1.570644314106303, + -1.570644314106303, + -1.5706443141063045, + -1.5706443141063187, + -1.5706443141063058, + -1.5706443141063058, + -1.5706443141063045 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -6.159954283775022, + "y": -0.3791242733929323 + }, + { + "x": -13.50816498096549, + "y": -1.2981796358329234 + }, + { + "x": -12.204468544705946, + "y": -1.8110739102318973 + }, + { + "x": -9.666593402095174, + "y": -2.005375875077746 + }, + { + "x": -9.564669313919012, + "y": -2.445720248398402 + }, + { + "x": -9.44270349581899, + "y": -2.8809396463032044 + }, + { + "x": -11.575794400307586, + "y": -4.269623087865426 + }, + { + "x": -12.473262782716148, + "y": -5.345360896730824 + }, + { + "x": -12.077069651450358, + "y": -6.188774843179132 + }, + { + "x": -12.725898164260059, + "y": -7.569119683713055 + }, + { + "x": -10.229262131692707, + "y": -6.906822525975329 + }, + { + "x": -8.794183258599304, + "y": -6.781939888425228 + }, + { + "x": -9.391170650557257, + "y": -8.051456602569687 + }, + { + "x": -8.129086806549708, + "y": -7.764944221309094 + }, + { + "x": -6.887089553280248, + "y": -7.3623102040645705 + }, + { + "x": -8.0026850148559, + "y": -9.73062576017547 + }, + { + "x": -8.17306688624086, + "y": -11.18962878130624 + }, + { + "x": -6.091460833166877, + "y": -9.565472962860326 + }, + { + "x": -6.007533240973544, + "y": -11.079950881514833 + }, + { + "x": -6.343200505056643, + "y": -13.725558850394606 + }, + { + "x": -4.544403811727165, + "y": -11.752222403306263 + }, + { + "x": -3.029051876137885, + "y": -9.615677691627766 + }, + { + "x": -3.011586998515412, + "y": -12.23350763904854 + }, + { + "x": -2.5347042784494533, + "y": -13.62282889127215 + }, + { + "x": -1.3594162219706618, + "y": -11.258551772843859 + }, + { + "x": -0.6400802497384461, + "y": -12.411746996674822 + }, + { + "x": -0.19497852595122822, + "y": -11.411255810636192 + }, + { + "x": 0.0015285833575262586, + "y": -10.055629959833112 + }, + { + "x": 0.00152858335738415, + "y": -10.05562995983027 + }, + { + "x": 0.0013757250216883676, + "y": -9.050066963849872 + }, + { + "x": 0.0015285833575262586, + "y": -10.055629959833112 + }, + { + "x": 0.001373901795744814, + "y": -9.038073058160023 + }, + { + "x": 0.0015232770755346792, + "y": -10.020723125078206 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196843 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.0016750560904199574, + "y": -11.019185919199543 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.0016750560907041745, + "y": -11.019185919196843 + }, + { + "x": 0.0013705004379005459, + "y": -9.01569757025186 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744721367 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.0013705004376163288, + "y": -9.01569757025186 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.001218222611356623, + "y": -8.01395339577951 + }, + { + "x": 0.0013705004376163288, + "y": -9.015697570252001 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.0015227782641602516, + "y": -10.01744174472421 + }, + { + "x": 0.001218222611356623, + "y": -8.01395339577951 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.0016750560907041745, + "y": -11.019185919196701 + }, + { + "x": 0.0015227782641602516, + "y": -10.01744174472421 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196843 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.001522778264018143, + "y": -10.01744174472421 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196843 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.0015227782643023602, + "y": -10.01744174472421 + }, + { + "x": 0.001218222611356623, + "y": -8.013953395782352 + }, + { + "x": 0.0013705004377584373, + "y": -9.015697570252001 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744721367 + }, + { + "x": 0.0015227782641602516, + "y": -10.01744174472421 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.001522778264018143, + "y": -10.017441744724351 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 88.38496119597512, + "y": -98.4029773094457, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 155.20273178651496, + "y": -2.8951887416430546, + "z": 1.0 + }, + { + "x": 154.92579367058397, + "y": -3.46365707666486, + "z": 1.0 + }, + { + "x": 154.64273338351381, + "y": -4.167631816676954, + "z": 1.0 + }, + { + "x": 154.44890421003072, + "y": -4.770275261371781, + "z": 1.0 + }, + { + "x": 154.268611816407, + "y": -5.507298142270336, + "z": 1.0 + }, + { + "x": 154.162323368481, + "y": -6.130640444882252, + "z": 1.0 + }, + { + "x": 154.09647483718254, + "y": -6.759539423961707, + "z": 1.0 + }, + { + "x": 154.07136072828882, + "y": -7.38586739845515, + "z": 1.0 + }, + { + "x": 154.07045676264278, + "y": -7.796281509985351, + "z": 1.0 + }, + { + "x": 154.06984533725478, + "y": -8.299606630835797, + "z": 1.0 + }, + { + "x": 154.0693561969444, + "y": -8.702266727515596, + "z": 1.0 + }, + { + "x": 154.06862248647877, + "y": -9.306256872536707, + "z": 1.0 + }, + { + "x": 154.06788877601315, + "y": -9.910247017557246, + "z": 1.0 + }, + { + "x": 154.06715506554758, + "y": -10.514237162577224, + "z": 1.0 + }, + { + "x": 154.0666659252372, + "y": -10.916897259258146, + "z": 1.0 + }, + { + "x": 154.06654364015958, + "y": -11.01756228342824, + "z": 1.0 + }, + { + "x": 154.06605662413546, + "y": -11.418473668533366, + "z": 1.0 + }, + { + "x": 154.06532610009936, + "y": -12.019840746190324, + "z": 1.0 + }, + { + "x": 154.06483908407523, + "y": -12.42075213129591, + "z": 1.0 + }, + { + "x": 154.06423031404506, + "y": -12.92189136267718, + "z": 1.0 + }, + { + "x": 154.06349979000896, + "y": -13.52325844033357, + "z": 1.0 + }, + { + "x": 154.06301277398484, + "y": -13.924169825439153, + "z": 1.0 + }, + { + "x": 154.06240400395467, + "y": -14.425309056820423, + "z": 1.0 + }, + { + "x": 154.0616734799185, + "y": -15.026676134477947, + "z": 1.0 + }, + { + "x": 154.0610647098884, + "y": -15.527815365859787, + "z": 1.0 + }, + { + "x": 154.06045593985823, + "y": -16.02895459724106, + "z": 1.0 + }, + { + "x": 154.05984716982812, + "y": -16.530093828622334, + "z": 1.0 + }, + { + "x": 154.059360153804, + "y": -16.931005213727346, + "z": 1.0 + }, + { + "x": 154.05875138377388, + "y": -17.43214444510862, + "z": 1.0 + }, + { + "x": 154.0581426137437, + "y": -17.933283676489893, + "z": 1.0 + }, + { + "x": 154.0575338437136, + "y": -18.434422907871166, + "z": 1.0 + }, + { + "x": 154.05680331967744, + "y": -19.035789985528126, + "z": 1.0 + }, + { + "x": 154.05631630365332, + "y": -19.436701370633706, + "z": 1.0 + }, + { + "x": 154.05558577961716, + "y": -20.03806844829067, + "z": 1.0 + }, + { + "x": 154.054855255581, + "y": -20.639435525948198, + "z": 1.0 + }, + { + "x": 154.05436823955688, + "y": -21.04034691105378, + "z": 1.0 + }, + { + "x": 154.05363771552072, + "y": -21.64171398871131, + "z": 1.0 + }, + { + "x": 154.0530289454906, + "y": -22.142853220092015, + "z": 1.0 + }, + { + "x": 154.05254192946649, + "y": -22.543764605197595, + "z": 1.0 + }, + { + "x": 154.05205491344236, + "y": -22.944675990302613, + "z": 1.0 + }, + { + "x": 154.05132438940626, + "y": -23.546043067959577, + "z": 1.0 + }, + { + "x": 154.05083737338214, + "y": -23.94695445306516, + "z": 1.0 + }, + { + "x": 154.05022860335197, + "y": -24.448093684446434, + "z": 1.0 + }, + { + "x": 154.04961983332186, + "y": -24.94923291582714, + "z": 1.0 + }, + { + "x": 154.0488893092857, + "y": -25.550599993484663, + "z": 1.0 + }, + { + "x": 154.04828053925553, + "y": -26.051739224866502, + "z": 1.0 + }, + { + "x": 154.04779352323146, + "y": -26.45265060997152, + "z": 1.0 + }, + { + "x": 154.0470629991953, + "y": -27.05401768762905, + "z": 1.0 + }, + { + "x": 154.04657598317118, + "y": -27.454929072733492, + "z": 1.0 + }, + { + "x": 154.0460889671471, + "y": -27.855840457838504, + "z": 1.0 + }, + { + "x": 154.0453584431109, + "y": -28.457207535496586, + "z": 1.0 + }, + { + "x": 154.0447496730808, + "y": -28.958346766877852, + "z": 1.0 + }, + { + "x": 154.04426265705666, + "y": -29.359258151982296, + "z": 1.0 + }, + { + "x": 154.04377564103254, + "y": -29.760169537087876, + "z": 1.0 + }, + { + "x": 154.04316687100243, + "y": -30.26130876846857, + "z": 1.0 + }, + { + "x": 154.0426798549783, + "y": -30.662220153573582, + "z": 1.0 + }, + { + "x": 154.04219283895424, + "y": -31.06313153867916, + "z": 1.0 + }, + { + "x": 154.04146231491808, + "y": -31.664498616336104, + "z": 1.0 + }, + { + "x": 154.0408535448879, + "y": -32.16563784771737, + "z": 1.0 + }, + { + "x": 154.04036652886384, + "y": -32.56654923282238, + "z": 1.0 + }, + { + "x": 154.03987951283972, + "y": -32.96746061792796, + "z": 1.0 + }, + { + "x": 154.03914898880356, + "y": -33.56882769558491, + "z": 1.0 + }, + { + "x": 154.03866197277944, + "y": -33.96973908068992, + "z": 1.0 + }, + { + "x": 154.03793144874328, + "y": -34.571106158348, + "z": 1.0 + }, + { + "x": 154.0373226787131, + "y": -35.07224538972927, + "z": 1.0 + }, + { + "x": 154.036592154677, + "y": -35.673612467386214, + "z": 1.0 + }, + { + "x": 154.03610513865289, + "y": -36.074523852491794, + "z": 1.0 + }, + { + "x": 154.03549636862272, + "y": -36.57566308387306, + "z": 1.0 + }, + { + "x": 154.03476584458656, + "y": -37.177030161530006, + "z": 1.0 + }, + { + "x": 154.03415707455645, + "y": -37.67816939291127, + "z": 1.0 + }, + { + "x": 154.03354830452628, + "y": -38.1793086242931, + "z": 1.0 + }, + { + "x": 154.03281778049012, + "y": -38.78067570195062, + "z": 1.0 + }, + { + "x": 154.03220901046, + "y": -39.28181493333131, + "z": 1.0 + }, + { + "x": 154.03147848642385, + "y": -39.883182010988826, + "z": 1.0 + }, + { + "x": 154.03099147039973, + "y": -40.284093396094406, + "z": 1.0 + }, + { + "x": 154.03038270036961, + "y": -40.785232627475104, + "z": 1.0 + }, + { + "x": 154.0298956843455, + "y": -41.18614401258068, + "z": 1.0 + }, + { + "x": 154.02940866832137, + "y": -41.58705539768569, + "z": 1.0 + }, + { + "x": 154.02867814428527, + "y": -42.18842247534264, + "z": 1.0 + }, + { + "x": 154.02794762024905, + "y": -42.78978955300072, + "z": 1.0 + }, + { + "x": 154.02733885021894, + "y": -43.290928784382, + "z": 1.0 + }, + { + "x": 154.02660832618278, + "y": -43.89229586203953, + "z": 1.0 + }, + { + "x": 154.02587780214662, + "y": -44.493662939697074, + "z": 1.0 + }, + { + "x": 154.0253907861225, + "y": -44.8945743248021, + "z": 1.0 + }, + { + "x": 154.0247820160924, + "y": -45.395713556183374, + "z": 1.0 + }, + { + "x": 154.02405149205623, + "y": -45.99708063384035, + "z": 1.0 + }, + { + "x": 154.02380798404414, + "y": -46.197536326393426, + "z": 1.0 + }, + { + "x": 154.02331963718677, + "y": -46.59954325286995, + "z": 1.0 + }, + { + "x": 154.02258711690075, + "y": -47.20255364258411, + "z": 1.0 + }, + { + "x": 154.02185459661473, + "y": -47.80556403229883, + "z": 1.0 + }, + { + "x": 154.02136624975736, + "y": -48.20757095877531, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 18, + "heading": [ + -1.5933732308870605, + -2.024123654791085, + -1.9853844803775595, + -1.920753503210538, + -1.8431230927316367, + -1.7784250031504312, + -1.7074032821837042, + -1.6431369583595543, + -1.5958870555446687, + -1.5724547754977745, + -1.572011098444287, + -1.5720110984443112, + -1.5720110984443483, + -1.5720110984443023, + -1.5720110984442548, + -1.5720110984443099, + -1.5720110984443811, + -1.5720110984442577, + -1.5720110984442572, + -1.5720110984443574, + -1.572011098444279, + -1.572011098444258, + -1.5720110984443574, + -1.5720110984443294, + -1.5720110984442772, + -1.5720110984443132, + -1.5720110984443139, + -1.572011098444295, + -1.572011098444295, + -1.5720110984443139, + -1.5720110984443139, + -1.5720110984442786, + -1.5720110984443139, + -1.5720110984443139, + -1.5720110984442957, + -1.5720110984443132, + -1.5720110984443132, + -1.5720110984442786, + -1.572011098444295, + -1.5720110984443414, + -1.572011098444258, + -1.5720110984442572, + -1.5720110984443574, + -1.5720110984443145, + -1.5720110984442786, + -1.5720110984443287, + -1.5720110984442943, + -1.5720110984442572, + -1.5720110984443145, + -1.5720110984442723, + -1.5720110984443132, + -1.5720110984443287, + -1.5720110984442959, + -1.5720110984443423, + -1.572011098444295, + -1.5720110984442959, + -1.5720110984442706, + -1.5720110984442572, + -1.57201109844433, + -1.572011098444295, + -1.5720110984442706, + -1.5720110984443139, + -1.5720110984443147, + -1.5720110984443132, + -1.5720110984443287, + -1.5720110984442786, + -1.5720110984442572, + -1.5720110984443574, + -1.57201109844433, + -1.5720110984442786, + -1.5720110984443132, + -1.5720110984443287, + -1.5720110984442786, + -1.5720110984442786, + -1.5720110984443132, + -1.572011098444295, + -1.572011098444295, + -1.5720110984443414, + -1.572011098444258, + -1.572011098444295, + -1.5720110984443287, + -1.5720110984442779, + -1.572011098444295, + -1.5720110984443139, + -1.572011098444295, + -1.5720110984442786, + -1.5720110984443423, + -1.5720110984443705, + -1.5720110984442879, + -1.572011098444269, + -1.5720110984442872 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -2.769381159309887, + "y": -5.684683350218052 + }, + { + "x": -5.599984030011456, + "y": -12.72443075033899 + }, + { + "x": -4.768894605532523, + "y": -13.066181847069211 + }, + { + "x": -3.741215671068119, + "y": -13.396663255933827 + }, + { + "x": -2.865808415497213, + "y": -13.603651835104706 + }, + { + "x": -1.7213697922446158, + "y": -12.522412816913704 + }, + { + "x": -0.9096264019217415, + "y": -12.552269535728984 + }, + { + "x": -0.2601807453976335, + "y": -10.367420860236445 + }, + { + "x": -0.015153910340472976, + "y": -9.137392323806468 + }, + { + "x": -0.011005656983797962, + "y": -9.059852175302447 + }, + { + "x": -0.012228507760028151, + "y": -10.066502417009104 + }, + { + "x": -0.014674209312488529, + "y": -12.079802900416503 + }, + { + "x": -0.014674209311920094, + "y": -12.07980290040517 + }, + { + "x": -0.012228507759459717, + "y": -10.066502417008998 + }, + { + "x": -0.0061142538800140755, + "y": -5.0332512085101655 + }, + { + "x": -0.006093011017469507, + "y": -5.0157640927522 + }, + { + "x": -0.012175400602245645, + "y": -10.022784627620833 + }, + { + "x": -0.012175400602245645, + "y": -10.022784627625434 + }, + { + "x": -0.010957860542930575, + "y": -9.020506164868554 + }, + { + "x": -0.013392940662697583, + "y": -11.025063090376612 + }, + { + "x": -0.012175400602245645, + "y": -10.022784627619732 + }, + { + "x": -0.010957860542930575, + "y": -9.020506164868518 + }, + { + "x": -0.013392940663266018, + "y": -11.025063090387945 + }, + { + "x": -0.013392940662697583, + "y": -11.025063090393648 + }, + { + "x": -0.01217540060281408, + "y": -10.022784627631136 + }, + { + "x": -0.01217540060281408, + "y": -10.02278462762547 + }, + { + "x": -0.010957860542362141, + "y": -9.020506164862852 + }, + { + "x": -0.010957860542362141, + "y": -9.020506164862852 + }, + { + "x": -0.01217540060281408, + "y": -10.02278462762547 + }, + { + "x": -0.01217540060281408, + "y": -10.02278462762547 + }, + { + "x": -0.013392940662697583, + "y": -11.025063090382332 + }, + { + "x": -0.01217540060281408, + "y": -10.022784627625398 + }, + { + "x": -0.01217540060281408, + "y": -10.022784627625434 + }, + { + "x": -0.014610480723149522, + "y": -12.027341553144915 + }, + { + "x": -0.01217540060281408, + "y": -10.022784627631118 + }, + { + "x": -0.01217540060281408, + "y": -10.022784627631118 + }, + { + "x": -0.013392940662697583, + "y": -11.025063090382332 + }, + { + "x": -0.010957860542362141, + "y": -9.020506164862852 + }, + { + "x": -0.009740320482478637, + "y": -8.018227702105989 + }, + { + "x": -0.012175400602245645, + "y": -10.02278462761982 + }, + { + "x": -0.012175400602245645, + "y": -10.02278462762547 + }, + { + "x": -0.010957860542930575, + "y": -9.020506164868571 + }, + { + "x": -0.01217540060281408, + "y": -10.022784627619785 + }, + { + "x": -0.013392940662697583, + "y": -11.025063090382297 + }, + { + "x": -0.013392940663266018, + "y": -11.02506309039363 + }, + { + "x": -0.010957860542362141, + "y": -9.020506164868571 + }, + { + "x": -0.012175400602245645, + "y": -10.02278462762547 + }, + { + "x": -0.01217540060281408, + "y": -10.022784627619714 + }, + { + "x": -0.009740320481910203, + "y": -8.01822770209455 + }, + { + "x": -0.01217540060281408, + "y": -10.02278462763094 + }, + { + "x": -0.013392940663266018, + "y": -11.025063090393488 + }, + { + "x": -0.010957860542362141, + "y": -9.020506164857096 + }, + { + "x": -0.009740320482478637, + "y": -8.018227702100234 + }, + { + "x": -0.010957860542362141, + "y": -9.020506164862745 + }, + { + "x": -0.010957860542362141, + "y": -9.02050616485706 + }, + { + "x": -0.009740320481910203, + "y": -8.018227702105882 + }, + { + "x": -0.012175400602245645, + "y": -10.02278462762522 + }, + { + "x": -0.013392940663266018, + "y": -11.025063090382119 + }, + { + "x": -0.010957860542362141, + "y": -9.02050616486278 + }, + { + "x": -0.009740320481910203, + "y": -8.018227702105918 + }, + { + "x": -0.01217540060281408, + "y": -10.022784627625256 + }, + { + "x": -0.01217540060281408, + "y": -10.022784627619572 + }, + { + "x": -0.01217540060281408, + "y": -10.02278462763094 + }, + { + "x": -0.013392940663266018, + "y": -11.025063090393488 + }, + { + "x": -0.013392940662697583, + "y": -11.025063090382119 + }, + { + "x": -0.012175400602245645, + "y": -10.022784627625256 + }, + { + "x": -0.010957860542930575, + "y": -9.020506164868465 + }, + { + "x": -0.013392940663266018, + "y": -11.025063090382119 + }, + { + "x": -0.013392940662697583, + "y": -11.025063090382119 + }, + { + "x": -0.01217540060281408, + "y": -10.02278462763094 + }, + { + "x": -0.013392940663266018, + "y": -11.025063090393488 + }, + { + "x": -0.013392940662697583, + "y": -11.025063090382119 + }, + { + "x": -0.013392940662697583, + "y": -11.025063090382048 + }, + { + "x": -0.01217540060281408, + "y": -10.02278462763094 + }, + { + "x": -0.010957860542362141, + "y": -9.02050616486278 + }, + { + "x": -0.010957860542362141, + "y": -9.02050616486271 + }, + { + "x": -0.009740320482478637, + "y": -8.018227702105847 + }, + { + "x": -0.012175400602245645, + "y": -10.022784627619643 + }, + { + "x": -0.014610480723149522, + "y": -12.02734155315035 + }, + { + "x": -0.013392940663266018, + "y": -11.025063090393559 + }, + { + "x": -0.013392940662697583, + "y": -11.025063090388088 + }, + { + "x": -0.014610480723149522, + "y": -12.027341553150777 + }, + { + "x": -0.01217540060281408, + "y": -10.022784627625683 + }, + { + "x": -0.010957860542362141, + "y": -9.020506164862994 + }, + { + "x": -0.013392940662697583, + "y": -11.025063090382474 + }, + { + "x": -0.009740320482478637, + "y": -8.018227702100518 + }, + { + "x": -0.0073185486945703815, + "y": -6.0246261902960185 + }, + { + "x": -0.012208671433882046, + "y": -10.050173161906812 + }, + { + "x": -0.014650405720431081, + "y": -12.060207794288829 + }, + { + "x": -0.012208671433882046, + "y": -10.050173161912 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 154.02136624975736, + "y": -48.20757095877531, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 327.0808235050242, + "y": -195.15922625059818, + "z": 1.0 + }, + { + "x": 326.5771403058819, + "y": -195.1591853215736, + "z": 1.0 + }, + { + "x": 326.0734571067396, + "y": -195.15914439254902, + "z": 1.0 + }, + { + "x": 325.6705105474251, + "y": -195.1591116493294, + "z": 1.0 + }, + { + "x": 325.0697613586538, + "y": -195.1590628327749, + "z": 1.0 + }, + { + "x": 324.56942668828424, + "y": -195.15902217584997, + "z": 1.0 + }, + { + "x": 324.1691589519886, + "y": -195.15898965031002, + "z": 1.0 + }, + { + "x": 323.56875734754516, + "y": -195.1589408620001, + "z": 1.0 + }, + { + "x": 323.1684896112495, + "y": -195.15890833646017, + "z": 1.0 + }, + { + "x": 322.7682218749539, + "y": -195.15887581092022, + "z": 1.0 + }, + { + "x": 322.2678872045844, + "y": -195.15883515399528, + "z": 1.0 + }, + { + "x": 321.6674856001403, + "y": -195.1587863656854, + "z": 1.0 + }, + { + "x": 321.0670839956975, + "y": -195.15873757737546, + "z": 1.0 + }, + { + "x": 320.466682391254, + "y": -195.15868878906554, + "z": 1.0 + }, + { + "x": 320.06641465495835, + "y": -195.1586562635256, + "z": 1.0 + }, + { + "x": 319.6661469186627, + "y": -195.15862373798566, + "z": 1.0 + }, + { + "x": 319.1658122482932, + "y": -195.15858308106073, + "z": 1.0 + }, + { + "x": 318.7655445119976, + "y": -195.15855055552078, + "z": 1.0 + }, + { + "x": 318.36527677570194, + "y": -195.15851802998083, + "z": 1.0 + }, + { + "x": 317.86494210533243, + "y": -195.15847737305592, + "z": 1.0 + }, + { + "x": 317.4646743690368, + "y": -195.15844484751597, + "z": 1.0 + }, + { + "x": 316.96433969866723, + "y": -195.15840419059103, + "z": 1.0 + }, + { + "x": 316.3639380942238, + "y": -195.1583554022811, + "z": 1.0 + }, + { + "x": 315.8636034238543, + "y": -195.1583147453562, + "z": 1.0 + }, + { + "x": 315.3632687534847, + "y": -195.15827408843126, + "z": 1.0 + }, + { + "x": 314.76286714904126, + "y": -195.15822530012133, + "z": 1.0 + }, + { + "x": 314.3625994127456, + "y": -195.15819277458138, + "z": 1.0 + }, + { + "x": 313.96233167645, + "y": -195.15816024904146, + "z": 1.0 + }, + { + "x": 313.36193007200654, + "y": -195.15811146073153, + "z": 1.0 + }, + { + "x": 312.861595401637, + "y": -195.1580708038066, + "z": 1.0 + }, + { + "x": 312.36126073126746, + "y": -195.15803014688169, + "z": 1.0 + }, + { + "x": 311.76085912682396, + "y": -195.15798135857176, + "z": 1.0 + }, + { + "x": 311.16045752238057, + "y": -195.15793257026183, + "z": 1.0 + }, + { + "x": 310.660122852011, + "y": -195.1578919133369, + "z": 1.0 + }, + { + "x": 310.15978818164143, + "y": -195.157851256412, + "z": 1.0 + }, + { + "x": 309.55938657719804, + "y": -195.15780246810206, + "z": 1.0 + }, + { + "x": 308.95898497275454, + "y": -195.15775367979214, + "z": 1.0 + }, + { + "x": 308.458650302385, + "y": -195.15771302286723, + "z": 1.0 + }, + { + "x": 307.8582486979416, + "y": -195.1576642345573, + "z": 1.0 + }, + { + "x": 307.45798096164594, + "y": -195.15763170901735, + "z": 1.0 + }, + { + "x": 307.0577132253503, + "y": -195.1575991834774, + "z": 1.0 + }, + { + "x": 306.6574454890547, + "y": -195.15756665793748, + "z": 1.0 + }, + { + "x": 306.05704388461123, + "y": -195.15751786962755, + "z": 1.0 + }, + { + "x": 305.4566422801678, + "y": -195.15746908131763, + "z": 1.0 + }, + { + "x": 305.0563745438716, + "y": -195.1574365557777, + "z": 1.0 + }, + { + "x": 304.5560398735026, + "y": -195.15739589885277, + "z": 1.0 + }, + { + "x": 304.0557052031331, + "y": -195.15735524192783, + "z": 1.0 + }, + { + "x": 303.55537053276356, + "y": -195.1573145850029, + "z": 1.0 + }, + { + "x": 302.95496892832006, + "y": -195.157265796693, + "z": 1.0 + }, + { + "x": 302.5547011920244, + "y": -195.15723327115305, + "z": 1.0 + }, + { + "x": 302.1544334557288, + "y": -195.1572007456131, + "z": 1.0 + }, + { + "x": 301.5540318512854, + "y": -195.15715195730317, + "z": 1.0 + }, + { + "x": 301.05369718091583, + "y": -195.15711130037826, + "z": 1.0 + }, + { + "x": 300.4532955764724, + "y": -195.15706251206834, + "z": 1.0 + }, + { + "x": 300.05302784017675, + "y": -195.15702998652839, + "z": 1.0 + }, + { + "x": 299.45262623573325, + "y": -195.1569811982185, + "z": 1.0 + }, + { + "x": 298.85222463128986, + "y": -195.15693240990856, + "z": 1.0 + }, + { + "x": 298.25182302684635, + "y": -195.15688362159864, + "z": 1.0 + }, + { + "x": 297.6514214224024, + "y": -195.15683483328874, + "z": 1.0 + }, + { + "x": 297.1510867520334, + "y": -195.1567941763638, + "z": 1.0 + }, + { + "x": 296.75081901573776, + "y": -195.15676165082385, + "z": 1.0 + }, + { + "x": 296.2504843453682, + "y": -195.15672099389892, + "z": 1.0 + }, + { + "x": 295.7501496749987, + "y": -195.156680336974, + "z": 1.0 + }, + { + "x": 295.24981500462917, + "y": -195.15663968004907, + "z": 1.0 + }, + { + "x": 294.64941340018567, + "y": -195.15659089173914, + "z": 1.0 + }, + { + "x": 294.24914566389003, + "y": -195.1565583661992, + "z": 1.0 + }, + { + "x": 293.7488109935205, + "y": -195.15651770927428, + "z": 1.0 + }, + { + "x": 293.248476323151, + "y": -195.15647705234935, + "z": 1.0 + }, + { + "x": 292.8482085868554, + "y": -195.1564445268094, + "z": 1.0 + }, + { + "x": 292.2478069824119, + "y": -195.15639573849947, + "z": 1.0 + }, + { + "x": 291.6474053779685, + "y": -195.15634695018957, + "z": 1.0 + }, + { + "x": 291.047003773525, + "y": -195.15629816187965, + "z": 1.0 + }, + { + "x": 290.64673603722935, + "y": -195.1562656363397, + "z": 1.0 + }, + { + "x": 290.04633443278595, + "y": -195.1562168480298, + "z": 1.0 + }, + { + "x": 289.6460666964903, + "y": -195.15618432248985, + "z": 1.0 + }, + { + "x": 289.2457989601947, + "y": -195.1561517969499, + "z": 1.0 + }, + { + "x": 288.6453973557512, + "y": -195.15610300863997, + "z": 1.0 + }, + { + "x": 288.0449957513078, + "y": -195.15605422033008, + "z": 1.0 + }, + { + "x": 287.4445941468643, + "y": -195.15600543202015, + "z": 1.0 + }, + { + "x": 286.84419254242084, + "y": -195.15595664371023, + "z": 1.0 + }, + { + "x": 286.3438578720513, + "y": -195.15591598678532, + "z": 1.0 + }, + { + "x": 285.7434562676079, + "y": -195.1558671984754, + "z": 1.0 + }, + { + "x": 285.34318853131225, + "y": -195.15583467293544, + "z": 1.0 + }, + { + "x": 284.74278692686875, + "y": -195.15578588462554, + "z": 1.0 + }, + { + "x": 284.24245225649923, + "y": -195.1557452277006, + "z": 1.0 + }, + { + "x": 283.7421175861297, + "y": -195.15570457077567, + "z": 1.0 + }, + { + "x": 283.1417159816862, + "y": -195.15565578246574, + "z": 1.0 + }, + { + "x": 282.6413813113167, + "y": -195.15561512554083, + "z": 1.0 + }, + { + "x": 282.1410466409472, + "y": -195.1555744686159, + "z": 1.0 + }, + { + "x": 281.6407119705776, + "y": -195.15553381169096, + "z": 1.0 + }, + { + "x": 281.1403773002075, + "y": -195.15549315476605, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 19, + "heading": [ + 3.1415113941303776, + 3.141511394130359, + 3.141511394130359, + 3.1415113941303905, + 3.141511394130348, + 3.1415113941303248, + 3.1415113941303634, + 3.1415113941303634, + 3.141511394130392, + 3.141511394130399, + 3.1415113941303634, + 3.141511394130389, + 3.141511394130387, + 3.141511394130363, + 3.1415113941303634, + 3.141511394130399, + 3.141511394130395, + 3.1415113941303634, + 3.1415113941303634, + 3.141511394130395, + 3.141511394130395, + 3.1415113941303634, + 3.1415113941303634, + 3.141511394130389, + 3.141511394130392, + 3.1415113941303634, + 3.1415113941303634, + 3.141511394130399, + 3.141511394130392, + 3.1415113941303634, + 3.141511394130392, + 3.141511394130389, + 3.1415113941303634, + 3.1415113941303634, + 3.141511394130392, + 3.141511394130389, + 3.1415113941303634, + 3.141511394130389, + 3.141511394130389, + 3.1415113941303634, + 3.1415113941303634, + 3.141511394130399, + 3.141511394130392, + 3.1415113941303634, + 3.141511394130392, + 3.141511394130395, + 3.141511394130363, + 3.1415113941303634, + 3.141511394130389, + 3.141511394130392, + 3.1415113941303634, + 3.1415113941303634, + 3.141511394130389, + 3.141511394130389, + 3.1415113941303634, + 3.141511394130392, + 3.141511394130387, + 3.1415113941303634, + 3.141511394130387, + 3.141511394130389, + 3.141511394130363, + 3.1415113941303634, + 3.141511394130392, + 3.141511394130392, + 3.1415113941303634, + 3.1415113941303634, + 3.141511394130395, + 3.141511394130392, + 3.1415113941303634, + 3.1415113941303634, + 3.141511394130387, + 3.141511394130387, + 3.1415113941303634, + 3.141511394130392, + 3.141511394130392, + 3.1415113941303634, + 3.1415113941303634, + 3.141511394130387, + 3.141511394130387, + 3.1415113941303634, + 3.141511394130389, + 3.141511394130389, + 3.1415113941303634, + 3.141511394130392, + 3.141511394130389, + 3.1415113941303634, + 3.1415113941303634, + 3.141511394130389, + 3.141511394130392, + 3.1415113941303634, + 3.141511394130392 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -5.036831991423014, + "y": 0.0004092902457841774 + }, + { + "x": -10.073663982846028, + "y": 0.0008185804915683548 + }, + { + "x": -9.06629758456802, + "y": 0.0007367224421273022 + }, + { + "x": -10.036957480858177, + "y": 0.0008155977411661297 + }, + { + "x": -11.010838591408856, + "y": 0.0008947347942012129 + }, + { + "x": -9.006024066652003, + "y": 0.0007318246488807745 + }, + { + "x": -10.006693407390799, + "y": 0.0008131384987564161 + }, + { + "x": -10.006693407390799, + "y": 0.000813138498472199 + }, + { + "x": -8.005354725912639, + "y": 0.0006505107987209158 + }, + { + "x": -9.006024066651435, + "y": 0.0007318246488807745 + }, + { + "x": -11.007362748135847, + "y": 0.0008944523483478406 + }, + { + "x": -12.008032088868958, + "y": 0.0009757661982234822 + }, + { + "x": -12.008032088863274, + "y": 0.0009757661985076993 + }, + { + "x": -10.006693407391367, + "y": 0.0008131384987564161 + }, + { + "x": -8.005354725912639, + "y": 0.0006505107987209158 + }, + { + "x": -9.006024066651435, + "y": 0.0007318246485965574 + }, + { + "x": -9.006024066651435, + "y": 0.0007318246488807745 + }, + { + "x": -8.005354725912639, + "y": 0.0006505107990051329 + }, + { + "x": -9.006024066651435, + "y": 0.0007318246485965574 + }, + { + "x": -9.006024066651435, + "y": 0.0007318246485965574 + }, + { + "x": -9.006024066652003, + "y": 0.0007318246488807745 + }, + { + "x": -11.007362748130163, + "y": 0.0008944523486320577 + }, + { + "x": -11.007362748129594, + "y": 0.0008944523483478406 + }, + { + "x": -10.006693407390799, + "y": 0.000813138498472199 + }, + { + "x": -11.007362748130163, + "y": 0.0008944523486320577 + }, + { + "x": -10.006693407390799, + "y": 0.0008131384987564161 + }, + { + "x": -8.005354725912639, + "y": 0.0006505107987209158 + }, + { + "x": -10.006693407390799, + "y": 0.000813138498472199 + }, + { + "x": -11.007362748130163, + "y": 0.0008944523486320577 + }, + { + "x": -10.006693407390799, + "y": 0.000813138498472199 + }, + { + "x": -11.007362748130163, + "y": 0.0008944523483478406 + }, + { + "x": -12.008032088868958, + "y": 0.0009757661985076993 + }, + { + "x": -11.007362748129594, + "y": 0.0008944523486320577 + }, + { + "x": -10.006693407391367, + "y": 0.000813138498472199 + }, + { + "x": -11.007362748129594, + "y": 0.0008944523483478406 + }, + { + "x": -12.008032088868958, + "y": 0.0009757661985076993 + }, + { + "x": -11.007362748130163, + "y": 0.0008944523483478406 + }, + { + "x": -11.007362748129594, + "y": 0.0008944523483478406 + }, + { + "x": -10.006693407390799, + "y": 0.0008131384987564161 + }, + { + "x": -8.005354725912639, + "y": 0.0006505107990051329 + }, + { + "x": -8.005354725912639, + "y": 0.0006505107987209158 + }, + { + "x": -10.006693407390799, + "y": 0.000813138498472199 + }, + { + "x": -12.008032088868958, + "y": 0.0009757661985076993 + }, + { + "x": -10.006693407396483, + "y": 0.000813138498472199 + }, + { + "x": -9.006024066652003, + "y": 0.0007318246485965574 + }, + { + "x": -10.006693407385114, + "y": 0.0008131384987564161 + }, + { + "x": -10.00669340739023, + "y": 0.0008131384987564161 + }, + { + "x": -11.007362748130163, + "y": 0.0008944523483478406 + }, + { + "x": -10.006693407391367, + "y": 0.000813138498472199 + }, + { + "x": -8.005354725912639, + "y": 0.0006505107990051329 + }, + { + "x": -10.00669340739023, + "y": 0.0008131384987564161 + }, + { + "x": -11.007362748129594, + "y": 0.0008944523483478406 + }, + { + "x": -11.007362748130163, + "y": 0.0008944523483478406 + }, + { + "x": -10.006693407390799, + "y": 0.0008131384987564161 + }, + { + "x": -10.006693407391367, + "y": 0.000813138498472199 + }, + { + "x": -12.008032088868958, + "y": 0.0009757661982234822 + }, + { + "x": -12.008032088868958, + "y": 0.0009757661985076993 + }, + { + "x": -12.008032088874643, + "y": 0.0009757661982234822 + }, + { + "x": -11.007362748129594, + "y": 0.0008944523483478406 + }, + { + "x": -9.006024066646319, + "y": 0.0007318246488807745 + }, + { + "x": -9.006024066652003, + "y": 0.0007318246488807745 + }, + { + "x": -10.006693407390799, + "y": 0.000813138498472199 + }, + { + "x": -10.00669340739023, + "y": 0.000813138498472199 + }, + { + "x": -11.007362748130163, + "y": 0.0008944523486320577 + }, + { + "x": -10.006693407391367, + "y": 0.0008131384987564161 + }, + { + "x": -9.006024066651435, + "y": 0.0007318246485965574 + }, + { + "x": -10.00669340739023, + "y": 0.000813138498472199 + }, + { + "x": -9.006024066651435, + "y": 0.0007318246488807745 + }, + { + "x": -10.006693407391367, + "y": 0.0008131384987564161 + }, + { + "x": -12.008032088868958, + "y": 0.0009757661982234822 + }, + { + "x": -12.008032088868958, + "y": 0.0009757661982234822 + }, + { + "x": -10.006693407391367, + "y": 0.0008131384987564161 + }, + { + "x": -10.00669340739023, + "y": 0.000813138498472199 + }, + { + "x": -10.00669340739023, + "y": 0.000813138498472199 + }, + { + "x": -8.005354725912639, + "y": 0.0006505107990051329 + }, + { + "x": -10.006693407391367, + "y": 0.0008131384987564161 + }, + { + "x": -12.008032088868958, + "y": 0.0009757661982234822 + }, + { + "x": -12.008032088868958, + "y": 0.0009757661982234822 + }, + { + "x": -12.008032088869527, + "y": 0.0009757661985076993 + }, + { + "x": -11.007362748130163, + "y": 0.0008944523483478406 + }, + { + "x": -11.007362748129594, + "y": 0.0008944523483478406 + }, + { + "x": -10.00669340739023, + "y": 0.0008131384987564161 + }, + { + "x": -10.006693407391367, + "y": 0.000813138498472199 + }, + { + "x": -11.007362748130163, + "y": 0.0008944523483478406 + }, + { + "x": -10.00669340739023, + "y": 0.0008131384987564161 + }, + { + "x": -11.007362748130163, + "y": 0.0008944523486320577 + }, + { + "x": -11.007362748130163, + "y": 0.0008944523483478406 + }, + { + "x": -10.00669340739023, + "y": 0.000813138498472199 + }, + { + "x": -10.006693407390799, + "y": 0.0008131384987564161 + }, + { + "x": -10.006693407397051, + "y": 0.000813138498472199 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 281.1403773002075, + "y": -195.15549315476605, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 92.39029670785891, + "y": -133.50179489117374, + "z": 1.0 + }, + { + "x": 92.39023562513496, + "y": -133.09996841179816, + "z": 1.0 + }, + { + "x": 92.39017454241102, + "y": -132.69814193242286, + "z": 1.0 + }, + { + "x": 92.39008291832509, + "y": -132.0954022133592, + "z": 1.0 + }, + { + "x": 92.39000656492016, + "y": -131.5931191141397, + "z": 1.0 + }, + { + "x": 92.38991494083423, + "y": -130.99037939507633, + "z": 1.0 + }, + { + "x": 92.38985385811029, + "y": -130.58855291570075, + "z": 1.0 + }, + { + "x": 92.38979277538634, + "y": -130.18672643632513, + "z": 1.0 + }, + { + "x": 92.38970115130041, + "y": -129.58398671726175, + "z": 1.0 + }, + { + "x": 92.38960952721449, + "y": -128.98124699819837, + "z": 1.0 + }, + { + "x": 92.38953317380957, + "y": -128.47896389897917, + "z": 1.0 + }, + { + "x": 92.38947209108561, + "y": -128.0771374196033, + "z": 1.0 + }, + { + "x": 92.38939573768069, + "y": -127.5748543203841, + "z": 1.0 + }, + { + "x": 92.38931938427575, + "y": -127.0725712211646, + "z": 1.0 + }, + { + "x": 92.38925830155179, + "y": -126.67074474178872, + "z": 1.0 + }, + { + "x": 92.38916667746587, + "y": -126.06800502272534, + "z": 1.0 + }, + { + "x": 92.38909032406094, + "y": -125.56572192350586, + "z": 1.0 + }, + { + "x": 92.389029241337, + "y": -125.16389544413025, + "z": 1.0 + }, + { + "x": 92.38895288793206, + "y": -124.66161234491105, + "z": 1.0 + }, + { + "x": 92.38887653452713, + "y": -124.15932924569157, + "z": 1.0 + }, + { + "x": 92.38881545180318, + "y": -123.7575027663157, + "z": 1.0 + }, + { + "x": 92.38875436907924, + "y": -123.35567628694037, + "z": 1.0 + }, + { + "x": 92.38866274499331, + "y": -122.7529365678767, + "z": 1.0 + }, + { + "x": 92.38857112090739, + "y": -122.15019684881332, + "z": 1.0 + }, + { + "x": 92.38847949682147, + "y": -121.54745712975023, + "z": 1.0 + }, + { + "x": 92.38841841409752, + "y": -121.14563065037433, + "z": 1.0 + }, + { + "x": 92.38832679001159, + "y": -120.54289093131095, + "z": 1.0 + }, + { + "x": 92.38825043660665, + "y": -120.04060783209147, + "z": 1.0 + }, + { + "x": 92.38821989524469, + "y": -119.83969459240367, + "z": 1.0 + }, + { + "x": 92.38815898411413, + "y": -119.43899692261479, + "z": 1.0 + }, + { + "x": 92.38806761741827, + "y": -118.83795041793134, + "z": 1.0 + }, + { + "x": 92.38799147850507, + "y": -118.33707833069512, + "z": 1.0 + }, + { + "x": 92.3879305673745, + "y": -117.93638066090614, + "z": 1.0 + }, + { + "x": 92.3878544284613, + "y": -117.43550857366992, + "z": 1.0 + }, + { + "x": 92.3877782895481, + "y": -116.93463648643372, + "z": 1.0 + }, + { + "x": 92.38768692285224, + "y": -116.33358998175025, + "z": 1.0 + }, + { + "x": 92.38762601172168, + "y": -115.93289231196128, + "z": 1.0 + }, + { + "x": 92.3875651005911, + "y": -115.53219464217231, + "z": 1.0 + }, + { + "x": 92.38747373389526, + "y": -114.93114813748885, + "z": 1.0 + }, + { + "x": 92.38739759498205, + "y": -114.43027605025264, + "z": 1.0 + }, + { + "x": 92.3873062282862, + "y": -113.82922954556918, + "z": 1.0 + }, + { + "x": 92.38724531715565, + "y": -113.42853187578021, + "z": 1.0 + }, + { + "x": 92.38718440602507, + "y": -113.02783420599124, + "z": 1.0 + }, + { + "x": 92.38710826711186, + "y": -112.52696211875502, + "z": 1.0 + }, + { + "x": 92.38704735598128, + "y": -112.12626444896576, + "z": 1.0 + }, + { + "x": 92.38698644485072, + "y": -111.72556677917707, + "z": 1.0 + }, + { + "x": 92.38689507815488, + "y": -111.12452027449362, + "z": 1.0 + }, + { + "x": 92.38681893924166, + "y": -110.6236481872574, + "z": 1.0 + }, + { + "x": 92.3867580281111, + "y": -110.22295051746842, + "z": 1.0 + }, + { + "x": 92.38668188919789, + "y": -109.72207843023222, + "z": 1.0 + }, + { + "x": 92.38660575028469, + "y": -109.221206342996, + "z": 1.0 + }, + { + "x": 92.38651438358883, + "y": -108.62015983831225, + "z": 1.0 + }, + { + "x": 92.38643824467563, + "y": -108.11928775107631, + "z": 1.0 + }, + { + "x": 92.38636210576243, + "y": -107.61841566384011, + "z": 1.0 + }, + { + "x": 92.38630119463186, + "y": -107.21771799405114, + "z": 1.0 + }, + { + "x": 92.38620982793601, + "y": -106.61667148936768, + "z": 1.0 + }, + { + "x": 92.38611846124016, + "y": -106.01562498468421, + "z": 1.0 + }, + { + "x": 92.3860575501096, + "y": -105.61492731489524, + "z": 1.0 + }, + { + "x": 92.38596618341374, + "y": -105.01388081021179, + "z": 1.0 + }, + { + "x": 92.38589004450054, + "y": -104.51300872297557, + "z": 1.0 + }, + { + "x": 92.38582913336998, + "y": -104.1123110531866, + "z": 1.0 + }, + { + "x": 92.38575299445677, + "y": -103.61143896595038, + "z": 1.0 + }, + { + "x": 92.3856920833262, + "y": -103.21074129616142, + "z": 1.0 + }, + { + "x": 92.38563117219563, + "y": -102.81004362637215, + "z": 1.0 + }, + { + "x": 92.38557026106506, + "y": -102.40934595658346, + "z": 1.0 + }, + { + "x": 92.38547889436921, + "y": -101.80829945190001, + "z": 1.0 + }, + { + "x": 92.38538752767336, + "y": -101.20725294721655, + "z": 1.0 + }, + { + "x": 92.3853266165428, + "y": -100.80655527742758, + "z": 1.0 + }, + { + "x": 92.38525047762958, + "y": -100.30568319019136, + "z": 1.0 + }, + { + "x": 92.38517433871638, + "y": -99.80481110295514, + "z": 1.0 + }, + { + "x": 92.38511342758582, + "y": -99.40411343316617, + "z": 1.0 + }, + { + "x": 92.3850372886726, + "y": -98.90324134592996, + "z": 1.0 + }, + { + "x": 92.38494592197677, + "y": -98.3021948412465, + "z": 1.0 + }, + { + "x": 92.38485455528091, + "y": -97.70114833656304, + "z": 1.0 + }, + { + "x": 92.38477841636771, + "y": -97.20027624932682, + "z": 1.0 + }, + { + "x": 92.3847022774545, + "y": -96.6994041620906, + "z": 1.0 + }, + { + "x": 92.38464136632393, + "y": -96.29870649230163, + "z": 1.0 + }, + { + "x": 92.38454999962808, + "y": -95.6976599876179, + "z": 1.0 + }, + { + "x": 92.38447386071488, + "y": -95.19678790038196, + "z": 1.0 + }, + { + "x": 92.38438249401904, + "y": -94.59574139569851, + "z": 1.0 + }, + { + "x": 92.38430635510582, + "y": -94.0948693084623, + "z": 1.0 + }, + { + "x": 92.38421498840998, + "y": -93.49382280377883, + "z": 1.0 + }, + { + "x": 92.38413884949676, + "y": -92.99295071654261, + "z": 1.0 + }, + { + "x": 92.38406271058355, + "y": -92.4920786293064, + "z": 1.0 + }, + { + "x": 92.38400179945297, + "y": -92.09138095951742, + "z": 1.0 + }, + { + "x": 92.38391043275713, + "y": -91.49033445483397, + "z": 1.0 + }, + { + "x": 92.38383429384392, + "y": -90.98946236759747, + "z": 1.0 + }, + { + "x": 92.38374292714808, + "y": -90.38841586291429, + "z": 1.0 + }, + { + "x": 92.38366678823488, + "y": -89.88754377567808, + "z": 1.0 + }, + { + "x": 92.38357542153902, + "y": -89.28649727099462, + "z": 1.0 + }, + { + "x": 92.38349928262582, + "y": -88.7856251837584, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 20, + "heading": [ + 1.5709483394834882, + 1.570948339483483, + 1.5709483394834831, + 1.57094833948349, + 1.5709483394834927, + 1.5709483394834927, + 1.57094833948349, + 1.570948339483483, + 1.57094833948349, + 1.5709483394834947, + 1.5709483394834798, + 1.5709483394834869, + 1.5709483394834869, + 1.570948339483476, + 1.5709483394835027, + 1.5709483394835042, + 1.5709483394834798, + 1.5709483394834711, + 1.5709483394834869, + 1.57094833948349, + 1.5709483394834869, + 1.570948339483483, + 1.57094833948349, + 1.5709483394834947, + 1.570948339483483, + 1.57094833948349, + 1.5709483394835042, + 1.5709483394834927, + 1.570948339483478, + 1.5709483394834656, + 1.5709483394834889, + 1.5709483394834876, + 1.5709483394834904, + 1.5709483394834904, + 1.5709483394834747, + 1.5709483394834876, + 1.5709483394834889, + 1.5709483394834922, + 1.5709483394834889, + 1.5709483394834876, + 1.5709483394834876, + 1.5709483394834747, + 1.5709483394834922, + 1.5709483394835062, + 1.570948339483506, + 1.5709483394834922, + 1.5709483394834747, + 1.5709483394834876, + 1.5709483394834904, + 1.5709483394834904, + 1.5709483394834889, + 1.5709483394834876, + 1.5709483394834876, + 1.5709483394834747, + 1.5709483394834904, + 1.5709483394834889, + 1.5709483394834864, + 1.5709483394834889, + 1.5709483394834889, + 1.5709483394834876, + 1.5709483394834747, + 1.5709483394834904, + 1.5709483394834904, + 1.5709483394834922, + 1.57094833948351, + 1.5709483394834889, + 1.5709483394834864, + 1.5709483394834889, + 1.5709483394834904, + 1.5709483394834889, + 1.5709483394834747, + 1.5709483394834904, + 1.5709483394834876, + 1.5709483394834864, + 1.5709483394834876, + 1.5709483394834889, + 1.5709483394834904, + 1.5709483394834887, + 1.5709483394834876, + 1.5709483394834747, + 1.5709483394834876, + 1.5709483394834876, + 1.5709483394834876, + 1.5709483394835029, + 1.5709483394835062, + 1.5709483394834889, + 1.5709483394834876, + 1.5709483394834876, + 1.5709483394834747, + 1.5709483394834876, + 1.5709483394834876 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -0.0006108272394556025, + "y": 4.018264793755861 + }, + { + "x": -0.001221654478911205, + "y": 8.03652958750888 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389653 + }, + { + "x": -0.0016797749086094882, + "y": 11.05022818283146 + }, + { + "x": -0.0016797749086094882, + "y": 11.050228182828619 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389653 + }, + { + "x": -0.001221654478911205, + "y": 8.036529587512007 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389938 + }, + { + "x": -0.001832481718508916, + "y": 12.054794381267584 + }, + { + "x": -0.0016797749084673796, + "y": 11.050228182825776 + }, + { + "x": -0.0013743612888106327, + "y": 9.041095785950688 + }, + { + "x": -0.0013743612888106327, + "y": 9.041095785950688 + }, + { + "x": -0.001527068098567952, + "y": 10.045661984387095 + }, + { + "x": -0.0013743612889527412, + "y": 9.041095785953814 + }, + { + "x": -0.001527068098852169, + "y": 10.045661984392495 + }, + { + "x": -0.0016797749084673796, + "y": 11.050228182828619 + }, + { + "x": -0.0013743612886685241, + "y": 9.041095785950972 + }, + { + "x": -0.0013743612888106327, + "y": 9.04109578594813 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984386811 + }, + { + "x": -0.0013743612888106327, + "y": 9.04109578595353 + }, + { + "x": -0.001221654478911205, + "y": 8.036529587512007 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389938 + }, + { + "x": -0.001832481718508916, + "y": 12.054794381270426 + }, + { + "x": -0.0018324817183668074, + "y": 12.054794381264742 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389938 + }, + { + "x": -0.001527068098852169, + "y": 10.04566198439278 + }, + { + "x": -0.0016797749086094882, + "y": 11.050228182828619 + }, + { + "x": -0.0010689476690117772, + "y": 7.031963389072757 + }, + { + "x": -0.0009145249252640042, + "y": 6.016109094766762 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744723357 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.0013705004377584373, + "y": 9.015697570252001 + }, + { + "x": -0.0013705004377584373, + "y": 9.015697570252001 + }, + { + "x": -0.001522778264018143, + "y": 10.01744174472421 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.001218222611356623, + "y": 8.013953395779367 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.001522778264018143, + "y": 10.017441744724351 + }, + { + "x": -0.001218222611356623, + "y": 8.013953395779367 + }, + { + "x": -0.0013705004379005459, + "y": 9.01569757025186 + }, + { + "x": -0.0013705004379005459, + "y": 9.015697570254844 + }, + { + "x": -0.001218222611356623, + "y": 8.01395339577951 + }, + { + "x": -0.001522778264018143, + "y": 10.017441744721367 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.0013705004377584373, + "y": 9.015697570252001 + }, + { + "x": -0.0013705004377584373, + "y": 9.01569757025186 + }, + { + "x": -0.0015227782641602516, + "y": 10.01744174472421 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919199685 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196843 + }, + { + "x": -0.001522778264018143, + "y": 10.017441744721367 + }, + { + "x": -0.0013705004377584373, + "y": 9.015697570251717 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0018273339169638803, + "y": 12.020930093669335 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0015227782641602516, + "y": 10.01744174472421 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.0013705004376163288, + "y": 9.01569757025186 + }, + { + "x": -0.0013705004377584373, + "y": 9.01569757025186 + }, + { + "x": -0.0013705004377584373, + "y": 9.01569757025186 + }, + { + "x": -0.001218222611356623, + "y": 8.013953395782352 + }, + { + "x": -0.0012182226114987316, + "y": 8.01395339577951 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744721367 + }, + { + "x": -0.0018273339169638803, + "y": 12.020930093669193 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0013705004377584373, + "y": 9.01569757025186 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0013705004376163288, + "y": 9.01569757025186 + }, + { + "x": -0.0013705004377584373, + "y": 9.01569757025186 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.0018273339169638803, + "y": 12.020930093669193 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196843 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.0013705004377584373, + "y": 9.01569757025186 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744727051 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.0016750560904199574, + "y": 11.019185919193859 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196843 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196843 + }, + { + "x": -0.0015227782643023602, + "y": 10.01744174472421 + }, + { + "x": -0.0013705004379005459, + "y": 9.01569757025186 + }, + { + "x": -0.0015227782641602516, + "y": 10.017441744724351 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919199543 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196843 + }, + { + "x": -0.0016750560904199574, + "y": 11.019185919193859 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196701 + }, + { + "x": -0.001675056090562066, + "y": 11.019185919196843 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 92.38349928262582, + "y": -88.7856251837584, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 88.40609795687595, + "y": -237.44900651847365, + "z": 1.0 + }, + { + "x": 88.40617401207619, + "y": -237.94932790846892, + "z": 1.0 + }, + { + "x": 88.40625006727643, + "y": -238.4496492984642, + "z": 1.0 + }, + { + "x": 88.40631091143662, + "y": -238.84990641046042, + "z": 1.0 + }, + { + "x": 88.40638696663686, + "y": -239.3502278004557, + "z": 1.0 + }, + { + "x": 88.40647823287715, + "y": -239.95061346845003, + "z": 1.0 + }, + { + "x": 88.40656949911744, + "y": -240.55099913644437, + "z": 1.0 + }, + { + "x": 88.40663034327763, + "y": -240.9512562484406, + "z": 1.0 + }, + { + "x": 88.40669118743781, + "y": -241.35151336043683, + "z": 1.0 + }, + { + "x": 88.4067824536781, + "y": -241.9518990284309, + "z": 1.0 + }, + { + "x": 88.40685850887834, + "y": -242.45222041842644, + "z": 1.0 + }, + { + "x": 88.40691935303853, + "y": -242.85247753042268, + "z": 1.0 + }, + { + "x": 88.40698019719873, + "y": -243.2527346424186, + "z": 1.0 + }, + { + "x": 88.40705625239896, + "y": -243.75305603241418, + "z": 1.0 + }, + { + "x": 88.40714751863925, + "y": -244.3534417004085, + "z": 1.0 + }, + { + "x": 88.40723878487954, + "y": -244.95382736840284, + "z": 1.0 + }, + { + "x": 88.40729962903973, + "y": -245.35408448039905, + "z": 1.0 + }, + { + "x": 88.40737568423997, + "y": -245.85440587039434, + "z": 1.0 + }, + { + "x": 88.4074517394402, + "y": -246.3547272603896, + "z": 1.0 + }, + { + "x": 88.4075125836004, + "y": -246.75498437238585, + "z": 1.0 + }, + { + "x": 88.40758863880063, + "y": -247.2553057623811, + "z": 1.0 + }, + { + "x": 88.40766469400087, + "y": -247.7556271523764, + "z": 1.0 + }, + { + "x": 88.40775596024116, + "y": -248.35601282037072, + "z": 1.0 + }, + { + "x": 88.4078320154414, + "y": -248.85633421036601, + "z": 1.0 + }, + { + "x": 88.40789285960159, + "y": -249.25659132236223, + "z": 1.0 + }, + { + "x": 88.40795370376178, + "y": -249.65684843435847, + "z": 1.0 + }, + { + "x": 88.40804497000208, + "y": -250.2572341023525, + "z": 1.0 + }, + { + "x": 88.40813623624236, + "y": -250.85761977034713, + "z": 1.0 + }, + { + "x": 88.40822750248265, + "y": -251.45800543834147, + "z": 1.0 + }, + { + "x": 88.40831876872294, + "y": -252.0583911063358, + "z": 1.0 + }, + { + "x": 88.40837961288312, + "y": -252.45864821833175, + "z": 1.0 + }, + { + "x": 88.40845566808336, + "y": -252.958969608327, + "z": 1.0 + }, + { + "x": 88.4085317232836, + "y": -253.4592909983223, + "z": 1.0 + }, + { + "x": 88.40862298952389, + "y": -254.05967666631662, + "z": 1.0 + }, + { + "x": 88.40868383368408, + "y": -254.45993377831314, + "z": 1.0 + }, + { + "x": 88.40874467784427, + "y": -254.86019089030938, + "z": 1.0 + }, + { + "x": 88.40880552200446, + "y": -255.2604480023056, + "z": 1.0 + }, + { + "x": 88.40889678824475, + "y": -255.8608336702999, + "z": 1.0 + }, + { + "x": 88.40897284344499, + "y": -256.36115506029523, + "z": 1.0 + }, + { + "x": 88.40904889864522, + "y": -256.86147645029047, + "z": 1.0 + }, + { + "x": 88.40912495384546, + "y": -257.36179784028576, + "z": 1.0 + }, + { + "x": 88.40921622008575, + "y": -257.9621835082798, + "z": 1.0 + }, + { + "x": 88.40929227528599, + "y": -258.4625048982751, + "z": 1.0 + }, + { + "x": 88.40936833048623, + "y": -258.96282628827066, + "z": 1.0 + }, + { + "x": 88.4094595967265, + "y": -259.563211956265, + "z": 1.0 + }, + { + "x": 88.40953565192675, + "y": -260.0635333462603, + "z": 1.0 + }, + { + "x": 88.40959649608695, + "y": -260.4637904582562, + "z": 1.0 + }, + { + "x": 88.40967255128719, + "y": -260.9641118482515, + "z": 1.0 + }, + { + "x": 88.40976381752746, + "y": -261.5644975162461, + "z": 1.0 + }, + { + "x": 88.40982466168767, + "y": -261.9647546282421, + "z": 1.0 + }, + { + "x": 88.40990071688789, + "y": -262.4650760182376, + "z": 1.0 + }, + { + "x": 88.4099919831282, + "y": -263.0654616862317, + "z": 1.0 + }, + { + "x": 88.41005282728837, + "y": -263.4657187982282, + "z": 1.0 + }, + { + "x": 88.41011367144857, + "y": -263.8659759102241, + "z": 1.0 + }, + { + "x": 88.41018972664881, + "y": -264.3662973002197, + "z": 1.0 + }, + { + "x": 88.410250570809, + "y": -264.7665544122159, + "z": 1.0 + }, + { + "x": 88.41031141496919, + "y": -265.1668115242121, + "z": 1.0 + }, + { + "x": 88.41037225912937, + "y": -265.5670686362084, + "z": 1.0 + }, + { + "x": 88.41044831432961, + "y": -266.0673900262036, + "z": 1.0 + }, + { + "x": 88.4105091584898, + "y": -266.4676471381999, + "z": 1.0 + }, + { + "x": 88.41060042473009, + "y": -267.0680328061942, + "z": 1.0 + }, + { + "x": 88.41067647993033, + "y": -267.5683541961895, + "z": 1.0 + }, + { + "x": 88.41075253513057, + "y": -268.0686755861847, + "z": 1.0 + }, + { + "x": 88.41081337929077, + "y": -268.4689326981807, + "z": 1.0 + }, + { + "x": 88.41090464553105, + "y": -269.0693183661753, + "z": 1.0 + }, + { + "x": 88.41096548969124, + "y": -269.4695754781715, + "z": 1.0 + }, + { + "x": 88.41102633385142, + "y": -269.86983259016773, + "z": 1.0 + }, + { + "x": 88.41111760009171, + "y": -270.4702182581621, + "z": 1.0 + }, + { + "x": 88.41119365529195, + "y": -270.97053964815734, + "z": 1.0 + }, + { + "x": 88.41126971049219, + "y": -271.47086103815263, + "z": 1.0 + }, + { + "x": 88.4113305546524, + "y": -271.87111815014856, + "z": 1.0 + }, + { + "x": 88.41140660985262, + "y": -272.37143954014414, + "z": 1.0 + }, + { + "x": 88.41148266505286, + "y": -272.8717609301394, + "z": 1.0 + }, + { + "x": 88.4115587202531, + "y": -273.37208232013495, + "z": 1.0 + }, + { + "x": 88.41163477545334, + "y": -273.8724037101299, + "z": 1.0 + }, + { + "x": 88.41171083065358, + "y": -274.37272510012514, + "z": 1.0 + }, + { + "x": 88.41178688585381, + "y": -274.8730464901204, + "z": 1.0 + }, + { + "x": 88.411847730014, + "y": -275.27330360211687, + "z": 1.0 + }, + { + "x": 88.4119085741742, + "y": -275.6735607141125, + "z": 1.0 + }, + { + "x": 88.41199984041448, + "y": -276.27394638210706, + "z": 1.0 + }, + { + "x": 88.41207589561472, + "y": -276.7742677721023, + "z": 1.0 + }, + { + "x": 88.41215195081497, + "y": -277.27458916209724, + "z": 1.0 + }, + { + "x": 88.41221279497516, + "y": -277.67484627409374, + "z": 1.0 + }, + { + "x": 88.41227363913535, + "y": -278.07510338608967, + "z": 1.0 + }, + { + "x": 88.41236490537563, + "y": -278.6754890540845, + "z": 1.0 + }, + { + "x": 88.41244096057588, + "y": -279.1758104440792, + "z": 1.0 + }, + { + "x": 88.41251701577612, + "y": -279.67613183407445, + "z": 1.0 + }, + { + "x": 88.41260828201641, + "y": -280.2765175020687, + "z": 1.0 + }, + { + "x": 88.4126691261766, + "y": -280.6767746140652, + "z": 1.0 + }, + { + "x": 88.41276039241689, + "y": -281.2771602820592, + "z": 1.0 + }, + { + "x": 88.41282123657707, + "y": -281.6774173940557, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 21, + "heading": [ + -1.5706443141063056, + -1.5706443141063047, + -1.5706443141063047, + -1.570644314106308, + -1.570644314106308, + -1.5706443141063022, + -1.5706443141063, + -1.5706443141063047, + -1.5706443141063118, + -1.5706443141063047, + -1.5706443141063022, + -1.570644314106308, + -1.570644314106294, + -1.570644314106308, + -1.570644314106315, + -1.5706443141063, + -1.5706443141063047, + -1.570644314106308, + -1.5706443141063047, + -1.570644314106308, + -1.570644314106308, + -1.5706443141063047, + -1.5706443141063022, + -1.5706443141063022, + -1.570644314106308, + -1.5706443141063118, + -1.5706443141062905, + -1.5706443141063, + -1.570644314106312, + -1.5706443141063, + -1.5706443141063047, + -1.5706443141063078, + -1.5706443141063047, + -1.5706443141063022, + -1.570644314106305, + -1.570644314106312, + -1.5706443141063118, + -1.5706443141063047, + -1.5706443141063022, + -1.5706443141063047, + -1.5706443141063047, + -1.5706443141063022, + -1.5706443141063022, + -1.570644314106305, + -1.570644314106315, + -1.570644314106315, + -1.570644314106292, + -1.570644314106292, + -1.570644314106315, + -1.570644314106305, + -1.570644314106308, + -1.5706443141063022, + -1.570644314106305, + -1.5706443141063118, + -1.5706443141062922, + -1.570644314106308, + -1.5706443141063118, + -1.570644314106312, + -1.570644314106308, + -1.570644314106308, + -1.570644314106305, + -1.5706443141063022, + -1.5706443141063047, + -1.570644314106292, + -1.570644314106305, + -1.570644314106319, + -1.5706443141063118, + -1.570644314106305, + -1.5706443141063022, + -1.5706443141063047, + -1.570644314106292, + -1.570644314106308, + -1.570644314106319, + -1.570644314106305, + -1.5706443141063047, + -1.5706443141063047, + -1.5706443141063047, + -1.570644314106308, + -1.570644314106294, + -1.5706443141063047, + -1.570644314106315, + -1.5706443141062905, + -1.5706443141062922, + -1.5706443141063118, + -1.570644314106319, + -1.5706443141063022, + -1.5706443141062905, + -1.5706443141063022, + -1.570644314106305, + -1.5706443141063047, + -1.5706443141063047 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0007605520023901136, + "y": -5.003213899952641 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799905566 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019915038 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019915038 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579896094 + }, + { + "x": 0.001825324805793116, + "y": -12.007713359886623 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799905566 + }, + { + "x": 0.0012168832037673383, + "y": -8.00514223992451 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799903008 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579896094 + }, + { + "x": 0.0013689936042737827, + "y": -9.00578501991788 + }, + { + "x": 0.0012168832039094468, + "y": -8.005142239921668 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019915038 + }, + { + "x": 0.001673214405144563, + "y": -11.007070579898937 + }, + { + "x": 0.001825324805793116, + "y": -12.007713359886623 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799905566 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019915038 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799905566 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019915038 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019915038 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799905566 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579896094 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579896094 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019915038 + }, + { + "x": 0.0012168832037673383, + "y": -8.00514223992451 + }, + { + "x": 0.0015211040049223357, + "y": -10.006427799902724 + }, + { + "x": 0.001825324805793116, + "y": -12.007713359886623 + }, + { + "x": 0.0018253248056510074, + "y": -12.007713359889749 + }, + { + "x": 0.001825324805793116, + "y": -12.007713359886623 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799902724 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019912196 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799905566 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579896094 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799908408 + }, + { + "x": 0.0012168832037673383, + "y": -8.005142239927636 + }, + { + "x": 0.0012168832037673383, + "y": -8.00514223992451 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799905282 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579896379 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799905566 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799905282 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579893252 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579893252 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799908693 + }, + { + "x": 0.001673214405144563, + "y": -11.007070579898937 + }, + { + "x": 0.001673214405144563, + "y": -11.007070579896094 + }, + { + "x": 0.0013689936044158912, + "y": -9.005785019912196 + }, + { + "x": 0.0013689936044158912, + "y": -9.005785019912196 + }, + { + "x": 0.001673214405144563, + "y": -11.007070579898937 + }, + { + "x": 0.0015211040047802271, + "y": -10.00642779990585 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019915038 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579896094 + }, + { + "x": 0.0015211040047802271, + "y": -10.00642779990585 + }, + { + "x": 0.0012168832037673383, + "y": -8.005142239924226 + }, + { + "x": 0.0013689936044158912, + "y": -9.005785019915038 + }, + { + "x": 0.0013689936042737827, + "y": -9.00578501991788 + }, + { + "x": 0.0012168832037673383, + "y": -8.005142239924226 + }, + { + "x": 0.0012168832037673383, + "y": -8.005142239924794 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019915038 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019915038 + }, + { + "x": 0.0015211040047802271, + "y": -10.00642779990585 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579896094 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799905282 + }, + { + "x": 0.0013689936044158912, + "y": -9.005785019912196 + }, + { + "x": 0.0015211040047802271, + "y": -10.00642779990585 + }, + { + "x": 0.0015211040046381186, + "y": -10.006427799908124 + }, + { + "x": 0.0012168832037673383, + "y": -8.005142239924226 + }, + { + "x": 0.0015211040047802271, + "y": -10.00642779990585 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579896094 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799905282 + }, + { + "x": 0.0013689936044158912, + "y": -9.005785019912196 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019915038 + }, + { + "x": 0.0015211040046381186, + "y": -10.006427799908124 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799908124 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799905282 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799901871 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799904714 + }, + { + "x": 0.0013689936042737827, + "y": -9.005785019917312 + }, + { + "x": 0.0012168832039094468, + "y": -8.005142239921383 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799901871 + }, + { + "x": 0.001673214405144563, + "y": -11.0070705798978 + }, + { + "x": 0.0015211040049223357, + "y": -10.006427799901871 + }, + { + "x": 0.0013689936044158912, + "y": -9.00578501991447 + }, + { + "x": 0.0012168832037673383, + "y": -8.005142239924226 + }, + { + "x": 0.0015211040046381186, + "y": -10.006427799907556 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579895526 + }, + { + "x": 0.0015211040049223357, + "y": -10.006427799899598 + }, + { + "x": 0.0016732144052866715, + "y": -11.007070579894958 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799907556 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799904714 + }, + { + "x": 0.0015211040047802271, + "y": -10.006427799904714 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 88.41282123657707, + "y": -281.6774173940557, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 92.38011802850588, + "y": -66.54238927212418, + "z": 1.0 + }, + { + "x": 92.38004167510093, + "y": -66.0401061729047, + "z": 1.0 + }, + { + "x": 92.37996532169599, + "y": -65.53782307368493, + "z": 1.0 + }, + { + "x": 92.37988896829106, + "y": -65.03553997446542, + "z": 1.0 + }, + { + "x": 92.37982788556711, + "y": -64.63371349509012, + "z": 1.0 + }, + { + "x": 92.37975153216217, + "y": -64.13143039587035, + "z": 1.0 + }, + { + "x": 92.37967517875724, + "y": -63.629147296650856, + "z": 1.0 + }, + { + "x": 92.3796140960333, + "y": -63.22732081727527, + "z": 1.0 + }, + { + "x": 92.37953774262836, + "y": -62.72503771805577, + "z": 1.0 + }, + { + "x": 92.37946138922342, + "y": -62.22275461883628, + "z": 1.0 + }, + { + "x": 92.3793697651375, + "y": -61.62001489977288, + "z": 1.0 + }, + { + "x": 92.37930868241357, + "y": -61.21818842039758, + "z": 1.0 + }, + { + "x": 92.37923232900862, + "y": -60.7159053211778, + "z": 1.0 + }, + { + "x": 92.37917124628467, + "y": -60.314078841802214, + "z": 1.0 + }, + { + "x": 92.37911016356072, + "y": -59.912252362426614, + "z": 1.0 + }, + { + "x": 92.3790185394748, + "y": -59.30951264336322, + "z": 1.0 + }, + { + "x": 92.37892691538889, + "y": -58.70677292430012, + "z": 1.0 + }, + { + "x": 92.37883529130296, + "y": -58.10403320523645, + "z": 1.0 + }, + { + "x": 92.37877420857902, + "y": -57.70220672586085, + "z": 1.0 + }, + { + "x": 92.37869785517408, + "y": -57.19992362664164, + "z": 1.0 + }, + { + "x": 92.37862150176916, + "y": -56.697640527421896, + "z": 1.0 + }, + { + "x": 92.37854514836424, + "y": -56.19535742820269, + "z": 1.0 + }, + { + "x": 92.3784687949593, + "y": -55.69307432898321, + "z": 1.0 + }, + { + "x": 92.37839244155437, + "y": -55.19079122976345, + "z": 1.0 + }, + { + "x": 92.37833135883041, + "y": -54.78896475038785, + "z": 1.0 + }, + { + "x": 92.37825500542549, + "y": -54.28668165116865, + "z": 1.0 + }, + { + "x": 92.37819392270154, + "y": -53.884855171793056, + "z": 1.0 + }, + { + "x": 92.37813283997758, + "y": -53.48302869241718, + "z": 1.0 + }, + { + "x": 92.37805648657265, + "y": -52.980745593197696, + "z": 1.0 + }, + { + "x": 92.37798013316771, + "y": -52.4784624939782, + "z": 1.0 + }, + { + "x": 92.37791905044377, + "y": -52.07663601460261, + "z": 1.0 + }, + { + "x": 92.37784269703883, + "y": -51.57435291538313, + "z": 1.0 + }, + { + "x": 92.37778161431488, + "y": -51.17252643600753, + "z": 1.0 + }, + { + "x": 92.37770526090996, + "y": -50.670243336788324, + "z": 1.0 + }, + { + "x": 92.37761363682404, + "y": -50.06750361772494, + "z": 1.0 + }, + { + "x": 92.37753728341909, + "y": -49.56522051850489, + "z": 1.0 + }, + { + "x": 92.37746093001417, + "y": -49.06293741928596, + "z": 1.0 + }, + { + "x": 92.37736930592824, + "y": -48.46019770022228, + "z": 1.0 + }, + { + "x": 92.37729295252328, + "y": -47.95791460100283, + "z": 1.0 + }, + { + "x": 92.37723186979933, + "y": -47.55608812162724, + "z": 1.0 + }, + { + "x": 92.3771555163944, + "y": -47.053805022407744, + "z": 1.0 + }, + { + "x": 92.37709443367045, + "y": -46.651978543032435, + "z": 1.0 + }, + { + "x": 92.37701808026551, + "y": -46.14969544381266, + "z": 1.0 + }, + { + "x": 92.37701808026551, + "y": -46.14969544381266, + "z": 1.0 + }, + { + "x": 92.37695708299036, + "y": -45.74843108063273, + "z": 1.0 + }, + { + "x": 92.37686558707763, + "y": -45.146534535862855, + "z": 1.0 + }, + { + "x": 92.37680458980248, + "y": -44.745270172682936, + "z": 1.0 + }, + { + "x": 92.37672834320854, + "y": -44.243689718708055, + "z": 1.0 + }, + { + "x": 92.3766520966146, + "y": -43.74210926473344, + "z": 1.0 + }, + { + "x": 92.37657585002066, + "y": -43.24052881075826, + "z": 1.0 + }, + { + "x": 92.37649960342672, + "y": -42.738948356783666, + "z": 1.0 + }, + { + "x": 92.376408107514, + "y": -42.137051812013794, + "z": 1.0 + }, + { + "x": 92.37631661160125, + "y": -41.53515526724364, + "z": 1.0 + }, + { + "x": 92.37624036500732, + "y": -41.03357481326876, + "z": 1.0 + }, + { + "x": 92.37616411841337, + "y": -40.53199435929386, + "z": 1.0 + }, + { + "x": 92.37607262250064, + "y": -39.93009781452399, + "z": 1.0 + }, + { + "x": 92.3760116252255, + "y": -39.52883345134437, + "z": 1.0 + }, + { + "x": 92.37592012931276, + "y": -38.92693690657421, + "z": 1.0 + }, + { + "x": 92.37584388271883, + "y": -38.42535645259932, + "z": 1.0 + }, + { + "x": 92.37576763612489, + "y": -37.923775998624706, + "z": 1.0 + }, + { + "x": 92.37569138953094, + "y": -37.42219554464954, + "z": 1.0 + }, + { + "x": 92.37561514293701, + "y": -36.92061509067493, + "z": 1.0 + }, + { + "x": 92.37552364702428, + "y": -36.31871854590506, + "z": 1.0 + }, + { + "x": 92.37543215111154, + "y": -35.716822001134915, + "z": 1.0 + }, + { + "x": 92.37534065519881, + "y": -35.11492545636504, + "z": 1.0 + }, + { + "x": 92.37526440860488, + "y": -34.61334500239043, + "z": 1.0 + }, + { + "x": 92.37517291269215, + "y": -34.01144845762056, + "z": 1.0 + }, + { + "x": 92.375111915417, + "y": -33.61018409444037, + "z": 1.0 + }, + { + "x": 92.37502041950427, + "y": -33.00828754967078, + "z": 1.0 + }, + { + "x": 92.37492892359154, + "y": -32.40639100490091, + "z": 1.0 + }, + { + "x": 92.37486792631638, + "y": -32.00512664172072, + "z": 1.0 + }, + { + "x": 92.37477643040366, + "y": -31.403230096951127, + "z": 1.0 + }, + { + "x": 92.37468493449093, + "y": -30.801333552181255, + "z": 1.0 + }, + { + "x": 92.37462393721577, + "y": -30.400069189001343, + "z": 1.0 + }, + { + "x": 92.37453244130305, + "y": -29.798172644231478, + "z": 1.0 + }, + { + "x": 92.3744561947091, + "y": -29.296592190256302, + "z": 1.0 + }, + { + "x": 92.37436469879637, + "y": -28.694695645486433, + "z": 1.0 + }, + { + "x": 92.37428845220244, + "y": -28.193115191511822, + "z": 1.0 + }, + { + "x": 92.37421220560849, + "y": -27.691534737536653, + "z": 1.0 + }, + { + "x": 92.37412070969576, + "y": -27.089638192766785, + "z": 1.0 + }, + { + "x": 92.3740597124206, + "y": -26.688373829586872, + "z": 1.0 + }, + { + "x": 92.37398346582667, + "y": -26.18679337561198, + "z": 1.0 + }, + { + "x": 92.37389196991394, + "y": -25.584896830842396, + "z": 1.0 + }, + { + "x": 92.37383097263879, + "y": -25.1836324676622, + "z": 1.0 + }, + { + "x": 92.37376997536363, + "y": -24.782368104482284, + "z": 1.0 + }, + { + "x": 92.37370897808847, + "y": -24.381103741302372, + "z": 1.0 + }, + { + "x": 92.37364798081333, + "y": -23.97983937812274, + "z": 1.0 + }, + { + "x": 92.37355648490059, + "y": -23.377942833352595, + "z": 1.0 + }, + { + "x": 92.37349548762545, + "y": -22.976678470172963, + "z": 1.0 + }, + { + "x": 92.3734192410315, + "y": -22.475098016197787, + "z": 1.0 + }, + { + "x": 92.37334299443756, + "y": -21.9735175622229, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 22, + "heading": [ + 1.5709483394834889, + 1.5709483394835184, + 1.5709483394835042, + 1.57094833948349, + 1.5709483394834869, + 1.5709483394834869, + 1.57094833948349, + 1.5709483394834869, + 1.5709483394834869, + 1.57094833948349, + 1.5709483394834927, + 1.570948339483476, + 1.5709483394834869, + 1.5709483394835027, + 1.570948339483483, + 1.57094833948349, + 1.570948339483483, + 1.570948339483483, + 1.57094833948349, + 1.5709483394834869, + 1.5709483394834758, + 1.5709483394834618, + 1.570948339483476, + 1.57094833948349, + 1.5709483394835027, + 1.5709483394834869, + 1.5709483394834711, + 1.5709483394835007, + 1.5709483394835027, + 1.57094833948349, + 1.5709483394834869, + 1.5709483394834869, + 1.5709483394834869, + 1.5709483394834711, + 1.5709483394834798, + 1.5709483394835053, + 1.57094833948349, + 1.5709483394834798, + 1.5709483394835182, + 1.5709483394835184, + 1.5709483394834869, + 1.5709483394834869, + 1.5709483394834869, + 1.57094833948349, + 1.5709483394834967, + 1.5709483394834896, + 1.5709483394834896, + 1.570948339483485, + 1.5709483394834753, + 1.5709483394834896, + 1.5709483394834896, + 1.5709483394834804, + 1.5709483394834967, + 1.5709483394834933, + 1.5709483394834896, + 1.5709483394834933, + 1.5709483394834753, + 1.5709483394834896, + 1.5709483394834933, + 1.5709483394834753, + 1.5709483394834896, + 1.5709483394834896, + 1.5709483394834804, + 1.5709483394834967, + 1.5709483394834967, + 1.5709483394834804, + 1.5709483394834804, + 1.5709483394834896, + 1.5709483394834896, + 1.570948339483485, + 1.5709483394834896, + 1.5709483394834896, + 1.570948339483485, + 1.5709483394834896, + 1.5709483394834896, + 1.5709483394834933, + 1.5709483394834933, + 1.5709483394834804, + 1.5709483394834896, + 1.5709483394834933, + 1.5709483394834896, + 1.570948339483485, + 1.5709483394834804, + 1.5709483394834896, + 1.5709483394834967, + 1.5709483394834967, + 1.570948339483479, + 1.5709483394834896, + 1.5709483394834896, + 1.570948339483485, + 1.5709483394834896 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -0.0007635340494971388, + "y": 5.022830992194827 + }, + { + "x": -0.001527068098852169, + "y": 10.045661984392495 + }, + { + "x": -0.0015270680987100604, + "y": 10.04566198439278 + }, + { + "x": -0.0013743612888106327, + "y": 9.04109578594813 + }, + { + "x": -0.0013743612888106327, + "y": 9.041095785950688 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984392638 + }, + { + "x": -0.0013743612888106327, + "y": 9.04109578595083 + }, + { + "x": -0.0013743612888106327, + "y": 9.04109578595083 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389938 + }, + { + "x": -0.0016797749086094882, + "y": 11.050228182828903 + }, + { + "x": -0.001527068098567952, + "y": 10.045661984386953 + }, + { + "x": -0.0013743612888106327, + "y": 9.04109578595083 + }, + { + "x": -0.0013743612889527412, + "y": 9.041095785953672 + }, + { + "x": -0.001221654478911205, + "y": 8.036529587511865 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389938 + }, + { + "x": -0.0018324817183668074, + "y": 12.054794381264955 + }, + { + "x": -0.0018324817183668074, + "y": 12.054794381267726 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984392709 + }, + { + "x": -0.0013743612888106327, + "y": 9.041095785948059 + }, + { + "x": -0.001527068098567952, + "y": 10.045661984389511 + }, + { + "x": -0.0015270680984258433, + "y": 10.045661984389511 + }, + { + "x": -0.001527068098567952, + "y": 10.045661984386882 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984392424 + }, + { + "x": -0.0013743612889527412, + "y": 9.041095785953601 + }, + { + "x": -0.0013743612888106327, + "y": 9.041095785947988 + }, + { + "x": -0.0013743612886685241, + "y": 9.041095785947917 + }, + { + "x": -0.0012216544790533135, + "y": 8.036529587514707 + }, + { + "x": -0.0013743612889527412, + "y": 9.041095785953601 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389795 + }, + { + "x": -0.0013743612888106327, + "y": 9.04109578595083 + }, + { + "x": -0.0013743612888106327, + "y": 9.041095785950688 + }, + { + "x": -0.0013743612888106327, + "y": 9.04109578595083 + }, + { + "x": -0.0013743612886685241, + "y": 9.041095785948059 + }, + { + "x": -0.0016797749084673796, + "y": 11.050228182825919 + }, + { + "x": -0.0016797749087515967, + "y": 11.050228182834374 + }, + { + "x": -0.0015270680987100604, + "y": 10.045661984389795 + }, + { + "x": -0.0016797749084673796, + "y": 11.05022818282606 + }, + { + "x": -0.0016797749088937053, + "y": 11.050228182831319 + }, + { + "x": -0.0013743612890948498, + "y": 9.041095785950404 + }, + { + "x": -0.0013743612888106327, + "y": 9.04109578595083 + }, + { + "x": -0.0013743612888106327, + "y": 9.041095785948059 + }, + { + "x": -0.0013743612888106327, + "y": 9.04109578595083 + }, + { + "x": -0.0007635340493550302, + "y": 5.02283099219774 + }, + { + "x": -0.000609972751561827, + "y": 4.012643631799335 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079498054 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079497912 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171548007 + }, + { + "x": -0.0015249318786914046, + "y": 10.031609079494928 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079497912 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0016774250666173884, + "y": 11.03476998744469 + }, + { + "x": -0.0018299182546854809, + "y": 12.03793089540028 + }, + { + "x": -0.001677425066759497, + "y": 11.034769987450375 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.001677425066759497, + "y": 11.034769987447675 + }, + { + "x": -0.0015249318786914046, + "y": 10.031609079494928 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.001677425066759497, + "y": 11.034769987450517 + }, + { + "x": -0.0015249318786914046, + "y": 10.03160907949507 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0016774250666173884, + "y": 11.034769987444832 + }, + { + "x": -0.0018299182546854809, + "y": 12.037930895400137 + }, + { + "x": -0.0018299182546854809, + "y": 12.037930895400137 + }, + { + "x": -0.0016774250666173884, + "y": 11.034769987444832 + }, + { + "x": -0.0016774250666173884, + "y": 11.034769987444832 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079500612 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0018299182545433723, + "y": 12.037930895394595 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079500612 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949784 + }, + { + "x": -0.0018299182545433723, + "y": 12.037930895394666 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949784 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.001677425066759497, + "y": 11.03476998745041 + }, + { + "x": -0.001677425066759497, + "y": 11.034769987450446 + }, + { + "x": -0.0016774250666173884, + "y": 11.034769987444797 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079497805 + }, + { + "x": -0.001677425066759497, + "y": 11.034769987450375 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079497805 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171548042 + }, + { + "x": -0.0016774250666173884, + "y": 11.034769987444761 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079497805 + }, + { + "x": -0.001219945503123654, + "y": 8.025287263601122 + }, + { + "x": -0.001219945503123654, + "y": 8.02528726359828 + }, + { + "x": -0.0012199455029815454, + "y": 8.025287263595438 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0015249318788335131, + "y": 10.03160907949777 + }, + { + "x": -0.0013724386909075292, + "y": 9.028448171548078 + }, + { + "x": -0.0015249318788335131, + "y": 10.031609079500647 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 92.37334299443756, + "y": -21.9735175622229, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 88.37158893513006, + "y": -10.434921050719414, + "z": 1.0 + }, + { + "x": 88.37165014933649, + "y": -10.837612474316, + "z": 1.0 + }, + { + "x": 88.37171136354294, + "y": -11.240303897912584, + "z": 1.0 + }, + { + "x": 88.3717723608181, + "y": -11.641568261092115, + "z": 1.0 + }, + { + "x": 88.37186385673083, + "y": -12.243464805862263, + "z": 1.0 + }, + { + "x": 88.37194010332476, + "y": -12.745045259837152, + "z": 1.0 + }, + { + "x": 88.37200110059992, + "y": -13.14630962301706, + "z": 1.0 + }, + { + "x": 88.37209259651264, + "y": -13.748206167786929, + "z": 1.0 + }, + { + "x": 88.3721535937878, + "y": -14.149470530966838, + "z": 1.0 + }, + { + "x": 88.37221459106296, + "y": -14.550734894146467, + "z": 1.0 + }, + { + "x": 88.37227558833811, + "y": -14.951999257326378, + "z": 1.0 + }, + { + "x": 88.37235183493205, + "y": -15.453579711301547, + "z": 1.0 + }, + { + "x": 88.37242808152598, + "y": -15.955160165276435, + "z": 1.0 + }, + { + "x": 88.37251957743872, + "y": -16.557056710046012, + "z": 1.0 + }, + { + "x": 88.37261107335145, + "y": -17.158953254815877, + "z": 1.0 + }, + { + "x": 88.37268731994538, + "y": -17.660533708791046, + "z": 1.0 + }, + { + "x": 88.37274831722054, + "y": -18.06179807197096, + "z": 1.0 + }, + { + "x": 88.37282456381448, + "y": -18.563378525945843, + "z": 1.0 + }, + { + "x": 88.37290081040842, + "y": -19.06495897992073, + "z": 1.0 + }, + { + "x": 88.37296180768358, + "y": -19.46622334310036, + "z": 1.0 + }, + { + "x": 88.37302280495872, + "y": -19.867487706280553, + "z": 1.0 + }, + { + "x": 88.37309905155267, + "y": -20.36906816025516, + "z": 1.0 + }, + { + "x": 88.3731752981466, + "y": -20.870648614230337, + "z": 1.0 + }, + { + "x": 88.37326679405933, + "y": -21.472545159000205, + "z": 1.0 + }, + { + "x": 88.37335828997207, + "y": -22.074441703769793, + "z": 1.0 + }, + { + "x": 88.37343453656601, + "y": -22.576022157744966, + "z": 1.0 + }, + { + "x": 88.37352603247874, + "y": -23.177918702514834, + "z": 1.0 + }, + { + "x": 88.37361752839146, + "y": -23.779815247284706, + "z": 1.0 + }, + { + "x": 88.37369377498541, + "y": -24.281395701259314, + "z": 1.0 + }, + { + "x": 88.37377002157935, + "y": -24.782976155234483, + "z": 1.0 + }, + { + "x": 88.3738462681733, + "y": -25.284556609209098, + "z": 1.0 + }, + { + "x": 88.37392251476723, + "y": -25.786137063184267, + "z": 1.0 + }, + { + "x": 88.37398351204239, + "y": -26.18740142636418, + "z": 1.0 + }, + { + "x": 88.37405975863632, + "y": -26.68898188033907, + "z": 1.0 + }, + { + "x": 88.37412075591148, + "y": -27.090246243518983, + "z": 1.0 + }, + { + "x": 88.3742122518242, + "y": -27.69214278828885, + "z": 1.0 + }, + { + "x": 88.37428849841815, + "y": -28.19372324226346, + "z": 1.0 + }, + { + "x": 88.37437999433088, + "y": -28.79561978703333, + "z": 1.0 + }, + { + "x": 88.37444099160604, + "y": -29.196884150213243, + "z": 1.0 + }, + { + "x": 88.37450198888118, + "y": -29.598148513393436, + "z": 1.0 + }, + { + "x": 88.3745934847939, + "y": -30.200045058163305, + "z": 1.0 + }, + { + "x": 88.37465448206906, + "y": -30.601309421343217, + "z": 1.0 + }, + { + "x": 88.37473072866301, + "y": -31.10288987531783, + "z": 1.0 + }, + { + "x": 88.37482222457574, + "y": -31.704786420087693, + "z": 1.0 + }, + { + "x": 88.3748832218509, + "y": -32.106050783267605, + "z": 1.0 + }, + { + "x": 88.37497471776362, + "y": -32.70794732803748, + "z": 1.0 + }, + { + "x": 88.37506621367635, + "y": -33.30984387280735, + "z": 1.0 + }, + { + "x": 88.3751272109515, + "y": -33.711108235987254, + "z": 1.0 + }, + { + "x": 88.37520345754544, + "y": -34.212688689962434, + "z": 1.0 + }, + { + "x": 88.37529495345817, + "y": -34.814585234732306, + "z": 1.0 + }, + { + "x": 88.37535595073332, + "y": -35.21584959791221, + "z": 1.0 + }, + { + "x": 88.37541694800848, + "y": -35.617113961091846, + "z": 1.0 + }, + { + "x": 88.3755084439212, + "y": -36.21901050586199, + "z": 1.0 + }, + { + "x": 88.37558469051514, + "y": -36.72059095983688, + "z": 1.0 + }, + { + "x": 88.3756456877903, + "y": -37.1218553230168, + "z": 1.0 + }, + { + "x": 88.37572193438423, + "y": -37.623435776991684, + "z": 1.0 + }, + { + "x": 88.37578293165939, + "y": -38.0247001401716, + "z": 1.0 + }, + { + "x": 88.37587442757211, + "y": -38.626596684941475, + "z": 1.0 + }, + { + "x": 88.37596592348486, + "y": -39.22849322971105, + "z": 1.0 + }, + { + "x": 88.37602692076, + "y": -39.62975759289125, + "z": 1.0 + }, + { + "x": 88.37611841667272, + "y": -40.231654137661124, + "z": 1.0 + }, + { + "x": 88.37620991258547, + "y": -40.83355068243071, + "z": 1.0 + }, + { + "x": 88.37627090986061, + "y": -41.2348150456109, + "z": 1.0 + }, + { + "x": 88.37634715645456, + "y": -41.73639549958551, + "z": 1.0 + }, + { + "x": 88.37640815372971, + "y": -42.13765986276542, + "z": 1.0 + }, + { + "x": 88.37648440032365, + "y": -42.6392403167406, + "z": 1.0 + }, + { + "x": 88.37657589623637, + "y": -43.24113686151047, + "z": 1.0 + }, + { + "x": 88.37663689351153, + "y": -43.642401224690374, + "z": 1.0 + }, + { + "x": 88.37672838942426, + "y": -44.244297769460246, + "z": 1.0 + }, + { + "x": 88.37678938669941, + "y": -44.64556213263988, + "z": 1.0 + }, + { + "x": 88.37686563329335, + "y": -45.14714258661505, + "z": 1.0 + }, + { + "x": 88.3769418798873, + "y": -45.64872304058966, + "z": 1.0 + }, + { + "x": 88.37701812648123, + "y": -46.15030349456484, + "z": 1.0 + }, + { + "x": 88.37707931482646, + "y": -46.55282479273959, + "z": 1.0 + }, + { + "x": 88.377155800258, + "y": -47.05597641545811, + "z": 1.0 + }, + { + "x": 88.37721698860321, + "y": -47.45849771363293, + "z": 1.0 + }, + { + "x": 88.37727817694844, + "y": -47.86101901180774, + "z": 1.0 + }, + { + "x": 88.37736995946628, + "y": -48.46480095906996, + "z": 1.0 + }, + { + "x": 88.37746869965171, + "y": -48.97708841609315, + "z": 1.0 + }, + { + "x": 88.40185746732712, + "y": -49.71365309840904, + "z": 1.0 + }, + { + "x": 88.44585825376632, + "y": -50.204616797586624, + "z": 1.0 + }, + { + "x": 88.55335565655965, + "y": -50.936077505571575, + "z": 1.0 + }, + { + "x": 88.71019196677977, + "y": -51.6585678626945, + "z": 1.0 + }, + { + "x": 88.91564576217036, + "y": -52.36876451225841, + "z": 1.0 + }, + { + "x": 89.12332049993944, + "y": -52.94884511931964, + "z": 1.0 + }, + { + "x": 89.41529380090776, + "y": -53.628069768414065, + "z": 1.0 + }, + { + "x": 89.63524235353502, + "y": -54.069212211922306, + "z": 1.0 + }, + { + "x": 89.87491205951238, + "y": -54.499960149336395, + "z": 1.0 + }, + { + "x": 90.27056376603892, + "y": -55.124948450891765, + "z": 1.0 + }, + { + "x": 90.63189274832027, + "y": -55.62401717672893, + "z": 1.0 + }, + { + "x": 90.94090186406459, + "y": -56.00807087257196, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 23, + "heading": [ + -1.5260968829987904, + -1.5706443141063537, + -1.5706443141063184, + -1.5706443141062898, + -1.5706443141063038, + -1.5706443141063127, + -1.5706443141063084, + -1.5706443141063038, + -1.5706443141063038, + -1.5706443141062967, + -1.5706443141062967, + -1.5706443141063084, + -1.570644314106318, + -1.5706443141062998, + -1.5706443141062967, + -1.5706443141063127, + -1.5706443141063084, + -1.5706443141063084, + -1.5706443141063038, + -1.5706443141062927, + -1.5706443141063142, + -1.5706443141063084, + -1.5706443141063038, + -1.5706443141063127, + -1.5706443141062967, + -1.5706443141062998, + -1.5706443141063127, + -1.5706443141063084, + -1.5706443141062998, + -1.5706443141063038, + -1.5706443141063038, + -1.5706443141063038, + -1.5706443141063084, + -1.5706443141063084, + -1.5706443141063084, + -1.5706443141063038, + -1.5706443141062998, + -1.5706443141062998, + -1.5706443141063038, + -1.5706443141063144, + -1.570644314106318, + -1.5706443141063038, + -1.5706443141062927, + -1.5706443141062998, + -1.5706443141063038, + -1.5706443141063038, + -1.5706443141063084, + -1.5706443141063038, + -1.5706443141063084, + -1.5706443141063127, + -1.5706443141063038, + -1.5706443141062967, + -1.5706443141063038, + -1.5706443141063127, + -1.5706443141063084, + -1.5706443141063084, + -1.5706443141063084, + -1.5706443141063038, + -1.5706443141062967, + -1.5706443141063038, + -1.570644314106318, + -1.5706443141062967, + -1.5706443141063038, + -1.5706443141063084, + -1.5706443141062927, + -1.5706443141063084, + -1.5706443141063127, + -1.5706443141063038, + -1.5706443141063038, + -1.5706443141063036, + -1.5706443141063084, + -1.5706443141063038, + -1.5706443141063038, + -1.5706443141063058, + -1.570644314106291, + -1.5706443141063064, + -1.5706443141063084, + -1.570644314106291, + -1.5706256181447933, + -1.5511908270386274, + -1.5151406473842302, + -1.4474924853507034, + -1.3909568256260652, + -1.3231140246525257, + -1.2609247954819858, + -1.1930819948683404, + -1.1421999017184103, + -1.0856642517891186, + -1.0290687118318207, + -0.978121757078758, + -0.9215254427402406 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0006121420642557496, + "y": -4.026914235965862 + }, + { + "x": 0.0012242841287957162, + "y": -8.053828471931705 + }, + { + "x": 0.0012221148161017936, + "y": -8.039557867761147 + }, + { + "x": 0.0015249318788335131, + "y": -10.031609079496793 + }, + { + "x": 0.0016774250666173884, + "y": -11.034769987450375 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171547971 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949777 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949777 + }, + { + "x": 0.001219945503123654, + "y": -8.025287263595384 + }, + { + "x": 0.001219945503123654, + "y": -8.025287263595402 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171550796 + }, + { + "x": 0.0015249318786914046, + "y": -10.031609079500576 + }, + { + "x": 0.001677425066759497, + "y": -11.034769987444655 + }, + { + "x": 0.0018299182546854809, + "y": -12.037930895394418 + }, + { + "x": 0.0016774250666173884, + "y": -11.034769987450339 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171550814 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171547971 + }, + { + "x": 0.0015249318788335131, + "y": -10.031609079497699 + }, + { + "x": 0.0013724386910496378, + "y": -9.028448171545165 + }, + { + "x": 0.0012199455029815454, + "y": -8.025287263598244 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171548007 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949784 + }, + { + "x": 0.0016774250666173884, + "y": -11.034769987450446 + }, + { + "x": 0.0018299182546854809, + "y": -12.03793089539456 + }, + { + "x": 0.001677425066759497, + "y": -11.034769987447604 + }, + { + "x": 0.0016774250666173884, + "y": -11.03476998745041 + }, + { + "x": 0.0018299182545433723, + "y": -12.037930895397402 + }, + { + "x": 0.001677425066759497, + "y": -11.034769987444797 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949777 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949784 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949784 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171550814 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171548042 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171548042 + }, + { + "x": 0.0015249318788335131, + "y": -10.031609079497805 + }, + { + "x": 0.001677425066759497, + "y": -11.034769987444761 + }, + { + "x": 0.001677425066759497, + "y": -11.034769987444797 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949784 + }, + { + "x": 0.0012199455029815454, + "y": -8.02528726360105 + }, + { + "x": 0.0015249318786914046, + "y": -10.031609079500612 + }, + { + "x": 0.0015249318788335131, + "y": -10.031609079497805 + }, + { + "x": 0.0013724386910496378, + "y": -9.028448171545236 + }, + { + "x": 0.001677425066759497, + "y": -11.034769987444761 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949777 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949784 + }, + { + "x": 0.0018299182545433723, + "y": -12.037930895397437 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949777 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171550849 + }, + { + "x": 0.0016774250666173884, + "y": -11.034769987450517 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949777 + }, + { + "x": 0.001219945503123654, + "y": -8.025287263595402 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949777 + }, + { + "x": 0.0016774250666173884, + "y": -11.034769987450375 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171548149 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171548007 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171548007 + }, + { + "x": 0.0015249318788335131, + "y": -10.031609079497912 + }, + { + "x": 0.0018299182546854809, + "y": -12.037930895394453 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949777 + }, + { + "x": 0.0015249318786914046, + "y": -10.031609079500754 + }, + { + "x": 0.0018299182546854809, + "y": -12.037930895394595 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949777 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171548007 + }, + { + "x": 0.0013724386910496378, + "y": -9.028448171545165 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171550849 + }, + { + "x": 0.0016774250666173884, + "y": -11.034769987450517 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949777 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949777 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949507 + }, + { + "x": 0.0013724386909075292, + "y": -9.028448171548007 + }, + { + "x": 0.0015249318788335131, + "y": -10.03160907949777 + }, + { + "x": 0.0015249318788335131, + "y": -10.031609079497912 + }, + { + "x": 0.0013743493916251737, + "y": -9.041017521499342 + }, + { + "x": 0.0013767377676288106, + "y": -9.056729208932737 + }, + { + "x": 0.001376737767486702, + "y": -9.056729208933376 + }, + { + "x": 0.0012237669044168342, + "y": -8.050425963496295 + }, + { + "x": 0.0015297086306986785, + "y": -10.063032454370315 + }, + { + "x": 0.0019052270327790666, + "y": -11.160694042854118 + }, + { + "x": 0.24487507860840196, + "y": -12.488521393390783 + }, + { + "x": 0.683895541146029, + "y": -12.27528381493471 + }, + { + "x": 1.5149818923252667, + "y": -12.22424407162535 + }, + { + "x": 2.6433371301345687, + "y": -14.539510651078729 + }, + { + "x": 3.6229010561071107, + "y": -14.326870066868338 + }, + { + "x": 4.131285331596644, + "y": -12.902772566251457 + }, + { + "x": 4.996480387374049, + "y": -12.593052561556561 + }, + { + "x": 5.11921853595581, + "y": -11.203670926026632 + }, + { + "x": 4.596182586046211, + "y": -8.718903809223306 + }, + { + "x": 6.353214125038988, + "y": -10.557362389694589 + }, + { + "x": 7.569806888078858, + "y": -11.240570273925314 + }, + { + "x": 6.703380980256668, + "y": -8.831224216801985 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 90.94090186406459, + "y": -56.00807087257196, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 334.3018481088766, + "y": -5.288249675787207, + "z": 1.0 + }, + { + "x": 334.483777617468, + "y": -5.696789019027442, + "z": 1.0 + }, + { + "x": 334.6335298766519, + "y": -6.1181936524140035, + "z": 1.0 + }, + { + "x": 334.7327699870293, + "y": -6.476662154719557, + "z": 1.0 + }, + { + "x": 334.8211665615416, + "y": -6.91505878669135, + "z": 1.0 + }, + { + "x": 334.86871357172106, + "y": -7.284721762788378, + "z": 1.0 + }, + { + "x": 334.8941339881858, + "y": -7.731212958309326, + "z": 1.0 + }, + { + "x": 334.89504189202273, + "y": -8.077929108123932, + "z": 1.0 + }, + { + "x": 334.89473870653876, + "y": -8.579882660367307, + "z": 1.0 + }, + { + "x": 334.8944961581516, + "y": -8.981445502159971, + "z": 1.0 + }, + { + "x": 334.89413233557093, + "y": -9.583789764850664, + "z": 1.0 + }, + { + "x": 334.8938291500871, + "y": -10.085743317094039, + "z": 1.0 + }, + { + "x": 334.8935259646031, + "y": -10.587696869336284, + "z": 1.0 + }, + { + "x": 334.8934046904095, + "y": -10.788478290233183, + "z": 1.0 + }, + { + "x": 334.8931013907418, + "y": -11.290620885066517, + "z": 1.0 + }, + { + "x": 334.89279827934456, + "y": -11.792451779440704, + "z": 1.0 + }, + { + "x": 334.8924345456679, + "y": -12.394648852689727, + "z": 1.0 + }, + { + "x": 334.8920708119913, + "y": -12.996845925937615, + "z": 1.0 + }, + { + "x": 334.8918283228735, + "y": -13.398310641438098, + "z": 1.0 + }, + { + "x": 334.89146458919686, + "y": -14.00050771468712, + "z": 1.0 + }, + { + "x": 334.8911008555202, + "y": -14.602704787936144, + "z": 1.0 + }, + { + "x": 334.8907371218436, + "y": -15.20490186118403, + "z": 1.0 + }, + { + "x": 334.89037338816695, + "y": -15.807098934433052, + "z": 1.0 + }, + { + "x": 334.89007027676973, + "y": -16.308929828807237, + "z": 1.0 + }, + { + "x": 334.8897065430931, + "y": -16.91112690205739, + "z": 1.0 + }, + { + "x": 334.88934280941646, + "y": -17.51332397530641, + "z": 1.0 + }, + { + "x": 334.88903969801925, + "y": -18.015154869680593, + "z": 1.0 + }, + { + "x": 334.8886759643426, + "y": -18.617351942929613, + "z": 1.0 + }, + { + "x": 334.8884334752248, + "y": -19.01881665842783, + "z": 1.0 + }, + { + "x": 334.888190986107, + "y": -19.420281373928308, + "z": 1.0 + }, + { + "x": 334.8878878747098, + "y": -19.922112268302495, + "z": 1.0 + }, + { + "x": 334.8876453855921, + "y": -20.32357698380184, + "z": 1.0 + }, + { + "x": 334.8874028964743, + "y": -20.725041699301187, + "z": 1.0 + }, + { + "x": 334.88716040735653, + "y": -21.126506414800534, + "z": 1.0 + }, + { + "x": 334.8868572959593, + "y": -21.628337309174718, + "z": 1.0 + }, + { + "x": 334.8865541845621, + "y": -22.1301682035489, + "z": 1.0 + }, + { + "x": 334.8862510731649, + "y": -22.631999097923085, + "z": 1.0 + }, + { + "x": 334.8860085840472, + "y": -23.033463813422433, + "z": 1.0 + }, + { + "x": 334.88564485037057, + "y": -23.63566088667032, + "z": 1.0 + }, + { + "x": 334.88534173897335, + "y": -24.137491781044503, + "z": 1.0 + }, + { + "x": 334.8849780052967, + "y": -24.739688854293526, + "z": 1.0 + }, + { + "x": 334.8846748938995, + "y": -25.241519748667706, + "z": 1.0 + }, + { + "x": 334.88431116022286, + "y": -25.84371682191673, + "z": 1.0 + }, + { + "x": 334.88400804882565, + "y": -26.34554771629091, + "z": 1.0 + }, + { + "x": 334.88370493742843, + "y": -26.847378610665096, + "z": 1.0 + }, + { + "x": 334.8833412037518, + "y": -27.449575683914127, + "z": 1.0 + }, + { + "x": 334.883098714634, + "y": -27.851040399414615, + "z": 1.0 + }, + { + "x": 334.8828562255162, + "y": -28.252505114912836, + "z": 1.0 + }, + { + "x": 334.88249249183957, + "y": -28.854702188163, + "z": 1.0 + }, + { + "x": 334.88212875816293, + "y": -29.456899261412033, + "z": 1.0 + }, + { + "x": 334.8817650244863, + "y": -30.059096334661064, + "z": 1.0 + }, + { + "x": 334.88140129080966, + "y": -30.66129340790896, + "z": 1.0 + }, + { + "x": 334.88109817941245, + "y": -31.163124302284288, + "z": 1.0 + }, + { + "x": 334.8807344457358, + "y": -31.765321375532185, + "z": 1.0 + }, + { + "x": 334.8804313343386, + "y": -32.267152269906376, + "z": 1.0 + }, + { + "x": 334.8801282229414, + "y": -32.76898316428171, + "z": 1.0 + }, + { + "x": 334.87982511154416, + "y": -33.27081405865589, + "z": 1.0 + }, + { + "x": 334.87952200014695, + "y": -33.77264495303008, + "z": 1.0 + }, + { + "x": 334.87921888874973, + "y": -34.274475847404275, + "z": 1.0 + }, + { + "x": 334.8789157773525, + "y": -34.77630674177734, + "z": 1.0 + }, + { + "x": 334.8786732882347, + "y": -35.17777145727783, + "z": 1.0 + }, + { + "x": 334.8783701768375, + "y": -35.67960235165202, + "z": 1.0 + }, + { + "x": 334.8780670654403, + "y": -36.18143324602622, + "z": 1.0 + }, + { + "x": 334.87770333176366, + "y": -36.78363031927525, + "z": 1.0 + }, + { + "x": 334.877460842646, + "y": -37.18509503477346, + "z": 1.0 + }, + { + "x": 334.87709710896934, + "y": -37.78729210802249, + "z": 1.0 + }, + { + "x": 334.8767939975721, + "y": -38.289123002396686, + "z": 1.0 + }, + { + "x": 334.8765515084543, + "y": -38.69058771789717, + "z": 1.0 + }, + { + "x": 334.87630901933653, + "y": -39.092052433395395, + "z": 1.0 + }, + { + "x": 334.8759452856599, + "y": -39.694249506644425, + "z": 1.0 + }, + { + "x": 334.87558155198326, + "y": -40.29644657989459, + "z": 1.0 + }, + { + "x": 334.87527844058604, + "y": -40.79827747426879, + "z": 1.0 + }, + { + "x": 334.8749147069094, + "y": -41.40047454751782, + "z": 1.0 + }, + { + "x": 334.8746722177916, + "y": -41.80193926301603, + "z": 1.0 + }, + { + "x": 334.8744297286738, + "y": -42.20340397851652, + "z": 1.0 + }, + { + "x": 334.8741266172766, + "y": -42.70523487289071, + "z": 1.0 + }, + { + "x": 334.87376288359997, + "y": -43.30743194613973, + "z": 1.0 + }, + { + "x": 334.8735203944823, + "y": -43.70889666163794, + "z": 1.0 + }, + { + "x": 334.87321728308507, + "y": -44.21072755601211, + "z": 1.0 + }, + { + "x": 334.8729747939673, + "y": -44.61219227151258, + "z": 1.0 + }, + { + "x": 334.87267168257006, + "y": -45.11402316588563, + "z": 1.0 + }, + { + "x": 334.8723079488934, + "y": -45.716220239135765, + "z": 1.0 + }, + { + "x": 334.8720048374962, + "y": -46.218051133509945, + "z": 1.0 + }, + { + "x": 334.87188359293737, + "y": -46.41878349125962, + "z": 1.0 + }, + { + "x": 334.8715801110045, + "y": -46.92122784405019, + "z": 1.0 + }, + { + "x": 334.87133732545817, + "y": -47.32318332628318, + "z": 1.0 + }, + { + "x": 334.8710338435253, + "y": -47.825627679074415, + "z": 1.0 + }, + { + "x": 334.8706696652059, + "y": -48.4285609024239, + "z": 1.0 + }, + { + "x": 334.87036618327295, + "y": -48.93100525521626, + "z": 1.0 + }, + { + "x": 334.8700627013401, + "y": -49.43344960800749, + "z": 1.0 + }, + { + "x": 334.8696985230207, + "y": -50.036382831355844, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 24, + "heading": [ + -1.5532445997494864, + -1.1518436168635509, + -1.1905972608595516, + -1.2617530685069873, + -1.3395403756927158, + -1.4041224818930387, + -1.4816294206080958, + -1.5376162787349619, + -1.5700837783804023, + -1.5714003377551682, + -1.5714003377550556, + -1.5714003377549617, + -1.5714003377550543, + -1.5714003377551682, + -1.5714003377551, + -1.57140033775507, + -1.5714003377550467, + -1.5714003377550303, + -1.5714003377550674, + -1.5714003377550667, + -1.5714003377550296, + -1.5714003377550303, + -1.5714003377550303, + -1.5714003377550467, + -1.5714003377550463, + -1.5714003377550292, + -1.5714003377550467, + -1.5714003377550467, + -1.571400337755068, + -1.571400337755124, + -1.5714003377550918, + -1.5714003377549668, + -1.5714003377549826, + -1.571400337755124, + -1.5714003377550925, + -1.5714003377550674, + -1.5714003377550674, + -1.5714003377549668, + -1.5714003377549548, + -1.5714003377550474, + -1.5714003377550467, + -1.5714003377550467, + -1.5714003377550467, + -1.5714003377550467, + -1.5714003377550674, + -1.5714003377550467, + -1.5714003377550667, + -1.571400337755124, + -1.5714003377550674, + -1.571400337755029, + -1.5714003377550296, + -1.5714003377550303, + -1.5714003377550467, + -1.5714003377550467, + -1.5714003377550474, + -1.5714003377550667, + -1.5714003377550667, + -1.5714003377550674, + -1.5714003377550674, + -1.571400337755068, + -1.5714003377550925, + -1.5714003377550918, + -1.5714003377550674, + -1.5714003377550467, + -1.5714003377549548, + -1.5714003377549548, + -1.5714003377550467, + -1.5714003377550918, + -1.571400337755124, + -1.571400337755068, + -1.571400337755029, + -1.5714003377550463, + -1.5714003377550467, + -1.571400337755068, + -1.571400337755124, + -1.5714003377550918, + -1.5714003377550467, + -1.5714003377549548, + -1.5714003377549675, + -1.5714003377550918, + -1.5714003377550927, + -1.5714003377550467, + -1.5714003377550463, + -1.5714003377550028, + -1.5714003377549923, + -1.5714003377551027, + -1.5714003377551022, + -1.571400337755011, + -1.5714003377551131, + -1.5714003377551644, + -1.5714003377550114 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 1.81929508591395, + "y": -4.085393432402347 + }, + { + "x": 3.316817677753079, + "y": -8.299439766267964 + }, + { + "x": 2.4899236956133564, + "y": -7.798731356921156 + }, + { + "x": 1.8763668488969643, + "y": -7.9686513427734695 + }, + { + "x": 1.3594358469174495, + "y": -8.080596080688203 + }, + { + "x": 0.7296742664419753, + "y": -8.161541716179759 + }, + { + "x": 0.2632832030167265, + "y": -7.932073453355546 + }, + { + "x": 0.006047183529744871, + "y": -8.486697020579808 + }, + { + "x": -0.005457338711494231, + "y": -9.035163940360391 + }, + { + "x": -0.006063709678301166, + "y": -10.03907104483357 + }, + { + "x": -0.006670080645108101, + "y": -11.042978149340676 + }, + { + "x": -0.006063709678301166, + "y": -10.0390710448562 + }, + { + "x": -0.004244596775606624, + "y": -7.027349731391439 + }, + { + "x": -0.004245738613235517, + "y": -7.0292401573023255 + }, + { + "x": -0.006064110649504073, + "y": -10.03973489207521 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232103 + }, + { + "x": -0.007274673532720044, + "y": -12.043941464969112 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887483708 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887495058 + }, + { + "x": -0.007274673532720044, + "y": -12.043941464980463 + }, + { + "x": -0.007274673532720044, + "y": -12.043941464969095 + }, + { + "x": -0.007274673532720044, + "y": -12.043941464969077 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232068 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676243383 + }, + { + "x": -0.007274673532720044, + "y": -12.043941464991725 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232032 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232032 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887472374 + }, + { + "x": -0.004849782355904608, + "y": -8.029294309986952 + }, + { + "x": -0.005456005150108467, + "y": -9.032956098746645 + }, + { + "x": -0.005456005148971599, + "y": -9.032956098735312 + }, + { + "x": -0.00484978235476774, + "y": -8.029294309986916 + }, + { + "x": -0.004849782355904608, + "y": -8.029294309986952 + }, + { + "x": -0.005456005150108467, + "y": -9.032956098735312 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887483672 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887483672 + }, + { + "x": -0.005456005148971599, + "y": -9.032956098735312 + }, + { + "x": -0.006062227943175458, + "y": -10.036617887472339 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676220699 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232068 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232032 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232032 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232032 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887483672 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232174 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887495183 + }, + { + "x": -0.004849782355904608, + "y": -8.029294309987094 + }, + { + "x": -0.006062227944312326, + "y": -10.03661788748385 + }, + { + "x": -0.007274673532720044, + "y": -12.043941464991974 + }, + { + "x": -0.007274673532720044, + "y": -12.04394146498064 + }, + { + "x": -0.007274673532720044, + "y": -12.043941464969272 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232245 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232245 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676220877 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887495218 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887495112 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887483743 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887483885 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887472588 + }, + { + "x": -0.005456005150108467, + "y": -9.032956098735525 + }, + { + "x": -0.005456005150108467, + "y": -9.032956098746823 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887483885 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232245 + }, + { + "x": -0.006062227943175458, + "y": -10.036617887472445 + }, + { + "x": -0.006062227943175458, + "y": -10.036617887472445 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232245 + }, + { + "x": -0.005456005150108467, + "y": -9.032956098746823 + }, + { + "x": -0.004849782355904608, + "y": -8.029294309987094 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887472516 + }, + { + "x": -0.007274673532720044, + "y": -12.043941464991974 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676243614 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232245 + }, + { + "x": -0.006062227944312326, + "y": -10.036617887472445 + }, + { + "x": -0.004849782355904608, + "y": -8.029294309987023 + }, + { + "x": -0.005456005150108467, + "y": -9.032956098746823 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676232103 + }, + { + "x": -0.006062227943175458, + "y": -10.036617887472232 + }, + { + "x": -0.005456005148971599, + "y": -9.032956098723801 + }, + { + "x": -0.005456005150108467, + "y": -9.032956098746467 + }, + { + "x": -0.005456005150108467, + "y": -9.03295609873517 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676231819 + }, + { + "x": -0.006668450738516185, + "y": -11.040279676243188 + }, + { + "x": -0.004243559560563881, + "y": -7.025632521238521 + }, + { + "x": -0.004247264917012217, + "y": -7.03176710540248 + }, + { + "x": -0.005462674791942845, + "y": -9.043998350235611 + }, + { + "x": -0.005462674791942845, + "y": -9.04399835024222 + }, + { + "x": -0.00667660252247515, + "y": -11.05377576140718 + }, + { + "x": -0.0066766025236120186, + "y": -11.053775761418478 + }, + { + "x": -0.006069638658345866, + "y": -10.048887055835962 + }, + { + "x": -0.00667660252247515, + "y": -11.053775761395812 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 334.8696985230207, + "y": -50.036382831355844, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 335.72938655142246, + "y": -58.63575611077631, + "z": 1.0 + }, + { + "x": 335.26862518724147, + "y": -58.22155991552123, + "z": 1.0 + }, + { + "x": 334.698387263307, + "y": -57.76731713412676, + "z": 1.0 + }, + { + "x": 334.3028154287997, + "y": -57.48483981665477, + "z": 1.0 + }, + { + "x": 333.8957244634312, + "y": -57.219229528144716, + "z": 1.0 + }, + { + "x": 333.4774670769269, + "y": -56.970813165394034, + "z": 1.0 + }, + { + "x": 333.0494715041758, + "y": -56.740398386255336, + "z": 1.0 + }, + { + "x": 332.61217496998677, + "y": -56.52816815784608, + "z": 1.0 + }, + { + "x": 331.94048368733047, + "y": -56.244729219671626, + "z": 1.0 + }, + { + "x": 331.3680067648105, + "y": -56.04123961894434, + "z": 1.0 + }, + { + "x": 330.6681152139086, + "y": -55.83714288248695, + "z": 1.0 + }, + { + "x": 329.95675694016956, + "y": -55.67754008286519, + "z": 1.0 + }, + { + "x": 329.2367567288088, + "y": -55.56306505257391, + "z": 1.0 + }, + { + "x": 328.63221699389953, + "y": -55.502475293783945, + "z": 1.0 + }, + { + "x": 327.9038158309816, + "y": -55.471785085123855, + "z": 1.0 + }, + { + "x": 327.47163572658246, + "y": -55.47111336395268, + "z": 1.0 + }, + { + "x": 326.96905200000987, + "y": -55.471174605179854, + "z": 1.0 + }, + { + "x": 326.3659515281231, + "y": -55.471248094652466, + "z": 1.0 + }, + { + "x": 325.8633678015507, + "y": -55.47130933587964, + "z": 1.0 + }, + { + "x": 325.46130082029276, + "y": -55.471358328861356, + "z": 1.0 + }, + { + "x": 325.15975058434924, + "y": -55.47139507359766, + "z": 1.0 + }, + { + "x": 324.6594655975632, + "y": -55.47145603471698, + "z": 1.0 + }, + { + "x": 324.1591806107769, + "y": -55.47151699583631, + "z": 1.0 + }, + { + "x": 323.65889562399076, + "y": -55.47157795695564, + "z": 1.0 + }, + { + "x": 323.1586106372048, + "y": -55.47163891807496, + "z": 1.0 + }, + { + "x": 322.65832565041853, + "y": -55.47169987919429, + "z": 1.0 + }, + { + "x": 322.0579836662754, + "y": -55.471773032537484, + "z": 1.0 + }, + { + "x": 321.45764168213185, + "y": -55.47184618588068, + "z": 1.0 + }, + { + "x": 320.85729969798865, + "y": -55.47191933922386, + "z": 1.0 + }, + { + "x": 320.3570147112025, + "y": -55.47198030034319, + "z": 1.0 + }, + { + "x": 319.756672727059, + "y": -55.472053453686385, + "z": 1.0 + }, + { + "x": 319.35644473763034, + "y": -55.47210222258184, + "z": 1.0 + }, + { + "x": 318.9562167482014, + "y": -55.47215099147729, + "z": 1.0 + }, + { + "x": 318.35587476405806, + "y": -55.47222414482049, + "z": 1.0 + }, + { + "x": 317.7555327799147, + "y": -55.47229729816368, + "z": 1.0 + }, + { + "x": 317.3553047904859, + "y": -55.47234606705915, + "z": 1.0 + }, + { + "x": 316.7549628063425, + "y": -55.47241922040233, + "z": 1.0 + }, + { + "x": 316.2546778195562, + "y": -55.47248018152166, + "z": 1.0 + }, + { + "x": 315.7543928327701, + "y": -55.47254114264099, + "z": 1.0 + }, + { + "x": 315.3541648433412, + "y": -55.472589911536446, + "z": 1.0 + }, + { + "x": 314.9539368539124, + "y": -55.4726386804319, + "z": 1.0 + }, + { + "x": 314.35359486976915, + "y": -55.472711833775094, + "z": 1.0 + }, + { + "x": 313.95336688034024, + "y": -55.47276060267056, + "z": 1.0 + }, + { + "x": 313.55313889091116, + "y": -55.472809371566015, + "z": 1.0 + }, + { + "x": 313.1529109014824, + "y": -55.47285814046148, + "z": 1.0 + }, + { + "x": 312.55256891733916, + "y": -55.47293129380468, + "z": 1.0 + }, + { + "x": 312.15234092791025, + "y": -55.47298006270013, + "z": 1.0 + }, + { + "x": 311.75211293848133, + "y": -55.4730288315956, + "z": 1.0 + }, + { + "x": 311.15177095433796, + "y": -55.47310198493878, + "z": 1.0 + }, + { + "x": 310.75154296490905, + "y": -55.47315075383425, + "z": 1.0 + }, + { + "x": 310.2512579781229, + "y": -55.473211714953564, + "z": 1.0 + }, + { + "x": 309.6509159939795, + "y": -55.47328486829676, + "z": 1.0 + }, + { + "x": 309.15063100719334, + "y": -55.47334582941609, + "z": 1.0 + }, + { + "x": 308.65034602040726, + "y": -55.47340679053542, + "z": 1.0 + }, + { + "x": 308.25011803097834, + "y": -55.473455559430874, + "z": 1.0 + }, + { + "x": 307.6497760468351, + "y": -55.47352871277407, + "z": 1.0 + }, + { + "x": 307.2495480574063, + "y": -55.47357748166952, + "z": 1.0 + }, + { + "x": 306.6492060732629, + "y": -55.47365063501272, + "z": 1.0 + }, + { + "x": 306.248978083834, + "y": -55.47369940390817, + "z": 1.0 + }, + { + "x": 305.6486360996905, + "y": -55.473772557251365, + "z": 1.0 + }, + { + "x": 305.2484081102616, + "y": -55.47382132614683, + "z": 1.0 + }, + { + "x": 304.84818012083275, + "y": -55.47387009504229, + "z": 1.0 + }, + { + "x": 304.24783813668955, + "y": -55.47394324838548, + "z": 1.0 + }, + { + "x": 303.7475531499034, + "y": -55.47400420950481, + "z": 1.0 + }, + { + "x": 303.3473251604744, + "y": -55.474052978400266, + "z": 1.0 + }, + { + "x": 302.9470971710456, + "y": -55.474101747295734, + "z": 1.0 + }, + { + "x": 302.3467551869023, + "y": -55.474174900638914, + "z": 1.0 + }, + { + "x": 301.9465271974734, + "y": -55.47422366953438, + "z": 1.0 + }, + { + "x": 301.5462992080445, + "y": -55.474272438429836, + "z": 1.0 + }, + { + "x": 301.1460712186156, + "y": -55.4743212073253, + "z": 1.0 + }, + { + "x": 300.5457292344722, + "y": -55.474394360668484, + "z": 1.0 + }, + { + "x": 300.1455012450434, + "y": -55.47444312956395, + "z": 1.0 + }, + { + "x": 299.6452162582573, + "y": -55.47450409068327, + "z": 1.0 + }, + { + "x": 299.24498826882837, + "y": -55.474552859578736, + "z": 1.0 + }, + { + "x": 298.7447032820422, + "y": -55.47461382069807, + "z": 1.0 + }, + { + "x": 298.3444752926133, + "y": -55.47466258959352, + "z": 1.0 + }, + { + "x": 297.7441333084698, + "y": -55.474735742936716, + "z": 1.0 + }, + { + "x": 297.2438483216839, + "y": -55.47479670405605, + "z": 1.0 + }, + { + "x": 296.843620332255, + "y": -55.4748454729515, + "z": 1.0 + }, + { + "x": 296.24327834811163, + "y": -55.474918626294695, + "z": 1.0 + }, + { + "x": 295.8430503586827, + "y": -55.47496739519015, + "z": 1.0 + }, + { + "x": 295.24270837453935, + "y": -55.47504054853334, + "z": 1.0 + }, + { + "x": 294.7424233877531, + "y": -55.475101509652674, + "z": 1.0 + }, + { + "x": 294.3421953983243, + "y": -55.47515027854813, + "z": 1.0 + }, + { + "x": 293.7418534141807, + "y": -55.47522343189132, + "z": 1.0 + }, + { + "x": 293.14151143003744, + "y": -55.47529658523452, + "z": 1.0 + }, + { + "x": 292.6412264432512, + "y": -55.475357546353834, + "z": 1.0 + }, + { + "x": 292.2409984538223, + "y": -55.4754063152493, + "z": 1.0 + }, + { + "x": 291.74071346703613, + "y": -55.47546727636862, + "z": 1.0 + }, + { + "x": 291.3404854776071, + "y": -55.47551604526409, + "z": 1.0 + }, + { + "x": 290.84020049082096, + "y": -55.4755770063834, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 25, + "heading": [ + -2.0911486832018613, + 2.409364246695374, + 2.4415698129842616, + 2.4899494772842057, + 2.5424788063606654, + 2.584577189082867, + 2.6266809113227545, + 2.668743372007666, + 2.7212726952459185, + 2.76854909399482, + 2.8315843006733368, + 2.8893665716104087, + 2.952401781124309, + 3.010184052581499, + 3.0732192687883306, + 3.1145766226218736, + 3.14093956899561, + -3.141470800804608, + -3.141470800804608, + -3.141470800804635, + -3.1414708008046373, + -3.14147080080462, + -3.141470800804616, + -3.1414708008046017, + -3.141470800804616, + -3.141470800804616, + -3.141470800804604, + -3.141470800804606, + -3.141470800804618, + -3.1414708008046173, + -3.1414708008046044, + -3.141470800804616, + -3.14147080080463, + -3.141470800804616, + -3.141470800804606, + -3.1414708008046017, + -3.141470800804616, + -3.1414708008046173, + -3.1414708008046017, + -3.141470800804614, + -3.14147080080463, + -3.141470800804616, + -3.1414708008046017, + -3.1414708008046124, + -3.1414708008046124, + -3.1414708008046017, + -3.141470800804616, + -3.1414708008046124, + -3.141470800804616, + -3.141470800804616, + -3.141470800804614, + -3.1414708008046173, + -3.1414708008046044, + -3.1414708008046017, + -3.141470800804614, + -3.141470800804616, + -3.141470800804616, + -3.141470800804616, + -3.141470800804616, + -3.141470800804616, + -3.1414708008046017, + -3.1414708008046124, + -3.141470800804616, + -3.141470800804604, + -3.141470800804614, + -3.1414708008046124, + -3.141470800804616, + -3.141470800804616, + -3.1414708008046124, + -3.1414708008046124, + -3.141470800804616, + -3.141470800804616, + -3.141470800804614, + -3.141470800804614, + -3.1414708008045986, + -3.141470800804614, + -3.141470800804616, + -3.141470800804604, + -3.141470800804614, + -3.141470800804616, + -3.141470800804616, + -3.141470800804616, + -3.1414708008046044, + -3.141470800804614, + -3.141470800804616, + -3.141470800804606, + -3.1414708008046173, + -3.141470800804614, + -3.141470800804614, + -3.141470800804614, + -3.141470800804614 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -4.607613641809962, + "y": 4.141961952550801 + }, + { + "x": -10.309992881154812, + "y": 8.6843897664955 + }, + { + "x": -9.658097584417646, + "y": 7.367200988664635 + }, + { + "x": -8.026627998758045, + "y": 5.480876059820474 + }, + { + "x": -8.253483518727762, + "y": 5.140266512607354 + }, + { + "x": -8.462529592553665, + "y": 4.788311418893798 + }, + { + "x": -8.6529210694016, + "y": 4.426450075479522 + }, + { + "x": -11.089878168453424, + "y": 4.9566916658370985 + }, + { + "x": -12.441682051762655, + "y": 4.869285389017435 + }, + { + "x": -12.723684734218637, + "y": 4.075863371846751 + }, + { + "x": -14.112498246409473, + "y": 3.6369953607914596 + }, + { + "x": -14.313584850997927, + "y": 2.7407782991303975 + }, + { + "x": -13.24539946270022, + "y": 1.7506478908124734 + }, + { + "x": -13.329408978272, + "y": 0.9127996745005618 + }, + { + "x": -11.605812673170703, + "y": 0.3136192983126307 + }, + { + "x": -9.347638309717468, + "y": 0.006104799440009856 + }, + { + "x": -11.056841984593575, + "y": -0.001347306997843134 + }, + { + "x": -11.05684198459187, + "y": -0.001347306997843134 + }, + { + "x": -9.04650707830342, + "y": -0.0011023420888989222 + }, + { + "x": -7.036172172014403, + "y": -0.0008573771802389274 + }, + { + "x": -8.018352227295509, + "y": -0.0009770585562307588 + }, + { + "x": -10.005699735723397, + "y": -0.0012192223864815332 + }, + { + "x": -10.005699735724534, + "y": -0.0012192223866236418 + }, + { + "x": -10.005699735721123, + "y": -0.0012192223864815332 + }, + { + "x": -10.00569973572226, + "y": -0.0012192223864815332 + }, + { + "x": -11.006269709293974, + "y": -0.0013411446252575843 + }, + { + "x": -12.006839682866826, + "y": -0.0014630668638915267 + }, + { + "x": -12.006839682867394, + "y": -0.0014630668637494182 + }, + { + "x": -11.006269709293406, + "y": -0.0013411446251154757 + }, + { + "x": -11.006269709296248, + "y": -0.0013411446252575843 + }, + { + "x": -10.005699735721691, + "y": -0.0012192223864815332 + }, + { + "x": -8.004559788575989, + "y": -0.0009753779090715398 + }, + { + "x": -10.005699735722828, + "y": -0.0012192223864815332 + }, + { + "x": -12.006839682867394, + "y": -0.0014630668638915267 + }, + { + "x": -10.005699735721691, + "y": -0.0012192223866236418 + }, + { + "x": -10.005699735721691, + "y": -0.0012192223864815332 + }, + { + "x": -11.006269709296816, + "y": -0.0013411446251154757 + }, + { + "x": -10.005699735723965, + "y": -0.0012192223866236418 + }, + { + "x": -9.005129762149977, + "y": -0.0010973001478475908 + }, + { + "x": -8.004559788577126, + "y": -0.0009753779090715398 + }, + { + "x": -10.005699735720555, + "y": -0.0012192223864815332 + }, + { + "x": -10.005699735721691, + "y": -0.0012192223866236418 + }, + { + "x": -8.004559788579968, + "y": -0.0009753779092136483 + }, + { + "x": -8.004559788578263, + "y": -0.0009753779092136483 + }, + { + "x": -10.005699735719986, + "y": -0.0012192223866236418 + }, + { + "x": -10.005699735721691, + "y": -0.0012192223864815332 + }, + { + "x": -8.004559788578263, + "y": -0.0009753779092136483 + }, + { + "x": -10.005699735722828, + "y": -0.0012192223864815332 + }, + { + "x": -10.005699735722828, + "y": -0.0012192223864815332 + }, + { + "x": -9.005129762150546, + "y": -0.0010973001478475908 + }, + { + "x": -11.00626970929568, + "y": -0.0013411446251154757 + }, + { + "x": -11.00626970929568, + "y": -0.0013411446252575843 + }, + { + "x": -10.00569973572226, + "y": -0.0012192223866236418 + }, + { + "x": -9.005129762149977, + "y": -0.0010973001478475908 + }, + { + "x": -10.005699735721691, + "y": -0.0012192223864815332 + }, + { + "x": -10.005699735720555, + "y": -0.0012192223864815332 + }, + { + "x": -10.005699735721691, + "y": -0.0012192223864815332 + }, + { + "x": -10.005699735722828, + "y": -0.0012192223864815332 + }, + { + "x": -10.005699735723965, + "y": -0.0012192223864815332 + }, + { + "x": -10.005699735723965, + "y": -0.0012192223866236418 + }, + { + "x": -8.004559788577694, + "y": -0.0009753779092136483 + }, + { + "x": -10.005699735720555, + "y": -0.0012192223864815332 + }, + { + "x": -11.006269709293406, + "y": -0.0013411446252575843 + }, + { + "x": -9.005129762151682, + "y": -0.0010973001478475908 + }, + { + "x": -8.004559788578263, + "y": -0.0009753779092136483 + }, + { + "x": -10.005699735720555, + "y": -0.0012192223864815332 + }, + { + "x": -10.005699735721691, + "y": -0.0012192223864815332 + }, + { + "x": -8.004559788578263, + "y": -0.0009753779092136483 + }, + { + "x": -8.004559788578263, + "y": -0.0009753779092136483 + }, + { + "x": -10.005699735722828, + "y": -0.0012192223864815332 + }, + { + "x": -10.005699735721691, + "y": -0.0012192223864815332 + }, + { + "x": -9.005129762149409, + "y": -0.0010973001478475908 + }, + { + "x": -9.005129762150546, + "y": -0.0010973001478475908 + }, + { + "x": -9.005129762150546, + "y": -0.0010973001479896993 + }, + { + "x": -9.005129762150546, + "y": -0.0010973001478475908 + }, + { + "x": -10.005699735723965, + "y": -0.0012192223864815332 + }, + { + "x": -11.006269709293974, + "y": -0.0013411446252575843 + }, + { + "x": -9.005129762148272, + "y": -0.0010973001478475908 + }, + { + "x": -10.005699735722828, + "y": -0.0012192223864815332 + }, + { + "x": -10.005699735722828, + "y": -0.0012192223864815332 + }, + { + "x": -10.005699735722828, + "y": -0.0012192223864815332 + }, + { + "x": -11.006269709296248, + "y": -0.0013411446252575843 + }, + { + "x": -9.005129762150546, + "y": -0.0010973001478475908 + }, + { + "x": -10.005699735723965, + "y": -0.0012192223864815332 + }, + { + "x": -12.00683968286853, + "y": -0.0014630668638915267 + }, + { + "x": -11.006269709295111, + "y": -0.0013411446251154757 + }, + { + "x": -9.005129762151682, + "y": -0.0010973001478475908 + }, + { + "x": -9.005129762150546, + "y": -0.0010973001478475908 + }, + { + "x": -9.005129762151682, + "y": -0.0010973001478475908 + }, + { + "x": -9.005129762151682, + "y": -0.0010973001478475908 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 290.84020049082096, + "y": -55.4755770063834, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 334.7845708455262, + "y": -190.97367165224483, + "z": 1.0 + }, + { + "x": 334.7842674203806, + "y": -191.47602198796034, + "z": 1.0 + }, + { + "x": 334.7839639952351, + "y": -191.97837232367357, + "z": 1.0 + }, + { + "x": 334.78359988506054, + "y": -192.5811927265308, + "z": 1.0 + }, + { + "x": 334.78335714494415, + "y": -192.98307299510117, + "z": 1.0 + }, + { + "x": 334.78299303476956, + "y": -193.58589339795952, + "z": 1.0 + }, + { + "x": 334.782628924595, + "y": -194.1887138008168, + "z": 1.0 + }, + { + "x": 334.7823861844786, + "y": -194.59059406938712, + "z": 1.0 + }, + { + "x": 334.7821434443622, + "y": -194.99247433795864, + "z": 1.0 + }, + { + "x": 334.7819007042457, + "y": -195.3943546065313, + "z": 1.0 + }, + { + "x": 334.7816579641293, + "y": -195.79623487510275, + "z": 1.0 + }, + { + "x": 334.7812938539547, + "y": -196.39905527795884, + "z": 1.0 + }, + { + "x": 334.7810511138383, + "y": -196.8009355465315, + "z": 1.0 + }, + { + "x": 334.78068700366373, + "y": -197.4037559493887, + "z": 1.0 + }, + { + "x": 334.78032289348914, + "y": -198.00657635224485, + "z": 1.0 + }, + { + "x": 334.78001946834354, + "y": -198.50892668796035, + "z": 1.0 + }, + { + "x": 334.77965535816895, + "y": -199.11174709081644, + "z": 1.0 + }, + { + "x": 334.77941261805256, + "y": -199.51362735938795, + "z": 1.0 + }, + { + "x": 334.7791091929071, + "y": -200.01597769510346, + "z": 1.0 + }, + { + "x": 334.7788057677616, + "y": -200.51832803081783, + "z": 1.0 + }, + { + "x": 334.7784416575869, + "y": -201.12114843367505, + "z": 1.0 + }, + { + "x": 334.7781382324414, + "y": -201.6234987693894, + "z": 1.0 + }, + { + "x": 334.7777741222668, + "y": -202.2263191722467, + "z": 1.0 + }, + { + "x": 334.7774100120922, + "y": -202.8291395751039, + "z": 1.0 + }, + { + "x": 334.77704590191763, + "y": -203.43195997796113, + "z": 1.0 + }, + { + "x": 334.77674247677214, + "y": -203.93431031367436, + "z": 1.0 + }, + { + "x": 334.77637836659744, + "y": -204.53713071653277, + "z": 1.0 + }, + { + "x": 334.77601425642285, + "y": -205.13995111939, + "z": 1.0 + }, + { + "x": 334.77571083127737, + "y": -205.64230145510322, + "z": 1.0 + }, + { + "x": 334.7754074061319, + "y": -206.14465179081873, + "z": 1.0 + }, + { + "x": 334.7751039809864, + "y": -206.6470021265331, + "z": 1.0 + }, + { + "x": 334.7747398708117, + "y": -207.24982252939145, + "z": 1.0 + }, + { + "x": 334.7744364456662, + "y": -207.75217286510355, + "z": 1.0 + }, + { + "x": 334.7740723354916, + "y": -208.35499326796304, + "z": 1.0 + }, + { + "x": 334.7737689103461, + "y": -208.85734360367633, + "z": 1.0 + }, + { + "x": 334.7735868552588, + "y": -209.15875380510494, + "z": 1.0 + }, + { + "x": 334.77322414725745, + "y": -209.7592527713511, + "z": 1.0 + }, + { + "x": 334.77298234192335, + "y": -210.1595854155138, + "z": 1.0 + }, + { + "x": 334.77274053658914, + "y": -210.55991805967767, + "z": 1.0 + }, + { + "x": 334.7724987312549, + "y": -210.96025070384263, + "z": 1.0 + }, + { + "x": 334.7722569259207, + "y": -211.36058334800651, + "z": 1.0 + }, + { + "x": 334.77189421791945, + "y": -211.96108231425114, + "z": 1.0 + }, + { + "x": 334.7715315099182, + "y": -212.56158128049805, + "z": 1.0 + }, + { + "x": 334.771289704584, + "y": -212.96191392466193, + "z": 1.0 + }, + { + "x": 334.77098744791624, + "y": -213.46232972986672, + "z": 1.0 + }, + { + "x": 334.770745642582, + "y": -213.8626623740306, + "z": 1.0 + }, + { + "x": 334.7704433859144, + "y": -214.3630781792354, + "z": 1.0 + }, + { + "x": 334.77014112924667, + "y": -214.86349398443912, + "z": 1.0 + }, + { + "x": 334.76983887257893, + "y": -215.3639097896439, + "z": 1.0 + }, + { + "x": 334.7695366159111, + "y": -215.8643255948499, + "z": 1.0 + }, + { + "x": 334.76917390790993, + "y": -216.46482456109453, + "z": 1.0 + }, + { + "x": 334.7689321025757, + "y": -216.86515720525836, + "z": 1.0 + }, + { + "x": 334.768629845908, + "y": -217.3655730104632, + "z": 1.0 + }, + { + "x": 334.76832758924013, + "y": -217.86598881566914, + "z": 1.0 + }, + { + "x": 334.76808578390603, + "y": -218.2663214598319, + "z": 1.0 + }, + { + "x": 334.76772307590477, + "y": -218.8668204260788, + "z": 1.0 + }, + { + "x": 334.76742081923703, + "y": -219.3672362312825, + "z": 1.0 + }, + { + "x": 334.7671790139028, + "y": -219.76756887544747, + "z": 1.0 + }, + { + "x": 334.7669372085686, + "y": -220.16790151961135, + "z": 1.0 + }, + { + "x": 334.76657450056734, + "y": -220.76840048585598, + "z": 1.0 + }, + { + "x": 334.76633269523313, + "y": -221.1687331300198, + "z": 1.0 + }, + { + "x": 334.7660908898989, + "y": -221.56906577418482, + "z": 1.0 + }, + { + "x": 334.7657886332312, + "y": -222.06948157938962, + "z": 1.0 + }, + { + "x": 334.7654259252299, + "y": -222.66998054563544, + "z": 1.0 + }, + { + "x": 334.76506321722866, + "y": -223.27047951188007, + "z": 1.0 + }, + { + "x": 334.7647609605609, + "y": -223.770895317086, + "z": 1.0 + }, + { + "x": 334.7645191552267, + "y": -224.17122796124988, + "z": 1.0 + }, + { + "x": 334.76415644722545, + "y": -224.7717269274945, + "z": 1.0 + }, + { + "x": 334.76391464189123, + "y": -225.17205957165953, + "z": 1.0 + }, + { + "x": 334.76355193388997, + "y": -225.77255853790416, + "z": 1.0 + }, + { + "x": 334.7633101285559, + "y": -226.17289118206799, + "z": 1.0 + }, + { + "x": 334.76306832322166, + "y": -226.573223826233, + "z": 1.0 + }, + { + "x": 334.7627660665539, + "y": -227.07363963143666, + "z": 1.0 + }, + { + "x": 334.7624638098862, + "y": -227.57405543664146, + "z": 1.0 + }, + { + "x": 334.7621011018849, + "y": -228.17455440288722, + "z": 1.0 + }, + { + "x": 334.76173839388355, + "y": -228.77505336913418, + "z": 1.0 + }, + { + "x": 334.7613756858823, + "y": -229.3755523353788, + "z": 1.0 + }, + { + "x": 334.7611338805481, + "y": -229.77588497954264, + "z": 1.0 + }, + { + "x": 334.760892075214, + "y": -230.17621762370766, + "z": 1.0 + }, + { + "x": 334.76065026987976, + "y": -230.57655026787148, + "z": 1.0 + }, + { + "x": 334.760348013212, + "y": -231.07696607307628, + "z": 1.0 + }, + { + "x": 334.7601062078778, + "y": -231.47729871724016, + "z": 1.0 + }, + { + "x": 334.7598644025436, + "y": -231.87763136140285, + "z": 1.0 + }, + { + "x": 334.7596225972095, + "y": -232.27796400556667, + "z": 1.0 + }, + { + "x": 334.7593807918753, + "y": -232.6782966497317, + "z": 1.0 + }, + { + "x": 334.7590180838739, + "y": -233.27879561597746, + "z": 1.0 + }, + { + "x": 334.7587762785398, + "y": -233.67912826014015, + "z": 1.0 + }, + { + "x": 334.7584740218721, + "y": -234.17954406534614, + "z": 1.0 + }, + { + "x": 334.7581113138708, + "y": -234.78004303159076, + "z": 1.0 + }, + { + "x": 334.75780905720296, + "y": -235.2804588367967, + "z": 1.0 + }, + { + "x": 334.75756725186886, + "y": -235.68079148095939, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 26, + "heading": [ + -1.5714003377550525, + -1.5714003377552381, + -1.5714003377551264, + -1.5714003377550139, + -1.5714003377550139, + -1.5714003377550132, + -1.5714003377550128, + -1.5714003377550139, + -1.571400337755014, + -1.5714003377551538, + -1.5714003377551538, + -1.5714003377550139, + -1.5714003377550132, + -1.5714003377550125, + -1.5714003377550139, + -1.571400337755116, + -1.5714003377551162, + -1.5714003377550139, + -1.5714003377550125, + -1.5714003377550125, + -1.5714003377551162, + -1.5714003377551162, + -1.5714003377550132, + -1.5714003377550132, + -1.5714003377550132, + -1.5714003377550139, + -1.571400337755116, + -1.571400337755107, + -1.5714003377550139, + -1.5714003377550132, + -1.5714003377550125, + -1.5714003377551156, + -1.5714003377551167, + -1.5714003377550132, + -1.5714003377550125, + -1.571400337755014, + -1.5714003377551413, + -1.571400337755055, + -1.5714003377549701, + -1.5714003377551105, + -1.5714003377551105, + -1.5714003377550552, + -1.5714003377550168, + -1.5714003377550538, + -1.5714003377550798, + -1.5714003377550798, + -1.5714003377549535, + -1.5714003377549417, + -1.5714003377550552, + -1.5714003377551675, + -1.5714003377550338, + -1.5714003377549417, + -1.5714003377550798, + -1.5714003377551675, + -1.5714003377550798, + -1.571400337754941, + -1.5714003377550338, + -1.5714003377550798, + -1.5714003377551105, + -1.5714003377550552, + -1.5714003377550552, + -1.5714003377551105, + -1.571400337755079, + -1.5714003377550338, + -1.5714003377550172, + -1.5714003377550338, + -1.571400337755079, + -1.5714003377550552, + -1.5714003377550545, + -1.5714003377550545, + -1.5714003377549417, + -1.5714003377549686, + -1.5714003377550798, + -1.5714003377550552, + -1.5714003377550338, + -1.5714003377551107, + -1.5714003377551113, + -1.5714003377550552, + -1.5714003377549686, + -1.5714003377549686, + -1.5714003377550798, + -1.5714003377550798, + -1.5714003377551122, + -1.5714003377549701, + -1.5714003377549686, + -1.5714003377551675, + -1.5714003377550552, + -1.5714003377549535, + -1.5714003377550338, + -1.571400337755137, + -1.5714003377550798 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -0.003034251456028869, + "y": -5.02350335715505 + }, + { + "x": -0.00606850291092087, + "y": -10.047006714287363 + }, + { + "x": -0.006675353200762402, + "y": -11.051707385704503 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714275994 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714287363 + }, + { + "x": -0.007282203491740802, + "y": -12.056408057156318 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714275994 + }, + { + "x": -0.004854802327827201, + "y": -8.037605371418408 + }, + { + "x": -0.00485480232896407, + "y": -8.037605371441714 + }, + { + "x": -0.00485480232896407, + "y": -8.037605371441146 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714275426 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714287363 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714298732 + }, + { + "x": -0.007282203491740802, + "y": -12.05640805713358 + }, + { + "x": -0.00667535320189927, + "y": -11.05170738571644 + }, + { + "x": -0.00667535320189927, + "y": -11.051707385715872 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714275994 + }, + { + "x": -0.005461652618805601, + "y": -9.042306042870223 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714298732 + }, + { + "x": -0.00667535320189927, + "y": -11.051707385715872 + }, + { + "x": -0.00667535320189927, + "y": -11.051707385715872 + }, + { + "x": -0.006675353200762402, + "y": -11.05170738571644 + }, + { + "x": -0.007282203491740802, + "y": -12.05640805714495 + }, + { + "x": -0.007282203491740802, + "y": -12.056408057144381 + }, + { + "x": -0.006675353200762402, + "y": -11.051707385704503 + }, + { + "x": -0.00667535320189927, + "y": -11.05170738571644 + }, + { + "x": -0.00728220349287767, + "y": -12.056408057156318 + }, + { + "x": -0.006675353200762402, + "y": -11.051707385704503 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714287363 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714298732 + }, + { + "x": -0.00667535320189927, + "y": -11.05170738572724 + }, + { + "x": -0.00667535320189927, + "y": -11.051707385704503 + }, + { + "x": -0.006675353200762402, + "y": -11.051707385715872 + }, + { + "x": -0.006675353200762402, + "y": -11.05170738572781 + }, + { + "x": -0.004854802327827201, + "y": -8.037605371418977 + }, + { + "x": -0.005447630886692423, + "y": -9.019091676747735 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104088522 + }, + { + "x": -0.004836106683114849, + "y": -8.006652883265701 + }, + { + "x": -0.0048361066842517175, + "y": -8.006652883288439 + }, + { + "x": -0.0048361066842517175, + "y": -8.006652883288439 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104085111 + }, + { + "x": -0.007254160025240708, + "y": -12.00997932491532 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104107848 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686775 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686775 + }, + { + "x": -0.005440620018362097, + "y": -9.007484493686775 + }, + { + "x": -0.006045133353609344, + "y": -10.008316104085111 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104085111 + }, + { + "x": -0.006045133355883081, + "y": -10.008316104107848 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714506184 + }, + { + "x": -0.006045133353609344, + "y": -10.008316104084543 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686775 + }, + { + "x": -0.006045133355883081, + "y": -10.008316104107848 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686775 + }, + { + "x": -0.006045133353609344, + "y": -10.00831610409648 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714506184 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686775 + }, + { + "x": -0.0048361066842517175, + "y": -8.006652883288439 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104085111 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104084543 + }, + { + "x": -0.0048361066842517175, + "y": -8.006652883288439 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493698144 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714506184 + }, + { + "x": -0.007254160025240708, + "y": -12.00997932490452 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714505616 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493698144 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104085111 + }, + { + "x": -0.006045133354746213, + "y": -10.00831610409648 + }, + { + "x": -0.006045133354746213, + "y": -10.00831610409648 + }, + { + "x": -0.006045133353609344, + "y": -10.008316104084543 + }, + { + "x": -0.004836106683114849, + "y": -8.006652883288439 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686775 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104084543 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714505616 + }, + { + "x": -0.007254160026377576, + "y": -12.009979324927258 + }, + { + "x": -0.007254160026377576, + "y": -12.00997932491589 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104084543 + }, + { + "x": -0.004836106683114849, + "y": -8.006652883288439 + }, + { + "x": -0.004836106683114849, + "y": -8.006652883288439 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686206 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686775 + }, + { + "x": -0.0048361066842517175, + "y": -8.006652883265701 + }, + { + "x": -0.004836106683114849, + "y": -8.006652883265133 + }, + { + "x": -0.004836106683114849, + "y": -8.006652883288439 + }, + { + "x": -0.006045133355883081, + "y": -10.008316104107848 + }, + { + "x": -0.006045133354746213, + "y": -10.008316104084543 + }, + { + "x": -0.005440620018362097, + "y": -9.007484493686775 + }, + { + "x": -0.00664964668999346, + "y": -11.009147714506184 + }, + { + "x": -0.006649646691130329, + "y": -11.009147714505616 + }, + { + "x": -0.005440620019498965, + "y": -9.007484493686206 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 334.75756725186886, + "y": -235.68079148095939, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 329.263169991849, + "y": 1.9436457072073068, + "z": 1.0 + }, + { + "x": 328.7804214359283, + "y": 1.9852061222393989, + "z": 1.0 + }, + { + "x": 328.29636526433956, + "y": 2.0067022980379825, + "z": 1.0 + }, + { + "x": 327.63924552920065, + "y": 2.010254613561665, + "z": 1.0 + }, + { + "x": 327.2376770785852, + "y": 2.0104679414741553, + "z": 1.0 + }, + { + "x": 326.635324402662, + "y": 2.010787933342891, + "z": 1.0 + }, + { + "x": 326.03297172673877, + "y": 2.011107925211627, + "z": 1.0 + }, + { + "x": 325.6314032761233, + "y": 2.0113212531241174, + "z": 1.0 + }, + { + "x": 325.6314032761233, + "y": 2.0113212531241174, + "z": 1.0 + }, + { + "x": 325.2306859929232, + "y": 2.0115341288652, + "z": 1.0 + }, + { + "x": 324.63011428605995, + "y": 2.0118531746177477, + "z": 1.0 + }, + { + "x": 324.2297331481511, + "y": 2.012065871786113, + "z": 1.0 + }, + { + "x": 323.7292567257651, + "y": 2.0123317432465693, + "z": 1.0 + }, + { + "x": 323.22878030337904, + "y": 2.0125976147070257, + "z": 1.0 + }, + { + "x": 322.8283991654702, + "y": 2.0128103118753917, + "z": 1.0 + }, + { + "x": 322.227827458607, + "y": 2.0131293576279394, + "z": 1.0 + }, + { + "x": 321.8274463206982, + "y": 2.0133420547963046, + "z": 1.0 + }, + { + "x": 321.42706518278936, + "y": 2.0135547519646697, + "z": 1.0 + }, + { + "x": 320.9265887604033, + "y": 2.013820623425126, + "z": 1.0 + }, + { + "x": 320.32601705354006, + "y": 2.014139669177674, + "z": 1.0 + }, + { + "x": 319.825540631154, + "y": 2.0144055406381303, + "z": 1.0 + }, + { + "x": 319.4251594932452, + "y": 2.0146182378064954, + "z": 1.0 + }, + { + "x": 319.02477835533637, + "y": 2.0148309349748605, + "z": 1.0 + }, + { + "x": 318.5243019329503, + "y": 2.015096806435317, + "z": 1.0 + }, + { + "x": 318.1239207950415, + "y": 2.015309503603683, + "z": 1.0 + }, + { + "x": 317.62344437265546, + "y": 2.0155753750641394, + "z": 1.0 + }, + { + "x": 317.1229679502694, + "y": 2.015841246524596, + "z": 1.0 + }, + { + "x": 316.62249152788337, + "y": 2.0161071179850523, + "z": 1.0 + }, + { + "x": 316.1220151054973, + "y": 2.0163729894455087, + "z": 1.0 + }, + { + "x": 315.62153868311134, + "y": 2.016638860905965, + "z": 1.0 + }, + { + "x": 315.1210622607253, + "y": 2.0169047323664215, + "z": 1.0 + }, + { + "x": 314.62058583833925, + "y": 2.017170603826878, + "z": 1.0 + }, + { + "x": 314.020014131476, + "y": 2.0174896495794266, + "z": 1.0 + }, + { + "x": 313.51953770908995, + "y": 2.017755521039883, + "z": 1.0 + }, + { + "x": 313.01906128670396, + "y": 2.0180213925003394, + "z": 1.0 + }, + { + "x": 312.5185848643179, + "y": 2.018287263960796, + "z": 1.0 + }, + { + "x": 312.1182037264091, + "y": 2.018499961129161, + "z": 1.0 + }, + { + "x": 311.51763201954583, + "y": 2.0188190068817087, + "z": 1.0 + }, + { + "x": 311.117250881637, + "y": 2.019031704050074, + "z": 1.0 + }, + { + "x": 310.61677445925096, + "y": 2.0192975755105302, + "z": 1.0 + }, + { + "x": 310.1162980368649, + "y": 2.0195634469709867, + "z": 1.0 + }, + { + "x": 309.51572633000166, + "y": 2.0198824927235353, + "z": 1.0 + }, + { + "x": 309.11534519209283, + "y": 2.0200951898919004, + "z": 1.0 + }, + { + "x": 308.5147734852296, + "y": 2.020414235644448, + "z": 1.0 + }, + { + "x": 308.1143923473208, + "y": 2.0206269328128132, + "z": 1.0 + }, + { + "x": 307.7140112094119, + "y": 2.0208396299811784, + "z": 1.0 + }, + { + "x": 307.3136300715031, + "y": 2.0210523271495435, + "z": 1.0 + }, + { + "x": 306.7130583646399, + "y": 2.0213713729020912, + "z": 1.0 + }, + { + "x": 306.1124866577766, + "y": 2.021690418654639, + "z": 1.0 + }, + { + "x": 305.6120102353906, + "y": 2.0219562901150954, + "z": 1.0 + }, + { + "x": 305.11153381300454, + "y": 2.0222221615755527, + "z": 1.0 + }, + { + "x": 304.7111526750957, + "y": 2.022434858743918, + "z": 1.0 + }, + { + "x": 304.2106762527097, + "y": 2.0227007302043742, + "z": 1.0 + }, + { + "x": 303.7101998303237, + "y": 2.0229666016648307, + "z": 1.0 + }, + { + "x": 303.20972340793764, + "y": 2.023232473125287, + "z": 1.0 + }, + { + "x": 302.6091517010744, + "y": 2.023551518877835, + "z": 1.0 + }, + { + "x": 302.20877056316556, + "y": 2.0237642160462, + "z": 1.0 + }, + { + "x": 301.6081988563023, + "y": 2.0240832617987476, + "z": 1.0 + }, + { + "x": 301.10772243391625, + "y": 2.024349133259204, + "z": 1.0 + }, + { + "x": 300.7073412960074, + "y": 2.02456183042757, + "z": 1.0 + }, + { + "x": 300.1067695891442, + "y": 2.024880876180118, + "z": 1.0 + }, + { + "x": 299.6062931667582, + "y": 2.0251467476405742, + "z": 1.0 + }, + { + "x": 299.20591202884935, + "y": 2.0253594448089394, + "z": 1.0 + }, + { + "x": 298.7054356064633, + "y": 2.025625316269396, + "z": 1.0 + }, + { + "x": 298.10486389960005, + "y": 2.0259443620219435, + "z": 1.0 + }, + { + "x": 297.7044827616912, + "y": 2.0261570591903086, + "z": 1.0 + }, + { + "x": 297.2040063393052, + "y": 2.026422930650765, + "z": 1.0 + }, + { + "x": 296.80362520139636, + "y": 2.02663562781913, + "z": 1.0 + }, + { + "x": 296.3031487790103, + "y": 2.0269014992795875, + "z": 1.0 + }, + { + "x": 295.7025770721471, + "y": 2.0272205450321352, + "z": 1.0 + }, + { + "x": 295.10200536528384, + "y": 2.027539590784683, + "z": 1.0 + }, + { + "x": 294.5014336584206, + "y": 2.0278586365372306, + "z": 1.0 + }, + { + "x": 293.9008619515574, + "y": 2.0281776822897783, + "z": 1.0 + }, + { + "x": 293.50048081364855, + "y": 2.0283903794581435, + "z": 1.0 + }, + { + "x": 293.1000996757397, + "y": 2.0286030766265086, + "z": 1.0 + }, + { + "x": 292.6997185378309, + "y": 2.0288157737948738, + "z": 1.0 + }, + { + "x": 292.19924211544486, + "y": 2.02908164525533, + "z": 1.0 + }, + { + "x": 291.7988609775361, + "y": 2.0292943424236953, + "z": 1.0 + }, + { + "x": 291.19828927067283, + "y": 2.029613388176244, + "z": 1.0 + }, + { + "x": 290.797908132764, + "y": 2.029826085344609, + "z": 1.0 + }, + { + "x": 290.2965826672941, + "y": 2.030018519555301, + "z": 1.0 + }, + { + "x": 289.6960108791071, + "y": 2.0300826181407468, + "z": 1.0 + }, + { + "x": 289.2956296869824, + "y": 2.030125350531044, + "z": 1.0 + }, + { + "x": 288.69505789879537, + "y": 2.03018944911649, + "z": 1.0 + }, + { + "x": 288.09448611060833, + "y": 2.0302535477019354, + "z": 1.0 + }, + { + "x": 287.6941049184836, + "y": 2.030296280092233, + "z": 1.0 + }, + { + "x": 287.29372372635896, + "y": 2.0303390124825302, + "z": 1.0 + }, + { + "x": 286.6931519381719, + "y": 2.030403111067976, + "z": 1.0 + }, + { + "x": 286.0925801499849, + "y": 2.0304672096534215, + "z": 1.0 + }, + { + "x": 285.592103659829, + "y": 2.0305206251412926, + "z": 1.0 + }, + { + "x": 285.09162716967313, + "y": 2.0305740406291646, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 27, + "heading": [ + 3.1391704606677107, + 3.0557131807973996, + 3.0764632585844023, + 3.1196464578883, + 3.138035772908013, + 3.141061416905, + 3.141061416905, + 3.141061416905, + 3.141061416905, + 3.141061416905023, + 3.1410614169050093, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049986, + 3.1410614169049986, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049986, + 3.1410614169049986, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.141061416904999, + 3.141061416904999, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.141061416904999, + 3.1410614169049986, + 3.1410614169049995, + 3.1410614169049995, + 3.141061416905, + 3.141061416905, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049986, + 3.1410614169049986, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049986, + 3.1410614169049986, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049986, + 3.141061416904999, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049995, + 3.1410614169049986, + 3.1410614169049986, + 3.141143359606275, + 3.1413598435064105, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253437, + 3.1414859243253432, + 3.1414859243253437, + 3.1414859243253437, + 3.141485924325344, + 3.1414859243253437 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -4.827485559206934, + "y": 0.4156041503209207 + }, + { + "x": -9.668047275094409, + "y": 0.6305659083067572 + }, + { + "x": -11.411759067276535, + "y": 0.2504849132226594 + }, + { + "x": -10.58688185754363, + "y": 0.03765643436172805 + }, + { + "x": -10.039211265386712, + "y": 0.005333197812262824 + }, + { + "x": -12.047053518464281, + "y": 0.006399837374715389 + }, + { + "x": -10.039211265386712, + "y": 0.005333197812262824 + }, + { + "x": -4.015684506154571, + "y": 0.0021332791249051297 + }, + { + "x": -4.007172832000947, + "y": 0.0021287574108264096 + }, + { + "x": -10.012889900633581, + "y": 0.005319214936303496 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209128477 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288215629 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209128477 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288224511 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209137359 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209128477 + }, + { + "x": -8.007622758176467, + "y": 0.0042539433673027816 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288215629 + }, + { + "x": -11.010481292493068, + "y": 0.005849172130041325 + }, + { + "x": -11.010481292493068, + "y": 0.005849172130041325 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288215629 + }, + { + "x": -8.007622758176467, + "y": 0.0042539433673027816 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288215629 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288224511 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288224511 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209128477 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209128477 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209128477 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209128477 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209128477 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209128477 + }, + { + "x": -11.010481292493068, + "y": 0.005849172130050206 + }, + { + "x": -11.010481292493068, + "y": 0.005849172130050206 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209128477 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209128477 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288215629 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209128477 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209128477 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288215629 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209128477 + }, + { + "x": -11.010481292493068, + "y": 0.005849172130050206 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209137359 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209128477 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209128477 + }, + { + "x": -8.007622758177035, + "y": 0.0042539433673027816 + }, + { + "x": -8.007622758177035, + "y": 0.0042539433673027816 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209128477 + }, + { + "x": -12.0114341372647, + "y": 0.006380915050954172 + }, + { + "x": -11.010481292493068, + "y": 0.005849172130041325 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209137359 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288224511 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288215629 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209128477 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209128477 + }, + { + "x": -11.010481292493068, + "y": 0.005849172130041325 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209128477 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209128477 + }, + { + "x": -11.010481292493068, + "y": 0.005849172130041325 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288224511 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209137359 + }, + { + "x": -11.0104812924925, + "y": 0.005849172130041325 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288215629 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288215629 + }, + { + "x": -11.010481292493068, + "y": 0.005849172130041325 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209128477 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288215629 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288215629 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288224511 + }, + { + "x": -11.0104812924925, + "y": 0.005849172130050206 + }, + { + "x": -12.0114341372647, + "y": 0.006380915050954172 + }, + { + "x": -12.011434137265269, + "y": 0.006380915050954172 + }, + { + "x": -12.0114341372647, + "y": 0.006380915050954172 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209128477 + }, + { + "x": -8.007622758176467, + "y": 0.0042539433673027816 + }, + { + "x": -8.007622758176467, + "y": 0.0042539433673027816 + }, + { + "x": -9.008575602948667, + "y": 0.004785686288215629 + }, + { + "x": -9.008575602948099, + "y": 0.004785686288215629 + }, + { + "x": -10.0095284477203, + "y": 0.005317429209137359 + }, + { + "x": -10.009528447720868, + "y": 0.005317429209137359 + }, + { + "x": -9.017066033787273, + "y": 0.0040513137905717755 + }, + { + "x": -11.018972536568867, + "y": 0.002565327961376873 + }, + { + "x": -10.009529803116948, + "y": 0.0010683097574304412 + }, + { + "x": -10.009529803117516, + "y": 0.0010683097574304412 + }, + { + "x": -12.011435763740792, + "y": 0.0012819717089129767 + }, + { + "x": -10.009529803117516, + "y": 0.0010683097574304412 + }, + { + "x": -8.007623842493672, + "y": 0.0008546478059479057 + }, + { + "x": -10.009529803116948, + "y": 0.0010683097574304412 + }, + { + "x": -12.011435763740792, + "y": 0.0012819717089129767 + }, + { + "x": -11.010482783429438, + "y": 0.001175140733167268 + }, + { + "x": -10.009529803117516, + "y": 0.0010683097574304412 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 285.09162716967313, + "y": 2.0305740406291646, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 104.12054777946341, + "y": -133.416111777875, + "z": 1.0 + }, + { + "x": 104.62081546714708, + "y": -133.4163352943318, + "z": 1.0 + }, + { + "x": 105.22113669236818, + "y": -133.41660351407995, + "z": 1.0 + }, + { + "x": 105.62135084251558, + "y": -133.41678232724541, + "z": 1.0 + }, + { + "x": 106.22167206773668, + "y": -133.41705054699358, + "z": 1.0 + }, + { + "x": 106.82199329295777, + "y": -133.41731876674174, + "z": 1.0 + }, + { + "x": 107.22220744310516, + "y": -133.4174975799072, + "z": 1.0 + }, + { + "x": 107.62242159325257, + "y": -133.41767639307264, + "z": 1.0 + }, + { + "x": 108.02263574339996, + "y": -133.4178552062381, + "z": 1.0 + }, + { + "x": 108.52290343108422, + "y": -133.4180787226949, + "z": 1.0 + }, + { + "x": 109.12322465630531, + "y": -133.41834694244307, + "z": 1.0 + }, + { + "x": 109.5234388064527, + "y": -133.41852575560853, + "z": 1.0 + }, + { + "x": 110.02370649413696, + "y": -133.41874927206533, + "z": 1.0 + }, + { + "x": 110.52397418182177, + "y": -133.41897278852215, + "z": 1.0 + }, + { + "x": 111.02424186950545, + "y": -133.41919630497895, + "z": 1.0 + }, + { + "x": 111.42445601965285, + "y": -133.4193751181444, + "z": 1.0 + }, + { + "x": 111.9247237073371, + "y": -133.41959863460121, + "z": 1.0 + }, + { + "x": 112.52504493255819, + "y": -133.41986685434938, + "z": 1.0 + }, + { + "x": 113.1253661577793, + "y": -133.42013507409754, + "z": 1.0 + }, + { + "x": 113.52558030792669, + "y": -133.420313887263, + "z": 1.0 + }, + { + "x": 114.02584799561093, + "y": -133.4205374037198, + "z": 1.0 + }, + { + "x": 114.52611568329576, + "y": -133.42076092017663, + "z": 1.0 + }, + { + "x": 115.02638337097943, + "y": -133.42098443663343, + "z": 1.0 + }, + { + "x": 115.52665105866369, + "y": -133.42120795309023, + "z": 1.0 + }, + { + "x": 115.92686520881108, + "y": -133.4213867662557, + "z": 1.0 + }, + { + "x": 116.52718643403217, + "y": -133.42165498600386, + "z": 1.0 + }, + { + "x": 116.92740058418013, + "y": -133.42183379916932, + "z": 1.0 + }, + { + "x": 117.32761473432697, + "y": -133.42201261233475, + "z": 1.0 + }, + { + "x": 117.92793595954807, + "y": -133.42228083208292, + "z": 1.0 + }, + { + "x": 118.52825718476973, + "y": -133.4225490518311, + "z": 1.0 + }, + { + "x": 119.0285248724534, + "y": -133.4227725682879, + "z": 1.0 + }, + { + "x": 119.62884609767448, + "y": -133.42304078803608, + "z": 1.0 + }, + { + "x": 120.22916732289558, + "y": -133.42330900778424, + "z": 1.0 + }, + { + "x": 120.72943501057982, + "y": -133.42353252424107, + "z": 1.0 + }, + { + "x": 121.32975623580091, + "y": -133.42380074398923, + "z": 1.0 + }, + { + "x": 121.83002392348516, + "y": -133.42402426044603, + "z": 1.0 + }, + { + "x": 122.3302916111694, + "y": -133.42424777690286, + "z": 1.0 + }, + { + "x": 122.83055929885364, + "y": -133.42447129335966, + "z": 1.0 + }, + { + "x": 123.43088052407474, + "y": -133.42473951310782, + "z": 1.0 + }, + { + "x": 123.93114821175898, + "y": -133.42496302956465, + "z": 1.0 + }, + { + "x": 124.43141589944322, + "y": -133.42518654602145, + "z": 1.0 + }, + { + "x": 124.83163004959118, + "y": -133.4253653591869, + "z": 1.0 + }, + { + "x": 125.33189773727486, + "y": -133.4255888756437, + "z": 1.0 + }, + { + "x": 125.73211188742226, + "y": -133.42576768880915, + "z": 1.0 + }, + { + "x": 126.2323795751065, + "y": -133.42599120526597, + "z": 1.0 + }, + { + "x": 126.73264726279075, + "y": -133.42621472172277, + "z": 1.0 + }, + { + "x": 127.33296848801184, + "y": -133.42648294147094, + "z": 1.0 + }, + { + "x": 127.93328971323294, + "y": -133.42675116121913, + "z": 1.0 + }, + { + "x": 128.33350386338032, + "y": -133.42692997438456, + "z": 1.0 + }, + { + "x": 128.83377155106513, + "y": -133.4271534908414, + "z": 1.0 + }, + { + "x": 129.43409277628567, + "y": -133.42742171058956, + "z": 1.0 + }, + { + "x": 130.03441400150675, + "y": -133.42768993033772, + "z": 1.0 + }, + { + "x": 130.534681689191, + "y": -133.42791344679452, + "z": 1.0 + }, + { + "x": 131.1350029144121, + "y": -133.4281816665427, + "z": 1.0 + }, + { + "x": 131.53521706455948, + "y": -133.42836047970815, + "z": 1.0 + }, + { + "x": 132.13553828978058, + "y": -133.4286286994563, + "z": 1.0 + }, + { + "x": 132.73585951500166, + "y": -133.4288969192045, + "z": 1.0 + }, + { + "x": 133.2361272026859, + "y": -133.4291204356613, + "z": 1.0 + }, + { + "x": 133.83644842790702, + "y": -133.42938865540947, + "z": 1.0 + }, + { + "x": 134.23666257805442, + "y": -133.42956746857493, + "z": 1.0 + }, + { + "x": 134.7369302657387, + "y": -133.42979098503173, + "z": 1.0 + }, + { + "x": 135.3372514909598, + "y": -133.4300592047799, + "z": 1.0 + }, + { + "x": 135.7374656411072, + "y": -133.43023801794536, + "z": 1.0 + }, + { + "x": 136.33778686632832, + "y": -133.43050623769352, + "z": 1.0 + }, + { + "x": 136.8380545540126, + "y": -133.43072975415032, + "z": 1.0 + }, + { + "x": 137.33832224169683, + "y": -133.43095327060715, + "z": 1.0 + }, + { + "x": 137.8385899293811, + "y": -133.43117678706395, + "z": 1.0 + }, + { + "x": 138.2388040795285, + "y": -133.4313556002294, + "z": 1.0 + }, + { + "x": 138.73907176721278, + "y": -133.4315791166862, + "z": 1.0 + }, + { + "x": 139.13928591736075, + "y": -133.43175792985167, + "z": 1.0 + }, + { + "x": 139.63955360504445, + "y": -133.43198144630847, + "z": 1.0 + }, + { + "x": 140.03976775519186, + "y": -133.4321602594739, + "z": 1.0 + }, + { + "x": 140.43998190533927, + "y": -133.43233907263937, + "z": 1.0 + }, + { + "x": 140.94024959302354, + "y": -133.43256258909616, + "z": 1.0 + }, + { + "x": 141.34046374317094, + "y": -133.43274140226163, + "z": 1.0 + }, + { + "x": 141.74067789331835, + "y": -133.43292021542706, + "z": 1.0 + }, + { + "x": 142.2409455810026, + "y": -133.4331437318839, + "z": 1.0 + }, + { + "x": 142.64115973115, + "y": -133.43332254504932, + "z": 1.0 + }, + { + "x": 143.14142741883484, + "y": -133.43354606150615, + "z": 1.0 + }, + { + "x": 143.64169510651854, + "y": -133.43376957796295, + "z": 1.0 + }, + { + "x": 144.24201633173965, + "y": -133.4340377977111, + "z": 1.0 + }, + { + "x": 144.7422840194245, + "y": -133.43426131416794, + "z": 1.0 + }, + { + "x": 145.14249816957133, + "y": -133.43444012733337, + "z": 1.0 + }, + { + "x": 145.74281939479243, + "y": -133.43470834708154, + "z": 1.0 + }, + { + "x": 146.2430870824767, + "y": -133.43493186353837, + "z": 1.0 + }, + { + "x": 146.74335477016095, + "y": -133.43515537999517, + "z": 1.0 + }, + { + "x": 147.14356892030892, + "y": -133.43533419316063, + "z": 1.0 + }, + { + "x": 147.54378307045576, + "y": -133.43551300632606, + "z": 1.0 + }, + { + "x": 148.04405075814003, + "y": -133.43573652278286, + "z": 1.0 + }, + { + "x": 148.44426490828744, + "y": -133.43591533594832, + "z": 1.0 + }, + { + "x": 148.9445325959717, + "y": -133.43613885240512, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 28, + "heading": [ + -0.0004467936815410096, + -0.00044679368152074914, + -0.0004467936815256359, + -0.0004467936815486416, + -0.0004467936815486416, + -0.0004467936815297082, + -0.00044679368154864794, + -0.0004467936815415416, + -0.0004467936815415416, + -0.000446793681545486, + -0.00044679368152539934, + -0.00044679368154864794, + -0.000446793681545486, + -0.0004467936815483878, + -0.00044679368154864794, + -0.00044679368151420533, + -0.000446793681545486, + -0.0004467936815512292, + -0.0004467936815297029, + -0.0004467936815486416, + -0.00044679368154549307, + -0.0004467936815483878, + -0.0004467936815486416, + -0.00044679368152048893, + -0.000446793681545486, + -0.00044679368154864794, + -0.0004467936815483941, + -0.0004467936815415416, + -0.00044679368152048893, + -0.00044679368155316874, + -0.0004467936815512292, + -0.00044679368152564166, + -0.0004467936815297135, + -0.0004467936815512292, + -0.0004467936815512292, + -0.00044679368152540514, + -0.00044679368154864794, + -0.00044679368154864794, + -0.00044679368152540514, + -0.0004467936815512292, + -0.00044679368154864794, + -0.00044679368154521107, + -0.00044679368154549307, + -0.00044679368151420533, + -0.000446793681545486, + -0.00044679368154864794, + -0.00044679368152540514, + -0.00044679368155338026, + -0.0004467936815486543, + -0.0004467936815452181, + -0.00044679368155122346, + -0.0004467936815299197, + -0.0004467936815254109, + -0.00044679368155122346, + -0.00044679368154864794, + -0.00044679368152024146, + -0.00044679368155338026, + -0.000446793681551235, + -0.00044679368152539934, + -0.00044679368154863525, + -0.00044679368154547193, + -0.00044679368152538784, + -0.00044679368154863525, + -0.00044679368154863525, + -0.00044679368152538784, + -0.00044679368154863525, + -0.00044679368154863525, + -0.00044679368154547193, + -0.00044679368154547193, + -0.0004467936815451899, + -0.00044679368154547193, + -0.0004467936815141912, + -0.0004467936815415336, + -0.00044679368154547193, + -0.00044679368154547193, + -0.0004467936815415336, + -0.000446793681545486, + -0.000446793681545486, + -0.0004467936815451899, + -0.00044679368154862257, + -0.00044679368152561856, + -0.00044679368155098114, + -0.00044679368154547193, + -0.0004467936815204826, + -0.0004467936815512119, + -0.00044679368154863525, + -0.000446793681545204, + -0.0004467936815415336, + -0.0004467936815141912, + -0.00044679368154547193, + -0.00044679368154547193 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 5.002676876836745, + "y": -0.0022351645679918875 + }, + { + "x": 11.005889129047688, + "y": -0.004917362049638996 + }, + { + "x": 10.005353753685, + "y": -0.004470329136267992 + }, + { + "x": 10.005353753685, + "y": -0.004470329136267992 + }, + { + "x": 12.006424504421886, + "y": -0.005364394963294217 + }, + { + "x": 10.005353753684858, + "y": -0.004470329136267992 + }, + { + "x": 8.004283002947972, + "y": -0.00357626330895755 + }, + { + "x": 8.004283002947972, + "y": -0.00357626330895755 + }, + { + "x": 9.004818378316486, + "y": -0.004023296222612771 + }, + { + "x": 11.005889129053514, + "y": -0.004917362049638996 + }, + { + "x": 10.005353753684858, + "y": -0.004470329136267992 + }, + { + "x": 9.004818378316486, + "y": -0.004023296222612771 + }, + { + "x": 10.005353753690684, + "y": -0.004470329136267992 + }, + { + "x": 10.005353753684858, + "y": -0.004470329136267992 + }, + { + "x": 9.004818378310802, + "y": -0.004023296222328554 + }, + { + "x": 9.004818378316486, + "y": -0.004023296222612771 + }, + { + "x": 11.005889129053372, + "y": -0.004917362049923213 + }, + { + "x": 12.006424504422029, + "y": -0.005364394963294217 + }, + { + "x": 10.005353753685, + "y": -0.004470329136267992 + }, + { + "x": 9.004818378316344, + "y": -0.004023296222612771 + }, + { + "x": 10.005353753690684, + "y": -0.004470329136267992 + }, + { + "x": 10.005353753685, + "y": -0.004470329136267992 + }, + { + "x": 10.005353753679316, + "y": -0.004470329135983775 + }, + { + "x": 9.004818378316486, + "y": -0.004023296222612771 + }, + { + "x": 10.005353753684858, + "y": -0.004470329136267992 + }, + { + "x": 10.005353753690542, + "y": -0.004470329136267992 + }, + { + "x": 8.004283002947972, + "y": -0.00357626330895755 + }, + { + "x": 10.005353753679316, + "y": -0.004470329135983775 + }, + { + "x": 12.00642450442757, + "y": -0.005364394963578434 + }, + { + "x": 11.005889129053372, + "y": -0.004917362049923213 + }, + { + "x": 11.005889129047546, + "y": -0.004917362049638996 + }, + { + "x": 12.006424504421744, + "y": -0.005364394963294217 + }, + { + "x": 11.005889129053372, + "y": -0.004917362049923213 + }, + { + "x": 11.005889129053372, + "y": -0.004917362049923213 + }, + { + "x": 11.005889129053372, + "y": -0.004917362049638996 + }, + { + "x": 10.005353753684858, + "y": -0.004470329136267992 + }, + { + "x": 10.005353753684858, + "y": -0.004470329136267992 + }, + { + "x": 11.005889129053372, + "y": -0.004917362049638996 + }, + { + "x": 11.005889129053372, + "y": -0.004917362049923213 + }, + { + "x": 10.005353753684858, + "y": -0.004470329136267992 + }, + { + "x": 9.004818378322028, + "y": -0.004023296222612771 + }, + { + "x": 9.004818378316344, + "y": -0.004023296222612771 + }, + { + "x": 9.004818378310802, + "y": -0.004023296222328554 + }, + { + "x": 9.004818378316486, + "y": -0.004023296222612771 + }, + { + "x": 10.005353753684858, + "y": -0.004470329136267992 + }, + { + "x": 11.005889129053372, + "y": -0.004917362049638996 + }, + { + "x": 12.006424504421886, + "y": -0.005364394963578434 + }, + { + "x": 10.005353753684716, + "y": -0.004470329136267992 + }, + { + "x": 9.004818378321886, + "y": -0.004023296222612771 + }, + { + "x": 11.005889129053514, + "y": -0.004917362049923213 + }, + { + "x": 12.006424504416202, + "y": -0.005364394963294217 + }, + { + "x": 11.00588912905323, + "y": -0.004917362049638996 + }, + { + "x": 11.005889129053514, + "y": -0.004917362049923213 + }, + { + "x": 10.005353753684858, + "y": -0.004470329136267992 + }, + { + "x": 10.005353753684858, + "y": -0.004470329135983775 + }, + { + "x": 12.006424504421886, + "y": -0.005364394963578434 + }, + { + "x": 11.00588912905323, + "y": -0.004917362049923213 + }, + { + "x": 11.005889129053514, + "y": -0.004917362049638996 + }, + { + "x": 10.005353753685142, + "y": -0.004470329136267992 + }, + { + "x": 9.00481837831677, + "y": -0.004023296222612771 + }, + { + "x": 11.005889129053799, + "y": -0.004917362049638996 + }, + { + "x": 10.005353753685142, + "y": -0.004470329136267992 + }, + { + "x": 10.005353753685142, + "y": -0.004470329136267992 + }, + { + "x": 11.005889129053799, + "y": -0.004917362049638996 + }, + { + "x": 10.005353753685142, + "y": -0.004470329136267992 + }, + { + "x": 10.005353753685142, + "y": -0.004470329136267992 + }, + { + "x": 9.00481837831677, + "y": -0.004023296222612771 + }, + { + "x": 9.00481837831677, + "y": -0.004023296222612771 + }, + { + "x": 9.004818378322454, + "y": -0.004023296222612771 + }, + { + "x": 9.00481837831677, + "y": -0.004023296222612771 + }, + { + "x": 9.004818378311086, + "y": -0.004023296222328554 + }, + { + "x": 8.004283002948114, + "y": -0.00357626330895755 + }, + { + "x": 9.00481837831677, + "y": -0.004023296222612771 + }, + { + "x": 9.00481837831677, + "y": -0.004023296222612771 + }, + { + "x": 8.004283002948114, + "y": -0.00357626330895755 + }, + { + "x": 9.004818378316486, + "y": -0.004023296222612771 + }, + { + "x": 9.004818378316486, + "y": -0.004023296222612771 + }, + { + "x": 9.004818378322454, + "y": -0.004023296222612771 + }, + { + "x": 10.005353753685426, + "y": -0.004470329136267992 + }, + { + "x": 11.005889129048114, + "y": -0.004917362049638996 + }, + { + "x": 11.005889129059483, + "y": -0.004917362049923213 + }, + { + "x": 9.00481837831677, + "y": -0.004023296222612771 + }, + { + "x": 10.005353753679458, + "y": -0.004470329135983775 + }, + { + "x": 11.005889129053799, + "y": -0.004917362049923213 + }, + { + "x": 10.005353753685142, + "y": -0.004470329136267992 + }, + { + "x": 9.00481837832217, + "y": -0.004023296222612771 + }, + { + "x": 8.004283002948114, + "y": -0.00357626330895755 + }, + { + "x": 9.004818378311086, + "y": -0.004023296222328554 + }, + { + "x": 9.00481837831677, + "y": -0.004023296222612771 + }, + { + "x": 9.00481837831677, + "y": -0.004023296222612771 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 148.9445325959717, + "y": -133.43613885240512, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 88.3788047961567, + "y": -57.90372801630079, + "z": 1.0 + }, + { + "x": 88.37888114956165, + "y": -58.40601111552, + "z": 1.0 + }, + { + "x": 88.37894223228558, + "y": -58.80783759489587, + "z": 1.0 + }, + { + "x": 88.3790338563715, + "y": -59.410577313959266, + "z": 1.0 + }, + { + "x": 88.37909493909547, + "y": -59.81240379333458, + "z": 1.0 + }, + { + "x": 88.37917129250039, + "y": -60.31468689255435, + "z": 1.0 + }, + { + "x": 88.37924764590532, + "y": -60.816969991773846, + "z": 1.0 + }, + { + "x": 88.37932399931026, + "y": -61.31925309099334, + "z": 1.0 + }, + { + "x": 88.37941562339618, + "y": -61.92199281005672, + "z": 1.0 + }, + { + "x": 88.3794919768011, + "y": -62.42427590927622, + "z": 1.0 + }, + { + "x": 88.37955305952507, + "y": -62.82610238865182, + "z": 1.0 + }, + { + "x": 88.37964468361099, + "y": -63.4288421077152, + "z": 1.0 + }, + { + "x": 88.37972103701591, + "y": -63.931125206934695, + "z": 1.0 + }, + { + "x": 88.37979739042085, + "y": -64.4334083061542, + "z": 1.0 + }, + { + "x": 88.37988901450677, + "y": -65.03614802521759, + "z": 1.0 + }, + { + "x": 88.3799806385927, + "y": -65.63888774428096, + "z": 1.0 + }, + { + "x": 88.38004172131664, + "y": -66.0407142236563, + "z": 1.0 + }, + { + "x": 88.38013334540257, + "y": -66.64345394271993, + "z": 1.0 + }, + { + "x": 88.3802249694885, + "y": -67.24619366178331, + "z": 1.0 + }, + { + "x": 88.3803165935744, + "y": -67.84893338084669, + "z": 1.0 + }, + { + "x": 88.38036240561738, + "y": -68.15030324037838, + "z": 1.0 + }, + { + "x": 88.38043854453058, + "y": -68.6511753276148, + "z": 1.0 + }, + { + "x": 88.38052991122643, + "y": -69.25222183229796, + "z": 1.0 + }, + { + "x": 88.38062127792227, + "y": -69.85326833698171, + "z": 1.0 + }, + { + "x": 88.38068218905285, + "y": -70.2539660067704, + "z": 1.0 + }, + { + "x": 88.38077355574869, + "y": -70.85501251145385, + "z": 1.0 + }, + { + "x": 88.38083446687926, + "y": -71.25571018124283, + "z": 1.0 + }, + { + "x": 88.38091060579247, + "y": -71.75658226847905, + "z": 1.0 + }, + { + "x": 88.38097151692303, + "y": -72.15727993826802, + "z": 1.0 + }, + { + "x": 88.3810324280536, + "y": -72.55797760805699, + "z": 1.0 + }, + { + "x": 88.38112379474946, + "y": -73.15902411274045, + "z": 1.0 + }, + { + "x": 88.38118470588003, + "y": -73.55972178252942, + "z": 1.0 + }, + { + "x": 88.38126084479323, + "y": -74.06059386976564, + "z": 1.0 + }, + { + "x": 88.38133698370643, + "y": -74.56146595700213, + "z": 1.0 + }, + { + "x": 88.38139789483701, + "y": -74.96216362679083, + "z": 1.0 + }, + { + "x": 88.38145880596757, + "y": -75.3628612965798, + "z": 1.0 + }, + { + "x": 88.38155017266342, + "y": -75.96390780126325, + "z": 1.0 + }, + { + "x": 88.38161108379398, + "y": -76.36460547105223, + "z": 1.0 + }, + { + "x": 88.38170245048984, + "y": -76.96565197573568, + "z": 1.0 + }, + { + "x": 88.38179381718568, + "y": -77.56669848041915, + "z": 1.0 + }, + { + "x": 88.38185472831624, + "y": -77.96739615020812, + "z": 1.0 + }, + { + "x": 88.38193086722946, + "y": -78.46826823744433, + "z": 1.0 + }, + { + "x": 88.38200700614266, + "y": -78.96914032468055, + "z": 1.0 + }, + { + "x": 88.38209837283851, + "y": -79.570186829364, + "z": 1.0 + }, + { + "x": 88.38217451175171, + "y": -80.07105891660022, + "z": 1.0 + }, + { + "x": 88.38226587844757, + "y": -80.67210542128367, + "z": 1.0 + }, + { + "x": 88.38234201736077, + "y": -81.17297750851989, + "z": 1.0 + }, + { + "x": 88.38240292849133, + "y": -81.57367517830914, + "z": 1.0 + }, + { + "x": 88.3824638396219, + "y": -81.97437284809784, + "z": 1.0 + }, + { + "x": 88.38255520631775, + "y": -82.5754193527813, + "z": 1.0 + }, + { + "x": 88.38261611744832, + "y": -82.97611702257026, + "z": 1.0 + }, + { + "x": 88.38269225636154, + "y": -83.47698910980648, + "z": 1.0 + }, + { + "x": 88.38278362305739, + "y": -84.07803561448995, + "z": 1.0 + }, + { + "x": 88.38287498975323, + "y": -84.6790821191734, + "z": 1.0 + }, + { + "x": 88.3829359008838, + "y": -85.07977978896237, + "z": 1.0 + }, + { + "x": 88.38302726757965, + "y": -85.68082629364584, + "z": 1.0 + }, + { + "x": 88.38310340649285, + "y": -86.18169838088205, + "z": 1.0 + }, + { + "x": 88.3831947731887, + "y": -86.7827448855655, + "z": 1.0 + }, + { + "x": 88.38325568431927, + "y": -87.18344255535447, + "z": 1.0 + }, + { + "x": 88.38333182323248, + "y": -87.68431464259069, + "z": 1.0 + }, + { + "x": 88.38340796214568, + "y": -88.18518672982691, + "z": 1.0 + }, + { + "x": 88.38348410105888, + "y": -88.68605881706341, + "z": 1.0 + }, + { + "x": 88.38354501218946, + "y": -89.0867564868521, + "z": 1.0 + }, + { + "x": 88.3836363788853, + "y": -89.68780299153555, + "z": 1.0 + }, + { + "x": 88.38372774558115, + "y": -90.28884949621902, + "z": 1.0 + }, + { + "x": 88.383819112277, + "y": -90.88989600090247, + "z": 1.0 + }, + { + "x": 88.38388002340757, + "y": -91.29059367069145, + "z": 1.0 + }, + { + "x": 88.38395616232077, + "y": -91.79146575792767, + "z": 1.0 + }, + { + "x": 88.38401707345133, + "y": -92.19216342771692, + "z": 1.0 + }, + { + "x": 88.38409321236455, + "y": -92.69303551495285, + "z": 1.0 + }, + { + "x": 88.38416935127776, + "y": -93.19390760218907, + "z": 1.0 + }, + { + "x": 88.38426071797362, + "y": -93.79495410687252, + "z": 1.0 + }, + { + "x": 88.38433685688682, + "y": -94.29582619410874, + "z": 1.0 + }, + { + "x": 88.38442822358267, + "y": -94.8968726987922, + "z": 1.0 + }, + { + "x": 88.38450436249587, + "y": -95.39774478602841, + "z": 1.0 + }, + { + "x": 88.38456527362645, + "y": -95.79844245581738, + "z": 1.0 + }, + { + "x": 88.38464141253965, + "y": -96.2993145430536, + "z": 1.0 + }, + { + "x": 88.38473277923549, + "y": -96.90036104773735, + "z": 1.0 + }, + { + "x": 88.3848089181487, + "y": -97.40123313497327, + "z": 1.0 + }, + { + "x": 88.38490028484455, + "y": -98.00227963965673, + "z": 1.0 + }, + { + "x": 88.38496119597512, + "y": -98.4029773094457, + "z": 1.0 + }, + { + "x": 88.38505256267096, + "y": -99.00402381412917, + "z": 1.0 + }, + { + "x": 88.38514392936682, + "y": -99.60507031881262, + "z": 1.0 + }, + { + "x": 88.38520484049738, + "y": -100.00576798860159, + "z": 1.0 + }, + { + "x": 88.3852809794106, + "y": -100.50664007583781, + "z": 1.0 + }, + { + "x": 88.38537234610644, + "y": -101.10768658052127, + "z": 1.0 + }, + { + "x": 88.385433257237, + "y": -101.50838425031024, + "z": 1.0 + }, + { + "x": 88.38552462393285, + "y": -102.1094307549937, + "z": 1.0 + }, + { + "x": 88.3856159906287, + "y": -102.71047725967743, + "z": 1.0 + }, + { + "x": 88.38570735732456, + "y": -103.31152376436062, + "z": 1.0 + }, + { + "x": 88.38578349623776, + "y": -103.81239585159683, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 29, + "heading": [ + -1.5706443141063042, + -1.570644314106275, + -1.5706443141063064, + -1.5706443141063173, + -1.5706443141062891, + -1.5706443141063064, + -1.5706443141063173, + -1.5706443141063031, + -1.5706443141063007, + -1.5706443141063136, + -1.5706443141063064, + -1.5706443141062891, + -1.5706443141063136, + -1.5706443141063173, + -1.5706443141063007, + -1.5706443141062985, + -1.5706443141063031, + -1.5706443141063031, + -1.5706443141062985, + -1.5706443141063102, + -1.5706443141063064, + -1.5706443141063022, + -1.5706443141063058, + -1.570644314106307, + -1.5706443141063045, + -1.5706443141063045, + -1.5706443141063045, + -1.570644314106303, + -1.5706443141063187, + -1.570644314106301, + -1.5706443141062902, + -1.5706443141062902, + -1.570644314106303, + -1.5706443141063187, + -1.570644314106303, + -1.570644314106301, + -1.5706443141063045, + -1.5706443141063045, + -1.5706443141063045, + -1.570644314106307, + -1.5706443141063187, + -1.570644314106303, + -1.5706443141063045, + -1.5706443141063058, + -1.5706443141063058, + -1.5706443141063058, + -1.5706443141063058, + -1.5706443141063187, + -1.570644314106301, + -1.5706443141063045, + -1.5706443141063045, + -1.5706443141062871, + -1.570644314106293, + -1.570644314106307, + -1.5706443141063187, + -1.5706443141063045, + -1.5706443141063058, + -1.5706443141063058, + -1.5706443141063045, + -1.570644314106303, + -1.5706443141063045, + -1.5706443141063187, + -1.570644314106303, + -1.5706443141063045, + -1.570644314106307, + -1.570644314106307, + -1.5706443141063045, + -1.570644314106303, + -1.5706443141063187, + -1.570644314106303, + -1.5706443141062902, + -1.570644314106293, + -1.5706443141063058, + -1.5706443141063058, + -1.5706443141063058, + -1.570644314106303, + -1.570644314106303, + -1.5706443141063187, + -1.5706443141063058, + -1.5706443141063058, + -1.5706443141063045, + -1.5706443141063045, + -1.570644314106307, + -1.5706443141063045, + -1.570644314106303, + -1.5706443141063058, + -1.5706443141063187, + -1.5706443141063045, + -1.570644314106307, + -1.570644314106295, + -1.570644314106293 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0007635340494971388, + "y": -5.022830992192127 + }, + { + "x": 0.0013743612888106327, + "y": -9.04109578595083 + }, + { + "x": 0.001527068098567952, + "y": -10.045661984392638 + }, + { + "x": 0.001527068098852169, + "y": -10.045661984387095 + }, + { + "x": 0.0013743612888106327, + "y": -9.04109578595083 + }, + { + "x": 0.001527068098567952, + "y": -10.045661984392638 + }, + { + "x": 0.0015270680987100604, + "y": -10.045661984389938 + }, + { + "x": 0.0016797749086094882, + "y": -11.05022818282876 + }, + { + "x": 0.0016797749084673796, + "y": -11.05022818282876 + }, + { + "x": 0.0013743612888106327, + "y": -9.041095785950972 + }, + { + "x": 0.001527068098852169, + "y": -10.045661984389795 + }, + { + "x": 0.0016797749084673796, + "y": -11.05022818282876 + }, + { + "x": 0.001527068098567952, + "y": -10.04566198439008 + }, + { + "x": 0.0016797749086094882, + "y": -11.050228182828903 + }, + { + "x": 0.001832481718508916, + "y": -12.054794381267584 + }, + { + "x": 0.0015270680987100604, + "y": -10.045661984387095 + }, + { + "x": 0.0015270680987100604, + "y": -10.045661984389653 + }, + { + "x": 0.001832481718508916, + "y": -12.054794381270142 + }, + { + "x": 0.0018324817183668074, + "y": -12.054794381267584 + }, + { + "x": 0.0013743612888106327, + "y": -9.041095785950688 + }, + { + "x": 0.0012195095617073548, + "y": -8.022419467681061 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919195849 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744721367 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.0013705004377584373, + "y": -9.015697570252001 + }, + { + "x": 0.0013705004376163288, + "y": -9.01569757025186 + }, + { + "x": 0.001218222611356623, + "y": -8.013953395779367 + }, + { + "x": 0.0015227782643023602, + "y": -10.017441744724351 + }, + { + "x": 0.0015227782643023602, + "y": -10.017441744724351 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.001522778264018143, + "y": -10.017441744727051 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.001218222611356623, + "y": -8.013953395776667 + }, + { + "x": 0.0015227782641602516, + "y": -10.01744174472421 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.001522778264018143, + "y": -10.017441744724351 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.0013705004376163288, + "y": -9.015697570254702 + }, + { + "x": 0.001218222611356623, + "y": -8.01395339577951 + }, + { + "x": 0.0015227782641602516, + "y": -10.01744174472151 + }, + { + "x": 0.0015227782641602516, + "y": -10.01744174472421 + }, + { + "x": 0.0013705004379005459, + "y": -9.01569757025186 + }, + { + "x": 0.0016750560907041745, + "y": -11.019185919196843 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.001522778264018143, + "y": -10.01744174472421 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196843 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.0015227782641602516, + "y": -10.01744174472421 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.001522778264018143, + "y": -10.017441744727194 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744721367 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.0013705004377584373, + "y": -9.015697570252001 + }, + { + "x": 0.0013705004376163288, + "y": -9.015697570254702 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.0015227782643023602, + "y": -10.01744174472151 + }, + { + "x": 0.0016750560907041745, + "y": -11.019185919196701 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.0016750560904199574, + "y": -11.019185919199685 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196701 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919193859 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.0015227782641602516, + "y": -10.017441744724351 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093669193 + }, + { + "x": 0.0015227782641602516, + "y": -10.01744174472421 + }, + { + "x": 0.0013705004377584373, + "y": -9.01569757025186 + }, + { + "x": 0.001675056090562066, + "y": -11.019185919196843 + }, + { + "x": 0.001522778264018143, + "y": -10.017441744724351 + }, + { + "x": 0.0015227782641602516, + "y": -10.01744174472421 + }, + { + "x": 0.0018273339169638803, + "y": -12.020930093671893 + }, + { + "x": 0.0018273339171059888, + "y": -12.020930093669193 + }, + { + "x": 0.0016750560907041745, + "y": -11.019185919194001 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 88.38578349623776, + "y": -103.81239585159683, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 158.03439763122856, + "y": -37.48257278576148, + "z": 1.0 + }, + { + "x": 158.03488464725268, + "y": -37.08166140065703, + "z": 1.0 + }, + { + "x": 158.0354934172828, + "y": -36.580522169275206, + "z": 1.0 + }, + { + "x": 158.0361021873129, + "y": -36.07938293789394, + "z": 1.0 + }, + { + "x": 158.03658920333703, + "y": -35.678471552789496, + "z": 1.0 + }, + { + "x": 158.03719797336714, + "y": -35.17733232140766, + "z": 1.0 + }, + { + "x": 158.03768498939127, + "y": -34.77642093630322, + "z": 1.0 + }, + { + "x": 158.0381720054154, + "y": -34.37550955119821, + "z": 1.0 + }, + { + "x": 158.0386590214395, + "y": -33.9745981660932, + "z": 1.0 + }, + { + "x": 158.03914603746358, + "y": -33.57368678098819, + "z": 1.0 + }, + { + "x": 158.03987656149974, + "y": -32.97231970333011, + "z": 1.0 + }, + { + "x": 158.0406070855359, + "y": -32.370952625672594, + "z": 1.0 + }, + { + "x": 158.04121585556607, + "y": -31.869813394291327, + "z": 1.0 + }, + { + "x": 158.0417028715902, + "y": -31.468902009186884, + "z": 1.0 + }, + { + "x": 158.0424333956263, + "y": -30.8675349315288, + "z": 1.0 + }, + { + "x": 158.0431639196625, + "y": -30.266167853871853, + "z": 1.0 + }, + { + "x": 158.04377268969262, + "y": -29.76502862249002, + "z": 1.0 + }, + { + "x": 158.04438145972279, + "y": -29.263889391109323, + "z": 1.0 + }, + { + "x": 158.0449902297529, + "y": -28.762750159727496, + "z": 1.0 + }, + { + "x": 158.04547724577696, + "y": -28.361838774622484, + "z": 1.0 + }, + { + "x": 158.0459642618011, + "y": -27.96092738951804, + "z": 1.0 + }, + { + "x": 158.04669478583725, + "y": -27.35956031185996, + "z": 1.0 + }, + { + "x": 158.0474253098734, + "y": -26.758193234202437, + "z": 1.0 + }, + { + "x": 158.04803407990357, + "y": -26.257054002821164, + "z": 1.0 + }, + { + "x": 158.04864284993369, + "y": -25.75591477143989, + "z": 1.0 + }, + { + "x": 158.0492516199638, + "y": -25.254775540058617, + "z": 1.0 + }, + { + "x": 158.049982144, + "y": -24.653408462401657, + "z": 1.0 + }, + { + "x": 158.05059091403012, + "y": -24.152269231020387, + "z": 1.0 + }, + { + "x": 158.05132143806628, + "y": -23.55090215336286, + "z": 1.0 + }, + { + "x": 158.0518084540904, + "y": -23.149990768257275, + "z": 1.0 + }, + { + "x": 158.05253897812656, + "y": -22.548623690599747, + "z": 1.0 + }, + { + "x": 158.05326950216272, + "y": -21.94725661294222, + "z": 1.0 + }, + { + "x": 158.0537565181868, + "y": -21.5463452278372, + "z": 1.0 + }, + { + "x": 158.0542435342109, + "y": -21.14543384273219, + "z": 1.0 + }, + { + "x": 158.05497405824707, + "y": -20.54406676507466, + "z": 1.0 + }, + { + "x": 158.0554610742712, + "y": -20.14315537996964, + "z": 1.0 + }, + { + "x": 158.0560698443013, + "y": -19.642016148588368, + "z": 1.0 + }, + { + "x": 158.05680036833752, + "y": -19.04064907093141, + "z": 1.0 + }, + { + "x": 158.05753089237368, + "y": -18.439281993273312, + "z": 1.0 + }, + { + "x": 158.05801790839774, + "y": -18.0383706081683, + "z": 1.0 + }, + { + "x": 158.0586266784279, + "y": -17.537231376787027, + "z": 1.0 + }, + { + "x": 158.05923544845803, + "y": -17.036092145406318, + "z": 1.0 + }, + { + "x": 158.05972246448215, + "y": -16.635180760300734, + "z": 1.0 + }, + { + "x": 158.0604529885183, + "y": -16.033813682643206, + "z": 1.0 + }, + { + "x": 158.06094000454243, + "y": -15.632902297538756, + "z": 1.0 + }, + { + "x": 158.0614270205665, + "y": -15.231990912433172, + "z": 1.0 + }, + { + "x": 158.06203579059667, + "y": -14.730851681051899, + "z": 1.0 + }, + { + "x": 158.06276631463282, + "y": -14.129484603394374, + "z": 1.0 + }, + { + "x": 158.06337508466294, + "y": -13.628345372013104, + "z": 1.0 + }, + { + "x": 158.06386210068706, + "y": -13.227433986908089, + "z": 1.0 + }, + { + "x": 158.06459262472322, + "y": -12.626066909251133, + "z": 1.0 + }, + { + "x": 158.06532314875938, + "y": -12.024699831593606, + "z": 1.0 + }, + { + "x": 158.0658101647835, + "y": -11.62378844648859, + "z": 1.0 + }, + { + "x": 158.06629718080762, + "y": -11.222877061383572, + "z": 1.0 + }, + { + "x": 158.06654068881966, + "y": -11.022421368830496, + "z": 1.0 + }, + { + "x": 158.06702812465142, + "y": -10.621164398262831, + "z": 1.0 + }, + { + "x": 158.06775927839897, + "y": -10.01927894240989, + "z": 1.0 + }, + { + "x": 158.06824671423072, + "y": -9.618021971841639, + "z": 1.0 + }, + { + "x": 158.0688560090204, + "y": -9.11645075863133, + "z": 1.0 + }, + { + "x": 158.0693434448521, + "y": -8.715193788063083, + "z": 1.0 + }, + { + "x": 158.07007459859972, + "y": -8.113308332210707, + "z": 1.0 + }, + { + "x": 158.07056203443148, + "y": -7.712051361642459, + "z": 1.0 + }, + { + "x": 158.06648688551132, + "y": -7.1584986324351565, + "z": 1.0 + }, + { + "x": 158.02461504747117, + "y": -6.51829522095581, + "z": 1.0 + }, + { + "x": 157.91537219000054, + "y": -5.756265280126636, + "z": 1.0 + }, + { + "x": 157.80713622040798, + "y": -5.254505269284559, + "z": 1.0 + }, + { + "x": 157.59217082782527, + "y": -4.514683268550397, + "z": 1.0 + }, + { + "x": 157.3662201428967, + "y": -3.9142137585897396, + "z": 1.0 + }, + { + "x": 157.15553063700315, + "y": -3.4461523429930967, + "z": 1.0 + }, + { + "x": 156.79117762382486, + "y": -2.7680225145010073, + "z": 1.0 + }, + { + "x": 156.3711601304941, + "y": -2.1228895130661045, + "z": 1.0 + }, + { + "x": 156.0616732746556, + "y": -1.7133932466808826, + "z": 1.0 + }, + { + "x": 155.72972937947105, + "y": -1.3218789148370773, + "z": 1.0 + }, + { + "x": 155.3763707435337, + "y": -0.9495760774742261, + "z": 1.0 + }, + { + "x": 154.9083553058013, + "y": -0.5146331051925972, + "z": 1.0 + }, + { + "x": 154.42830485703843, + "y": -0.12187522067055712, + "z": 1.0 + }, + { + "x": 153.82225338896444, + "y": 0.31096146168839445, + "z": 1.0 + }, + { + "x": 153.18733284384513, + "y": 0.699261120180888, + "z": 1.0 + }, + { + "x": 152.74938521124585, + "y": 0.9325766110953226, + "z": 1.0 + }, + { + "x": 152.0729321872387, + "y": 1.242908208394323, + "z": 1.0 + }, + { + "x": 151.37610097632384, + "y": 1.5042882774523922, + "z": 1.0 + }, + { + "x": 150.9019679824224, + "y": 1.6506809930010826, + "z": 1.0 + }, + { + "x": 150.30040348196218, + "y": 1.8017426140988086, + "z": 1.0 + }, + { + "x": 149.5682777598086, + "y": 1.9355006328820132, + "z": 1.0 + }, + { + "x": 148.95215542328614, + "y": 2.0069078165924625, + "z": 1.0 + }, + { + "x": 148.20833740082458, + "y": 2.044065519194717, + "z": 1.0 + }, + { + "x": 147.66901799637068, + "y": 2.045241054680691, + "z": 1.0 + }, + { + "x": 147.26776073202618, + "y": 2.045283880573532, + "z": 1.0 + }, + { + "x": 146.6658748355094, + "y": 2.0453481194127936, + "z": 1.0 + }, + { + "x": 146.2646175711649, + "y": 2.045390945305635, + "z": 1.0 + }, + { + "x": 145.76304599073424, + "y": 2.0454444776716865, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 30, + "heading": [ + 1.85681491850764, + 1.5695815551454493, + 1.5695815551454981, + 1.5695815551455368, + 1.5695815551454975, + 1.5695815551454981, + 1.5695815551454981, + 1.5695815551454502, + 1.5695815551454508, + 1.569581555145522, + 1.5695815551455368, + 1.5695815551454988, + 1.5695815551454637, + 1.5695815551454344, + 1.569581555145536, + 1.5695815551454981, + 1.5695815551454637, + 1.5695815551454793, + 1.5695815551454793, + 1.5695815551455619, + 1.569581555145521, + 1.5695815551454793, + 1.5695815551454988, + 1.569581555145464, + 1.5695815551454793, + 1.569581555145536, + 1.5695815551454633, + 1.5695815551454633, + 1.5695815551455155, + 1.56958155514548, + 1.56958155514548, + 1.5695815551454981, + 1.569581555145536, + 1.569581555145522, + 1.5695815551454793, + 1.5695815551454793, + 1.5695815551454981, + 1.5695815551454633, + 1.569581555145451, + 1.5695815551455368, + 1.5695815551454981, + 1.5695815551454786, + 1.5695815551454981, + 1.56958155514548, + 1.5695815551454786, + 1.569581555145522, + 1.569581555145499, + 1.569581555145464, + 1.5695815551455155, + 1.5695815551454981, + 1.5695815551454786, + 1.5695815551454977, + 1.5695815551454793, + 1.569581555145451, + 1.5695815551454995, + 1.569581555145491, + 1.5695815551455252, + 1.5695815551455259, + 1.569581555145456, + 1.569581555145519, + 1.5695815551455252, + 1.5695815551454686, + 1.5745538254927947, + 1.6092667617277412, + 1.6781491685846572, + 1.7412118605974554, + 1.8254586180935752, + 1.8886150095974155, + 1.9587252808138194, + 2.0358018759865435, + 2.105871504850858, + 2.1759411589315487, + 2.246010784166259, + 2.3020664946610165, + 2.364869264322417, + 2.423872974200282, + 2.491630517482241, + 2.557044715117108, + 2.6164612050779623, + 2.687721824022901, + 2.74710565983511, + 2.8064895092109574, + 2.871811731469634, + 2.9311956033917057, + 2.990579471172711, + 3.0619309698677264, + 3.1117269203157245, + 3.14029731984635, + 3.1414859243253437, + 3.1414859243253432, + 3.1414859243253432 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": 0.0048701602412393186, + "y": 4.009113851044432 + }, + { + "x": 0.010957860542362141, + "y": 9.02050616486271 + }, + { + "x": 0.012175400602245645, + "y": 10.02278462763094 + }, + { + "x": 0.010957860542362141, + "y": 9.020506164857096 + }, + { + "x": 0.010957860542362141, + "y": 9.02050616486278 + }, + { + "x": 0.010957860542362141, + "y": 9.02050616486278 + }, + { + "x": 0.009740320482478637, + "y": 8.018227702094478 + }, + { + "x": 0.009740320482478637, + "y": 8.018227702100162 + }, + { + "x": 0.009740320481910203, + "y": 8.018227702100234 + }, + { + "x": 0.012175400602245645, + "y": 10.02278462763094 + }, + { + "x": 0.014610480723149522, + "y": 12.027341553155964 + }, + { + "x": 0.013392940663266018, + "y": 11.025063090387803 + }, + { + "x": 0.010957860542930575, + "y": 9.020506164857096 + }, + { + "x": 0.012175400602245645, + "y": 10.022784627625256 + }, + { + "x": 0.014610480723149522, + "y": 12.027341553150315 + }, + { + "x": 0.013392940663266018, + "y": 11.025063090387803 + }, + { + "x": 0.01217540060281408, + "y": 10.022784627625292 + }, + { + "x": 0.01217540060281408, + "y": 10.022784627625256 + }, + { + "x": 0.010957860541793707, + "y": 9.020506164868394 + }, + { + "x": 0.009740320481910203, + "y": 8.01822770209455 + }, + { + "x": 0.01217540060281408, + "y": 10.022784627625256 + }, + { + "x": 0.014610480723149522, + "y": 12.027341553156035 + }, + { + "x": 0.013392940663266018, + "y": 11.025063090387945 + }, + { + "x": 0.01217540060281408, + "y": 10.02278462762547 + }, + { + "x": 0.012175400602245645, + "y": 10.02278462762547 + }, + { + "x": 0.013392940663266018, + "y": 11.025063090382332 + }, + { + "x": 0.013392940663266018, + "y": 11.025063090382297 + }, + { + "x": 0.013392940662697583, + "y": 11.025063090387981 + }, + { + "x": 0.01217540060281408, + "y": 10.022784627631118 + }, + { + "x": 0.01217540060281408, + "y": 10.022784627631118 + }, + { + "x": 0.014610480723149522, + "y": 12.027341553150563 + }, + { + "x": 0.012175400602245645, + "y": 10.02278462762547 + }, + { + "x": 0.009740320481910203, + "y": 8.018227702100305 + }, + { + "x": 0.01217540060281408, + "y": 10.022784627625398 + }, + { + "x": 0.01217540060281408, + "y": 10.02278462762547 + }, + { + "x": 0.010957860542362141, + "y": 9.020506164862923 + }, + { + "x": 0.013392940663266018, + "y": 11.025063090382332 + }, + { + "x": 0.014610480723717956, + "y": 12.027341553150563 + }, + { + "x": 0.012175400602245645, + "y": 10.022784627631083 + }, + { + "x": 0.010957860542362141, + "y": 9.020506164862852 + }, + { + "x": 0.01217540060281408, + "y": 10.02278462761982 + }, + { + "x": 0.010957860542362141, + "y": 9.020506164862923 + }, + { + "x": 0.01217540060281408, + "y": 10.022784627631118 + }, + { + "x": 0.01217540060281408, + "y": 10.022784627619785 + }, + { + "x": 0.009740320481910203, + "y": 8.01822770210034 + }, + { + "x": 0.010957860542362141, + "y": 9.020506164868571 + }, + { + "x": 0.013392940663266018, + "y": 11.025063090387981 + }, + { + "x": 0.013392940662697583, + "y": 11.025063090387945 + }, + { + "x": 0.010957860542362141, + "y": 9.020506164862852 + }, + { + "x": 0.01217540060281408, + "y": 10.022784627619714 + }, + { + "x": 0.014610480723149522, + "y": 12.027341553144826 + }, + { + "x": 0.01217540060281408, + "y": 10.022784627625434 + }, + { + "x": 0.009740320482478637, + "y": 8.01822770210034 + }, + { + "x": 0.007305240361574761, + "y": 6.0136707765809305 + }, + { + "x": 0.00730943843791465, + "y": 6.0171266312074145 + }, + { + "x": 0.01218589579309537, + "y": 10.03142426420606 + }, + { + "x": 0.01218589579309537, + "y": 10.031424264211921 + }, + { + "x": 0.01096730621441111, + "y": 9.028281837785599 + }, + { + "x": 0.010967306213842676, + "y": 9.028281837785563 + }, + { + "x": 0.01218589579309537, + "y": 10.031424264206237 + }, + { + "x": 0.012185895793663803, + "y": 10.031424264206237 + }, + { + "x": -0.035877130883932296, + "y": 9.548096997755504 + }, + { + "x": -0.4594698696030264, + "y": 11.937561406866486 + }, + { + "x": -1.5111469551078471, + "y": 14.022333523085209 + }, + { + "x": -2.1747882706318933, + "y": 12.637899516712512 + }, + { + "x": -3.232013621752685, + "y": 12.415820115762388 + }, + { + "x": -4.409160775112753, + "y": 13.402915106948194 + }, + { + "x": -4.366401908221178, + "y": 10.685309255573001 + }, + { + "x": -5.750425190718431, + "y": 11.461912440887323 + }, + { + "x": -7.843705065090489, + "y": 13.232628299269921 + }, + { + "x": -7.295043491692752, + "y": 10.546292678201247 + }, + { + "x": -6.414307510230515, + "y": 8.010105982290272 + }, + { + "x": -6.853025311218914, + "y": 7.638171692066564 + }, + { + "x": -8.213740736697446, + "y": 8.0724580964448 + }, + { + "x": -9.480658864952716, + "y": 8.27700856803669 + }, + { + "x": -10.86101916836867, + "y": 8.255945668809916 + }, + { + "x": -12.409720131933, + "y": 8.211363408514451 + }, + { + "x": -10.728681777185898, + "y": 6.2161514940692815 + }, + { + "x": -11.144006566064206, + "y": 5.4364708821343495 + }, + { + "x": -13.732842349220107, + "y": 5.717116663570696 + }, + { + "x": -11.709642048163005, + "y": 4.077727846067596 + }, + { + "x": -10.756974943616626, + "y": 2.974543366464164 + }, + { + "x": -13.336902226137965, + "y": 2.848196398809306 + }, + { + "x": -13.482480586760346, + "y": 2.051652024936539 + }, + { + "x": -13.599403589840335, + "y": 1.0856488631270356 + }, + { + "x": -12.831374269154594, + "y": 0.38333238088228416 + }, + { + "x": -9.405766687983999, + "y": 0.01218361378815036 + }, + { + "x": -10.031431608612706, + "y": 0.0010706473210264633 + }, + { + "x": -10.031431608612706, + "y": 0.0010706473210309042 + }, + { + "x": -9.02828844775172, + "y": 0.000963582588928702 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 145.76304599073424, + "y": 2.0454444776716865, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 334.8085442829706, + "y": -151.28327510229786, + "z": 1.0 + }, + { + "x": 334.80818118447087, + "y": -151.88442057736455, + "z": 1.0 + }, + { + "x": 334.80793911880437, + "y": -152.28518422740973, + "z": 1.0 + }, + { + "x": 334.80763653672125, + "y": -152.78613878996623, + "z": 1.0 + }, + { + "x": 334.8073339546381, + "y": -153.28709335252273, + "z": 1.0 + }, + { + "x": 334.807031372555, + "y": -153.78804791507923, + "z": 1.0 + }, + { + "x": 334.80666827405526, + "y": -154.389193390147, + "z": 1.0 + }, + { + "x": 334.80636569197213, + "y": -154.8901479527035, + "z": 1.0 + }, + { + "x": 334.80612362630563, + "y": -155.29091160274868, + "z": 1.0 + }, + { + "x": 334.80588156063914, + "y": -155.6916752527939, + "z": 1.0 + }, + { + "x": 334.805578978556, + "y": -156.19262981535041, + "z": 1.0 + }, + { + "x": 334.80521588005627, + "y": -156.79377529041818, + "z": 1.0 + }, + { + "x": 334.80491329797314, + "y": -157.29472985297468, + "z": 1.0 + }, + { + "x": 334.8045501994734, + "y": -157.89587532804245, + "z": 1.0 + }, + { + "x": 334.80418710097365, + "y": -158.49702080311027, + "z": 1.0 + }, + { + "x": 334.8038240024739, + "y": -159.09816627817918, + "z": 1.0 + }, + { + "x": 334.80346090397427, + "y": -159.69931175324473, + "z": 1.0 + }, + { + "x": 334.80315832189103, + "y": -160.2002663158035, + "z": 1.0 + }, + { + "x": 334.8028557398079, + "y": -160.70122087836, + "z": 1.0 + }, + { + "x": 334.8024926413083, + "y": -161.3023663534267, + "z": 1.0 + }, + { + "x": 334.80219005922504, + "y": -161.80332091598433, + "z": 1.0 + }, + { + "x": 334.80188747714203, + "y": -162.3042754785397, + "z": 1.0 + }, + { + "x": 334.80164541147553, + "y": -162.70503912858487, + "z": 1.0 + }, + { + "x": 334.8013428293924, + "y": -163.20599369114137, + "z": 1.0 + }, + { + "x": 334.8010402473093, + "y": -163.70694825369787, + "z": 1.0 + }, + { + "x": 334.8007981816428, + "y": -164.1077119037431, + "z": 1.0 + }, + { + "x": 334.80049559955967, + "y": -164.6086664662996, + "z": 1.0 + }, + { + "x": 334.80025353389317, + "y": -165.0094301163448, + "z": 1.0 + }, + { + "x": 334.80001146822667, + "y": -165.41019376639002, + "z": 1.0 + }, + { + "x": 334.79970888614355, + "y": -165.91114832894652, + "z": 1.0 + }, + { + "x": 334.7993457876438, + "y": -166.5122938040143, + "z": 1.0 + }, + { + "x": 334.79898268914405, + "y": -167.11343927908212, + "z": 1.0 + }, + { + "x": 334.79868010706093, + "y": -167.61439384163862, + "z": 1.0 + }, + { + "x": 334.7983170085612, + "y": -168.21553931670644, + "z": 1.0 + }, + { + "x": 334.7980749428947, + "y": -168.61630296675162, + "z": 1.0 + }, + { + "x": 334.79777236081156, + "y": -169.11725752930812, + "z": 1.0 + }, + { + "x": 334.7974092623118, + "y": -169.71840300437594, + "z": 1.0 + }, + { + "x": 334.79704616381207, + "y": -170.31954847944263, + "z": 1.0 + }, + { + "x": 334.79674358172895, + "y": -170.82050304199913, + "z": 1.0 + }, + { + "x": 334.79650151606245, + "y": -171.22126669204658, + "z": 1.0 + }, + { + "x": 334.7961384175627, + "y": -171.82241216711327, + "z": 1.0 + }, + { + "x": 334.7958358354796, + "y": -172.3233667296709, + "z": 1.0 + }, + { + "x": 334.79547273697983, + "y": -172.9245122047376, + "z": 1.0 + }, + { + "x": 334.7951701548967, + "y": -173.4254667672941, + "z": 1.0 + }, + { + "x": 334.7949280892302, + "y": -173.82623041733814, + "z": 1.0 + }, + { + "x": 334.79456499073046, + "y": -174.4273758924071, + "z": 1.0 + }, + { + "x": 334.79432292506397, + "y": -174.82813954245228, + "z": 1.0 + }, + { + "x": 334.7939598265642, + "y": -175.4292850175201, + "z": 1.0 + }, + { + "x": 334.7936572444811, + "y": -175.9302395800766, + "z": 1.0 + }, + { + "x": 334.793354662398, + "y": -176.4311941426331, + "z": 1.0 + }, + { + "x": 334.7931125967315, + "y": -176.83195779267828, + "z": 1.0 + }, + { + "x": 334.792870531065, + "y": -177.23272144272346, + "z": 1.0 + }, + { + "x": 334.79256794898185, + "y": -177.73367600527996, + "z": 1.0 + }, + { + "x": 334.79226536689873, + "y": -178.23463056783646, + "z": 1.0 + }, + { + "x": 334.7919627848156, + "y": -178.73558513039404, + "z": 1.0 + }, + { + "x": 334.7916602027325, + "y": -179.2365396929494, + "z": 1.0 + }, + { + "x": 334.7914181370661, + "y": -179.63730334299345, + "z": 1.0 + }, + { + "x": 334.7911760713995, + "y": -180.03806699303976, + "z": 1.0 + }, + { + "x": 334.7909340057331, + "y": -180.43883064308386, + "z": 1.0 + }, + { + "x": 334.79063142364987, + "y": -180.93978520564258, + "z": 1.0 + }, + { + "x": 334.7903893579834, + "y": -181.34054885568668, + "z": 1.0 + }, + { + "x": 334.7901472923169, + "y": -181.741312505733, + "z": 1.0 + }, + { + "x": 334.78978419381724, + "y": -182.34245798079849, + "z": 1.0 + }, + { + "x": 334.7894210953175, + "y": -182.94360345586625, + "z": 1.0 + }, + { + "x": 334.7891790296509, + "y": -183.34436710591376, + "z": 1.0 + }, + { + "x": 334.7889369639845, + "y": -183.74513075595667, + "z": 1.0 + }, + { + "x": 334.7886343819014, + "y": -184.2460853185143, + "z": 1.0 + }, + { + "x": 334.78839231623476, + "y": -184.64684896856062, + "z": 1.0 + }, + { + "x": 334.78808973415175, + "y": -185.14780353111593, + "z": 1.0 + }, + { + "x": 334.78778715206863, + "y": -185.64875809367243, + "z": 1.0 + }, + { + "x": 334.7875444119521, + "y": -186.050638362244, + "z": 1.0 + }, + { + "x": 334.78718030177754, + "y": -186.65345876510128, + "z": 1.0 + }, + { + "x": 334.78693756166115, + "y": -187.0553390336716, + "z": 1.0 + }, + { + "x": 334.78669482154476, + "y": -187.4572193022454, + "z": 1.0 + }, + { + "x": 334.78645208142837, + "y": -187.85909957081577, + "z": 1.0 + }, + { + "x": 334.7860879712538, + "y": -188.461919973673, + "z": 1.0 + }, + { + "x": 334.7858452311374, + "y": -188.86380024224337, + "z": 1.0 + }, + { + "x": 334.7856024910209, + "y": -189.2656805108171, + "z": 1.0 + }, + { + "x": 334.7852990658754, + "y": -189.7680308465292, + "z": 1.0 + }, + { + "x": 334.7849349557008, + "y": -190.37085124938875, + "z": 1.0 + }, + { + "x": 334.7845708455262, + "y": -190.97367165224483, + "z": 1.0 + }, + { + "x": 334.78420673535163, + "y": -191.57649205510205, + "z": 1.0 + }, + { + "x": 334.7839639952351, + "y": -191.97837232367357, + "z": 1.0 + }, + { + "x": 334.78372125511873, + "y": -192.38025259224509, + "z": 1.0 + }, + { + "x": 334.78335714494415, + "y": -192.98307299510117, + "z": 1.0 + }, + { + "x": 334.78311440482776, + "y": -193.38495326367382, + "z": 1.0 + }, + { + "x": 334.78275029465317, + "y": -193.98777366653104, + "z": 1.0 + }, + { + "x": 334.7824468695077, + "y": -194.4901240022454, + "z": 1.0 + }, + { + "x": 334.7822041293913, + "y": -194.89200427081693, + "z": 1.0 + }, + { + "x": 334.7819007042457, + "y": -195.3943546065313, + "z": 1.0 + }, + { + "x": 334.7816579641293, + "y": -195.79623487510275, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 31, + "heading": [ + -1.571400337755052, + -1.5714003377550565, + -1.571400337755056, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.571400337755055, + -1.5714003377549615, + -1.5714003377550554, + -1.5714003377551675, + -1.5714003377549528, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377549302, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.571400337755056, + -1.571400337755056, + -1.5714003377550538, + -1.5714003377550547, + -1.5714003377550554, + -1.5714003377550554, + -1.571400337755056, + -1.5714003377550563, + -1.5714003377550554, + -1.5714003377550547, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550547, + -1.5714003377550554, + -1.5714003377549308, + -1.5714003377550554, + -1.5714003377550554, + -1.5714003377550547, + -1.5714003377551808, + -1.5714003377550554, + -1.5714003377549426, + -1.5714003377549621, + -1.5714003377551675, + -1.5714003377550554, + -1.5714003377549302, + -1.57140033775518, + -1.5714003377550554, + -1.5714003377549426, + -1.5714003377551624, + -1.5714003377551262, + -1.5714003377550139, + -1.5714003377550123, + -1.5714003377550123, + -1.5714003377550139, + -1.5714003377550139, + -1.5714003377551538, + -1.571400337755139, + -1.5714003377550132, + -1.5714003377550128, + -1.5714003377550139, + -1.5714003377551264, + -1.5714003377551546, + -1.5714003377550139, + -1.5714003377550132, + -1.5714003377550125, + -1.5714003377550132, + -1.5714003377550132, + -1.5714003377551389, + -1.571400337755139 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -0.003630984997471387, + "y": -6.011454750666871 + }, + { + "x": -0.006051641662452312, + "y": -10.019091251118653 + }, + { + "x": -0.0054464774962070805, + "y": -9.017182126016792 + }, + { + "x": -0.006051641662452312, + "y": -10.019091251130021 + }, + { + "x": -0.006051641662452312, + "y": -10.019091251130021 + }, + { + "x": -0.006656805828697543, + "y": -11.021000376242682 + }, + { + "x": -0.006656805828697543, + "y": -11.021000376242682 + }, + { + "x": -0.0054464774962070805, + "y": -9.017182126016792 + }, + { + "x": -0.004841313329961849, + "y": -8.01527300090413 + }, + { + "x": -0.0054464774962070805, + "y": -9.01718212601736 + }, + { + "x": -0.006656805828697543, + "y": -11.021000376242682 + }, + { + "x": -0.006656805828697543, + "y": -11.021000376242682 + }, + { + "x": -0.006656805828697543, + "y": -11.021000376242682 + }, + { + "x": -0.007261969994942774, + "y": -12.022909501355912 + }, + { + "x": -0.007261969994942774, + "y": -12.02290950136728 + }, + { + "x": -0.007261969993805906, + "y": -12.022909501344543 + }, + { + "x": -0.006656805828697543, + "y": -11.02100037624325 + }, + { + "x": -0.00605164166358918, + "y": -10.019091251152759 + }, + { + "x": -0.0066568058275606745, + "y": -11.021000376231882 + }, + { + "x": -0.006656805828697543, + "y": -11.02100037624325 + }, + { + "x": -0.006051641662452312, + "y": -10.019091251130021 + }, + { + "x": -0.005446477495070212, + "y": -9.017182126005423 + }, + { + "x": -0.0054464774962070805, + "y": -9.017182126016792 + }, + { + "x": -0.006051641662452312, + "y": -10.019091251130021 + }, + { + "x": -0.0054464774962070805, + "y": -9.01718212601736 + }, + { + "x": -0.0054464774962070805, + "y": -9.01718212601736 + }, + { + "x": -0.0054464774962070805, + "y": -9.017182126016792 + }, + { + "x": -0.004841313329961849, + "y": -8.01527300090413 + }, + { + "x": -0.0054464774962070805, + "y": -9.01718212601736 + }, + { + "x": -0.006656805828697543, + "y": -11.021000376242682 + }, + { + "x": -0.007261969994942774, + "y": -12.022909501355912 + }, + { + "x": -0.006656805828697543, + "y": -11.02100037624325 + }, + { + "x": -0.006656805828697543, + "y": -11.02100037624325 + }, + { + "x": -0.006051641662452312, + "y": -10.019091251130021 + }, + { + "x": -0.0054464774962070805, + "y": -9.017182126016792 + }, + { + "x": -0.006656805828697543, + "y": -11.02100037624325 + }, + { + "x": -0.007261969994942774, + "y": -12.022909501345111 + }, + { + "x": -0.006656805828697543, + "y": -11.021000376231882 + }, + { + "x": -0.0054464774962070805, + "y": -9.017182126039529 + }, + { + "x": -0.006051641662452312, + "y": -10.01909125114139 + }, + { + "x": -0.006656805828697543, + "y": -11.02100037624325 + }, + { + "x": -0.006656805828697543, + "y": -11.02100037624325 + }, + { + "x": -0.006656805828697543, + "y": -11.021000376231882 + }, + { + "x": -0.0054464774962070805, + "y": -9.017182126005423 + }, + { + "x": -0.006051641662452312, + "y": -10.019091251130021 + }, + { + "x": -0.006051641662452312, + "y": -10.01909125114139 + }, + { + "x": -0.006051641662452312, + "y": -10.019091251130021 + }, + { + "x": -0.006656805828697543, + "y": -11.02100037624325 + }, + { + "x": -0.006051641662452312, + "y": -10.019091251130021 + }, + { + "x": -0.0054464774962070805, + "y": -9.017182126016792 + }, + { + "x": -0.004841313329961849, + "y": -8.015273000903562 + }, + { + "x": -0.0054464774962070805, + "y": -9.017182126016792 + }, + { + "x": -0.006051641662452312, + "y": -10.019091251130021 + }, + { + "x": -0.006051641662452312, + "y": -10.019091251140821 + }, + { + "x": -0.006051641662452312, + "y": -10.019091251129453 + }, + { + "x": -0.005446477495070212, + "y": -9.017182125994054 + }, + { + "x": -0.004841313329961849, + "y": -8.015273000903562 + }, + { + "x": -0.004841313329961849, + "y": -8.01527300090413 + }, + { + "x": -0.0054464774962070805, + "y": -9.01718212602816 + }, + { + "x": -0.005446477497343949, + "y": -9.01718212602816 + }, + { + "x": -0.004841313329961849, + "y": -8.01527300090413 + }, + { + "x": -0.006051641661315443, + "y": -10.019091251118084 + }, + { + "x": -0.007261969993805906, + "y": -12.022909501332606 + }, + { + "x": -0.00605164166358918, + "y": -10.019091251152759 + }, + { + "x": -0.004841313329961849, + "y": -8.01527300090413 + }, + { + "x": -0.005446477495070212, + "y": -9.017182126005423 + }, + { + "x": -0.005446477497343949, + "y": -9.017182126039529 + }, + { + "x": -0.0054464774962070805, + "y": -9.017182126016223 + }, + { + "x": -0.006051641661315443, + "y": -10.019091251118084 + }, + { + "x": -0.005453221996276625, + "y": -9.028348311280752 + }, + { + "x": -0.00606850291092087, + "y": -10.0470067142885 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714275994 + }, + { + "x": -0.004854802327827201, + "y": -8.037605371441146 + }, + { + "x": -0.004854802327827201, + "y": -8.037605371441714 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714275994 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714275994 + }, + { + "x": -0.00485480232896407, + "y": -8.037605371441146 + }, + { + "x": -0.00546165261994247, + "y": -9.042306042858286 + }, + { + "x": -0.006675353200762402, + "y": -11.05170738571644 + }, + { + "x": -0.007282203491740802, + "y": -12.056408057156318 + }, + { + "x": -0.007282203491740802, + "y": -12.056408057133012 + }, + { + "x": -0.00606850291092087, + "y": -10.047006714287363 + }, + { + "x": -0.00485480232896407, + "y": -8.037605371430345 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714275994 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714287363 + }, + { + "x": -0.0060685029097840015, + "y": -10.047006714298732 + }, + { + "x": -0.006675353200762402, + "y": -11.051707385715872 + }, + { + "x": -0.005461652618805601, + "y": -9.042306042858854 + }, + { + "x": -0.00546165261994247, + "y": -9.042306042858854 + }, + { + "x": -0.00546165261994247, + "y": -9.042306042858286 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 334.7816579641293, + "y": -195.79623487510275, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + }, + { + "position": [ + { + "x": 333.4145457505004, + "y": -126.94869021368251, + "z": 1.0 + }, + { + "x": 333.11065915516724, + "y": -127.28159127629539, + "z": 1.0 + }, + { + "x": 332.8388202990402, + "y": -127.5408461529031, + "z": 1.0 + }, + { + "x": 332.4740998353168, + "y": -127.84544927046008, + "z": 1.0 + }, + { + "x": 332.21851234968426, + "y": -128.0375613087877, + "z": 1.0 + }, + { + "x": 331.8883716074788, + "y": -128.26280080705058, + "z": 1.0 + }, + { + "x": 331.5471902743561, + "y": -128.47094126593532, + "z": 1.0 + }, + { + "x": 331.2668891448755, + "y": -128.62477820697123, + "z": 1.0 + }, + { + "x": 330.90852362645415, + "y": -128.8004960130125, + "z": 1.0 + }, + { + "x": 330.5411803754363, + "y": -128.95793338659394, + "z": 1.0 + }, + { + "x": 330.2418326926179, + "y": -129.07028837051308, + "z": 1.0 + }, + { + "x": 329.86162131658267, + "y": -129.19343286851142, + "z": 1.0 + }, + { + "x": 329.39783113296505, + "y": -129.31541954743648, + "z": 1.0 + }, + { + "x": 329.0062340233228, + "y": -129.39527707047642, + "z": 1.0 + }, + { + "x": 328.69034455550616, + "y": -129.44474248388758, + "z": 1.0 + }, + { + "x": 328.2930775110379, + "y": -129.4884137314665, + "z": 1.0 + }, + { + "x": 327.89463092744916, + "y": -129.51171443296764, + "z": 1.0 + }, + { + "x": 327.4468638830473, + "y": -129.51589217222232, + "z": 1.0 + }, + { + "x": 326.8449815717829, + "y": -129.51562325499071, + "z": 1.0 + }, + { + "x": 326.4437266976067, + "y": -129.5154439768363, + "z": 1.0 + }, + { + "x": 325.84184438634173, + "y": -129.5151750596047, + "z": 1.0 + }, + { + "x": 325.6412169492547, + "y": -129.5150854205275, + "z": 1.0 + }, + { + "x": 325.24065291057445, + "y": -129.51490645103408, + "z": 1.0 + }, + { + "x": 324.64033168535275, + "y": -129.51463823128591, + "z": 1.0 + }, + { + "x": 324.0400104601322, + "y": -129.51437001153772, + "z": 1.0 + }, + { + "x": 323.5397427724479, + "y": -129.51414649508092, + "z": 1.0 + }, + { + "x": 322.93942154722663, + "y": -129.51387827533276, + "z": 1.0 + }, + { + "x": 322.3391003220055, + "y": -129.51361005558456, + "z": 1.0 + }, + { + "x": 321.93888617185803, + "y": -129.51343124241913, + "z": 1.0 + }, + { + "x": 321.5386720217107, + "y": -129.51325242925367, + "z": 1.0 + }, + { + "x": 321.1384578715632, + "y": -129.51307361608823, + "z": 1.0 + }, + { + "x": 320.5381366463421, + "y": -129.51280539634007, + "z": 1.0 + }, + { + "x": 319.93781542112094, + "y": -129.51253717659188, + "z": 1.0 + }, + { + "x": 319.43754773343665, + "y": -129.51231366013508, + "z": 1.0 + }, + { + "x": 318.93728004575235, + "y": -129.51209014367828, + "z": 1.0 + }, + { + "x": 318.43701235806805, + "y": -129.51186662722145, + "z": 1.0 + }, + { + "x": 318.0367982079206, + "y": -129.51168781405602, + "z": 1.0 + }, + { + "x": 317.6365840577731, + "y": -129.51150900089056, + "z": 1.0 + }, + { + "x": 317.23636990762566, + "y": -129.51133018772512, + "z": 1.0 + }, + { + "x": 316.73610221994136, + "y": -129.5111066712683, + "z": 1.0 + }, + { + "x": 316.1357809947202, + "y": -129.51083845152013, + "z": 1.0 + }, + { + "x": 315.5354597694991, + "y": -129.51057023177196, + "z": 1.0 + }, + { + "x": 315.1352456193516, + "y": -129.5103914186065, + "z": 1.0 + }, + { + "x": 314.5349243941305, + "y": -129.51012319885834, + "z": 1.0 + }, + { + "x": 313.93460316890935, + "y": -129.50985497911017, + "z": 1.0 + }, + { + "x": 313.5343890187619, + "y": -129.5096761659447, + "z": 1.0 + }, + { + "x": 313.0341213310776, + "y": -129.5094526494879, + "z": 1.0 + }, + { + "x": 312.5338536433933, + "y": -129.5092291330311, + "z": 1.0 + }, + { + "x": 312.033585955709, + "y": -129.50900561657429, + "z": 1.0 + }, + { + "x": 311.6333718055615, + "y": -129.50882680340885, + "z": 1.0 + }, + { + "x": 311.0330505803404, + "y": -129.5085585836607, + "z": 1.0 + }, + { + "x": 310.43272935511925, + "y": -129.5082903639125, + "z": 1.0 + }, + { + "x": 309.8324081298981, + "y": -129.50802214416433, + "z": 1.0 + }, + { + "x": 309.43219397975065, + "y": -129.5078433309989, + "z": 1.0 + }, + { + "x": 308.93192629206635, + "y": -129.50761981454207, + "z": 1.0 + }, + { + "x": 308.5317121419189, + "y": -129.50744100137663, + "z": 1.0 + }, + { + "x": 308.13149799177154, + "y": -129.50726218821117, + "z": 1.0 + }, + { + "x": 307.7312838416241, + "y": -129.50708337504574, + "z": 1.0 + }, + { + "x": 307.13096261640237, + "y": -129.50681515529757, + "z": 1.0 + }, + { + "x": 306.5306413911818, + "y": -129.50654693554938, + "z": 1.0 + }, + { + "x": 305.93032016596055, + "y": -129.50627871580122, + "z": 1.0 + }, + { + "x": 305.43005247827625, + "y": -129.50605519934442, + "z": 1.0 + }, + { + "x": 304.8297312530551, + "y": -129.50578697959622, + "z": 1.0 + }, + { + "x": 304.229410027834, + "y": -129.50551875984806, + "z": 1.0 + }, + { + "x": 303.7291423401497, + "y": -129.50529524339126, + "z": 1.0 + }, + { + "x": 303.3289281900022, + "y": -129.5051164302258, + "z": 1.0 + }, + { + "x": 302.8286605023179, + "y": -129.504892913769, + "z": 1.0 + }, + { + "x": 302.2283392770968, + "y": -129.50462469402083, + "z": 1.0 + }, + { + "x": 301.7280715894125, + "y": -129.504401177564, + "z": 1.0 + }, + { + "x": 301.327857439265, + "y": -129.50422236439857, + "z": 1.0 + }, + { + "x": 300.7275362140433, + "y": -129.5039541446504, + "z": 1.0 + }, + { + "x": 300.3273220638964, + "y": -129.50377533148495, + "z": 1.0 + }, + { + "x": 299.8270543762121, + "y": -129.50355181502815, + "z": 1.0 + }, + { + "x": 299.3267866885278, + "y": -129.50332829857132, + "z": 1.0 + }, + { + "x": 298.92657253838047, + "y": -129.50314948540588, + "z": 1.0 + }, + { + "x": 298.32625131315876, + "y": -129.50288126565772, + "z": 1.0 + }, + { + "x": 297.82598362547503, + "y": -129.5026577492009, + "z": 1.0 + }, + { + "x": 297.2256624002538, + "y": -129.50238952945273, + "z": 1.0 + }, + { + "x": 296.7253947125689, + "y": -129.50216601299593, + "z": 1.0 + }, + { + "x": 296.12507348734835, + "y": -129.50189779324774, + "z": 1.0 + }, + { + "x": 295.7248593372009, + "y": -129.5017189800823, + "z": 1.0 + }, + { + "x": 295.1245381119792, + "y": -129.50145076033414, + "z": 1.0 + }, + { + "x": 294.7243239618324, + "y": -129.50127194716868, + "z": 1.0 + }, + { + "x": 294.32410981168437, + "y": -129.50109313400324, + "z": 1.0 + }, + { + "x": 293.82384212400063, + "y": -129.5008696175464, + "z": 1.0 + }, + { + "x": 293.4236279738532, + "y": -129.50069080438098, + "z": 1.0 + }, + { + "x": 292.9233602861689, + "y": -129.50046728792415, + "z": 1.0 + }, + { + "x": 292.32303906094774, + "y": -129.500199068176, + "z": 1.0 + }, + { + "x": 291.9228249108003, + "y": -129.50002025501055, + "z": 1.0 + }, + { + "x": 291.32250368557914, + "y": -129.49975203526236, + "z": 1.0 + }, + { + "x": 290.9222895354317, + "y": -129.49957322209693, + "z": 1.0 + } + ], + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": 32, + "heading": [ + 1.9659351147996624, + -2.3106621792270796, + -2.342126791184687, + -2.4166839819179406, + -2.4663910593611247, + -2.5225037539646777, + -2.5683436896219303, + -2.614183605833329, + -2.6652237205605016, + -2.7112171490512793, + -2.757063638376234, + -2.8079968773903605, + -2.858930107778461, + -2.9098633595080114, + -2.960796591246271, + -3.011729844024768, + -3.057624659728072, + -3.1091318330827113, + -3.1378687395670917, + 3.141145859908236, + 3.141145859908236, + 3.1411458599082356, + 3.1411458599082875, + 3.141145859908284, + 3.14114585990824, + 3.141145859908242, + 3.141145859908268, + 3.14114585990824, + 3.1411458599082445, + 3.1411458599082516, + 3.1411458599082516, + 3.141145859908273, + 3.14114585990824, + 3.1411458599082422, + 3.141145859908273, + 3.1411458599082445, + 3.141145859908248, + 3.1411458599082516, + 3.1411458599082516, + 3.141145859908248, + 3.1411458599082422, + 3.1411458599082636, + 3.1411458599082445, + 3.1411458599082445, + 3.1411458599082636, + 3.1411458599082445, + 3.141145859908248, + 3.141145859908273, + 3.1411458599082445, + 3.141145859908248, + 3.141145859908273, + 3.14114585990824, + 3.14114585990824, + 3.141145859908273, + 3.141145859908248, + 3.141145859908248, + 3.1411458599082516, + 3.1411458599082516, + 3.1411458599082733, + 3.14114585990824, + 3.1411458599082396, + 3.141145859908268, + 3.1411458599082422, + 3.14114585990824, + 3.141145859908268, + 3.141145859908248, + 3.141145859908248, + 3.141145859908268, + 3.1411458599082422, + 3.141145859908248, + 3.1411458599082733, + 3.1411458599082445, + 3.1411458599082476, + 3.1411458599082445, + 3.1411458599082476, + 3.1411458599082733, + 3.1411458599082422, + 3.141145859908242, + 3.141145859908268, + 3.1411458599082422, + 3.1411458599082445, + 3.1411458599082733, + 3.1411458599082445, + 3.1411458599082516, + 3.141145859908248, + 3.1411458599082476, + 3.141145859908248, + 3.1411458599082422, + 3.141145859908273, + 3.1411458599082445, + 3.1411458599082445 + ], + "velocity": [ + { + "x": 0.0, + "y": 0.0 + }, + { + "x": -3.0388659533315376, + "y": -3.3290106261287633 + }, + { + "x": -5.757254514601868, + "y": -5.921559392205893 + }, + { + "x": -6.3655931985044845, + "y": -5.638579941646924 + }, + { + "x": -6.203079493559471, + "y": -4.9671515588460124 + }, + { + "x": -5.857282278379898, + "y": -4.173515365905018 + }, + { + "x": -6.713220753281348, + "y": -4.33379957147622 + }, + { + "x": -6.214824626032964, + "y": -3.6197739992064726 + }, + { + "x": -6.386666479019709, + "y": -3.2955474707716803 + }, + { + "x": -7.257087694392226, + "y": -3.3315517962270746 + }, + { + "x": -6.666909338362643, + "y": -2.697923575005916 + }, + { + "x": -6.795590588536129, + "y": -2.3549948191748626 + }, + { + "x": -8.440015596528383, + "y": -2.4513117692339392 + }, + { + "x": -8.553872932598665, + "y": -2.018442019650024 + }, + { + "x": -7.074865774588943, + "y": -1.2932293645110349 + }, + { + "x": -7.131565122849111, + "y": -0.9313666099006923 + }, + { + "x": -7.957136280570012, + "y": -0.6697194908005599 + }, + { + "x": -8.462136279906076, + "y": -0.27478440755828615 + }, + { + "x": -10.496493556662472, + "y": -0.039088220230780735 + }, + { + "x": -10.031371854406075, + "y": 0.004481953860135945 + }, + { + "x": -10.03137185441176, + "y": 0.004481953860135945 + }, + { + "x": -8.025097483519517, + "y": 0.0035855630881087563 + }, + { + "x": -6.011914757672798, + "y": 0.0026860857062160903 + }, + { + "x": -10.008852639019779, + "y": 0.00447189241583601 + }, + { + "x": -12.00642450442274, + "y": 0.005364394963578434 + }, + { + "x": -11.005889129048683, + "y": 0.004917362049923213 + }, + { + "x": -11.005889129055504, + "y": 0.004917362049638996 + }, + { + "x": -12.006424504423876, + "y": 0.005364394963578434 + }, + { + "x": -10.005353753685995, + "y": 0.004470329136267992 + }, + { + "x": -8.004283002948114, + "y": 0.00357626330895755 + }, + { + "x": -8.004283002948114, + "y": 0.00357626330895755 + }, + { + "x": -10.005353753685995, + "y": 0.004470329135983775 + }, + { + "x": -12.00642450442274, + "y": 0.005364394963578434 + }, + { + "x": -11.005889129054367, + "y": 0.004917362049923213 + }, + { + "x": -10.005353753685995, + "y": 0.004470329135983775 + }, + { + "x": -10.005353753685995, + "y": 0.004470329136267992 + }, + { + "x": -9.004818378317623, + "y": 0.004023296222612771 + }, + { + "x": -8.00428300294925, + "y": 0.00357626330895755 + }, + { + "x": -8.00428300294925, + "y": 0.00357626330895755 + }, + { + "x": -9.004818378317623, + "y": 0.004023296222612771 + }, + { + "x": -11.005889129054367, + "y": 0.004917362049923213 + }, + { + "x": -12.00642450442274, + "y": 0.005364394963294217 + }, + { + "x": -10.005353753685995, + "y": 0.004470329136267992 + }, + { + "x": -10.005353753685995, + "y": 0.004470329136267992 + }, + { + "x": -12.00642450442274, + "y": 0.005364394963294217 + }, + { + "x": -10.005353753685995, + "y": 0.004470329136267992 + }, + { + "x": -9.004818378317623, + "y": 0.004023296222612771 + }, + { + "x": -10.005353753685995, + "y": 0.004470329135983775 + }, + { + "x": -10.005353753685995, + "y": 0.004470329136267992 + }, + { + "x": -9.004818378317623, + "y": 0.004023296222612771 + }, + { + "x": -10.005353753685995, + "y": 0.004470329135983775 + }, + { + "x": -12.00642450442274, + "y": 0.005364394963578434 + }, + { + "x": -12.00642450442274, + "y": 0.005364394963578434 + }, + { + "x": -10.005353753685995, + "y": 0.004470329135983775 + }, + { + "x": -9.004818378317623, + "y": 0.004023296222612771 + }, + { + "x": -9.004818378317623, + "y": 0.004023296222612771 + }, + { + "x": -8.004283002948114, + "y": 0.00357626330895755 + }, + { + "x": -8.004283002948114, + "y": 0.00357626330895755 + }, + { + "x": -10.00535375369168, + "y": 0.004470329135983775 + }, + { + "x": -12.00642450442274, + "y": 0.005364394963578434 + }, + { + "x": -12.006424504418192, + "y": 0.005364394963578434 + }, + { + "x": -11.005889129055504, + "y": 0.004917362049638996 + }, + { + "x": -11.005889129054367, + "y": 0.004917362049923213 + }, + { + "x": -12.00642450442274, + "y": 0.005364394963578434 + }, + { + "x": -11.005889129054367, + "y": 0.004917362049638996 + }, + { + "x": -9.004818378317623, + "y": 0.004023296222612771 + }, + { + "x": -9.004818378317623, + "y": 0.004023296222612771 + }, + { + "x": -11.005889129054367, + "y": 0.004917362049638996 + }, + { + "x": -11.005889129054367, + "y": 0.004917362049923213 + }, + { + "x": -9.004818378317623, + "y": 0.004023296222612771 + }, + { + "x": -10.00535375369168, + "y": 0.004470329135983775 + }, + { + "x": -10.005353753685995, + "y": 0.004470329136267992 + }, + { + "x": -9.004818378311938, + "y": 0.004023296222612771 + }, + { + "x": -10.005353753685995, + "y": 0.004470329136267992 + }, + { + "x": -9.004818378316486, + "y": 0.004023296222612771 + }, + { + "x": -10.005353753690542, + "y": 0.004470329135983775 + }, + { + "x": -11.005889129054367, + "y": 0.004917362049923213 + }, + { + "x": -11.00588912904982, + "y": 0.004917362049923213 + }, + { + "x": -11.005889129061188, + "y": 0.004917362049638996 + }, + { + "x": -11.005889129054367, + "y": 0.004917362049923213 + }, + { + "x": -10.00535375368031, + "y": 0.004470329136267992 + }, + { + "x": -10.00535375369168, + "y": 0.004470329135983775 + }, + { + "x": -10.005353753684858, + "y": 0.004470329136267992 + }, + { + "x": -8.004283002948114, + "y": 0.00357626330895755 + }, + { + "x": -9.004818378317623, + "y": 0.004023296222612771 + }, + { + "x": -9.004818378311938, + "y": 0.004023296222612771 + }, + { + "x": -9.004818378317623, + "y": 0.004023296222612771 + }, + { + "x": -11.005889129054367, + "y": 0.004917362049923213 + }, + { + "x": -10.005353753685995, + "y": 0.004470329135983775 + }, + { + "x": -10.005353753685995, + "y": 0.004470329136267992 + }, + { + "x": -10.005353753685995, + "y": 0.004470329136267992 + } + ], + "valid": [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true + ], + "goalPosition": { + "x": 290.9222895354317, + "y": -129.49957322209693, + "z": 1.0 + }, + "type": "vehicle", + "mark_as_expert": false + } + ], + "roads": [ + { + "id": 0, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 348.227876521873, + "y": -4.0006836701775725, + "z": 0.0 + }, + { + "x": 349.26673351814094, + "y": -4.001235549176161, + "z": 0.0 + }, + { + "x": 350.3055905144089, + "y": -4.001787428174748, + "z": 0.0 + }, + { + "x": 351.34444751067684, + "y": -4.002339307173337, + "z": 0.0 + }, + { + "x": 352.3833045069448, + "y": -4.002891186171924, + "z": 0.0 + }, + { + "x": 353.42216150321275, + "y": -4.0034430651705115, + "z": 0.0 + }, + { + "x": 354.4610184994807, + "y": -4.0039949441691, + "z": 0.0 + }, + { + "x": 355.49987549574865, + "y": -4.004546823167687, + "z": 0.0 + }, + { + "x": 356.5387324920166, + "y": -4.005098702166276, + "z": 0.0 + }, + { + "x": 357.57758948828456, + "y": -4.005650581164863, + "z": 0.0 + }, + { + "x": 358.6164464845525, + "y": -4.006202460163451, + "z": 0.0 + }, + { + "x": 359.65530348082046, + "y": -4.006754339162039, + "z": 0.0 + }, + { + "x": 360.6941604770884, + "y": -4.007306218160627, + "z": 0.0 + }, + { + "x": 361.7330174733564, + "y": -4.007858097159215, + "z": 0.0 + }, + { + "x": 362.7718744696244, + "y": -4.008409976157803, + "z": 0.0 + }, + { + "x": 363.81073146589233, + "y": -4.00896185515639, + "z": 0.0 + }, + { + "x": 364.8495884621603, + "y": -4.009513734154979, + "z": 0.0 + }, + { + "x": 365.88844545842824, + "y": -4.010065613153566, + "z": 0.0 + }, + { + "x": 366.9273024546962, + "y": -4.0106174921521545, + "z": 0.0 + }, + { + "x": 367.96615945096414, + "y": -4.011169371150742, + "z": 0.0 + }, + { + "x": 369.0050164472321, + "y": -4.011721250149329, + "z": 0.0 + }, + { + "x": 370.04387344350005, + "y": -4.012273129147918, + "z": 0.0 + }, + { + "x": 371.082730439768, + "y": -4.012825008146505, + "z": 0.0 + }, + { + "x": 372.12158743603595, + "y": -4.013376887145093, + "z": 0.0 + }, + { + "x": 373.1604444323039, + "y": -4.013928766143681, + "z": 0.0 + }, + { + "x": 374.19930142857186, + "y": -4.014480645142269, + "z": 0.0 + }, + { + "x": 375.2381584248398, + "y": -4.015032524140857, + "z": 0.0 + }, + { + "x": 376.27701542110776, + "y": -4.015584403139445, + "z": 0.0 + }, + { + "x": 377.3158724173757, + "y": -4.016136282138032, + "z": 0.0 + }, + { + "x": 378.35472941364367, + "y": -4.016688161136621, + "z": 0.0 + }, + { + "x": 379.3935864099116, + "y": -4.017240040135208, + "z": 0.0 + }, + { + "x": 380.4324434061796, + "y": -4.0177919191337965, + "z": 0.0 + }, + { + "x": 381.4713004024475, + "y": -4.018343798132384, + "z": 0.0 + }, + { + "x": 382.5101573987155, + "y": -4.018895677130972, + "z": 0.0 + }, + { + "x": 383.54901439498343, + "y": -4.01944755612956, + "z": 0.0 + }, + { + "x": 384.5878713912514, + "y": -4.019999435128147, + "z": 0.0 + } + ] + }, + { + "id": 1, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 384.59212128452987, + "y": 3.9799994360222173, + "z": 0.0 + }, + { + "x": 383.5532642882619, + "y": 3.980551315020805, + "z": 0.0 + }, + { + "x": 382.51440729199396, + "y": 3.981103194019393, + "z": 0.0 + }, + { + "x": 381.475550295726, + "y": 3.981655073017981, + "z": 0.0 + }, + { + "x": 380.43669329945806, + "y": 3.982206952016569, + "z": 0.0 + }, + { + "x": 379.3978363031901, + "y": 3.9827588310151567, + "z": 0.0 + }, + { + "x": 378.35897930692215, + "y": 3.9833107100137446, + "z": 0.0 + }, + { + "x": 377.3201223106542, + "y": 3.9838625890123325, + "z": 0.0 + }, + { + "x": 376.28126531438625, + "y": 3.9844144680109204, + "z": 0.0 + }, + { + "x": 375.2424083181183, + "y": 3.984966347009508, + "z": 0.0 + }, + { + "x": 374.20355132185034, + "y": 3.9855182260080957, + "z": 0.0 + }, + { + "x": 373.1646943255824, + "y": 3.9860701050066836, + "z": 0.0 + }, + { + "x": 372.12583732931444, + "y": 3.9866219840052715, + "z": 0.0 + }, + { + "x": 371.0869803330465, + "y": 3.9871738630038593, + "z": 0.0 + }, + { + "x": 370.04812333677853, + "y": 3.9877257420024472, + "z": 0.0 + }, + { + "x": 369.0092663405106, + "y": 3.988277621001035, + "z": 0.0 + }, + { + "x": 367.9704093442426, + "y": 3.988829499999623, + "z": 0.0 + }, + { + "x": 366.9315523479747, + "y": 3.989381378998211, + "z": 0.0 + }, + { + "x": 365.8926953517067, + "y": 3.9899332579967988, + "z": 0.0 + }, + { + "x": 364.85383835543877, + "y": 3.9904851369953867, + "z": 0.0 + }, + { + "x": 363.8149813591708, + "y": 3.9910370159939745, + "z": 0.0 + }, + { + "x": 362.77612436290286, + "y": 3.9915888949925624, + "z": 0.0 + }, + { + "x": 361.7372673666349, + "y": 3.9921407739911503, + "z": 0.0 + }, + { + "x": 360.6984103703669, + "y": 3.992692652989738, + "z": 0.0 + }, + { + "x": 359.65955337409895, + "y": 3.9932445319883256, + "z": 0.0 + }, + { + "x": 358.620696377831, + "y": 3.9937964109869135, + "z": 0.0 + }, + { + "x": 357.58183938156304, + "y": 3.9943482899855014, + "z": 0.0 + }, + { + "x": 356.5429823852951, + "y": 3.9949001689840893, + "z": 0.0 + }, + { + "x": 355.50412538902714, + "y": 3.995452047982677, + "z": 0.0 + }, + { + "x": 354.4652683927592, + "y": 3.996003926981265, + "z": 0.0 + }, + { + "x": 353.42641139649123, + "y": 3.996555805979853, + "z": 0.0 + }, + { + "x": 352.3875544002233, + "y": 3.997107684978441, + "z": 0.0 + }, + { + "x": 351.3486974039553, + "y": 3.9976595639770287, + "z": 0.0 + }, + { + "x": 350.3098404076874, + "y": 3.9982114429756166, + "z": 0.0 + }, + { + "x": 349.2709834114194, + "y": 3.9987633219742045, + "z": 0.0 + }, + { + "x": 348.23212641515147, + "y": 3.9993152009727924, + "z": 0.0 + } + ] + }, + { + "id": 2, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 384.5899963378906, + "y": -0.019999999552965164, + "z": 0.0 + }, + { + "x": 383.5511393416227, + "y": -0.019448120554377307, + "z": 0.0 + }, + { + "x": 382.5122823453547, + "y": -0.01889624155578945, + "z": 0.0 + }, + { + "x": 381.47342534908677, + "y": -0.018344362557201593, + "z": 0.0 + }, + { + "x": 380.4345683528188, + "y": -0.017792483558613733, + "z": 0.0 + }, + { + "x": 379.39571135655086, + "y": -0.017240604560025876, + "z": 0.0 + }, + { + "x": 378.3568543602829, + "y": -0.01668872556143802, + "z": 0.0 + }, + { + "x": 377.31799736401496, + "y": -0.016136846562850162, + "z": 0.0 + }, + { + "x": 376.279140367747, + "y": -0.015584967564262307, + "z": 0.0 + }, + { + "x": 375.24028337147905, + "y": -0.01503308856567445, + "z": 0.0 + }, + { + "x": 374.2014263752111, + "y": -0.014481209567086591, + "z": 0.0 + }, + { + "x": 373.16256937894315, + "y": -0.013929330568498734, + "z": 0.0 + }, + { + "x": 372.1237123826752, + "y": -0.013377451569910877, + "z": 0.0 + }, + { + "x": 371.08485538640724, + "y": -0.01282557257132305, + "z": 0.0 + }, + { + "x": 370.0459983901393, + "y": -0.012273693572735195, + "z": 0.0 + }, + { + "x": 369.00714139387134, + "y": -0.011721814574147336, + "z": 0.0 + }, + { + "x": 367.9682843976034, + "y": -0.01116993557555948, + "z": 0.0 + }, + { + "x": 366.92942740133543, + "y": -0.01061805657697162, + "z": 0.0 + }, + { + "x": 365.8905704050675, + "y": -0.010066177578383764, + "z": 0.0 + }, + { + "x": 364.8517134087995, + "y": -0.009514298579795905, + "z": 0.0 + }, + { + "x": 363.8128564125316, + "y": -0.008962419581208046, + "z": 0.0 + }, + { + "x": 362.7739994162636, + "y": -0.00841054058262019, + "z": 0.0 + }, + { + "x": 361.73514241999567, + "y": -0.00785866158403233, + "z": 0.0 + }, + { + "x": 360.69628542372766, + "y": -0.007306782585444471, + "z": 0.0 + }, + { + "x": 359.6574284274597, + "y": -0.006754903586856614, + "z": 0.0 + }, + { + "x": 358.61857143119175, + "y": -0.0062030245882687554, + "z": 0.0 + }, + { + "x": 357.5797144349238, + "y": -0.005651145589680897, + "z": 0.0 + }, + { + "x": 356.54085743865585, + "y": -0.00509926659109304, + "z": 0.0 + }, + { + "x": 355.5020004423879, + "y": -0.004547387592505183, + "z": 0.0 + }, + { + "x": 354.46314344611994, + "y": -0.003995508593917322, + "z": 0.0 + }, + { + "x": 353.424286449852, + "y": -0.0034436295953294634, + "z": 0.0 + }, + { + "x": 352.38542945358404, + "y": -0.0028917505967416064, + "z": 0.0 + }, + { + "x": 351.3465724573161, + "y": -0.002339871598153753, + "z": 0.0 + }, + { + "x": 350.30771546104813, + "y": -0.001787992599565896, + "z": 0.0 + }, + { + "x": 349.2688584647802, + "y": -0.0012361136009780352, + "z": 0.0 + }, + { + "x": 348.2300014685122, + "y": -0.0006842346023901782, + "z": 0.0 + } + ] + }, + { + "id": 3, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 348.2289389951926, + "y": -2.0006839523899815, + "z": 0.0 + }, + { + "x": 349.26779599146056, + "y": -2.0012358313885694, + "z": 0.0 + }, + { + "x": 350.3066529877285, + "y": -2.0017877103871573, + "z": 0.0 + }, + { + "x": 351.34550998399646, + "y": -2.002339589385745, + "z": 0.0 + }, + { + "x": 352.3843669802644, + "y": -2.0028914683843326, + "z": 0.0 + }, + { + "x": 353.42322397653237, + "y": -2.0034433473829205, + "z": 0.0 + }, + { + "x": 354.4620809728003, + "y": -2.0039952263815084, + "z": 0.0 + }, + { + "x": 355.5009379690683, + "y": -2.0045471053800963, + "z": 0.0 + }, + { + "x": 356.5397949653362, + "y": -2.005098984378684, + "z": 0.0 + }, + { + "x": 357.5786519616042, + "y": -2.005650863377272, + "z": 0.0 + }, + { + "x": 358.61750895787213, + "y": -2.00620274237586, + "z": 0.0 + }, + { + "x": 359.6563659541401, + "y": -2.006754621374448, + "z": 0.0 + }, + { + "x": 360.69522295040804, + "y": -2.0073065003730357, + "z": 0.0 + }, + { + "x": 361.73407994667605, + "y": -2.0078583793716236, + "z": 0.0 + }, + { + "x": 362.772936942944, + "y": -2.0084102583702115, + "z": 0.0 + }, + { + "x": 363.81179393921195, + "y": -2.0089621373687994, + "z": 0.0 + }, + { + "x": 364.8506509354799, + "y": -2.0095140163673872, + "z": 0.0 + }, + { + "x": 365.88950793174786, + "y": -2.010065895365975, + "z": 0.0 + }, + { + "x": 366.9283649280158, + "y": -2.010617774364563, + "z": 0.0 + }, + { + "x": 367.96722192428376, + "y": -2.011169653363151, + "z": 0.0 + }, + { + "x": 369.0060789205517, + "y": -2.0117215323617383, + "z": 0.0 + }, + { + "x": 370.04493591681967, + "y": -2.0122734113603262, + "z": 0.0 + }, + { + "x": 371.0837929130876, + "y": -2.012825290358914, + "z": 0.0 + }, + { + "x": 372.1226499093556, + "y": -2.013377169357502, + "z": 0.0 + }, + { + "x": 373.1615069056235, + "y": -2.01392904835609, + "z": 0.0 + }, + { + "x": 374.2003639018915, + "y": -2.0144809273546778, + "z": 0.0 + }, + { + "x": 375.23922089815943, + "y": -2.0150328063532656, + "z": 0.0 + }, + { + "x": 376.2780778944274, + "y": -2.0155846853518535, + "z": 0.0 + }, + { + "x": 377.31693489069534, + "y": -2.0161365643504414, + "z": 0.0 + }, + { + "x": 378.3557918869633, + "y": -2.0166884433490293, + "z": 0.0 + }, + { + "x": 379.39464888323124, + "y": -2.017240322347617, + "z": 0.0 + }, + { + "x": 380.4335058794992, + "y": -2.017792201346205, + "z": 0.0 + }, + { + "x": 381.47236287576715, + "y": -2.018344080344793, + "z": 0.0 + }, + { + "x": 382.5112198720351, + "y": -2.018895959343381, + "z": 0.0 + }, + { + "x": 383.55007686830305, + "y": -2.0194478383419687, + "z": 0.0 + }, + { + "x": 384.588933864571, + "y": -2.019999717340556, + "z": 0.0 + } + ] + }, + { + "id": 4, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 384.59105881121025, + "y": 1.979999718234626, + "z": 0.0 + }, + { + "x": 383.5522018149423, + "y": 1.980551597233214, + "z": 0.0 + }, + { + "x": 382.51334481867434, + "y": 1.9811034762318018, + "z": 0.0 + }, + { + "x": 381.4744878224064, + "y": 1.9816553552303897, + "z": 0.0 + }, + { + "x": 380.43563082613844, + "y": 1.9822072342289776, + "z": 0.0 + }, + { + "x": 379.3967738298705, + "y": 1.9827591132275655, + "z": 0.0 + }, + { + "x": 378.35791683360253, + "y": 1.9833109922261534, + "z": 0.0 + }, + { + "x": 377.3190598373346, + "y": 1.9838628712247413, + "z": 0.0 + }, + { + "x": 376.2802028410666, + "y": 1.9844147502233291, + "z": 0.0 + }, + { + "x": 375.2413458447987, + "y": 1.9849666292219166, + "z": 0.0 + }, + { + "x": 374.2024888485307, + "y": 1.9855185082205045, + "z": 0.0 + }, + { + "x": 373.16363185226277, + "y": 1.9860703872190923, + "z": 0.0 + }, + { + "x": 372.1247748559948, + "y": 1.9866222662176802, + "z": 0.0 + }, + { + "x": 371.08591785972686, + "y": 1.9871741452162681, + "z": 0.0 + }, + { + "x": 370.0470608634589, + "y": 1.987726024214856, + "z": 0.0 + }, + { + "x": 369.00820386719096, + "y": 1.9882779032134439, + "z": 0.0 + }, + { + "x": 367.969346870923, + "y": 1.9888297822120318, + "z": 0.0 + }, + { + "x": 366.93048987465505, + "y": 1.9893816612106197, + "z": 0.0 + }, + { + "x": 365.8916328783871, + "y": 1.9899335402092075, + "z": 0.0 + }, + { + "x": 364.85277588211915, + "y": 1.9904854192077954, + "z": 0.0 + }, + { + "x": 363.8139188858512, + "y": 1.9910372982063833, + "z": 0.0 + }, + { + "x": 362.77506188958324, + "y": 1.9915891772049712, + "z": 0.0 + }, + { + "x": 361.7362048933153, + "y": 1.992141056203559, + "z": 0.0 + }, + { + "x": 360.6973478970473, + "y": 1.992692935202147, + "z": 0.0 + }, + { + "x": 359.6584909007793, + "y": 1.9932448142007344, + "z": 0.0 + }, + { + "x": 358.6196339045114, + "y": 1.9937966931993223, + "z": 0.0 + }, + { + "x": 357.5807769082434, + "y": 1.9943485721979102, + "z": 0.0 + }, + { + "x": 356.54191991197547, + "y": 1.994900451196498, + "z": 0.0 + }, + { + "x": 355.5030629157075, + "y": 1.995452330195086, + "z": 0.0 + }, + { + "x": 354.46420591943956, + "y": 1.9960042091936738, + "z": 0.0 + }, + { + "x": 353.4253489231716, + "y": 1.9965560881922617, + "z": 0.0 + }, + { + "x": 352.38649192690366, + "y": 1.9971079671908496, + "z": 0.0 + }, + { + "x": 351.3476349306357, + "y": 1.9976598461894375, + "z": 0.0 + }, + { + "x": 350.30877793436775, + "y": 1.9982117251880254, + "z": 0.0 + }, + { + "x": 349.2699209380998, + "y": 1.9987636041866133, + "z": 0.0 + }, + { + "x": 348.23106394183185, + "y": 1.9993154831852011, + "z": 0.0 + } + ] + }, + { + "id": 5, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 168.07958339564385, + "y": -3.956937384133082, + "z": 0.0 + }, + { + "x": 169.08308657463155, + "y": -3.957044487289655, + "z": 0.0 + }, + { + "x": 170.08658975361928, + "y": -3.957151590446228, + "z": 0.0 + }, + { + "x": 171.090092932607, + "y": -3.957258693602801, + "z": 0.0 + }, + { + "x": 172.0935961115947, + "y": -3.9573657967593734, + "z": 0.0 + }, + { + "x": 173.0970992905824, + "y": -3.9574728999159463, + "z": 0.0 + }, + { + "x": 174.10060246957013, + "y": -3.9575800030725192, + "z": 0.0 + }, + { + "x": 175.10410564855783, + "y": -3.957687106229092, + "z": 0.0 + }, + { + "x": 176.10760882754556, + "y": -3.957794209385665, + "z": 0.0 + }, + { + "x": 177.11111200653326, + "y": -3.9579013125422375, + "z": 0.0 + }, + { + "x": 178.114615185521, + "y": -3.9580084156988105, + "z": 0.0 + }, + { + "x": 179.1181183645087, + "y": -3.9581155188553834, + "z": 0.0 + }, + { + "x": 180.1216215434964, + "y": -3.9582226220119563, + "z": 0.0 + }, + { + "x": 181.12512472248412, + "y": -3.958329725168529, + "z": 0.0 + }, + { + "x": 182.12862790147184, + "y": -3.9584368283251017, + "z": 0.0 + }, + { + "x": 183.13213108045954, + "y": -3.9585439314816746, + "z": 0.0 + }, + { + "x": 184.13563425944724, + "y": -3.9586510346382475, + "z": 0.0 + }, + { + "x": 185.13913743843494, + "y": -3.9587581377948204, + "z": 0.0 + }, + { + "x": 186.1426406174227, + "y": -3.9588652409513934, + "z": 0.0 + }, + { + "x": 187.1461437964104, + "y": -3.958972344107966, + "z": 0.0 + }, + { + "x": 188.1496469753981, + "y": -3.9590794472645388, + "z": 0.0 + }, + { + "x": 189.1531501543858, + "y": -3.9591865504211117, + "z": 0.0 + }, + { + "x": 190.15665333337355, + "y": -3.9592936535776846, + "z": 0.0 + }, + { + "x": 191.16015651236125, + "y": -3.9594007567342575, + "z": 0.0 + }, + { + "x": 192.16365969134895, + "y": -3.95950785989083, + "z": 0.0 + }, + { + "x": 193.16716287033665, + "y": -3.959614963047403, + "z": 0.0 + }, + { + "x": 194.17066604932438, + "y": -3.959722066203976, + "z": 0.0 + }, + { + "x": 195.1741692283121, + "y": -3.9598291693605487, + "z": 0.0 + }, + { + "x": 196.1776724072998, + "y": -3.9599362725171217, + "z": 0.0 + }, + { + "x": 197.18117558628754, + "y": -3.960043375673694, + "z": 0.0 + }, + { + "x": 198.1846787652752, + "y": -3.960150478830267, + "z": 0.0 + }, + { + "x": 199.18818194426294, + "y": -3.96025758198684, + "z": 0.0 + }, + { + "x": 200.1916851232506, + "y": -3.960364685143413, + "z": 0.0 + }, + { + "x": 201.19518830223834, + "y": -3.9604717882999854, + "z": 0.0 + }, + { + "x": 202.198691481226, + "y": -3.9605788914565583, + "z": 0.0 + }, + { + "x": 203.20219466021373, + "y": -3.960685994613131, + "z": 0.0 + }, + { + "x": 204.2056978392014, + "y": -3.960793097769704, + "z": 0.0 + }, + { + "x": 205.2092010181891, + "y": -3.960900200926277, + "z": 0.0 + }, + { + "x": 206.2127041971768, + "y": -3.9610073040828495, + "z": 0.0 + }, + { + "x": 207.2162073761645, + "y": -3.9611144072394224, + "z": 0.0 + }, + { + "x": 208.2197105551522, + "y": -3.9612215103959953, + "z": 0.0 + }, + { + "x": 209.2232137341399, + "y": -3.9613286135525683, + "z": 0.0 + }, + { + "x": 210.2267169131276, + "y": -3.961435716709141, + "z": 0.0 + }, + { + "x": 211.2302200921153, + "y": -3.9615428198657137, + "z": 0.0 + }, + { + "x": 212.233723271103, + "y": -3.9616499230222866, + "z": 0.0 + }, + { + "x": 213.2372264500907, + "y": -3.9617570261788595, + "z": 0.0 + }, + { + "x": 214.2407296290784, + "y": -3.9618641293354324, + "z": 0.0 + }, + { + "x": 215.2442328080661, + "y": -3.9619712324920053, + "z": 0.0 + }, + { + "x": 216.2477359870538, + "y": -3.962078335648578, + "z": 0.0 + }, + { + "x": 217.2512391660415, + "y": -3.9621854388051507, + "z": 0.0 + }, + { + "x": 218.2547423450292, + "y": -3.9622925419617236, + "z": 0.0 + }, + { + "x": 219.2582455240169, + "y": -3.9623996451182966, + "z": 0.0 + }, + { + "x": 220.2617487030046, + "y": -3.962506748274869, + "z": 0.0 + }, + { + "x": 221.2652518819923, + "y": -3.962613851431442, + "z": 0.0 + }, + { + "x": 222.26875506098, + "y": -3.962720954588015, + "z": 0.0 + }, + { + "x": 223.2722582399677, + "y": -3.962828057744588, + "z": 0.0 + }, + { + "x": 224.2757614189554, + "y": -3.9629351609011607, + "z": 0.0 + }, + { + "x": 225.2792645979431, + "y": -3.963042264057733, + "z": 0.0 + }, + { + "x": 226.2827677769308, + "y": -3.963149367214306, + "z": 0.0 + }, + { + "x": 227.2862709559185, + "y": -3.963256470370879, + "z": 0.0 + }, + { + "x": 228.2897741349062, + "y": -3.963363573527452, + "z": 0.0 + }, + { + "x": 229.2932773138939, + "y": -3.963470676684025, + "z": 0.0 + }, + { + "x": 230.2967804928816, + "y": -3.9635777798405973, + "z": 0.0 + }, + { + "x": 231.3002836718693, + "y": -3.9636848829971703, + "z": 0.0 + }, + { + "x": 232.303786850857, + "y": -3.963791986153743, + "z": 0.0 + }, + { + "x": 233.3072900298447, + "y": -3.963899089310316, + "z": 0.0 + }, + { + "x": 234.3107932088324, + "y": -3.9640061924668886, + "z": 0.0 + }, + { + "x": 235.3142963878201, + "y": -3.9641132956234615, + "z": 0.0 + }, + { + "x": 236.31779956680776, + "y": -3.9642203987800344, + "z": 0.0 + }, + { + "x": 237.3213027457955, + "y": -3.9643275019366073, + "z": 0.0 + }, + { + "x": 238.32480592478316, + "y": -3.9644346050931802, + "z": 0.0 + }, + { + "x": 239.3283091037709, + "y": -3.9645417082497527, + "z": 0.0 + }, + { + "x": 240.33181228275856, + "y": -3.9646488114063256, + "z": 0.0 + }, + { + "x": 241.3353154617463, + "y": -3.9647559145628986, + "z": 0.0 + }, + { + "x": 242.33881864073396, + "y": -3.9648630177194715, + "z": 0.0 + }, + { + "x": 243.34232181972166, + "y": -3.9649701208760444, + "z": 0.0 + }, + { + "x": 244.34582499870936, + "y": -3.965077224032617, + "z": 0.0 + }, + { + "x": 245.34932817769706, + "y": -3.96518432718919, + "z": 0.0 + }, + { + "x": 246.35283135668476, + "y": -3.9652914303457627, + "z": 0.0 + }, + { + "x": 247.35633453567246, + "y": -3.9653985335023356, + "z": 0.0 + }, + { + "x": 248.35983771466016, + "y": -3.9655056366589085, + "z": 0.0 + }, + { + "x": 249.36334089364786, + "y": -3.965612739815481, + "z": 0.0 + }, + { + "x": 250.36684407263556, + "y": -3.965719842972054, + "z": 0.0 + }, + { + "x": 251.37034725162326, + "y": -3.965826946128627, + "z": 0.0 + }, + { + "x": 252.37385043061096, + "y": -3.9659340492851998, + "z": 0.0 + }, + { + "x": 253.37735360959866, + "y": -3.9660411524417722, + "z": 0.0 + }, + { + "x": 254.38085678858636, + "y": -3.966148255598345, + "z": 0.0 + }, + { + "x": 255.38435996757406, + "y": -3.966255358754918, + "z": 0.0 + }, + { + "x": 256.38786314656176, + "y": -3.966362461911491, + "z": 0.0 + }, + { + "x": 257.3913663255494, + "y": -3.966469565068064, + "z": 0.0 + }, + { + "x": 258.39486950453716, + "y": -3.9665766682246364, + "z": 0.0 + }, + { + "x": 259.3983726835248, + "y": -3.9666837713812093, + "z": 0.0 + }, + { + "x": 260.40187586251255, + "y": -3.9667908745377822, + "z": 0.0 + }, + { + "x": 261.4053790415002, + "y": -3.966897977694355, + "z": 0.0 + }, + { + "x": 262.40888222048795, + "y": -3.967005080850928, + "z": 0.0 + }, + { + "x": 263.4123853994757, + "y": -3.9671121840075005, + "z": 0.0 + }, + { + "x": 264.41588857846335, + "y": -3.9672192871640735, + "z": 0.0 + }, + { + "x": 265.4193917574511, + "y": -3.9673263903206464, + "z": 0.0 + }, + { + "x": 266.42289493643875, + "y": -3.9674334934772193, + "z": 0.0 + }, + { + "x": 267.4263981154265, + "y": -3.9675405966337918, + "z": 0.0 + }, + { + "x": 268.4299012944142, + "y": -3.9676476997903647, + "z": 0.0 + }, + { + "x": 269.4334044734019, + "y": -3.9677548029469376, + "z": 0.0 + }, + { + "x": 270.4369076523896, + "y": -3.9678619061035105, + "z": 0.0 + }, + { + "x": 271.4404108313773, + "y": -3.9679690092600834, + "z": 0.0 + }, + { + "x": 272.443914010365, + "y": -3.968076112416656, + "z": 0.0 + }, + { + "x": 273.44741718935273, + "y": -3.968183215573229, + "z": 0.0 + }, + { + "x": 274.4509203683404, + "y": -3.9682903187298018, + "z": 0.0 + }, + { + "x": 275.45442354732813, + "y": -3.9683974218863747, + "z": 0.0 + }, + { + "x": 276.45792672631586, + "y": -3.9685045250429476, + "z": 0.0 + }, + { + "x": 277.46142990530353, + "y": -3.96861162819952, + "z": 0.0 + }, + { + "x": 278.46493308429126, + "y": -3.968718731356093, + "z": 0.0 + }, + { + "x": 279.46843626327893, + "y": -3.968825834512666, + "z": 0.0 + }, + { + "x": 280.47193944226666, + "y": -3.968932937669239, + "z": 0.0 + }, + { + "x": 281.4754426212544, + "y": -3.9690400408258117, + "z": 0.0 + }, + { + "x": 282.47894580024206, + "y": -3.969147143982384, + "z": 0.0 + }, + { + "x": 283.4824489792298, + "y": -3.969254247138957, + "z": 0.0 + }, + { + "x": 284.48595215821746, + "y": -3.96936135029553, + "z": 0.0 + }, + { + "x": 285.4894553372052, + "y": -3.969468453452103, + "z": 0.0 + }, + { + "x": 286.4929585161929, + "y": -3.969575556608676, + "z": 0.0 + }, + { + "x": 287.4964616951806, + "y": -3.9696826597652484, + "z": 0.0 + }, + { + "x": 288.4999648741683, + "y": -3.9697897629218213, + "z": 0.0 + }, + { + "x": 289.50346805315604, + "y": -3.969896866078394, + "z": 0.0 + }, + { + "x": 290.50684979722337, + "y": -3.9700344178870632, + "z": 0.0 + }, + { + "x": 291.5088343943909, + "y": -3.970552431015961, + "z": 0.0 + }, + { + "x": 292.512279288484, + "y": -3.971085498227681, + "z": 0.0 + }, + { + "x": 293.51578233158676, + "y": -3.971618595907629, + "z": 0.0 + }, + { + "x": 294.51928537468945, + "y": -3.972151693587575, + "z": 0.0 + }, + { + "x": 295.5227884177921, + "y": -3.9726847912675227, + "z": 0.0 + }, + { + "x": 296.52629146089487, + "y": -3.9732178889474707, + "z": 0.0 + }, + { + "x": 297.52979450399755, + "y": -3.973750986627417, + "z": 0.0 + }, + { + "x": 298.53329754710023, + "y": -3.974284084307364, + "z": 0.0 + }, + { + "x": 299.536800590203, + "y": -3.974817181987312, + "z": 0.0 + }, + { + "x": 300.54030363330565, + "y": -3.9753502796672584, + "z": 0.0 + }, + { + "x": 301.54380667640834, + "y": -3.975883377347206, + "z": 0.0 + }, + { + "x": 302.5473097195111, + "y": -3.976416475027154, + "z": 0.0 + }, + { + "x": 303.55081276261376, + "y": -3.9769495727071003, + "z": 0.0 + }, + { + "x": 304.55431580571644, + "y": -3.9774826703870474, + "z": 0.0 + }, + { + "x": 305.5578188488192, + "y": -3.9780157680669954, + "z": 0.0 + }, + { + "x": 306.56132189192186, + "y": -3.978548865746942, + "z": 0.0 + }, + { + "x": 307.56482493502455, + "y": -3.9790819634268892, + "z": 0.0 + }, + { + "x": 308.5683279781273, + "y": -3.9796150611068373, + "z": 0.0 + }, + { + "x": 309.57183102122997, + "y": -3.9801481587867835, + "z": 0.0 + }, + { + "x": 310.57533406433265, + "y": -3.9806812564667307, + "z": 0.0 + }, + { + "x": 311.5788371074354, + "y": -3.981214354146679, + "z": 0.0 + }, + { + "x": 312.5823401505381, + "y": -3.9817474518266254, + "z": 0.0 + }, + { + "x": 313.58584319364076, + "y": -3.9822805495065725, + "z": 0.0 + }, + { + "x": 314.58934623674344, + "y": -3.9828136471865196, + "z": 0.0 + }, + { + "x": 315.5928492798462, + "y": -3.9833467448664677, + "z": 0.0 + }, + { + "x": 316.59635232294886, + "y": -3.9838798425464144, + "z": 0.0 + }, + { + "x": 317.59985536605154, + "y": -3.9844129402263615, + "z": 0.0 + }, + { + "x": 318.6033584091543, + "y": -3.9849460379063095, + "z": 0.0 + }, + { + "x": 319.60686145225696, + "y": -3.9854791355862558, + "z": 0.0 + }, + { + "x": 320.61036449535965, + "y": -3.986012233266203, + "z": 0.0 + }, + { + "x": 321.6138675384624, + "y": -3.986545330946151, + "z": 0.0 + }, + { + "x": 322.61737058156507, + "y": -3.9870784286260976, + "z": 0.0 + }, + { + "x": 323.62087362466775, + "y": -3.9876115263060448, + "z": 0.0 + }, + { + "x": 324.6243766677705, + "y": -3.988144623985993, + "z": 0.0 + }, + { + "x": 325.6278797108732, + "y": -3.988677721665939, + "z": 0.0 + } + ] + }, + { + "id": 6, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 325.63212960415166, + "y": 4.011321149484425, + "z": 0.0 + }, + { + "x": 324.628626561049, + "y": 4.011854247164374, + "z": 0.0 + }, + { + "x": 323.62512351794624, + "y": 4.012387344844321, + "z": 0.0 + }, + { + "x": 322.62162047484355, + "y": 4.012920442524267, + "z": 0.0 + }, + { + "x": 321.61811743174087, + "y": 4.013453540204216, + "z": 0.0 + }, + { + "x": 320.61461438863813, + "y": 4.0139866378841615, + "z": 0.0 + }, + { + "x": 319.61111134553545, + "y": 4.014519735564109, + "z": 0.0 + }, + { + "x": 318.60760830243277, + "y": 4.015052833244058, + "z": 0.0 + }, + { + "x": 317.60410525933, + "y": 4.015585930924003, + "z": 0.0 + }, + { + "x": 316.60060221622734, + "y": 4.016119028603951, + "z": 0.0 + }, + { + "x": 315.59709917312466, + "y": 4.016652126283899, + "z": 0.0 + }, + { + "x": 314.5935961300219, + "y": 4.017185223963845, + "z": 0.0 + }, + { + "x": 313.59009308691924, + "y": 4.017718321643793, + "z": 0.0 + }, + { + "x": 312.58659004381656, + "y": 4.0182514193237395, + "z": 0.0 + }, + { + "x": 311.5830870007139, + "y": 4.018784517003688, + "z": 0.0 + }, + { + "x": 310.57958395761113, + "y": 4.019317614683634, + "z": 0.0 + }, + { + "x": 309.57608091450845, + "y": 4.019850712363581, + "z": 0.0 + }, + { + "x": 308.57257787140577, + "y": 4.02038381004353, + "z": 0.0 + }, + { + "x": 307.56907482830303, + "y": 4.020916907723476, + "z": 0.0 + }, + { + "x": 306.56557178520035, + "y": 4.021450005403423, + "z": 0.0 + }, + { + "x": 305.56206874209767, + "y": 4.021983103083371, + "z": 0.0 + }, + { + "x": 304.5585656989949, + "y": 4.0225162007633175, + "z": 0.0 + }, + { + "x": 303.55506265589224, + "y": 4.023049298443264, + "z": 0.0 + }, + { + "x": 302.55155961278956, + "y": 4.023582396123213, + "z": 0.0 + }, + { + "x": 301.5480565696868, + "y": 4.024115493803159, + "z": 0.0 + }, + { + "x": 300.54455352658414, + "y": 4.024648591483106, + "z": 0.0 + }, + { + "x": 299.54105048348146, + "y": 4.0251816891630545, + "z": 0.0 + }, + { + "x": 298.5375474403787, + "y": 4.025714786843, + "z": 0.0 + }, + { + "x": 297.53404439727603, + "y": 4.026247884522948, + "z": 0.0 + }, + { + "x": 296.53054135417335, + "y": 4.026780982202896, + "z": 0.0 + }, + { + "x": 295.5270383110706, + "y": 4.027314079882842, + "z": 0.0 + }, + { + "x": 294.52353526796793, + "y": 4.02784717756279, + "z": 0.0 + }, + { + "x": 293.52003222486525, + "y": 4.028380275242737, + "z": 0.0 + }, + { + "x": 292.5165291817625, + "y": 4.028913372922684, + "z": 0.0 + }, + { + "x": 291.5129679896503, + "y": 4.029446501070859, + "z": 0.0 + }, + { + "x": 290.5079464882093, + "y": 4.029965506942243, + "z": 0.0 + }, + { + "x": 289.50432188727, + "y": 4.0301030883570625, + "z": 0.0 + }, + { + "x": 288.5008187082823, + "y": 4.0302101915136355, + "z": 0.0 + }, + { + "x": 287.49731552929455, + "y": 4.030317294670208, + "z": 0.0 + }, + { + "x": 286.4938123503069, + "y": 4.030424397826781, + "z": 0.0 + }, + { + "x": 285.49030917131915, + "y": 4.030531500983354, + "z": 0.0 + }, + { + "x": 284.4868059923314, + "y": 4.030638604139927, + "z": 0.0 + }, + { + "x": 283.48330281334376, + "y": 4.030745707296499, + "z": 0.0 + }, + { + "x": 282.479799634356, + "y": 4.030852810453072, + "z": 0.0 + }, + { + "x": 281.47629645536836, + "y": 4.030959913609645, + "z": 0.0 + }, + { + "x": 280.4727932763806, + "y": 4.031067016766218, + "z": 0.0 + }, + { + "x": 279.4692900973929, + "y": 4.031174119922791, + "z": 0.0 + }, + { + "x": 278.46578691840523, + "y": 4.031281223079364, + "z": 0.0 + }, + { + "x": 277.4622837394175, + "y": 4.031388326235937, + "z": 0.0 + }, + { + "x": 276.45878056042983, + "y": 4.03149542939251, + "z": 0.0 + }, + { + "x": 275.4552773814421, + "y": 4.0316025325490825, + "z": 0.0 + }, + { + "x": 274.4517742024544, + "y": 4.0317096357056545, + "z": 0.0 + }, + { + "x": 273.4482710234667, + "y": 4.0318167388622275, + "z": 0.0 + }, + { + "x": 272.444767844479, + "y": 4.0319238420188, + "z": 0.0 + }, + { + "x": 271.44126466549125, + "y": 4.032030945175373, + "z": 0.0 + }, + { + "x": 270.4377614865036, + "y": 4.032138048331946, + "z": 0.0 + }, + { + "x": 269.43425830751585, + "y": 4.032245151488519, + "z": 0.0 + }, + { + "x": 268.4307551285282, + "y": 4.032352254645092, + "z": 0.0 + }, + { + "x": 267.42725194954045, + "y": 4.032459357801665, + "z": 0.0 + }, + { + "x": 266.4237487705527, + "y": 4.032566460958238, + "z": 0.0 + }, + { + "x": 265.42024559156505, + "y": 4.032673564114811, + "z": 0.0 + }, + { + "x": 264.4167424125773, + "y": 4.032780667271383, + "z": 0.0 + }, + { + "x": 263.41323923358965, + "y": 4.032887770427956, + "z": 0.0 + }, + { + "x": 262.4097360546019, + "y": 4.032994873584529, + "z": 0.0 + }, + { + "x": 261.4062328756142, + "y": 4.033101976741102, + "z": 0.0 + }, + { + "x": 260.4027296966265, + "y": 4.0332090798976745, + "z": 0.0 + }, + { + "x": 259.3992265176388, + "y": 4.033316183054247, + "z": 0.0 + }, + { + "x": 258.3957233386511, + "y": 4.03342328621082, + "z": 0.0 + }, + { + "x": 257.3922201596634, + "y": 4.033530389367393, + "z": 0.0 + }, + { + "x": 256.3887169806757, + "y": 4.033637492523966, + "z": 0.0 + }, + { + "x": 255.38521380168802, + "y": 4.033744595680538, + "z": 0.0 + }, + { + "x": 254.38171062270033, + "y": 4.033851698837111, + "z": 0.0 + }, + { + "x": 253.37820744371263, + "y": 4.033958801993684, + "z": 0.0 + }, + { + "x": 252.37470426472493, + "y": 4.034065905150257, + "z": 0.0 + }, + { + "x": 251.37120108573723, + "y": 4.03417300830683, + "z": 0.0 + }, + { + "x": 250.36769790674953, + "y": 4.034280111463403, + "z": 0.0 + }, + { + "x": 249.36419472776183, + "y": 4.034387214619976, + "z": 0.0 + }, + { + "x": 248.36069154877413, + "y": 4.034494317776549, + "z": 0.0 + }, + { + "x": 247.35718836978643, + "y": 4.034601420933122, + "z": 0.0 + }, + { + "x": 246.35368519079873, + "y": 4.0347085240896945, + "z": 0.0 + }, + { + "x": 245.35018201181103, + "y": 4.0348156272462665, + "z": 0.0 + }, + { + "x": 244.34667883282333, + "y": 4.034922730402839, + "z": 0.0 + }, + { + "x": 243.34317565383563, + "y": 4.035029833559412, + "z": 0.0 + }, + { + "x": 242.33967247484793, + "y": 4.035136936715985, + "z": 0.0 + }, + { + "x": 241.33616929586026, + "y": 4.035244039872558, + "z": 0.0 + }, + { + "x": 240.33266611687253, + "y": 4.035351143029131, + "z": 0.0 + }, + { + "x": 239.32916293788486, + "y": 4.035458246185704, + "z": 0.0 + }, + { + "x": 238.32565975889713, + "y": 4.035565349342277, + "z": 0.0 + }, + { + "x": 237.32215657990946, + "y": 4.03567245249885, + "z": 0.0 + }, + { + "x": 236.31865340092173, + "y": 4.035779555655422, + "z": 0.0 + }, + { + "x": 235.31515022193406, + "y": 4.035886658811995, + "z": 0.0 + }, + { + "x": 234.31164704294636, + "y": 4.035993761968568, + "z": 0.0 + }, + { + "x": 233.30814386395866, + "y": 4.036100865125141, + "z": 0.0 + }, + { + "x": 232.30464068497096, + "y": 4.036207968281714, + "z": 0.0 + }, + { + "x": 231.30113750598326, + "y": 4.0363150714382865, + "z": 0.0 + }, + { + "x": 230.29763432699556, + "y": 4.036422174594859, + "z": 0.0 + }, + { + "x": 229.29413114800786, + "y": 4.036529277751432, + "z": 0.0 + }, + { + "x": 228.29062796902016, + "y": 4.036636380908005, + "z": 0.0 + }, + { + "x": 227.28712479003246, + "y": 4.036743484064578, + "z": 0.0 + }, + { + "x": 226.28362161104477, + "y": 4.03685058722115, + "z": 0.0 + }, + { + "x": 225.28011843205707, + "y": 4.036957690377723, + "z": 0.0 + }, + { + "x": 224.27661525306937, + "y": 4.037064793534296, + "z": 0.0 + }, + { + "x": 223.27311207408167, + "y": 4.037171896690869, + "z": 0.0 + }, + { + "x": 222.26960889509397, + "y": 4.037278999847442, + "z": 0.0 + }, + { + "x": 221.26610571610627, + "y": 4.037386103004015, + "z": 0.0 + }, + { + "x": 220.26260253711857, + "y": 4.037493206160588, + "z": 0.0 + }, + { + "x": 219.25909935813087, + "y": 4.037600309317161, + "z": 0.0 + }, + { + "x": 218.25559617914317, + "y": 4.0377074124737335, + "z": 0.0 + }, + { + "x": 217.25209300015547, + "y": 4.037814515630306, + "z": 0.0 + }, + { + "x": 216.24858982116777, + "y": 4.0379216187868785, + "z": 0.0 + }, + { + "x": 215.24508664218007, + "y": 4.038028721943451, + "z": 0.0 + }, + { + "x": 214.24158346319237, + "y": 4.038135825100024, + "z": 0.0 + }, + { + "x": 213.23808028420467, + "y": 4.038242928256597, + "z": 0.0 + }, + { + "x": 212.23457710521697, + "y": 4.03835003141317, + "z": 0.0 + }, + { + "x": 211.23107392622927, + "y": 4.038457134569743, + "z": 0.0 + }, + { + "x": 210.22757074724157, + "y": 4.038564237726316, + "z": 0.0 + }, + { + "x": 209.22406756825387, + "y": 4.038671340882889, + "z": 0.0 + }, + { + "x": 208.22056438926617, + "y": 4.038778444039462, + "z": 0.0 + }, + { + "x": 207.21706121027847, + "y": 4.038885547196034, + "z": 0.0 + }, + { + "x": 206.21355803129077, + "y": 4.038992650352607, + "z": 0.0 + }, + { + "x": 205.21005485230307, + "y": 4.03909975350918, + "z": 0.0 + }, + { + "x": 204.20655167331537, + "y": 4.039206856665753, + "z": 0.0 + }, + { + "x": 203.2030484943277, + "y": 4.0393139598223256, + "z": 0.0 + }, + { + "x": 202.19954531533998, + "y": 4.0394210629788985, + "z": 0.0 + }, + { + "x": 201.1960421363523, + "y": 4.039528166135471, + "z": 0.0 + }, + { + "x": 200.19253895736458, + "y": 4.039635269292044, + "z": 0.0 + }, + { + "x": 199.1890357783769, + "y": 4.039742372448617, + "z": 0.0 + }, + { + "x": 198.18553259938918, + "y": 4.039849475605189, + "z": 0.0 + }, + { + "x": 197.1820294204015, + "y": 4.039956578761762, + "z": 0.0 + }, + { + "x": 196.17852624141378, + "y": 4.040063681918335, + "z": 0.0 + }, + { + "x": 195.17502306242608, + "y": 4.040170785074908, + "z": 0.0 + }, + { + "x": 194.17151988343835, + "y": 4.040277888231481, + "z": 0.0 + }, + { + "x": 193.16801670445062, + "y": 4.040384991388054, + "z": 0.0 + }, + { + "x": 192.16451352546292, + "y": 4.040492094544627, + "z": 0.0 + }, + { + "x": 191.16101034647522, + "y": 4.0405991977012, + "z": 0.0 + }, + { + "x": 190.15750716748752, + "y": 4.040706300857773, + "z": 0.0 + }, + { + "x": 189.15400398849977, + "y": 4.0408134040143455, + "z": 0.0 + }, + { + "x": 188.15050080951207, + "y": 4.0409205071709176, + "z": 0.0 + }, + { + "x": 187.14699763052437, + "y": 4.0410276103274905, + "z": 0.0 + }, + { + "x": 186.14349445153667, + "y": 4.041134713484063, + "z": 0.0 + }, + { + "x": 185.1399912725489, + "y": 4.041241816640636, + "z": 0.0 + }, + { + "x": 184.1364880935612, + "y": 4.041348919797209, + "z": 0.0 + }, + { + "x": 183.1329849145735, + "y": 4.041456022953782, + "z": 0.0 + }, + { + "x": 182.1294817355858, + "y": 4.041563126110355, + "z": 0.0 + }, + { + "x": 181.12597855659808, + "y": 4.041670229266928, + "z": 0.0 + }, + { + "x": 180.12247537761036, + "y": 4.041777332423501, + "z": 0.0 + }, + { + "x": 179.11897219862266, + "y": 4.041884435580073, + "z": 0.0 + }, + { + "x": 178.11546901963496, + "y": 4.041991538736646, + "z": 0.0 + }, + { + "x": 177.11196584064723, + "y": 4.042098641893219, + "z": 0.0 + }, + { + "x": 176.10846266165953, + "y": 4.042205745049792, + "z": 0.0 + }, + { + "x": 175.1049594826718, + "y": 4.042312848206365, + "z": 0.0 + }, + { + "x": 174.1014563036841, + "y": 4.0424199513629375, + "z": 0.0 + }, + { + "x": 173.09795312469637, + "y": 4.04252705451951, + "z": 0.0 + }, + { + "x": 172.09444994570867, + "y": 4.042634157676083, + "z": 0.0 + }, + { + "x": 171.09094676672098, + "y": 4.042741260832656, + "z": 0.0 + }, + { + "x": 170.08744358773325, + "y": 4.042848363989229, + "z": 0.0 + }, + { + "x": 169.08394040874552, + "y": 4.042955467145801, + "z": 0.0 + }, + { + "x": 168.08043722975782, + "y": 4.043062570302374, + "z": 0.0 + } + ] + }, + { + "id": 7, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 325.6300046575124, + "y": 0.01132171390924333, + "z": 0.0 + }, + { + "x": 324.62650161440973, + "y": 0.01185481158919055, + "z": 0.0 + }, + { + "x": 323.622998571307, + "y": 0.012387909269137768, + "z": 0.0 + }, + { + "x": 322.6194955282043, + "y": 0.012921006949084988, + "z": 0.0 + }, + { + "x": 321.61599248510163, + "y": 0.013454104629032206, + "z": 0.0 + }, + { + "x": 320.6124894419989, + "y": 0.013987202308979426, + "z": 0.0 + }, + { + "x": 319.6089863988962, + "y": 0.014520299988926646, + "z": 0.0 + }, + { + "x": 318.6054833557935, + "y": 0.015053397668873866, + "z": 0.0 + }, + { + "x": 317.6019803126908, + "y": 0.015586495348821084, + "z": 0.0 + }, + { + "x": 316.5984772695881, + "y": 0.016119593028768302, + "z": 0.0 + }, + { + "x": 315.5949742264854, + "y": 0.016652690708715546, + "z": 0.0 + }, + { + "x": 314.5914711833827, + "y": 0.017185788388662773, + "z": 0.0 + }, + { + "x": 313.58796814028, + "y": 0.017718886068609992, + "z": 0.0 + }, + { + "x": 312.5844650971773, + "y": 0.018251983748557212, + "z": 0.0 + }, + { + "x": 311.58096205407463, + "y": 0.01878508142850443, + "z": 0.0 + }, + { + "x": 310.5774590109719, + "y": 0.019318179108451648, + "z": 0.0 + }, + { + "x": 309.5739559678692, + "y": 0.019851276788398868, + "z": 0.0 + }, + { + "x": 308.5704529247665, + "y": 0.020384374468346088, + "z": 0.0 + }, + { + "x": 307.5669498816638, + "y": 0.020917472148293304, + "z": 0.0 + }, + { + "x": 306.5634468385611, + "y": 0.021450569828240527, + "z": 0.0 + }, + { + "x": 305.5599437954584, + "y": 0.021983667508187747, + "z": 0.0 + }, + { + "x": 304.5564407523557, + "y": 0.022516765188134964, + "z": 0.0 + }, + { + "x": 303.552937709253, + "y": 0.023049862868082183, + "z": 0.0 + }, + { + "x": 302.5494346661503, + "y": 0.023582960548029403, + "z": 0.0 + }, + { + "x": 301.5459316230476, + "y": 0.024116058227976623, + "z": 0.0 + }, + { + "x": 300.5424285799449, + "y": 0.024649155907923843, + "z": 0.0 + }, + { + "x": 299.5389255368422, + "y": 0.025182253587871063, + "z": 0.0 + }, + { + "x": 298.5354224937395, + "y": 0.025715351267818282, + "z": 0.0 + }, + { + "x": 297.5319194506368, + "y": 0.0262484489477655, + "z": 0.0 + }, + { + "x": 296.5284164075341, + "y": 0.02678154662771272, + "z": 0.0 + }, + { + "x": 295.52491336443137, + "y": 0.027314644307659938, + "z": 0.0 + }, + { + "x": 294.5214103213287, + "y": 0.02784774198760716, + "z": 0.0 + }, + { + "x": 293.517907278226, + "y": 0.028380839667554406, + "z": 0.0 + }, + { + "x": 292.51440423512327, + "y": 0.02891393734750163, + "z": 0.0 + }, + { + "x": 291.5109011920206, + "y": 0.02944703502744885, + "z": 0.0 + }, + { + "x": 290.50739814271634, + "y": 0.029965544527589767, + "z": 0.0 + }, + { + "x": 289.503894970213, + "y": 0.03010311113933422, + "z": 0.0 + }, + { + "x": 288.5003917912253, + "y": 0.030210214295907045, + "z": 0.0 + }, + { + "x": 287.49688861223757, + "y": 0.03031731745247987, + "z": 0.0 + }, + { + "x": 286.4933854332499, + "y": 0.030424420609052698, + "z": 0.0 + }, + { + "x": 285.48988225426217, + "y": 0.030531523765625523, + "z": 0.0 + }, + { + "x": 284.48637907527444, + "y": 0.030638626922198348, + "z": 0.0 + }, + { + "x": 283.48287589628677, + "y": 0.030745730078771173, + "z": 0.0 + }, + { + "x": 282.47937271729904, + "y": 0.030852833235343997, + "z": 0.0 + }, + { + "x": 281.4758695383114, + "y": 0.030959936391916822, + "z": 0.0 + }, + { + "x": 280.47236635932364, + "y": 0.031067039548489647, + "z": 0.0 + }, + { + "x": 279.4688631803359, + "y": 0.031174142705062476, + "z": 0.0 + }, + { + "x": 278.46536000134824, + "y": 0.031281245861635304, + "z": 0.0 + }, + { + "x": 277.4618568223605, + "y": 0.031388349018208125, + "z": 0.0 + }, + { + "x": 276.45835364337285, + "y": 0.031495452174780954, + "z": 0.0 + }, + { + "x": 275.4548504643851, + "y": 0.031602555331353775, + "z": 0.0 + }, + { + "x": 274.4513472853974, + "y": 0.0317096584879266, + "z": 0.0 + }, + { + "x": 273.4478441064097, + "y": 0.03181676164449943, + "z": 0.0 + }, + { + "x": 272.444340927422, + "y": 0.03192386480107225, + "z": 0.0 + }, + { + "x": 271.44083774843426, + "y": 0.03203096795764508, + "z": 0.0 + }, + { + "x": 270.4373345694466, + "y": 0.0321380711142179, + "z": 0.0 + }, + { + "x": 269.43383139045886, + "y": 0.03224517427079073, + "z": 0.0 + }, + { + "x": 268.4303282114712, + "y": 0.03235227742736355, + "z": 0.0 + }, + { + "x": 267.42682503248346, + "y": 0.03245938058393638, + "z": 0.0 + }, + { + "x": 266.42332185349574, + "y": 0.0325664837405092, + "z": 0.0 + }, + { + "x": 265.41981867450806, + "y": 0.03267358689708203, + "z": 0.0 + }, + { + "x": 264.41631549552034, + "y": 0.03278069005365486, + "z": 0.0 + }, + { + "x": 263.41281231653267, + "y": 0.03288779321022768, + "z": 0.0 + }, + { + "x": 262.40930913754494, + "y": 0.03299489636680051, + "z": 0.0 + }, + { + "x": 261.4058059585572, + "y": 0.03310199952337333, + "z": 0.0 + }, + { + "x": 260.40230277956954, + "y": 0.03320910267994615, + "z": 0.0 + }, + { + "x": 259.3987996005818, + "y": 0.03331620583651898, + "z": 0.0 + }, + { + "x": 258.39529642159414, + "y": 0.03342330899309181, + "z": 0.0 + }, + { + "x": 257.3917932426064, + "y": 0.03353041214966463, + "z": 0.0 + }, + { + "x": 256.38829006361874, + "y": 0.03363751530623746, + "z": 0.0 + }, + { + "x": 255.38478688463104, + "y": 0.03374461846281028, + "z": 0.0 + }, + { + "x": 254.38128370564334, + "y": 0.0338517216193831, + "z": 0.0 + }, + { + "x": 253.37778052665564, + "y": 0.03395882477595593, + "z": 0.0 + }, + { + "x": 252.37427734766794, + "y": 0.03406592793252876, + "z": 0.0 + }, + { + "x": 251.37077416868024, + "y": 0.03417303108910158, + "z": 0.0 + }, + { + "x": 250.36727098969254, + "y": 0.03428013424567441, + "z": 0.0 + }, + { + "x": 249.36376781070484, + "y": 0.03438723740224723, + "z": 0.0 + }, + { + "x": 248.36026463171714, + "y": 0.03449434055882005, + "z": 0.0 + }, + { + "x": 247.35676145272944, + "y": 0.03460144371539288, + "z": 0.0 + }, + { + "x": 246.35325827374174, + "y": 0.0347085468719657, + "z": 0.0 + }, + { + "x": 245.34975509475404, + "y": 0.03481565002853853, + "z": 0.0 + }, + { + "x": 244.34625191576635, + "y": 0.03492275318511135, + "z": 0.0 + }, + { + "x": 243.34274873677865, + "y": 0.03502985634168418, + "z": 0.0 + }, + { + "x": 242.33924555779095, + "y": 0.035136959498257, + "z": 0.0 + }, + { + "x": 241.33574237880327, + "y": 0.03524406265482983, + "z": 0.0 + }, + { + "x": 240.33223919981555, + "y": 0.03535116581140265, + "z": 0.0 + }, + { + "x": 239.32873602082788, + "y": 0.03545826896797548, + "z": 0.0 + }, + { + "x": 238.32523284184015, + "y": 0.0355653721245483, + "z": 0.0 + }, + { + "x": 237.32172966285248, + "y": 0.03567247528112112, + "z": 0.0 + }, + { + "x": 236.31822648386475, + "y": 0.03577957843769394, + "z": 0.0 + }, + { + "x": 235.31472330487708, + "y": 0.03588668159426677, + "z": 0.0 + }, + { + "x": 234.31122012588938, + "y": 0.03599378475083959, + "z": 0.0 + }, + { + "x": 233.30771694690168, + "y": 0.03610088790741242, + "z": 0.0 + }, + { + "x": 232.30421376791398, + "y": 0.03620799106398524, + "z": 0.0 + }, + { + "x": 231.30071058892628, + "y": 0.03631509422055807, + "z": 0.0 + }, + { + "x": 230.29720740993858, + "y": 0.03642219737713089, + "z": 0.0 + }, + { + "x": 229.29370423095088, + "y": 0.03652930053370372, + "z": 0.0 + }, + { + "x": 228.29020105196318, + "y": 0.03663640369027654, + "z": 0.0 + }, + { + "x": 227.28669787297548, + "y": 0.036743506846849364, + "z": 0.0 + }, + { + "x": 226.28319469398778, + "y": 0.03685061000342219, + "z": 0.0 + }, + { + "x": 225.27969151500008, + "y": 0.03695771315999501, + "z": 0.0 + }, + { + "x": 224.27618833601238, + "y": 0.03706481631656784, + "z": 0.0 + }, + { + "x": 223.27268515702468, + "y": 0.03717191947314067, + "z": 0.0 + }, + { + "x": 222.26918197803698, + "y": 0.03727902262971349, + "z": 0.0 + }, + { + "x": 221.26567879904928, + "y": 0.03738612578628631, + "z": 0.0 + }, + { + "x": 220.26217562006158, + "y": 0.03749322894285914, + "z": 0.0 + }, + { + "x": 219.25867244107388, + "y": 0.03760033209943196, + "z": 0.0 + }, + { + "x": 218.25516926208618, + "y": 0.037707435256004784, + "z": 0.0 + }, + { + "x": 217.25166608309848, + "y": 0.03781453841257761, + "z": 0.0 + }, + { + "x": 216.24816290411079, + "y": 0.03792164156915044, + "z": 0.0 + }, + { + "x": 215.24465972512309, + "y": 0.03802874472572326, + "z": 0.0 + }, + { + "x": 214.2411565461354, + "y": 0.03813584788229609, + "z": 0.0 + }, + { + "x": 213.2376533671477, + "y": 0.03824295103886891, + "z": 0.0 + }, + { + "x": 212.23415018816, + "y": 0.038350054195441734, + "z": 0.0 + }, + { + "x": 211.2306470091723, + "y": 0.03845715735201456, + "z": 0.0 + }, + { + "x": 210.2271438301846, + "y": 0.03856426050858739, + "z": 0.0 + }, + { + "x": 209.2236406511969, + "y": 0.03867136366516021, + "z": 0.0 + }, + { + "x": 208.2201374722092, + "y": 0.03877846682173303, + "z": 0.0 + }, + { + "x": 207.2166342932215, + "y": 0.03888556997830586, + "z": 0.0 + }, + { + "x": 206.2131311142338, + "y": 0.03899267313487868, + "z": 0.0 + }, + { + "x": 205.2096279352461, + "y": 0.03909977629145151, + "z": 0.0 + }, + { + "x": 204.2061247562584, + "y": 0.03920687944802433, + "z": 0.0 + }, + { + "x": 203.20262157727072, + "y": 0.03931398260459716, + "z": 0.0 + }, + { + "x": 202.199118398283, + "y": 0.03942108576116999, + "z": 0.0 + }, + { + "x": 201.19561521929532, + "y": 0.03952818891774281, + "z": 0.0 + }, + { + "x": 200.1921120403076, + "y": 0.03963529207431563, + "z": 0.0 + }, + { + "x": 199.18860886131992, + "y": 0.03974239523088846, + "z": 0.0 + }, + { + "x": 198.1851056823322, + "y": 0.03984949838746128, + "z": 0.0 + }, + { + "x": 197.18160250334452, + "y": 0.03995660154403411, + "z": 0.0 + }, + { + "x": 196.1780993243568, + "y": 0.04006370470060694, + "z": 0.0 + }, + { + "x": 195.1745961453691, + "y": 0.04017080785717976, + "z": 0.0 + }, + { + "x": 194.17109296638137, + "y": 0.04027791101375259, + "z": 0.0 + }, + { + "x": 193.16758978739364, + "y": 0.04038501417032541, + "z": 0.0 + }, + { + "x": 192.16408660840594, + "y": 0.04049211732689824, + "z": 0.0 + }, + { + "x": 191.16058342941824, + "y": 0.04059922048347107, + "z": 0.0 + }, + { + "x": 190.15708025043054, + "y": 0.04070632364004389, + "z": 0.0 + }, + { + "x": 189.15357707144278, + "y": 0.04081342679661672, + "z": 0.0 + }, + { + "x": 188.15007389245508, + "y": 0.040920529953189545, + "z": 0.0 + }, + { + "x": 187.14657071346738, + "y": 0.041027633109762374, + "z": 0.0 + }, + { + "x": 186.14306753447968, + "y": 0.041134736266335195, + "z": 0.0 + }, + { + "x": 185.13956435549193, + "y": 0.04124183942290802, + "z": 0.0 + }, + { + "x": 184.13606117650423, + "y": 0.04134894257948085, + "z": 0.0 + }, + { + "x": 183.13255799751653, + "y": 0.04145604573605368, + "z": 0.0 + }, + { + "x": 182.12905481852883, + "y": 0.0415631488926265, + "z": 0.0 + }, + { + "x": 181.1255516395411, + "y": 0.04167025204919933, + "z": 0.0 + }, + { + "x": 180.12204846055337, + "y": 0.04177735520577216, + "z": 0.0 + }, + { + "x": 179.11854528156567, + "y": 0.04188445836234498, + "z": 0.0 + }, + { + "x": 178.11504210257797, + "y": 0.04199156151891781, + "z": 0.0 + }, + { + "x": 177.11153892359025, + "y": 0.04209866467549064, + "z": 0.0 + }, + { + "x": 176.10803574460255, + "y": 0.04220576783206346, + "z": 0.0 + }, + { + "x": 175.10453256561482, + "y": 0.042312870988636286, + "z": 0.0 + }, + { + "x": 174.10102938662712, + "y": 0.042419974145209115, + "z": 0.0 + }, + { + "x": 173.0975262076394, + "y": 0.042527077301781936, + "z": 0.0 + }, + { + "x": 172.0940230286517, + "y": 0.042634180458354765, + "z": 0.0 + }, + { + "x": 171.090519849664, + "y": 0.042741283614927586, + "z": 0.0 + }, + { + "x": 170.08701667067626, + "y": 0.042848386771500414, + "z": 0.0 + }, + { + "x": 169.08351349168854, + "y": 0.04295548992807324, + "z": 0.0 + }, + { + "x": 168.08001031270084, + "y": 0.043062593084646064, + "z": 0.0 + } + ] + }, + { + "id": 8, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 168.07979685417234, + "y": -1.956937395524218, + "z": 0.0 + }, + { + "x": 169.08330003316004, + "y": -1.957044498680791, + "z": 0.0 + }, + { + "x": 170.08680321214777, + "y": -1.9571516018373638, + "z": 0.0 + }, + { + "x": 171.0903063911355, + "y": -1.9572587049939367, + "z": 0.0 + }, + { + "x": 172.0938095701232, + "y": -1.9573658081505094, + "z": 0.0 + }, + { + "x": 173.0973127491109, + "y": -1.9574729113070821, + "z": 0.0 + }, + { + "x": 174.10081592809863, + "y": -1.957580014463655, + "z": 0.0 + }, + { + "x": 175.10431910708633, + "y": -1.957687117620228, + "z": 0.0 + }, + { + "x": 176.10782228607405, + "y": -1.9577942207768009, + "z": 0.0 + }, + { + "x": 177.11132546506175, + "y": -1.9579013239333733, + "z": 0.0 + }, + { + "x": 178.11482864404948, + "y": -1.9580084270899463, + "z": 0.0 + }, + { + "x": 179.11833182303718, + "y": -1.9581155302465192, + "z": 0.0 + }, + { + "x": 180.12183500202488, + "y": -1.958222633403092, + "z": 0.0 + }, + { + "x": 181.1253381810126, + "y": -1.958329736559665, + "z": 0.0 + }, + { + "x": 182.12884136000034, + "y": -1.9584368397162375, + "z": 0.0 + }, + { + "x": 183.13234453898804, + "y": -1.9585439428728104, + "z": 0.0 + }, + { + "x": 184.13584771797574, + "y": -1.9586510460293833, + "z": 0.0 + }, + { + "x": 185.13935089696344, + "y": -1.9587581491859563, + "z": 0.0 + }, + { + "x": 186.1428540759512, + "y": -1.9588652523425292, + "z": 0.0 + }, + { + "x": 187.1463572549389, + "y": -1.9589723554991016, + "z": 0.0 + }, + { + "x": 188.1498604339266, + "y": -1.9590794586556746, + "z": 0.0 + }, + { + "x": 189.1533636129143, + "y": -1.9591865618122475, + "z": 0.0 + }, + { + "x": 190.15686679190205, + "y": -1.9592936649688204, + "z": 0.0 + }, + { + "x": 191.16036997088975, + "y": -1.9594007681253933, + "z": 0.0 + }, + { + "x": 192.16387314987745, + "y": -1.9595078712819658, + "z": 0.0 + }, + { + "x": 193.16737632886515, + "y": -1.9596149744385387, + "z": 0.0 + }, + { + "x": 194.17087950785287, + "y": -1.9597220775951116, + "z": 0.0 + }, + { + "x": 195.1743826868406, + "y": -1.9598291807516846, + "z": 0.0 + }, + { + "x": 196.1778858658283, + "y": -1.9599362839082572, + "z": 0.0 + }, + { + "x": 197.18138904481603, + "y": -1.96004338706483, + "z": 0.0 + }, + { + "x": 198.1848922238037, + "y": -1.9601504902214029, + "z": 0.0 + }, + { + "x": 199.18839540279143, + "y": -1.9602575933779758, + "z": 0.0 + }, + { + "x": 200.1918985817791, + "y": -1.9603646965345487, + "z": 0.0 + }, + { + "x": 201.19540176076683, + "y": -1.9604717996911212, + "z": 0.0 + }, + { + "x": 202.1989049397545, + "y": -1.960578902847694, + "z": 0.0 + }, + { + "x": 203.20240811874223, + "y": -1.960686006004267, + "z": 0.0 + }, + { + "x": 204.2059112977299, + "y": -1.96079310916084, + "z": 0.0 + }, + { + "x": 205.2094144767176, + "y": -1.9609002123174128, + "z": 0.0 + }, + { + "x": 206.2129176557053, + "y": -1.9610073154739853, + "z": 0.0 + }, + { + "x": 207.216420834693, + "y": -1.9611144186305582, + "z": 0.0 + }, + { + "x": 208.2199240136807, + "y": -1.9612215217871312, + "z": 0.0 + }, + { + "x": 209.2234271926684, + "y": -1.961328624943704, + "z": 0.0 + }, + { + "x": 210.2269303716561, + "y": -1.961435728100277, + "z": 0.0 + }, + { + "x": 211.2304335506438, + "y": -1.9615428312568495, + "z": 0.0 + }, + { + "x": 212.2339367296315, + "y": -1.9616499344134224, + "z": 0.0 + }, + { + "x": 213.2374399086192, + "y": -1.9617570375699953, + "z": 0.0 + }, + { + "x": 214.2409430876069, + "y": -1.9618641407265682, + "z": 0.0 + }, + { + "x": 215.2444462665946, + "y": -1.961971243883141, + "z": 0.0 + }, + { + "x": 216.2479494455823, + "y": -1.9620783470397136, + "z": 0.0 + }, + { + "x": 217.25145262457, + "y": -1.9621854501962865, + "z": 0.0 + }, + { + "x": 218.2549558035577, + "y": -1.9622925533528595, + "z": 0.0 + }, + { + "x": 219.2584589825454, + "y": -1.9623996565094324, + "z": 0.0 + }, + { + "x": 220.2619621615331, + "y": -1.9625067596660049, + "z": 0.0 + }, + { + "x": 221.2654653405208, + "y": -1.9626138628225778, + "z": 0.0 + }, + { + "x": 222.2689685195085, + "y": -1.9627209659791507, + "z": 0.0 + }, + { + "x": 223.2724716984962, + "y": -1.9628280691357236, + "z": 0.0 + }, + { + "x": 224.2759748774839, + "y": -1.9629351722922965, + "z": 0.0 + }, + { + "x": 225.2794780564716, + "y": -1.963042275448869, + "z": 0.0 + }, + { + "x": 226.2829812354593, + "y": -1.963149378605442, + "z": 0.0 + }, + { + "x": 227.286484414447, + "y": -1.9632564817620148, + "z": 0.0 + }, + { + "x": 228.2899875934347, + "y": -1.9633635849185878, + "z": 0.0 + }, + { + "x": 229.2934907724224, + "y": -1.9634706880751607, + "z": 0.0 + }, + { + "x": 230.2969939514101, + "y": -1.9635777912317331, + "z": 0.0 + }, + { + "x": 231.3004971303978, + "y": -1.963684894388306, + "z": 0.0 + }, + { + "x": 232.3040003093855, + "y": -1.963791997544879, + "z": 0.0 + }, + { + "x": 233.3075034883732, + "y": -1.963899100701452, + "z": 0.0 + }, + { + "x": 234.31100666736089, + "y": -1.9640062038580244, + "z": 0.0 + }, + { + "x": 235.31450984634859, + "y": -1.9641133070145973, + "z": 0.0 + }, + { + "x": 236.31801302533626, + "y": -1.9642204101711702, + "z": 0.0 + }, + { + "x": 237.32151620432398, + "y": -1.9643275133277431, + "z": 0.0 + }, + { + "x": 238.32501938331166, + "y": -1.964434616484316, + "z": 0.0 + }, + { + "x": 239.32852256229938, + "y": -1.9645417196408885, + "z": 0.0 + }, + { + "x": 240.33202574128705, + "y": -1.9646488227974614, + "z": 0.0 + }, + { + "x": 241.33552892027478, + "y": -1.9647559259540344, + "z": 0.0 + }, + { + "x": 242.33903209926245, + "y": -1.9648630291106073, + "z": 0.0 + }, + { + "x": 243.34253527825015, + "y": -1.9649701322671802, + "z": 0.0 + }, + { + "x": 244.34603845723785, + "y": -1.9650772354237527, + "z": 0.0 + }, + { + "x": 245.34954163622555, + "y": -1.9651843385803256, + "z": 0.0 + }, + { + "x": 246.35304481521325, + "y": -1.9652914417368985, + "z": 0.0 + }, + { + "x": 247.35654799420095, + "y": -1.9653985448934714, + "z": 0.0 + }, + { + "x": 248.36005117318865, + "y": -1.9655056480500444, + "z": 0.0 + }, + { + "x": 249.36355435217635, + "y": -1.9656127512066168, + "z": 0.0 + }, + { + "x": 250.36705753116405, + "y": -1.9657198543631897, + "z": 0.0 + }, + { + "x": 251.37056071015175, + "y": -1.9658269575197627, + "z": 0.0 + }, + { + "x": 252.37406388913945, + "y": -1.9659340606763356, + "z": 0.0 + }, + { + "x": 253.37756706812715, + "y": -1.966041163832908, + "z": 0.0 + }, + { + "x": 254.38107024711485, + "y": -1.966148266989481, + "z": 0.0 + }, + { + "x": 255.38457342610255, + "y": -1.966255370146054, + "z": 0.0 + }, + { + "x": 256.38807660509025, + "y": -1.9663624733026268, + "z": 0.0 + }, + { + "x": 257.3915797840779, + "y": -1.9664695764591997, + "z": 0.0 + }, + { + "x": 258.39508296306565, + "y": -1.9665766796157722, + "z": 0.0 + }, + { + "x": 259.3985861420533, + "y": -1.9666837827723451, + "z": 0.0 + }, + { + "x": 260.40208932104105, + "y": -1.966790885928918, + "z": 0.0 + }, + { + "x": 261.4055925000287, + "y": -1.966897989085491, + "z": 0.0 + }, + { + "x": 262.40909567901645, + "y": -1.9670050922420639, + "z": 0.0 + }, + { + "x": 263.4125988580042, + "y": -1.9671121953986364, + "z": 0.0 + }, + { + "x": 264.41610203699184, + "y": -1.9672192985552093, + "z": 0.0 + }, + { + "x": 265.4196052159796, + "y": -1.9673264017117822, + "z": 0.0 + }, + { + "x": 266.42310839496724, + "y": -1.967433504868355, + "z": 0.0 + }, + { + "x": 267.426611573955, + "y": -1.9675406080249278, + "z": 0.0 + }, + { + "x": 268.4301147529427, + "y": -1.9676477111815005, + "z": 0.0 + }, + { + "x": 269.43361793193037, + "y": -1.9677548143380734, + "z": 0.0 + }, + { + "x": 270.4371211109181, + "y": -1.9678619174946463, + "z": 0.0 + }, + { + "x": 271.44062428990577, + "y": -1.9679690206512193, + "z": 0.0 + }, + { + "x": 272.4441274688935, + "y": -1.9680761238077917, + "z": 0.0 + }, + { + "x": 273.4476306478812, + "y": -1.9681832269643647, + "z": 0.0 + }, + { + "x": 274.4511338268689, + "y": -1.9682903301209376, + "z": 0.0 + }, + { + "x": 275.4546370058566, + "y": -1.9683974332775105, + "z": 0.0 + }, + { + "x": 276.45814018484435, + "y": -1.9685045364340834, + "z": 0.0 + }, + { + "x": 277.461643363832, + "y": -1.9686116395906559, + "z": 0.0 + }, + { + "x": 278.46514654281975, + "y": -1.9687187427472288, + "z": 0.0 + }, + { + "x": 279.4686497218074, + "y": -1.9688258459038017, + "z": 0.0 + }, + { + "x": 280.47215290079515, + "y": -1.9689329490603746, + "z": 0.0 + }, + { + "x": 281.4756560797829, + "y": -1.9690400522169476, + "z": 0.0 + }, + { + "x": 282.47915925877055, + "y": -1.96914715537352, + "z": 0.0 + }, + { + "x": 283.4826624377583, + "y": -1.969254258530093, + "z": 0.0 + }, + { + "x": 284.48616561674595, + "y": -1.9693613616866659, + "z": 0.0 + }, + { + "x": 285.4896687957337, + "y": -1.9694684648432388, + "z": 0.0 + }, + { + "x": 286.4931719747214, + "y": -1.9695755679998117, + "z": 0.0 + }, + { + "x": 287.4966751537091, + "y": -1.9696826711563842, + "z": 0.0 + }, + { + "x": 288.5001783326968, + "y": -1.969789774312957, + "z": 0.0 + }, + { + "x": 289.50368151168453, + "y": -1.96989687746953, + "z": 0.0 + }, + { + "x": 290.5071239699698, + "y": -1.9700344366797367, + "z": 0.0 + }, + { + "x": 291.50986779320573, + "y": -1.970552697994256, + "z": 0.0 + }, + { + "x": 292.51334176180364, + "y": -1.9710857804400896, + "z": 0.0 + }, + { + "x": 293.5168448049064, + "y": -1.9716188781200372, + "z": 0.0 + }, + { + "x": 294.52034784800907, + "y": -1.972151975799984, + "z": 0.0 + }, + { + "x": 295.52385089111175, + "y": -1.9726850734799315, + "z": 0.0 + }, + { + "x": 296.5273539342145, + "y": -1.973218171159879, + "z": 0.0 + }, + { + "x": 297.53085697731717, + "y": -1.9737512688398258, + "z": 0.0 + }, + { + "x": 298.53436002041985, + "y": -1.974284366519773, + "z": 0.0 + }, + { + "x": 299.5378630635226, + "y": -1.9748174641997205, + "z": 0.0 + }, + { + "x": 300.5413661066253, + "y": -1.9753505618796672, + "z": 0.0 + }, + { + "x": 301.54486914972796, + "y": -1.9758836595596148, + "z": 0.0 + }, + { + "x": 302.5483721928307, + "y": -1.9764167572395623, + "z": 0.0 + }, + { + "x": 303.5518752359334, + "y": -1.976949854919509, + "z": 0.0 + }, + { + "x": 304.55537827903606, + "y": -1.9774829525994562, + "z": 0.0 + }, + { + "x": 305.5588813221388, + "y": -1.9780160502794037, + "z": 0.0 + }, + { + "x": 306.5623843652415, + "y": -1.9785491479593509, + "z": 0.0 + }, + { + "x": 307.56588740834417, + "y": -1.979082245639298, + "z": 0.0 + }, + { + "x": 308.5693904514469, + "y": -1.9796153433192456, + "z": 0.0 + }, + { + "x": 309.5728934945496, + "y": -1.9801484409991923, + "z": 0.0 + }, + { + "x": 310.5763965376523, + "y": -1.9806815386791394, + "z": 0.0 + }, + { + "x": 311.579899580755, + "y": -1.9812146363590875, + "z": 0.0 + }, + { + "x": 312.5834026238577, + "y": -1.9817477340390341, + "z": 0.0 + }, + { + "x": 313.5869056669604, + "y": -1.9822808317189813, + "z": 0.0 + }, + { + "x": 314.59040871006306, + "y": -1.9828139293989284, + "z": 0.0 + }, + { + "x": 315.5939117531658, + "y": -1.983347027078876, + "z": 0.0 + }, + { + "x": 316.5974147962685, + "y": -1.9838801247588231, + "z": 0.0 + }, + { + "x": 317.60091783937116, + "y": -1.9844132224387703, + "z": 0.0 + }, + { + "x": 318.6044208824739, + "y": -1.9849463201187179, + "z": 0.0 + }, + { + "x": 319.6079239255766, + "y": -1.9854794177986645, + "z": 0.0 + }, + { + "x": 320.61142696867927, + "y": -1.9860125154786117, + "z": 0.0 + }, + { + "x": 321.614930011782, + "y": -1.9865456131585593, + "z": 0.0 + }, + { + "x": 322.6184330548847, + "y": -1.9870787108385064, + "z": 0.0 + }, + { + "x": 323.6219360979874, + "y": -1.9876118085184535, + "z": 0.0 + }, + { + "x": 324.6254391410901, + "y": -1.9881449061984011, + "z": 0.0 + }, + { + "x": 325.6289421841928, + "y": -1.9886780038783478, + "z": 0.0 + } + ] + }, + { + "id": 9, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.63106713083204, + "y": 2.0113214316968344, + "z": 0.0 + }, + { + "x": 324.62756408772935, + "y": 2.011854529376782, + "z": 0.0 + }, + { + "x": 323.6240610446266, + "y": 2.012387627056729, + "z": 0.0 + }, + { + "x": 322.62055800152393, + "y": 2.0129207247366763, + "z": 0.0 + }, + { + "x": 321.61705495842125, + "y": 2.013453822416624, + "z": 0.0 + }, + { + "x": 320.6135519153185, + "y": 2.0139869200965705, + "z": 0.0 + }, + { + "x": 319.6100488722158, + "y": 2.0145200177765177, + "z": 0.0 + }, + { + "x": 318.60654582911314, + "y": 2.0150531154564657, + "z": 0.0 + }, + { + "x": 317.6030427860104, + "y": 2.0155862131364124, + "z": 0.0 + }, + { + "x": 316.5995397429077, + "y": 2.0161193108163595, + "z": 0.0 + }, + { + "x": 315.59603669980504, + "y": 2.016652408496307, + "z": 0.0 + }, + { + "x": 314.5925336567023, + "y": 2.017185506176254, + "z": 0.0 + }, + { + "x": 313.5890306135996, + "y": 2.0177186038562014, + "z": 0.0 + }, + { + "x": 312.58552757049694, + "y": 2.0182517015361485, + "z": 0.0 + }, + { + "x": 311.58202452739425, + "y": 2.018784799216096, + "z": 0.0 + }, + { + "x": 310.5785214842915, + "y": 2.019317896896043, + "z": 0.0 + }, + { + "x": 309.57501844118883, + "y": 2.01985099457599, + "z": 0.0 + }, + { + "x": 308.57151539808615, + "y": 2.020384092255938, + "z": 0.0 + }, + { + "x": 307.5680123549834, + "y": 2.0209171899358847, + "z": 0.0 + }, + { + "x": 306.5645093118807, + "y": 2.021450287615832, + "z": 0.0 + }, + { + "x": 305.56100626877804, + "y": 2.0219833852957794, + "z": 0.0 + }, + { + "x": 304.5575032256753, + "y": 2.022516482975726, + "z": 0.0 + }, + { + "x": 303.5540001825726, + "y": 2.023049580655673, + "z": 0.0 + }, + { + "x": 302.55049713946994, + "y": 2.023582678335621, + "z": 0.0 + }, + { + "x": 301.5469940963672, + "y": 2.024115776015568, + "z": 0.0 + }, + { + "x": 300.5434910532645, + "y": 2.024648873695515, + "z": 0.0 + }, + { + "x": 299.53998801016184, + "y": 2.0251819713754626, + "z": 0.0 + }, + { + "x": 298.5364849670591, + "y": 2.0257150690554093, + "z": 0.0 + }, + { + "x": 297.5329819239564, + "y": 2.026248166735357, + "z": 0.0 + }, + { + "x": 296.52947888085373, + "y": 2.0267812644153045, + "z": 0.0 + }, + { + "x": 295.525975837751, + "y": 2.027314362095251, + "z": 0.0 + }, + { + "x": 294.5224727946483, + "y": 2.0278474597751983, + "z": 0.0 + }, + { + "x": 293.5189697515456, + "y": 2.028380557455146, + "z": 0.0 + }, + { + "x": 292.5154667084429, + "y": 2.028913655135093, + "z": 0.0 + }, + { + "x": 291.51193459083544, + "y": 2.0294467680491537, + "z": 0.0 + }, + { + "x": 290.50767231546286, + "y": 2.0299655257349163, + "z": 0.0 + }, + { + "x": 289.5041084287415, + "y": 2.0301030997481986, + "z": 0.0 + }, + { + "x": 288.5006052497538, + "y": 2.030210202904771, + "z": 0.0 + }, + { + "x": 287.49710207076606, + "y": 2.030317306061344, + "z": 0.0 + }, + { + "x": 286.4935988917784, + "y": 2.030424409217917, + "z": 0.0 + }, + { + "x": 285.49009571279066, + "y": 2.03053151237449, + "z": 0.0 + }, + { + "x": 284.48659253380293, + "y": 2.0306386155310627, + "z": 0.0 + }, + { + "x": 283.48308935481526, + "y": 2.030745718687635, + "z": 0.0 + }, + { + "x": 282.47958617582754, + "y": 2.030852821844208, + "z": 0.0 + }, + { + "x": 281.47608299683986, + "y": 2.030959925000781, + "z": 0.0 + }, + { + "x": 280.47257981785214, + "y": 2.031067028157354, + "z": 0.0 + }, + { + "x": 279.4690766388644, + "y": 2.031174131313927, + "z": 0.0 + }, + { + "x": 278.46557345987674, + "y": 2.0312812344704994, + "z": 0.0 + }, + { + "x": 277.462070280889, + "y": 2.0313883376270723, + "z": 0.0 + }, + { + "x": 276.45856710190134, + "y": 2.031495440783645, + "z": 0.0 + }, + { + "x": 275.4550639229136, + "y": 2.031602543940218, + "z": 0.0 + }, + { + "x": 274.4515607439259, + "y": 2.0317096470967906, + "z": 0.0 + }, + { + "x": 273.4480575649382, + "y": 2.0318167502533635, + "z": 0.0 + }, + { + "x": 272.4445543859505, + "y": 2.0319238534099364, + "z": 0.0 + }, + { + "x": 271.44105120696275, + "y": 2.0320309565665093, + "z": 0.0 + }, + { + "x": 270.4375480279751, + "y": 2.0321380597230823, + "z": 0.0 + }, + { + "x": 269.43404484898736, + "y": 2.0322451628796547, + "z": 0.0 + }, + { + "x": 268.4305416699997, + "y": 2.0323522660362277, + "z": 0.0 + }, + { + "x": 267.42703849101196, + "y": 2.0324593691928006, + "z": 0.0 + }, + { + "x": 266.4235353120242, + "y": 2.0325664723493735, + "z": 0.0 + }, + { + "x": 265.42003213303656, + "y": 2.0326735755059464, + "z": 0.0 + }, + { + "x": 264.41652895404883, + "y": 2.032780678662519, + "z": 0.0 + }, + { + "x": 263.41302577506116, + "y": 2.032887781819092, + "z": 0.0 + }, + { + "x": 262.40952259607343, + "y": 2.0329948849756647, + "z": 0.0 + }, + { + "x": 261.4060194170857, + "y": 2.0331019881322376, + "z": 0.0 + }, + { + "x": 260.40251623809803, + "y": 2.0332090912888106, + "z": 0.0 + }, + { + "x": 259.3990130591103, + "y": 2.033316194445383, + "z": 0.0 + }, + { + "x": 258.39550988012263, + "y": 2.033423297601956, + "z": 0.0 + }, + { + "x": 257.3920067011349, + "y": 2.033530400758529, + "z": 0.0 + }, + { + "x": 256.38850352214723, + "y": 2.033637503915102, + "z": 0.0 + }, + { + "x": 255.38500034315953, + "y": 2.0337446070716743, + "z": 0.0 + }, + { + "x": 254.38149716417183, + "y": 2.033851710228247, + "z": 0.0 + }, + { + "x": 253.37799398518413, + "y": 2.03395881338482, + "z": 0.0 + }, + { + "x": 252.37449080619643, + "y": 2.034065916541393, + "z": 0.0 + }, + { + "x": 251.37098762720873, + "y": 2.034173019697966, + "z": 0.0 + }, + { + "x": 250.36748444822103, + "y": 2.0342801228545384, + "z": 0.0 + }, + { + "x": 249.36398126923334, + "y": 2.0343872260111113, + "z": 0.0 + }, + { + "x": 248.36047809024564, + "y": 2.0344943291676842, + "z": 0.0 + }, + { + "x": 247.35697491125794, + "y": 2.034601432324257, + "z": 0.0 + }, + { + "x": 246.35347173227024, + "y": 2.03470853548083, + "z": 0.0 + }, + { + "x": 245.34996855328254, + "y": 2.0348156386374026, + "z": 0.0 + }, + { + "x": 244.34646537429484, + "y": 2.0349227417939755, + "z": 0.0 + }, + { + "x": 243.34296219530714, + "y": 2.0350298449505484, + "z": 0.0 + }, + { + "x": 242.33945901631944, + "y": 2.0351369481071213, + "z": 0.0 + }, + { + "x": 241.33595583733177, + "y": 2.0352440512636942, + "z": 0.0 + }, + { + "x": 240.33245265834404, + "y": 2.0353511544202667, + "z": 0.0 + }, + { + "x": 239.32894947935637, + "y": 2.0354582575768396, + "z": 0.0 + }, + { + "x": 238.32544630036864, + "y": 2.0355653607334125, + "z": 0.0 + }, + { + "x": 237.32194312138097, + "y": 2.0356724638899855, + "z": 0.0 + }, + { + "x": 236.31843994239324, + "y": 2.035779567046558, + "z": 0.0 + }, + { + "x": 235.31493676340557, + "y": 2.035886670203131, + "z": 0.0 + }, + { + "x": 234.31143358441787, + "y": 2.0359937733597038, + "z": 0.0 + }, + { + "x": 233.30793040543017, + "y": 2.0361008765162767, + "z": 0.0 + }, + { + "x": 232.30442722644247, + "y": 2.0362079796728496, + "z": 0.0 + }, + { + "x": 231.30092404745477, + "y": 2.036315082829422, + "z": 0.0 + }, + { + "x": 230.29742086846707, + "y": 2.036422185985995, + "z": 0.0 + }, + { + "x": 229.29391768947937, + "y": 2.036529289142568, + "z": 0.0 + }, + { + "x": 228.29041451049167, + "y": 2.036636392299141, + "z": 0.0 + }, + { + "x": 227.28691133150397, + "y": 2.0367434954557138, + "z": 0.0 + }, + { + "x": 226.28340815251627, + "y": 2.0368505986122862, + "z": 0.0 + }, + { + "x": 225.27990497352857, + "y": 2.036957701768859, + "z": 0.0 + }, + { + "x": 224.27640179454087, + "y": 2.037064804925432, + "z": 0.0 + }, + { + "x": 223.27289861555317, + "y": 2.037171908082005, + "z": 0.0 + }, + { + "x": 222.26939543656547, + "y": 2.0372790112385775, + "z": 0.0 + }, + { + "x": 221.26589225757778, + "y": 2.0373861143951504, + "z": 0.0 + }, + { + "x": 220.26238907859008, + "y": 2.0374932175517233, + "z": 0.0 + }, + { + "x": 219.25888589960238, + "y": 2.037600320708296, + "z": 0.0 + }, + { + "x": 218.25538272061468, + "y": 2.037707423864869, + "z": 0.0 + }, + { + "x": 217.25187954162698, + "y": 2.0378145270214416, + "z": 0.0 + }, + { + "x": 216.24837636263928, + "y": 2.0379216301780145, + "z": 0.0 + }, + { + "x": 215.24487318365158, + "y": 2.0380287333345875, + "z": 0.0 + }, + { + "x": 214.24137000466388, + "y": 2.0381358364911604, + "z": 0.0 + }, + { + "x": 213.23786682567618, + "y": 2.0382429396477333, + "z": 0.0 + }, + { + "x": 212.23436364668848, + "y": 2.0383500428043058, + "z": 0.0 + }, + { + "x": 211.23086046770078, + "y": 2.0384571459608787, + "z": 0.0 + }, + { + "x": 210.22735728871308, + "y": 2.0385642491174516, + "z": 0.0 + }, + { + "x": 209.22385410972538, + "y": 2.0386713522740245, + "z": 0.0 + }, + { + "x": 208.22035093073768, + "y": 2.0387784554305974, + "z": 0.0 + }, + { + "x": 207.21684775174998, + "y": 2.03888555858717, + "z": 0.0 + }, + { + "x": 206.21334457276228, + "y": 2.038992661743743, + "z": 0.0 + }, + { + "x": 205.20984139377458, + "y": 2.0390997649003157, + "z": 0.0 + }, + { + "x": 204.20633821478688, + "y": 2.0392068680568887, + "z": 0.0 + }, + { + "x": 203.2028350357992, + "y": 2.039313971213461, + "z": 0.0 + }, + { + "x": 202.19933185681148, + "y": 2.039421074370034, + "z": 0.0 + }, + { + "x": 201.1958286778238, + "y": 2.039528177526607, + "z": 0.0 + }, + { + "x": 200.19232549883608, + "y": 2.03963528068318, + "z": 0.0 + }, + { + "x": 199.1888223198484, + "y": 2.039742383839753, + "z": 0.0 + }, + { + "x": 198.18531914086068, + "y": 2.0398494869963253, + "z": 0.0 + }, + { + "x": 197.181815961873, + "y": 2.039956590152898, + "z": 0.0 + }, + { + "x": 196.17831278288529, + "y": 2.040063693309471, + "z": 0.0 + }, + { + "x": 195.1748096038976, + "y": 2.040170796466044, + "z": 0.0 + }, + { + "x": 194.17130642490986, + "y": 2.040277899622617, + "z": 0.0 + }, + { + "x": 193.16780324592213, + "y": 2.0403850027791894, + "z": 0.0 + }, + { + "x": 192.16430006693443, + "y": 2.0404921059357624, + "z": 0.0 + }, + { + "x": 191.16079688794673, + "y": 2.0405992090923353, + "z": 0.0 + }, + { + "x": 190.15729370895903, + "y": 2.040706312248908, + "z": 0.0 + }, + { + "x": 189.15379052997127, + "y": 2.040813415405481, + "z": 0.0 + }, + { + "x": 188.15028735098358, + "y": 2.0409205185620536, + "z": 0.0 + }, + { + "x": 187.14678417199588, + "y": 2.0410276217186265, + "z": 0.0 + }, + { + "x": 186.14328099300818, + "y": 2.0411347248751994, + "z": 0.0 + }, + { + "x": 185.13977781402042, + "y": 2.0412418280317723, + "z": 0.0 + }, + { + "x": 184.13627463503272, + "y": 2.0413489311883453, + "z": 0.0 + }, + { + "x": 183.13277145604502, + "y": 2.0414560343449177, + "z": 0.0 + }, + { + "x": 182.12926827705732, + "y": 2.0415631375014907, + "z": 0.0 + }, + { + "x": 181.1257650980696, + "y": 2.0416702406580636, + "z": 0.0 + }, + { + "x": 180.12226191908186, + "y": 2.0417773438146365, + "z": 0.0 + }, + { + "x": 179.11875874009417, + "y": 2.041884446971209, + "z": 0.0 + }, + { + "x": 178.11525556110647, + "y": 2.041991550127782, + "z": 0.0 + }, + { + "x": 177.11175238211874, + "y": 2.042098653284355, + "z": 0.0 + }, + { + "x": 176.10824920313104, + "y": 2.0422057564409277, + "z": 0.0 + }, + { + "x": 175.1047460241433, + "y": 2.0423128595975006, + "z": 0.0 + }, + { + "x": 174.1012428451556, + "y": 2.042419962754073, + "z": 0.0 + }, + { + "x": 173.09773966616788, + "y": 2.042527065910646, + "z": 0.0 + }, + { + "x": 172.09423648718018, + "y": 2.042634169067219, + "z": 0.0 + }, + { + "x": 171.09073330819248, + "y": 2.042741272223792, + "z": 0.0 + }, + { + "x": 170.08723012920476, + "y": 2.042848375380365, + "z": 0.0 + }, + { + "x": 169.08372695021703, + "y": 2.0429554785369373, + "z": 0.0 + }, + { + "x": 168.08022377122933, + "y": 2.04306258169351, + "z": 0.0 + } + ] + }, + { + "id": 10, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 102.69023839464042, + "y": -3.9501270959538224, + "z": 0.0 + }, + { + "x": 103.72121398505429, + "y": -3.9500684091140976, + "z": 0.0 + }, + { + "x": 104.75153497744992, + "y": -3.9501784280806986, + "z": 0.0 + }, + { + "x": 105.78251058129288, + "y": -3.95028846334898, + "z": 0.0 + }, + { + "x": 106.81348618513584, + "y": -3.9503984986172616, + "z": 0.0 + }, + { + "x": 107.8444617889788, + "y": -3.950508533885543, + "z": 0.0 + }, + { + "x": 108.87543739282175, + "y": -3.9506185691538245, + "z": 0.0 + }, + { + "x": 109.90641299666471, + "y": -3.950728604422106, + "z": 0.0 + }, + { + "x": 110.93738860050767, + "y": -3.9508386396903874, + "z": 0.0 + }, + { + "x": 111.96836420435064, + "y": -3.950948674958669, + "z": 0.0 + }, + { + "x": 112.9993398081936, + "y": -3.95105871022695, + "z": 0.0 + }, + { + "x": 114.03031541203654, + "y": -3.9511687454952313, + "z": 0.0 + }, + { + "x": 115.0612910158795, + "y": -3.951278780763513, + "z": 0.0 + }, + { + "x": 116.09226661972247, + "y": -3.9513888160317943, + "z": 0.0 + }, + { + "x": 117.12324222356543, + "y": -3.9514988513000757, + "z": 0.0 + }, + { + "x": 118.15421782740839, + "y": -3.951608886568357, + "z": 0.0 + }, + { + "x": 119.18519343125135, + "y": -3.9517189218366386, + "z": 0.0 + }, + { + "x": 120.2161690350943, + "y": -3.95182895710492, + "z": 0.0 + }, + { + "x": 121.24714463893727, + "y": -3.951938992373201, + "z": 0.0 + }, + { + "x": 122.27812024278022, + "y": -3.9520490276414826, + "z": 0.0 + }, + { + "x": 123.30909584662318, + "y": -3.952159062909764, + "z": 0.0 + }, + { + "x": 124.34007145046614, + "y": -3.9522690981780455, + "z": 0.0 + }, + { + "x": 125.3710470543091, + "y": -3.952379133446327, + "z": 0.0 + }, + { + "x": 126.40202265815206, + "y": -3.9524891687146084, + "z": 0.0 + }, + { + "x": 127.43299826199502, + "y": -3.95259920398289, + "z": 0.0 + }, + { + "x": 128.46397386583797, + "y": -3.9527092392511713, + "z": 0.0 + }, + { + "x": 129.49494946968093, + "y": -3.9528192745194524, + "z": 0.0 + }, + { + "x": 130.5259250735239, + "y": -3.952929309787734, + "z": 0.0 + }, + { + "x": 131.55690067736685, + "y": -3.9530393450560153, + "z": 0.0 + }, + { + "x": 132.58787628120982, + "y": -3.9531493803242967, + "z": 0.0 + }, + { + "x": 133.61885188505278, + "y": -3.953259415592578, + "z": 0.0 + }, + { + "x": 134.64982748889574, + "y": -3.9533694508608597, + "z": 0.0 + }, + { + "x": 135.6808030927387, + "y": -3.953479486129141, + "z": 0.0 + }, + { + "x": 136.71177869658166, + "y": -3.9535895213974226, + "z": 0.0 + }, + { + "x": 137.74275430042462, + "y": -3.9536995566657036, + "z": 0.0 + }, + { + "x": 138.77372990426755, + "y": -3.953809591933985, + "z": 0.0 + }, + { + "x": 139.80470550811052, + "y": -3.9539196272022665, + "z": 0.0 + }, + { + "x": 140.83568111195348, + "y": -3.954029662470548, + "z": 0.0 + }, + { + "x": 141.86665671579644, + "y": -3.9541396977388295, + "z": 0.0 + }, + { + "x": 142.8976323196394, + "y": -3.954249733007111, + "z": 0.0 + }, + { + "x": 143.92860792348236, + "y": -3.9543597682753924, + "z": 0.0 + }, + { + "x": 144.95958352732532, + "y": -3.954469803543674, + "z": 0.0 + } + ] + }, + { + "id": 11, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 144.9604373614393, + "y": 4.045530150891783, + "z": 0.0 + }, + { + "x": 143.92946175759633, + "y": 4.045640186160065, + "z": 0.0 + }, + { + "x": 142.89848615375337, + "y": 4.045750221428346, + "z": 0.0 + }, + { + "x": 141.8675105499104, + "y": 4.045860256696628, + "z": 0.0 + }, + { + "x": 140.83653494606745, + "y": 4.045970291964909, + "z": 0.0 + }, + { + "x": 139.80555934222448, + "y": 4.04608032723319, + "z": 0.0 + }, + { + "x": 138.77458373838152, + "y": 4.046190362501472, + "z": 0.0 + }, + { + "x": 137.7436081345386, + "y": 4.046300397769753, + "z": 0.0 + }, + { + "x": 136.71263253069563, + "y": 4.046410433038035, + "z": 0.0 + }, + { + "x": 135.68165692685267, + "y": 4.046520468306316, + "z": 0.0 + }, + { + "x": 134.6506813230097, + "y": 4.0466305035745975, + "z": 0.0 + }, + { + "x": 133.61970571916675, + "y": 4.0467405388428785, + "z": 0.0 + }, + { + "x": 132.58873011532378, + "y": 4.04685057411116, + "z": 0.0 + }, + { + "x": 131.55775451148082, + "y": 4.0469606093794415, + "z": 0.0 + }, + { + "x": 130.52677890763786, + "y": 4.0470706446477225, + "z": 0.0 + }, + { + "x": 129.4958033037949, + "y": 4.047180679916004, + "z": 0.0 + }, + { + "x": 128.46482769995194, + "y": 4.047290715184285, + "z": 0.0 + }, + { + "x": 127.43385209610899, + "y": 4.047400750452567, + "z": 0.0 + }, + { + "x": 126.40287649226603, + "y": 4.047510785720848, + "z": 0.0 + }, + { + "x": 125.37190088842307, + "y": 4.04762082098913, + "z": 0.0 + }, + { + "x": 124.34092528458011, + "y": 4.047730856257411, + "z": 0.0 + }, + { + "x": 123.30994968073715, + "y": 4.047840891525692, + "z": 0.0 + }, + { + "x": 122.27897407689419, + "y": 4.047950926793974, + "z": 0.0 + }, + { + "x": 121.24799847305124, + "y": 4.048060962062255, + "z": 0.0 + }, + { + "x": 120.21702286920826, + "y": 4.048170997330537, + "z": 0.0 + }, + { + "x": 119.18604726536532, + "y": 4.048281032598818, + "z": 0.0 + }, + { + "x": 118.15507166152236, + "y": 4.0483910678671, + "z": 0.0 + }, + { + "x": 117.1240960576794, + "y": 4.048501103135381, + "z": 0.0 + }, + { + "x": 116.09312045383643, + "y": 4.048611138403662, + "z": 0.0 + }, + { + "x": 115.06214484999347, + "y": 4.048721173671944, + "z": 0.0 + }, + { + "x": 114.03116924615051, + "y": 4.048831208940225, + "z": 0.0 + }, + { + "x": 113.00019364230756, + "y": 4.048941244208507, + "z": 0.0 + }, + { + "x": 111.9692180384646, + "y": 4.049051279476788, + "z": 0.0 + }, + { + "x": 110.93824243462164, + "y": 4.04916131474507, + "z": 0.0 + }, + { + "x": 109.90726683077868, + "y": 4.049271350013351, + "z": 0.0 + }, + { + "x": 108.87629122693572, + "y": 4.049381385281633, + "z": 0.0 + }, + { + "x": 107.84531562309277, + "y": 4.049491420549914, + "z": 0.0 + }, + { + "x": 106.81434001924981, + "y": 4.049601455818195, + "z": 0.0 + }, + { + "x": 105.78336441540685, + "y": 4.049711491086477, + "z": 0.0 + }, + { + "x": 104.75238881156389, + "y": 4.049821526354758, + "z": 0.0 + }, + { + "x": 103.7207585962736, + "y": 4.04993157792472, + "z": 0.0 + }, + { + "x": 102.68978300585972, + "y": 4.049872891084994, + "z": 0.0 + } + ] + }, + { + "id": 12, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 144.9600104443823, + "y": 0.04553017367405473, + "z": 0.0 + }, + { + "x": 143.92903484053934, + "y": 0.045640208942336134, + "z": 0.0 + }, + { + "x": 142.89805923669638, + "y": 0.04575024421061754, + "z": 0.0 + }, + { + "x": 141.86708363285342, + "y": 0.045860279478898945, + "z": 0.0 + }, + { + "x": 140.83610802901046, + "y": 0.04597031474718035, + "z": 0.0 + }, + { + "x": 139.8051324251675, + "y": 0.046080350015461756, + "z": 0.0 + }, + { + "x": 138.77415682132454, + "y": 0.04619038528374317, + "z": 0.0 + }, + { + "x": 137.7431812174816, + "y": 0.04630042055202457, + "z": 0.0 + }, + { + "x": 136.71220561363864, + "y": 0.04641045582030597, + "z": 0.0 + }, + { + "x": 135.68123000979568, + "y": 0.046520491088587385, + "z": 0.0 + }, + { + "x": 134.65025440595272, + "y": 0.04663052635686878, + "z": 0.0 + }, + { + "x": 133.61927880210976, + "y": 0.04674056162515019, + "z": 0.0 + }, + { + "x": 132.5883031982668, + "y": 0.0468505968934316, + "z": 0.0 + }, + { + "x": 131.55732759442384, + "y": 0.046960632161713, + "z": 0.0 + }, + { + "x": 130.52635199058088, + "y": 0.047070667429994405, + "z": 0.0 + }, + { + "x": 129.49537638673792, + "y": 0.04718070269827582, + "z": 0.0 + }, + { + "x": 128.46440078289496, + "y": 0.04729073796655722, + "z": 0.0 + }, + { + "x": 127.43342517905201, + "y": 0.04740077323483862, + "z": 0.0 + }, + { + "x": 126.40244957520905, + "y": 0.047510808503120026, + "z": 0.0 + }, + { + "x": 125.37147397136609, + "y": 0.04762084377140144, + "z": 0.0 + }, + { + "x": 124.34049836752313, + "y": 0.047730879039682844, + "z": 0.0 + }, + { + "x": 123.30952276368016, + "y": 0.04784091430796424, + "z": 0.0 + }, + { + "x": 122.2785471598372, + "y": 0.047950949576245655, + "z": 0.0 + }, + { + "x": 121.24757155599426, + "y": 0.04806098484452706, + "z": 0.0 + }, + { + "x": 120.21659595215128, + "y": 0.048171020112808466, + "z": 0.0 + }, + { + "x": 119.18562034830833, + "y": 0.04828105538108987, + "z": 0.0 + }, + { + "x": 118.15464474446537, + "y": 0.04839109064937128, + "z": 0.0 + }, + { + "x": 117.12366914062241, + "y": 0.04850112591765268, + "z": 0.0 + }, + { + "x": 116.09269353677945, + "y": 0.04861116118593409, + "z": 0.0 + }, + { + "x": 115.06171793293649, + "y": 0.04872119645421549, + "z": 0.0 + }, + { + "x": 114.03074232909353, + "y": 0.0488312317224969, + "z": 0.0 + }, + { + "x": 112.99976672525058, + "y": 0.048941266990778304, + "z": 0.0 + }, + { + "x": 111.96879112140762, + "y": 0.04905130225905971, + "z": 0.0 + }, + { + "x": 110.93781551756466, + "y": 0.049161337527341115, + "z": 0.0 + }, + { + "x": 109.9068399137217, + "y": 0.04927137279562252, + "z": 0.0 + }, + { + "x": 108.87586430987874, + "y": 0.049381408063903925, + "z": 0.0 + }, + { + "x": 107.84488870603579, + "y": 0.04949144333218533, + "z": 0.0 + }, + { + "x": 106.81391310219283, + "y": 0.049601478600466736, + "z": 0.0 + }, + { + "x": 105.78293749834987, + "y": 0.04971151386874814, + "z": 0.0 + }, + { + "x": 104.7519618945069, + "y": 0.04982154913702955, + "z": 0.0 + }, + { + "x": 103.72098629066394, + "y": 0.04993158440531095, + "z": 0.0 + }, + { + "x": 102.69001070025007, + "y": 0.04987289756558597, + "z": 0.0 + } + ] + }, + { + "id": 13, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 102.69012454744524, + "y": -1.9501270991941182, + "z": 0.0 + }, + { + "x": 103.72110013785911, + "y": -1.9500684123543934, + "z": 0.0 + }, + { + "x": 104.75174843597841, + "y": -1.9501784394718344, + "z": 0.0 + }, + { + "x": 105.78272403982137, + "y": -1.950288474740116, + "z": 0.0 + }, + { + "x": 106.81369964366434, + "y": -1.9503985100083974, + "z": 0.0 + }, + { + "x": 107.8446752475073, + "y": -1.9505085452766788, + "z": 0.0 + }, + { + "x": 108.87565085135024, + "y": -1.9506185805449603, + "z": 0.0 + }, + { + "x": 109.9066264551932, + "y": -1.9507286158132418, + "z": 0.0 + }, + { + "x": 110.93760205903617, + "y": -1.9508386510815232, + "z": 0.0 + }, + { + "x": 111.96857766287913, + "y": -1.9509486863498047, + "z": 0.0 + }, + { + "x": 112.99955326672209, + "y": -1.9510587216180857, + "z": 0.0 + }, + { + "x": 114.03052887056504, + "y": -1.9511687568863672, + "z": 0.0 + }, + { + "x": 115.061504474408, + "y": -1.9512787921546486, + "z": 0.0 + }, + { + "x": 116.09248007825096, + "y": -1.95138882742293, + "z": 0.0 + }, + { + "x": 117.12345568209392, + "y": -1.9514988626912115, + "z": 0.0 + }, + { + "x": 118.15443128593688, + "y": -1.951608897959493, + "z": 0.0 + }, + { + "x": 119.18540688977984, + "y": -1.9517189332277745, + "z": 0.0 + }, + { + "x": 120.21638249362279, + "y": -1.951828968496056, + "z": 0.0 + }, + { + "x": 121.24735809746576, + "y": -1.951939003764337, + "z": 0.0 + }, + { + "x": 122.27833370130871, + "y": -1.9520490390326184, + "z": 0.0 + }, + { + "x": 123.30930930515167, + "y": -1.9521590743008999, + "z": 0.0 + }, + { + "x": 124.34028490899463, + "y": -1.9522691095691813, + "z": 0.0 + }, + { + "x": 125.3712605128376, + "y": -1.9523791448374628, + "z": 0.0 + }, + { + "x": 126.40223611668056, + "y": -1.9524891801057442, + "z": 0.0 + }, + { + "x": 127.43321172052352, + "y": -1.9525992153740257, + "z": 0.0 + }, + { + "x": 128.46418732436646, + "y": -1.9527092506423072, + "z": 0.0 + }, + { + "x": 129.49516292820942, + "y": -1.9528192859105882, + "z": 0.0 + }, + { + "x": 130.52613853205239, + "y": -1.9529293211788696, + "z": 0.0 + }, + { + "x": 131.55711413589535, + "y": -1.953039356447151, + "z": 0.0 + }, + { + "x": 132.5880897397383, + "y": -1.9531493917154326, + "z": 0.0 + }, + { + "x": 133.61906534358127, + "y": -1.953259426983714, + "z": 0.0 + }, + { + "x": 134.65004094742423, + "y": -1.9533694622519955, + "z": 0.0 + }, + { + "x": 135.6810165512672, + "y": -1.953479497520277, + "z": 0.0 + }, + { + "x": 136.71199215511015, + "y": -1.9535895327885584, + "z": 0.0 + }, + { + "x": 137.7429677589531, + "y": -1.9536995680568394, + "z": 0.0 + }, + { + "x": 138.77394336279605, + "y": -1.9538096033251209, + "z": 0.0 + }, + { + "x": 139.804918966639, + "y": -1.9539196385934023, + "z": 0.0 + }, + { + "x": 140.83589457048197, + "y": -1.9540296738616838, + "z": 0.0 + }, + { + "x": 141.86687017432493, + "y": -1.9541397091299653, + "z": 0.0 + }, + { + "x": 142.8978457781679, + "y": -1.9542497443982467, + "z": 0.0 + }, + { + "x": 143.92882138201085, + "y": -1.9543597796665282, + "z": 0.0 + }, + { + "x": 144.9597969858538, + "y": -1.9544698149348096, + "z": 0.0 + } + ] + }, + { + "id": 14, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 144.9602239029108, + "y": 2.045530162282919, + "z": 0.0 + }, + { + "x": 143.92924829906784, + "y": 2.0456401975512004, + "z": 0.0 + }, + { + "x": 142.89827269522488, + "y": 2.045750232819482, + "z": 0.0 + }, + { + "x": 141.86729709138191, + "y": 2.0458602680877633, + "z": 0.0 + }, + { + "x": 140.83632148753895, + "y": 2.0459703033560444, + "z": 0.0 + }, + { + "x": 139.805345883696, + "y": 2.046080338624326, + "z": 0.0 + }, + { + "x": 138.77437027985303, + "y": 2.0461903738926073, + "z": 0.0 + }, + { + "x": 137.7433946760101, + "y": 2.0463004091608887, + "z": 0.0 + }, + { + "x": 136.71241907216714, + "y": 2.04641044442917, + "z": 0.0 + }, + { + "x": 135.68144346832418, + "y": 2.0465204796974517, + "z": 0.0 + }, + { + "x": 134.65046786448121, + "y": 2.046630514965733, + "z": 0.0 + }, + { + "x": 133.61949226063825, + "y": 2.0467405502340146, + "z": 0.0 + }, + { + "x": 132.5885166567953, + "y": 2.0468505855022956, + "z": 0.0 + }, + { + "x": 131.55754105295233, + "y": 2.046960620770577, + "z": 0.0 + }, + { + "x": 130.52656544910937, + "y": 2.0470706560388585, + "z": 0.0 + }, + { + "x": 129.4955898452664, + "y": 2.04718069130714, + "z": 0.0 + }, + { + "x": 128.46461424142345, + "y": 2.0472907265754214, + "z": 0.0 + }, + { + "x": 127.4336386375805, + "y": 2.047400761843703, + "z": 0.0 + }, + { + "x": 126.40266303373754, + "y": 2.0475107971119844, + "z": 0.0 + }, + { + "x": 125.37168742989458, + "y": 2.047620832380266, + "z": 0.0 + }, + { + "x": 124.34071182605162, + "y": 2.047730867648547, + "z": 0.0 + }, + { + "x": 123.30973622220866, + "y": 2.0478409029168283, + "z": 0.0 + }, + { + "x": 122.2787606183657, + "y": 2.0479509381851098, + "z": 0.0 + }, + { + "x": 121.24778501452275, + "y": 2.048060973453391, + "z": 0.0 + }, + { + "x": 120.21680941067977, + "y": 2.0481710087216727, + "z": 0.0 + }, + { + "x": 119.18583380683683, + "y": 2.048281043989954, + "z": 0.0 + }, + { + "x": 118.15485820299386, + "y": 2.0483910792582356, + "z": 0.0 + }, + { + "x": 117.1238825991509, + "y": 2.048501114526517, + "z": 0.0 + }, + { + "x": 116.09290699530794, + "y": 2.048611149794798, + "z": 0.0 + }, + { + "x": 115.06193139146498, + "y": 2.0487211850630795, + "z": 0.0 + }, + { + "x": 114.03095578762202, + "y": 2.048831220331361, + "z": 0.0 + }, + { + "x": 112.99998018377907, + "y": 2.0489412555996425, + "z": 0.0 + }, + { + "x": 111.96900457993611, + "y": 2.049051290867924, + "z": 0.0 + }, + { + "x": 110.93802897609315, + "y": 2.0491613261362054, + "z": 0.0 + }, + { + "x": 109.90705337225019, + "y": 2.049271361404487, + "z": 0.0 + }, + { + "x": 108.87607776840723, + "y": 2.0493813966727683, + "z": 0.0 + }, + { + "x": 107.84510216456428, + "y": 2.0494914319410493, + "z": 0.0 + }, + { + "x": 106.81412656072132, + "y": 2.049601467209331, + "z": 0.0 + }, + { + "x": 105.78315095687836, + "y": 2.0497115024776122, + "z": 0.0 + }, + { + "x": 104.7521753530354, + "y": 2.0498215377458937, + "z": 0.0 + }, + { + "x": 103.72087244346878, + "y": 2.049931581165015, + "z": 0.0 + }, + { + "x": 102.6898968530549, + "y": 2.04987289432529, + "z": 0.0 + } + ] + }, + { + "id": 15, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 11.031303375477442, + "y": -3.97999978801159, + "z": 0.0 + }, + { + "x": 12.051452811327586, + "y": -3.9796673112888272, + "z": 0.0 + }, + { + "x": 13.07160224717773, + "y": -3.979334834566064, + "z": 0.0 + }, + { + "x": 14.091751683027873, + "y": -3.979002357843301, + "z": 0.0 + }, + { + "x": 15.111901118878016, + "y": -3.9786698811205383, + "z": 0.0 + }, + { + "x": 16.132050554728153, + "y": -3.978337404397776, + "z": 0.0 + }, + { + "x": 17.152199990578296, + "y": -3.9780049276750122, + "z": 0.0 + }, + { + "x": 18.17234942642844, + "y": -3.9776724509522494, + "z": 0.0 + }, + { + "x": 19.192498862278583, + "y": -3.977339974229486, + "z": 0.0 + }, + { + "x": 20.212648298128727, + "y": -3.9770074975067233, + "z": 0.0 + }, + { + "x": 21.23279773397887, + "y": -3.9766750207839605, + "z": 0.0 + }, + { + "x": 22.252947169829014, + "y": -3.9763425440611972, + "z": 0.0 + }, + { + "x": 23.273096605679157, + "y": -3.9760100673384344, + "z": 0.0 + }, + { + "x": 24.2932460415293, + "y": -3.9756775906156716, + "z": 0.0 + }, + { + "x": 25.313395477379444, + "y": -3.9753451138929083, + "z": 0.0 + }, + { + "x": 26.333544913229588, + "y": -3.9750126371701455, + "z": 0.0 + }, + { + "x": 27.35369434907973, + "y": -3.9746801604473823, + "z": 0.0 + }, + { + "x": 28.373843784929875, + "y": -3.9743476837246194, + "z": 0.0 + }, + { + "x": 29.39399322078002, + "y": -3.9740152070018566, + "z": 0.0 + }, + { + "x": 30.414142656630162, + "y": -3.9736827302790934, + "z": 0.0 + }, + { + "x": 31.434292092480312, + "y": -3.9733502535563305, + "z": 0.0 + }, + { + "x": 32.454441528330456, + "y": -3.9730177768335677, + "z": 0.0 + }, + { + "x": 33.4745909641806, + "y": -3.9726853001108045, + "z": 0.0 + }, + { + "x": 34.49474040003074, + "y": -3.9723528233880416, + "z": 0.0 + }, + { + "x": 35.514889835880886, + "y": -3.972020346665279, + "z": 0.0 + }, + { + "x": 36.53503927173103, + "y": -3.9716878699425155, + "z": 0.0 + }, + { + "x": 37.55518870758117, + "y": -3.9713553932197527, + "z": 0.0 + }, + { + "x": 38.57533814343132, + "y": -3.97102291649699, + "z": 0.0 + }, + { + "x": 39.59548757928146, + "y": -3.9706904397742266, + "z": 0.0 + }, + { + "x": 40.615637015131604, + "y": -3.970357963051464, + "z": 0.0 + }, + { + "x": 41.63578645098175, + "y": -3.970025486328701, + "z": 0.0 + }, + { + "x": 42.65593588683189, + "y": -3.9696930096059377, + "z": 0.0 + }, + { + "x": 43.676085322682034, + "y": -3.969360532883175, + "z": 0.0 + }, + { + "x": 44.69623475853218, + "y": -3.969028056160412, + "z": 0.0 + }, + { + "x": 45.71638419438232, + "y": -3.968695579437649, + "z": 0.0 + }, + { + "x": 46.736533630232465, + "y": -3.968363102714886, + "z": 0.0 + }, + { + "x": 47.75668306608261, + "y": -3.968030625992123, + "z": 0.0 + }, + { + "x": 48.77683250193275, + "y": -3.96769814926936, + "z": 0.0 + }, + { + "x": 49.796981937782895, + "y": -3.967365672546597, + "z": 0.0 + }, + { + "x": 50.81713137363304, + "y": -3.967033195823834, + "z": 0.0 + }, + { + "x": 51.83728080948318, + "y": -3.966700719101071, + "z": 0.0 + }, + { + "x": 52.857430245333326, + "y": -3.966368242378308, + "z": 0.0 + }, + { + "x": 53.87757968118347, + "y": -3.966035765655545, + "z": 0.0 + }, + { + "x": 54.89772911703361, + "y": -3.965703288932782, + "z": 0.0 + }, + { + "x": 55.91787855288376, + "y": -3.9653708122100193, + "z": 0.0 + }, + { + "x": 56.9380279887339, + "y": -3.965038335487256, + "z": 0.0 + }, + { + "x": 57.95817742458404, + "y": -3.964705858764493, + "z": 0.0 + }, + { + "x": 58.97832686043419, + "y": -3.9643733820417304, + "z": 0.0 + }, + { + "x": 59.99847629628433, + "y": -3.964040905318967, + "z": 0.0 + }, + { + "x": 61.018625732134474, + "y": -3.9637084285962043, + "z": 0.0 + }, + { + "x": 62.03877516798462, + "y": -3.9633759518734415, + "z": 0.0 + }, + { + "x": 63.05892460383476, + "y": -3.9630434751506782, + "z": 0.0 + }, + { + "x": 64.07907403968491, + "y": -3.9627109984279154, + "z": 0.0 + }, + { + "x": 65.09922347553506, + "y": -3.9623785217051526, + "z": 0.0 + }, + { + "x": 66.1193729113852, + "y": -3.9620460449823893, + "z": 0.0 + }, + { + "x": 67.13952234723534, + "y": -3.9617135682596265, + "z": 0.0 + }, + { + "x": 68.15967178308549, + "y": -3.9613810915368637, + "z": 0.0 + }, + { + "x": 69.17982121893563, + "y": -3.9610486148141004, + "z": 0.0 + }, + { + "x": 70.19997065478577, + "y": -3.9607161380913376, + "z": 0.0 + }, + { + "x": 71.22012009063592, + "y": -3.9603836613685743, + "z": 0.0 + }, + { + "x": 72.24026952648606, + "y": -3.9600511846458115, + "z": 0.0 + }, + { + "x": 73.2604189623362, + "y": -3.9597187079230487, + "z": 0.0 + }, + { + "x": 74.28056839818635, + "y": -3.9593862312002854, + "z": 0.0 + }, + { + "x": 75.30071783403649, + "y": -3.9590537544775226, + "z": 0.0 + }, + { + "x": 76.32086726988663, + "y": -3.95872127775476, + "z": 0.0 + }, + { + "x": 77.34101670573678, + "y": -3.9583888010319965, + "z": 0.0 + }, + { + "x": 78.36116614158692, + "y": -3.9580563243092337, + "z": 0.0 + }, + { + "x": 79.38131557743706, + "y": -3.957723847586471, + "z": 0.0 + } + ] + }, + { + "id": 16, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 79.3787082989861, + "y": 4.042275727544709, + "z": 0.0 + }, + { + "x": 78.35855886313595, + "y": 4.041943250821946, + "z": 0.0 + }, + { + "x": 77.33840942728581, + "y": 4.041610774099183, + "z": 0.0 + }, + { + "x": 76.31825999143567, + "y": 4.0412782973764205, + "z": 0.0 + }, + { + "x": 75.29811055558552, + "y": 4.040945820653657, + "z": 0.0 + }, + { + "x": 74.27796111973538, + "y": 4.040613343930894, + "z": 0.0 + }, + { + "x": 73.25781168388524, + "y": 4.040280867208131, + "z": 0.0 + }, + { + "x": 72.2376622480351, + "y": 4.039948390485368, + "z": 0.0 + }, + { + "x": 71.21751281218495, + "y": 4.0396159137626055, + "z": 0.0 + }, + { + "x": 70.1973633763348, + "y": 4.039283437039843, + "z": 0.0 + }, + { + "x": 69.17721394048466, + "y": 4.038950960317079, + "z": 0.0 + }, + { + "x": 68.15706450463452, + "y": 4.038618483594316, + "z": 0.0 + }, + { + "x": 67.13691506878438, + "y": 4.038286006871553, + "z": 0.0 + }, + { + "x": 66.11676563293423, + "y": 4.0379535301487905, + "z": 0.0 + }, + { + "x": 65.09661619708409, + "y": 4.037621053426028, + "z": 0.0 + }, + { + "x": 64.07646676123395, + "y": 4.037288576703265, + "z": 0.0 + }, + { + "x": 63.05631732538381, + "y": 4.036956099980501, + "z": 0.0 + }, + { + "x": 62.036167889533665, + "y": 4.036623623257738, + "z": 0.0 + }, + { + "x": 61.01601845368352, + "y": 4.036291146534976, + "z": 0.0 + }, + { + "x": 59.99586901783338, + "y": 4.035958669812213, + "z": 0.0 + }, + { + "x": 58.975719581983235, + "y": 4.03562619308945, + "z": 0.0 + }, + { + "x": 57.95557014613309, + "y": 4.035293716366686, + "z": 0.0 + }, + { + "x": 56.93542071028295, + "y": 4.034961239643923, + "z": 0.0 + }, + { + "x": 55.915271274432804, + "y": 4.034628762921161, + "z": 0.0 + }, + { + "x": 54.89512183858266, + "y": 4.034296286198398, + "z": 0.0 + }, + { + "x": 53.87497240273252, + "y": 4.033963809475635, + "z": 0.0 + }, + { + "x": 52.854822966882374, + "y": 4.033631332752872, + "z": 0.0 + }, + { + "x": 51.83467353103223, + "y": 4.033298856030108, + "z": 0.0 + }, + { + "x": 50.81452409518209, + "y": 4.032966379307346, + "z": 0.0 + }, + { + "x": 49.79437465933194, + "y": 4.032633902584583, + "z": 0.0 + }, + { + "x": 48.7742252234818, + "y": 4.03230142586182, + "z": 0.0 + }, + { + "x": 47.754075787631656, + "y": 4.031968949139057, + "z": 0.0 + }, + { + "x": 46.73392635178151, + "y": 4.031636472416294, + "z": 0.0 + }, + { + "x": 45.71377691593137, + "y": 4.031303995693531, + "z": 0.0 + }, + { + "x": 44.693627480081226, + "y": 4.030971518970768, + "z": 0.0 + }, + { + "x": 43.67347804423108, + "y": 4.030639042248005, + "z": 0.0 + }, + { + "x": 42.65332860838094, + "y": 4.030306565525242, + "z": 0.0 + }, + { + "x": 41.633179172530795, + "y": 4.029974088802479, + "z": 0.0 + }, + { + "x": 40.61302973668065, + "y": 4.0296416120797165, + "z": 0.0 + }, + { + "x": 39.59288030083051, + "y": 4.029309135356953, + "z": 0.0 + }, + { + "x": 38.572730864980365, + "y": 4.02897665863419, + "z": 0.0 + }, + { + "x": 37.55258142913022, + "y": 4.028644181911427, + "z": 0.0 + }, + { + "x": 36.53243199328008, + "y": 4.028311705188664, + "z": 0.0 + }, + { + "x": 35.512282557429934, + "y": 4.0279792284659015, + "z": 0.0 + }, + { + "x": 34.49213312157979, + "y": 4.027646751743138, + "z": 0.0 + }, + { + "x": 33.47198368572965, + "y": 4.027314275020375, + "z": 0.0 + }, + { + "x": 32.451834249879504, + "y": 4.026981798297612, + "z": 0.0 + }, + { + "x": 31.43168481402936, + "y": 4.026649321574849, + "z": 0.0 + }, + { + "x": 30.41153537817921, + "y": 4.0263168448520865, + "z": 0.0 + }, + { + "x": 29.391385942329066, + "y": 4.025984368129324, + "z": 0.0 + }, + { + "x": 28.371236506478922, + "y": 4.02565189140656, + "z": 0.0 + }, + { + "x": 27.35108707062878, + "y": 4.025319414683797, + "z": 0.0 + }, + { + "x": 26.330937634778635, + "y": 4.024986937961034, + "z": 0.0 + }, + { + "x": 25.310788198928492, + "y": 4.0246544612382715, + "z": 0.0 + }, + { + "x": 24.29063876307835, + "y": 4.024321984515509, + "z": 0.0 + }, + { + "x": 23.270489327228205, + "y": 4.023989507792746, + "z": 0.0 + }, + { + "x": 22.25033989137806, + "y": 4.023657031069982, + "z": 0.0 + }, + { + "x": 21.230190455527918, + "y": 4.023324554347219, + "z": 0.0 + }, + { + "x": 20.210041019677774, + "y": 4.0229920776244565, + "z": 0.0 + }, + { + "x": 19.18989158382763, + "y": 4.022659600901694, + "z": 0.0 + }, + { + "x": 18.169742147977487, + "y": 4.022327124178931, + "z": 0.0 + }, + { + "x": 17.149592712127344, + "y": 4.021994647456168, + "z": 0.0 + }, + { + "x": 16.1294432762772, + "y": 4.021662170733405, + "z": 0.0 + }, + { + "x": 15.109293840427064, + "y": 4.0213296940106416, + "z": 0.0 + }, + { + "x": 14.08914440457692, + "y": 4.020997217287879, + "z": 0.0 + }, + { + "x": 13.068994968726777, + "y": 4.020664740565116, + "z": 0.0 + }, + { + "x": 12.048845532876634, + "y": 4.020332263842353, + "z": 0.0 + }, + { + "x": 11.02869609702649, + "y": 4.019999787119589, + "z": 0.0 + } + ] + }, + { + "id": 17, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 79.38001193821158, + "y": 0.04227593997911919, + "z": 0.0 + }, + { + "x": 78.35986250236144, + "y": 0.041943463256356214, + "z": 0.0 + }, + { + "x": 77.3397130665113, + "y": 0.041610986533593235, + "z": 0.0 + }, + { + "x": 76.31956363066115, + "y": 0.04127850981083026, + "z": 0.0 + }, + { + "x": 75.299414194811, + "y": 0.04094603308806729, + "z": 0.0 + }, + { + "x": 74.27926475896086, + "y": 0.04061355636530431, + "z": 0.0 + }, + { + "x": 73.25911532311072, + "y": 0.04028107964254134, + "z": 0.0 + }, + { + "x": 72.23896588726058, + "y": 0.039948602919778364, + "z": 0.0 + }, + { + "x": 71.21881645141043, + "y": 0.039616126197015385, + "z": 0.0 + }, + { + "x": 70.19866701556029, + "y": 0.03928364947425241, + "z": 0.0 + }, + { + "x": 69.17851757971015, + "y": 0.03895117275148943, + "z": 0.0 + }, + { + "x": 68.15836814386, + "y": 0.03861869602872646, + "z": 0.0 + }, + { + "x": 67.13821870800986, + "y": 0.03828621930596349, + "z": 0.0 + }, + { + "x": 66.11806927215972, + "y": 0.037953742583200514, + "z": 0.0 + }, + { + "x": 65.09791983630957, + "y": 0.037621265860437535, + "z": 0.0 + }, + { + "x": 64.07777040045943, + "y": 0.03728878913767456, + "z": 0.0 + }, + { + "x": 63.057620964609285, + "y": 0.03695631241491158, + "z": 0.0 + }, + { + "x": 62.03747152875914, + "y": 0.03662383569214861, + "z": 0.0 + }, + { + "x": 61.017322092909, + "y": 0.03629135896938564, + "z": 0.0 + }, + { + "x": 59.997172657058854, + "y": 0.03595888224662266, + "z": 0.0 + }, + { + "x": 58.97702322120871, + "y": 0.035626405523859685, + "z": 0.0 + }, + { + "x": 57.95687378535857, + "y": 0.03529392880109671, + "z": 0.0 + }, + { + "x": 56.936724349508424, + "y": 0.03496145207833373, + "z": 0.0 + }, + { + "x": 55.91657491365828, + "y": 0.03462897535557076, + "z": 0.0 + }, + { + "x": 54.89642547780814, + "y": 0.03429649863280779, + "z": 0.0 + }, + { + "x": 53.87627604195799, + "y": 0.03396402191004481, + "z": 0.0 + }, + { + "x": 52.85612660610785, + "y": 0.033631545187281835, + "z": 0.0 + }, + { + "x": 51.835977170257706, + "y": 0.03329906846451886, + "z": 0.0 + }, + { + "x": 50.81582773440756, + "y": 0.03296659174175588, + "z": 0.0 + }, + { + "x": 49.79567829855742, + "y": 0.03263411501899291, + "z": 0.0 + }, + { + "x": 48.775528862707276, + "y": 0.03230163829622994, + "z": 0.0 + }, + { + "x": 47.75537942685713, + "y": 0.03196916157346696, + "z": 0.0 + }, + { + "x": 46.73522999100699, + "y": 0.031636684850703985, + "z": 0.0 + }, + { + "x": 45.715080555156845, + "y": 0.031304208127941005, + "z": 0.0 + }, + { + "x": 44.6949311193067, + "y": 0.030971731405178032, + "z": 0.0 + }, + { + "x": 43.67478168345656, + "y": 0.03063925468241506, + "z": 0.0 + }, + { + "x": 42.654632247606415, + "y": 0.030306777959652087, + "z": 0.0 + }, + { + "x": 41.63448281175627, + "y": 0.029974301236889107, + "z": 0.0 + }, + { + "x": 40.61433337590613, + "y": 0.029641824514126138, + "z": 0.0 + }, + { + "x": 39.594183940055984, + "y": 0.029309347791363162, + "z": 0.0 + }, + { + "x": 38.57403450420584, + "y": 0.028976871068600186, + "z": 0.0 + }, + { + "x": 37.5538850683557, + "y": 0.028644394345837213, + "z": 0.0 + }, + { + "x": 36.533735632505554, + "y": 0.028311917623074237, + "z": 0.0 + }, + { + "x": 35.51358619665541, + "y": 0.027979440900311257, + "z": 0.0 + }, + { + "x": 34.49343676080527, + "y": 0.027646964177548285, + "z": 0.0 + }, + { + "x": 33.47328732495512, + "y": 0.02731448745478531, + "z": 0.0 + }, + { + "x": 32.45313788910498, + "y": 0.026982010732022332, + "z": 0.0 + }, + { + "x": 31.432988453254836, + "y": 0.02664953400925936, + "z": 0.0 + }, + { + "x": 30.412839017404686, + "y": 0.02631705728649638, + "z": 0.0 + }, + { + "x": 29.392689581554542, + "y": 0.025984580563733407, + "z": 0.0 + }, + { + "x": 28.3725401457044, + "y": 0.02565210384097043, + "z": 0.0 + }, + { + "x": 27.352390709854255, + "y": 0.02531962711820746, + "z": 0.0 + }, + { + "x": 26.33224127400411, + "y": 0.024987150395444482, + "z": 0.0 + }, + { + "x": 25.312091838153968, + "y": 0.024654673672681506, + "z": 0.0 + }, + { + "x": 24.291942402303825, + "y": 0.024322196949918534, + "z": 0.0 + }, + { + "x": 23.27179296645368, + "y": 0.023989720227155554, + "z": 0.0 + }, + { + "x": 22.251643530603538, + "y": 0.023657243504392578, + "z": 0.0 + }, + { + "x": 21.231494094753394, + "y": 0.023324766781629605, + "z": 0.0 + }, + { + "x": 20.21134465890325, + "y": 0.02299229005886663, + "z": 0.0 + }, + { + "x": 19.191195223053107, + "y": 0.022659813336103656, + "z": 0.0 + }, + { + "x": 18.171045787202964, + "y": 0.02232733661334068, + "z": 0.0 + }, + { + "x": 17.15089635135282, + "y": 0.021994859890577707, + "z": 0.0 + }, + { + "x": 16.130746915502677, + "y": 0.02166238316781473, + "z": 0.0 + }, + { + "x": 15.11059747965254, + "y": 0.021329906445051755, + "z": 0.0 + }, + { + "x": 14.090448043802397, + "y": 0.020997429722288782, + "z": 0.0 + }, + { + "x": 13.070298607952253, + "y": 0.020664952999525806, + "z": 0.0 + }, + { + "x": 12.05014917210211, + "y": 0.02033247627676283, + "z": 0.0 + }, + { + "x": 11.029999736251966, + "y": 0.019999999553999857, + "z": 0.0 + } + ] + }, + { + "id": 18, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 11.030651555864704, + "y": -1.979999894228795, + "z": 0.0 + }, + { + "x": 12.050800991714848, + "y": -1.9796674175060323, + "z": 0.0 + }, + { + "x": 13.070950427564991, + "y": -1.979334940783269, + "z": 0.0 + }, + { + "x": 14.091099863415135, + "y": -1.9790024640605062, + "z": 0.0 + }, + { + "x": 15.111249299265278, + "y": -1.9786699873377434, + "z": 0.0 + }, + { + "x": 16.131398735115415, + "y": -1.9783375106149805, + "z": 0.0 + }, + { + "x": 17.151548170965558, + "y": -1.9780050338922173, + "z": 0.0 + }, + { + "x": 18.1716976068157, + "y": -1.9776725571694544, + "z": 0.0 + }, + { + "x": 19.191847042665845, + "y": -1.9773400804466912, + "z": 0.0 + }, + { + "x": 20.21199647851599, + "y": -1.9770076037239284, + "z": 0.0 + }, + { + "x": 21.232145914366132, + "y": -1.9766751270011655, + "z": 0.0 + }, + { + "x": 22.252295350216276, + "y": -1.9763426502784023, + "z": 0.0 + }, + { + "x": 23.27244478606642, + "y": -1.9760101735556395, + "z": 0.0 + }, + { + "x": 24.292594221916563, + "y": -1.9756776968328766, + "z": 0.0 + }, + { + "x": 25.312743657766706, + "y": -1.9753452201101134, + "z": 0.0 + }, + { + "x": 26.33289309361685, + "y": -1.9750127433873506, + "z": 0.0 + }, + { + "x": 27.353042529466993, + "y": -1.9746802666645873, + "z": 0.0 + }, + { + "x": 28.373191965317137, + "y": -1.9743477899418245, + "z": 0.0 + }, + { + "x": 29.39334140116728, + "y": -1.9740153132190617, + "z": 0.0 + }, + { + "x": 30.413490837017424, + "y": -1.9736828364962984, + "z": 0.0 + }, + { + "x": 31.433640272867574, + "y": -1.9733503597735356, + "z": 0.0 + }, + { + "x": 32.45378970871772, + "y": -1.9730178830507727, + "z": 0.0 + }, + { + "x": 33.473939144567865, + "y": -1.9726854063280095, + "z": 0.0 + }, + { + "x": 34.49408858041801, + "y": -1.9723529296052467, + "z": 0.0 + }, + { + "x": 35.51423801626815, + "y": -1.9720204528824838, + "z": 0.0 + }, + { + "x": 36.534387452118295, + "y": -1.9716879761597206, + "z": 0.0 + }, + { + "x": 37.55453688796844, + "y": -1.9713554994369578, + "z": 0.0 + }, + { + "x": 38.57468632381858, + "y": -1.971023022714195, + "z": 0.0 + }, + { + "x": 39.594835759668726, + "y": -1.9706905459914317, + "z": 0.0 + }, + { + "x": 40.61498519551887, + "y": -1.9703580692686689, + "z": 0.0 + }, + { + "x": 41.63513463136901, + "y": -1.970025592545906, + "z": 0.0 + }, + { + "x": 42.655284067219156, + "y": -1.9696931158231428, + "z": 0.0 + }, + { + "x": 43.6754335030693, + "y": -1.96936063910038, + "z": 0.0 + }, + { + "x": 44.69558293891944, + "y": -1.9690281623776171, + "z": 0.0 + }, + { + "x": 45.71573237476959, + "y": -1.9686956856548539, + "z": 0.0 + }, + { + "x": 46.73588181061973, + "y": -1.968363208932091, + "z": 0.0 + }, + { + "x": 47.756031246469874, + "y": -1.9680307322093282, + "z": 0.0 + }, + { + "x": 48.77618068232002, + "y": -1.967698255486565, + "z": 0.0 + }, + { + "x": 49.79633011817016, + "y": -1.9673657787638021, + "z": 0.0 + }, + { + "x": 50.816479554020304, + "y": -1.9670333020410389, + "z": 0.0 + }, + { + "x": 51.83662898987045, + "y": -1.966700825318276, + "z": 0.0 + }, + { + "x": 52.85677842572059, + "y": -1.9663683485955132, + "z": 0.0 + }, + { + "x": 53.876927861570735, + "y": -1.96603587187275, + "z": 0.0 + }, + { + "x": 54.89707729742088, + "y": -1.9657033951499872, + "z": 0.0 + }, + { + "x": 55.91722673327102, + "y": -1.9653709184272243, + "z": 0.0 + }, + { + "x": 56.937376169121166, + "y": -1.965038441704461, + "z": 0.0 + }, + { + "x": 57.95752560497131, + "y": -1.9647059649816982, + "z": 0.0 + }, + { + "x": 58.97767504082145, + "y": -1.9643734882589354, + "z": 0.0 + }, + { + "x": 59.997824476671596, + "y": -1.9640410115361722, + "z": 0.0 + }, + { + "x": 61.01797391252174, + "y": -1.9637085348134093, + "z": 0.0 + }, + { + "x": 62.03812334837188, + "y": -1.9633760580906465, + "z": 0.0 + }, + { + "x": 63.05827278422203, + "y": -1.9630435813678833, + "z": 0.0 + }, + { + "x": 64.07842222007217, + "y": -1.9627111046451204, + "z": 0.0 + }, + { + "x": 65.09857165592231, + "y": -1.9623786279223576, + "z": 0.0 + }, + { + "x": 66.11872109177246, + "y": -1.9620461511995944, + "z": 0.0 + }, + { + "x": 67.1388705276226, + "y": -1.9617136744768315, + "z": 0.0 + }, + { + "x": 68.15901996347274, + "y": -1.9613811977540687, + "z": 0.0 + }, + { + "x": 69.17916939932289, + "y": -1.9610487210313055, + "z": 0.0 + }, + { + "x": 70.19931883517303, + "y": -1.9607162443085426, + "z": 0.0 + }, + { + "x": 71.21946827102317, + "y": -1.9603837675857794, + "z": 0.0 + }, + { + "x": 72.23961770687332, + "y": -1.9600512908630165, + "z": 0.0 + }, + { + "x": 73.25976714272346, + "y": -1.9597188141402537, + "z": 0.0 + }, + { + "x": 74.2799165785736, + "y": -1.9593863374174905, + "z": 0.0 + }, + { + "x": 75.30006601442375, + "y": -1.9590538606947276, + "z": 0.0 + }, + { + "x": 76.32021545027389, + "y": -1.9587213839719648, + "z": 0.0 + }, + { + "x": 77.34036488612404, + "y": -1.9583889072492016, + "z": 0.0 + }, + { + "x": 78.36051432197418, + "y": -1.9580564305264387, + "z": 0.0 + }, + { + "x": 79.38066375782432, + "y": -1.957723953803676, + "z": 0.0 + } + ] + }, + { + "id": 19, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 79.37936011859884, + "y": 2.0422758337619142, + "z": 0.0 + }, + { + "x": 78.3592106827487, + "y": 2.041943357039151, + "z": 0.0 + }, + { + "x": 77.33906124689855, + "y": 2.041610880316388, + "z": 0.0 + }, + { + "x": 76.31891181104841, + "y": 2.0412784035936253, + "z": 0.0 + }, + { + "x": 75.29876237519827, + "y": 2.040945926870862, + "z": 0.0 + }, + { + "x": 74.27861293934812, + "y": 2.0406134501480993, + "z": 0.0 + }, + { + "x": 73.25846350349798, + "y": 2.0402809734253364, + "z": 0.0 + }, + { + "x": 72.23831406764783, + "y": 2.039948496702573, + "z": 0.0 + }, + { + "x": 71.21816463179769, + "y": 2.0396160199798103, + "z": 0.0 + }, + { + "x": 70.19801519594755, + "y": 2.0392835432570475, + "z": 0.0 + }, + { + "x": 69.1778657600974, + "y": 2.0389510665342843, + "z": 0.0 + }, + { + "x": 68.15771632424726, + "y": 2.0386185898115214, + "z": 0.0 + }, + { + "x": 67.13756688839712, + "y": 2.0382861130887586, + "z": 0.0 + }, + { + "x": 66.11741745254697, + "y": 2.0379536363659954, + "z": 0.0 + }, + { + "x": 65.09726801669683, + "y": 2.0376211596432325, + "z": 0.0 + }, + { + "x": 64.07711858084669, + "y": 2.0372886829204697, + "z": 0.0 + }, + { + "x": 63.05696914499654, + "y": 2.0369562061977065, + "z": 0.0 + }, + { + "x": 62.0368197091464, + "y": 2.0366237294749436, + "z": 0.0 + }, + { + "x": 61.016670273296256, + "y": 2.036291252752181, + "z": 0.0 + }, + { + "x": 59.99652083744611, + "y": 2.0359587760294175, + "z": 0.0 + }, + { + "x": 58.97637140159597, + "y": 2.0356262993066547, + "z": 0.0 + }, + { + "x": 57.956221965745826, + "y": 2.0352938225838915, + "z": 0.0 + }, + { + "x": 56.93607252989568, + "y": 2.0349613458611286, + "z": 0.0 + }, + { + "x": 55.91592309404554, + "y": 2.034628869138366, + "z": 0.0 + }, + { + "x": 54.895773658195395, + "y": 2.0342963924156026, + "z": 0.0 + }, + { + "x": 53.87562422234525, + "y": 2.0339639156928397, + "z": 0.0 + }, + { + "x": 52.85547478649511, + "y": 2.033631438970077, + "z": 0.0 + }, + { + "x": 51.835325350644965, + "y": 2.0332989622473137, + "z": 0.0 + }, + { + "x": 50.81517591479482, + "y": 2.032966485524551, + "z": 0.0 + }, + { + "x": 49.79502647894468, + "y": 2.032634008801788, + "z": 0.0 + }, + { + "x": 48.774877043094534, + "y": 2.0323015320790248, + "z": 0.0 + }, + { + "x": 47.75472760724439, + "y": 2.031969055356262, + "z": 0.0 + }, + { + "x": 46.73457817139425, + "y": 2.031636578633499, + "z": 0.0 + }, + { + "x": 45.714428735544104, + "y": 2.031304101910736, + "z": 0.0 + }, + { + "x": 44.69427929969396, + "y": 2.030971625187973, + "z": 0.0 + }, + { + "x": 43.67412986384382, + "y": 2.03063914846521, + "z": 0.0 + }, + { + "x": 42.65398042799367, + "y": 2.030306671742447, + "z": 0.0 + }, + { + "x": 41.63383099214353, + "y": 2.029974195019684, + "z": 0.0 + }, + { + "x": 40.613681556293386, + "y": 2.0296417182969213, + "z": 0.0 + }, + { + "x": 39.59353212044324, + "y": 2.029309241574158, + "z": 0.0 + }, + { + "x": 38.5733826845931, + "y": 2.028976764851395, + "z": 0.0 + }, + { + "x": 37.553233248742956, + "y": 2.0286442881286324, + "z": 0.0 + }, + { + "x": 36.53308381289281, + "y": 2.028311811405869, + "z": 0.0 + }, + { + "x": 35.51293437704267, + "y": 2.0279793346831063, + "z": 0.0 + }, + { + "x": 34.492784941192525, + "y": 2.027646857960343, + "z": 0.0 + }, + { + "x": 33.47263550534238, + "y": 2.0273143812375802, + "z": 0.0 + }, + { + "x": 32.45248606949224, + "y": 2.0269819045148174, + "z": 0.0 + }, + { + "x": 31.432336633642098, + "y": 2.026649427792054, + "z": 0.0 + }, + { + "x": 30.412187197791948, + "y": 2.0263169510692913, + "z": 0.0 + }, + { + "x": 29.392037761941804, + "y": 2.0259844743465285, + "z": 0.0 + }, + { + "x": 28.37188832609166, + "y": 2.0256519976237652, + "z": 0.0 + }, + { + "x": 27.351738890241517, + "y": 2.0253195209010024, + "z": 0.0 + }, + { + "x": 26.331589454391374, + "y": 2.0249870441782396, + "z": 0.0 + }, + { + "x": 25.31144001854123, + "y": 2.0246545674554763, + "z": 0.0 + }, + { + "x": 24.291290582691087, + "y": 2.0243220907327135, + "z": 0.0 + }, + { + "x": 23.271141146840943, + "y": 2.0239896140099507, + "z": 0.0 + }, + { + "x": 22.2509917109908, + "y": 2.0236571372871874, + "z": 0.0 + }, + { + "x": 21.230842275140656, + "y": 2.0233246605644246, + "z": 0.0 + }, + { + "x": 20.210692839290513, + "y": 2.022992183841662, + "z": 0.0 + }, + { + "x": 19.19054340344037, + "y": 2.0226597071188985, + "z": 0.0 + }, + { + "x": 18.170393967590226, + "y": 2.0223272303961357, + "z": 0.0 + }, + { + "x": 17.150244531740082, + "y": 2.021994753673373, + "z": 0.0 + }, + { + "x": 16.13009509588994, + "y": 2.02166227695061, + "z": 0.0 + }, + { + "x": 15.109945660039802, + "y": 2.021329800227847, + "z": 0.0 + }, + { + "x": 14.089796224189659, + "y": 2.0209973235050835, + "z": 0.0 + }, + { + "x": 13.069646788339515, + "y": 2.0206648467823207, + "z": 0.0 + }, + { + "x": 12.049497352489372, + "y": 2.020332370059558, + "z": 0.0 + }, + { + "x": 11.029347916639228, + "y": 2.0199998933367946, + "z": 0.0 + } + ] + }, + { + "id": 20, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 325.6417606480552, + "y": -127.51508546382411, + "z": 0.0 + }, + { + "x": 324.6362898963956, + "y": -127.5146362258154, + "z": 0.0 + }, + { + "x": 323.63081914473594, + "y": -127.51418698780671, + "z": 0.0 + }, + { + "x": 322.6253483930765, + "y": -127.513737749798, + "z": 0.0 + }, + { + "x": 321.6198776414169, + "y": -127.51328851178928, + "z": 0.0 + }, + { + "x": 320.61440688975733, + "y": -127.51283927378057, + "z": 0.0 + }, + { + "x": 319.60893613809776, + "y": -127.51239003577186, + "z": 0.0 + }, + { + "x": 318.6034653864382, + "y": -127.51194079776315, + "z": 0.0 + }, + { + "x": 317.5979946347786, + "y": -127.51149155975443, + "z": 0.0 + }, + { + "x": 316.592523883119, + "y": -127.51104232174572, + "z": 0.0 + }, + { + "x": 315.5870531314593, + "y": -127.51059308373704, + "z": 0.0 + }, + { + "x": 314.58158237979984, + "y": -127.51014384572832, + "z": 0.0 + }, + { + "x": 313.57611162814027, + "y": -127.50969460771961, + "z": 0.0 + }, + { + "x": 312.5706408764807, + "y": -127.5092453697109, + "z": 0.0 + }, + { + "x": 311.5651701248211, + "y": -127.50879613170218, + "z": 0.0 + }, + { + "x": 310.55969937316155, + "y": -127.50834689369347, + "z": 0.0 + }, + { + "x": 309.554228621502, + "y": -127.50789765568476, + "z": 0.0 + }, + { + "x": 308.5487578698423, + "y": -127.50744841767607, + "z": 0.0 + }, + { + "x": 307.54328711818283, + "y": -127.50699917966736, + "z": 0.0 + }, + { + "x": 306.53781636652326, + "y": -127.50654994165865, + "z": 0.0 + }, + { + "x": 305.5323456148637, + "y": -127.50610070364993, + "z": 0.0 + }, + { + "x": 304.5268748632041, + "y": -127.50565146564122, + "z": 0.0 + }, + { + "x": 303.5214041115445, + "y": -127.50520222763251, + "z": 0.0 + }, + { + "x": 302.5159333598849, + "y": -127.5047529896238, + "z": 0.0 + }, + { + "x": 301.51046260822534, + "y": -127.50430375161508, + "z": 0.0 + }, + { + "x": 300.50499185656565, + "y": -127.5038545136064, + "z": 0.0 + }, + { + "x": 299.4995211049062, + "y": -127.50340527559769, + "z": 0.0 + }, + { + "x": 298.4940503532466, + "y": -127.50295603758897, + "z": 0.0 + }, + { + "x": 297.48857960158705, + "y": -127.50250679958026, + "z": 0.0 + }, + { + "x": 296.4831088499275, + "y": -127.50205756157155, + "z": 0.0 + }, + { + "x": 295.4776380982679, + "y": -127.50160832356283, + "z": 0.0 + }, + { + "x": 294.47216734660833, + "y": -127.50115908555412, + "z": 0.0 + }, + { + "x": 293.46669659494864, + "y": -127.50070984754544, + "z": 0.0 + }, + { + "x": 292.4612258432892, + "y": -127.50026060953672, + "z": 0.0 + }, + { + "x": 291.4557550916296, + "y": -127.49981137152801, + "z": 0.0 + }, + { + "x": 290.45028433997, + "y": -127.4993621335193, + "z": 0.0 + }, + { + "x": 289.4448135883104, + "y": -127.49891289551059, + "z": 0.0 + }, + { + "x": 288.43934283665084, + "y": -127.49846365750187, + "z": 0.0 + }, + { + "x": 287.43387208499126, + "y": -127.49801441949316, + "z": 0.0 + }, + { + "x": 286.4284013333317, + "y": -127.49756518148445, + "z": 0.0 + }, + { + "x": 285.422930581672, + "y": -127.49711594347576, + "z": 0.0 + }, + { + "x": 284.41745983001255, + "y": -127.49666670546705, + "z": 0.0 + }, + { + "x": 283.411989078353, + "y": -127.49621746745834, + "z": 0.0 + }, + { + "x": 282.4065183266934, + "y": -127.49576822944962, + "z": 0.0 + }, + { + "x": 281.40104757503383, + "y": -127.49531899144091, + "z": 0.0 + }, + { + "x": 280.39557682337426, + "y": -127.4948697534322, + "z": 0.0 + }, + { + "x": 279.3901060717147, + "y": -127.49442051542349, + "z": 0.0 + }, + { + "x": 278.384635320055, + "y": -127.4939712774148, + "z": 0.0 + }, + { + "x": 277.3791645683955, + "y": -127.49352203940609, + "z": 0.0 + }, + { + "x": 276.3736938167359, + "y": -127.49307280139737, + "z": 0.0 + }, + { + "x": 275.36822306507634, + "y": -127.49262356338866, + "z": 0.0 + }, + { + "x": 274.36275231341676, + "y": -127.49217432537995, + "z": 0.0 + }, + { + "x": 273.3572815617572, + "y": -127.49172508737124, + "z": 0.0 + }, + { + "x": 272.3518108100976, + "y": -127.49127584936252, + "z": 0.0 + }, + { + "x": 271.34634005843805, + "y": -127.49082661135381, + "z": 0.0 + }, + { + "x": 270.34086930677836, + "y": -127.49037737334513, + "z": 0.0 + }, + { + "x": 269.3353985551189, + "y": -127.48992813533641, + "z": 0.0 + }, + { + "x": 268.3299278034593, + "y": -127.4894788973277, + "z": 0.0 + }, + { + "x": 267.32445705179975, + "y": -127.48902965931899, + "z": 0.0 + }, + { + "x": 266.3189863001402, + "y": -127.48858042131027, + "z": 0.0 + }, + { + "x": 265.31351554848055, + "y": -127.48813118330156, + "z": 0.0 + }, + { + "x": 264.308044796821, + "y": -127.48768194529285, + "z": 0.0 + }, + { + "x": 263.3025740451613, + "y": -127.48723270728416, + "z": 0.0 + }, + { + "x": 262.29710329350183, + "y": -127.48678346927545, + "z": 0.0 + }, + { + "x": 261.29163254184226, + "y": -127.48633423126674, + "z": 0.0 + }, + { + "x": 260.2861617901827, + "y": -127.48588499325803, + "z": 0.0 + }, + { + "x": 259.2806910385231, + "y": -127.48543575524931, + "z": 0.0 + }, + { + "x": 258.27522028686354, + "y": -127.4849865172406, + "z": 0.0 + }, + { + "x": 257.26974953520397, + "y": -127.48453727923189, + "z": 0.0 + }, + { + "x": 256.2642787835444, + "y": -127.48408804122317, + "z": 0.0 + }, + { + "x": 255.2588080318847, + "y": -127.48363880321449, + "z": 0.0 + }, + { + "x": 254.25333728022525, + "y": -127.48318956520578, + "z": 0.0 + }, + { + "x": 253.24786652856568, + "y": -127.48274032719706, + "z": 0.0 + }, + { + "x": 252.24239577690608, + "y": -127.48229108918835, + "z": 0.0 + }, + { + "x": 251.2369250252465, + "y": -127.48184185117964, + "z": 0.0 + }, + { + "x": 250.23145427358693, + "y": -127.48139261317093, + "z": 0.0 + }, + { + "x": 249.22598352192736, + "y": -127.48094337516221, + "z": 0.0 + }, + { + "x": 248.22051277026767, + "y": -127.48049413715353, + "z": 0.0 + }, + { + "x": 247.21504201860822, + "y": -127.48004489914481, + "z": 0.0 + }, + { + "x": 246.20957126694861, + "y": -127.4795956611361, + "z": 0.0 + }, + { + "x": 245.20410051528904, + "y": -127.47914642312739, + "z": 0.0 + }, + { + "x": 244.19862976362947, + "y": -127.47869718511868, + "z": 0.0 + }, + { + "x": 243.1931590119699, + "y": -127.47824794710996, + "z": 0.0 + }, + { + "x": 242.18768826031032, + "y": -127.47779870910125, + "z": 0.0 + }, + { + "x": 241.18221750865075, + "y": -127.47734947109254, + "z": 0.0 + }, + { + "x": 240.17674675699107, + "y": -127.47690023308385, + "z": 0.0 + }, + { + "x": 239.17127600533158, + "y": -127.47645099507514, + "z": 0.0 + }, + { + "x": 238.165805253672, + "y": -127.47600175706643, + "z": 0.0 + }, + { + "x": 237.16033450201243, + "y": -127.47555251905771, + "z": 0.0 + }, + { + "x": 236.15486375035286, + "y": -127.475103281049, + "z": 0.0 + }, + { + "x": 235.1493929986933, + "y": -127.47465404304029, + "z": 0.0 + }, + { + "x": 234.14392224703371, + "y": -127.47420480503158, + "z": 0.0 + }, + { + "x": 233.138451495374, + "y": -127.47375556702289, + "z": 0.0 + }, + { + "x": 232.13298074371454, + "y": -127.47330632901418, + "z": 0.0 + }, + { + "x": 231.12750999205497, + "y": -127.47285709100547, + "z": 0.0 + }, + { + "x": 230.1220392403954, + "y": -127.47240785299675, + "z": 0.0 + }, + { + "x": 229.1165684887358, + "y": -127.47195861498804, + "z": 0.0 + }, + { + "x": 228.1110977370762, + "y": -127.47150937697933, + "z": 0.0 + }, + { + "x": 227.10562698541662, + "y": -127.47106013897061, + "z": 0.0 + }, + { + "x": 226.10015623375702, + "y": -127.4706109009619, + "z": 0.0 + }, + { + "x": 225.0946854820973, + "y": -127.47016166295322, + "z": 0.0 + }, + { + "x": 224.08921473043785, + "y": -127.4697124249445, + "z": 0.0 + }, + { + "x": 223.08374397877824, + "y": -127.46926318693579, + "z": 0.0 + }, + { + "x": 222.07827322711867, + "y": -127.46881394892708, + "z": 0.0 + }, + { + "x": 221.07280247545907, + "y": -127.46836471091837, + "z": 0.0 + }, + { + "x": 220.06733172379947, + "y": -127.46791547290965, + "z": 0.0 + }, + { + "x": 219.0618609721399, + "y": -127.46746623490094, + "z": 0.0 + }, + { + "x": 218.05639022048018, + "y": -127.46701699689226, + "z": 0.0 + }, + { + "x": 217.0509194688207, + "y": -127.46656775888354, + "z": 0.0 + }, + { + "x": 216.04544871716112, + "y": -127.46611852087483, + "z": 0.0 + }, + { + "x": 215.03997796550152, + "y": -127.46566928286612, + "z": 0.0 + }, + { + "x": 214.03450721384192, + "y": -127.4652200448574, + "z": 0.0 + }, + { + "x": 213.02903646218235, + "y": -127.46477080684869, + "z": 0.0 + }, + { + "x": 212.02356571052275, + "y": -127.46432156883998, + "z": 0.0 + }, + { + "x": 211.01809495886314, + "y": -127.46387233083126, + "z": 0.0 + }, + { + "x": 210.01262420720346, + "y": -127.46342309282258, + "z": 0.0 + }, + { + "x": 209.00715345554397, + "y": -127.46297385481387, + "z": 0.0 + }, + { + "x": 208.00168270388437, + "y": -127.46252461680515, + "z": 0.0 + }, + { + "x": 206.9962119522248, + "y": -127.46207537879644, + "z": 0.0 + }, + { + "x": 205.9907412005652, + "y": -127.46162614078773, + "z": 0.0 + }, + { + "x": 204.9852704489056, + "y": -127.46117690277902, + "z": 0.0 + }, + { + "x": 203.97979969724602, + "y": -127.4607276647703, + "z": 0.0 + }, + { + "x": 202.9743289455863, + "y": -127.46027842676162, + "z": 0.0 + }, + { + "x": 201.96885819392682, + "y": -127.4598291887529, + "z": 0.0 + }, + { + "x": 200.96338744226725, + "y": -127.4593799507442, + "z": 0.0 + }, + { + "x": 199.95791669060765, + "y": -127.45893071273548, + "z": 0.0 + }, + { + "x": 198.95244593894805, + "y": -127.45848147472677, + "z": 0.0 + }, + { + "x": 197.94697518728847, + "y": -127.45803223671805, + "z": 0.0 + }, + { + "x": 196.94150443562887, + "y": -127.45758299870934, + "z": 0.0 + }, + { + "x": 195.93603368396927, + "y": -127.45713376070063, + "z": 0.0 + }, + { + "x": 194.93056293230958, + "y": -127.45668452269194, + "z": 0.0 + }, + { + "x": 193.9250921806501, + "y": -127.45623528468323, + "z": 0.0 + }, + { + "x": 192.9196214289905, + "y": -127.45578604667452, + "z": 0.0 + }, + { + "x": 191.91415067733092, + "y": -127.4553368086658, + "z": 0.0 + }, + { + "x": 190.90867992567132, + "y": -127.45488757065709, + "z": 0.0 + }, + { + "x": 189.90320917401175, + "y": -127.45443833264838, + "z": 0.0 + }, + { + "x": 188.89773842235215, + "y": -127.45398909463967, + "z": 0.0 + }, + { + "x": 187.89226767069243, + "y": -127.45353985663098, + "z": 0.0 + }, + { + "x": 186.88679691903297, + "y": -127.45309061862227, + "z": 0.0 + }, + { + "x": 185.88132616737337, + "y": -127.45264138061356, + "z": 0.0 + }, + { + "x": 184.87585541571377, + "y": -127.45219214260484, + "z": 0.0 + }, + { + "x": 183.8703846640542, + "y": -127.45174290459613, + "z": 0.0 + }, + { + "x": 182.8649139123946, + "y": -127.45129366658742, + "z": 0.0 + }, + { + "x": 181.859443160735, + "y": -127.4508444285787, + "z": 0.0 + }, + { + "x": 180.85397240907542, + "y": -127.45039519056999, + "z": 0.0 + }, + { + "x": 179.8485016574157, + "y": -127.44994595256131, + "z": 0.0 + }, + { + "x": 178.84303090575622, + "y": -127.4494967145526, + "z": 0.0 + }, + { + "x": 177.83756015409665, + "y": -127.44904747654388, + "z": 0.0 + }, + { + "x": 176.83208940243705, + "y": -127.44859823853517, + "z": 0.0 + }, + { + "x": 175.82661865077745, + "y": -127.44814900052646, + "z": 0.0 + }, + { + "x": 174.82114789911788, + "y": -127.44769976251774, + "z": 0.0 + }, + { + "x": 173.81567714745827, + "y": -127.44725052450903, + "z": 0.0 + }, + { + "x": 172.81020639579856, + "y": -127.44680128650035, + "z": 0.0 + }, + { + "x": 171.8047356441391, + "y": -127.44635204849163, + "z": 0.0 + }, + { + "x": 170.7992648924795, + "y": -127.44590281048292, + "z": 0.0 + }, + { + "x": 169.7937941408199, + "y": -127.44545357247421, + "z": 0.0 + }, + { + "x": 168.78832338916033, + "y": -127.4450043344655, + "z": 0.0 + }, + { + "x": 167.78285263750072, + "y": -127.44455509645678, + "z": 0.0 + }, + { + "x": 166.77738188584112, + "y": -127.44410585844807, + "z": 0.0 + }, + { + "x": 165.77191113418155, + "y": -127.44365662043936, + "z": 0.0 + }, + { + "x": 164.76644038252184, + "y": -127.44320738243067, + "z": 0.0 + }, + { + "x": 163.76096963086238, + "y": -127.44275814442196, + "z": 0.0 + }, + { + "x": 162.75549887920278, + "y": -127.44230890641325, + "z": 0.0 + }, + { + "x": 161.7500281275432, + "y": -127.44185966840453, + "z": 0.0 + }, + { + "x": 160.74455737588363, + "y": -127.44141043039582, + "z": 0.0 + }, + { + "x": 159.73908662422403, + "y": -127.4409611923871, + "z": 0.0 + }, + { + "x": 158.73361587256446, + "y": -127.4405119543784, + "z": 0.0 + }, + { + "x": 157.72814512090474, + "y": -127.44006271636971, + "z": 0.0 + }, + { + "x": 156.72267436924528, + "y": -127.439613478361, + "z": 0.0 + }, + { + "x": 155.7172036175857, + "y": -127.43916424035228, + "z": 0.0 + }, + { + "x": 154.7117328659261, + "y": -127.43871500234357, + "z": 0.0 + }, + { + "x": 153.70626211426654, + "y": -127.43826576433486, + "z": 0.0 + }, + { + "x": 152.70079136260694, + "y": -127.43781652632615, + "z": 0.0 + }, + { + "x": 151.69532061094736, + "y": -127.43736728831743, + "z": 0.0 + }, + { + "x": 150.6898498592878, + "y": -127.43691805030872, + "z": 0.0 + }, + { + "x": 149.68437910762808, + "y": -127.43646881230003, + "z": 0.0 + }, + { + "x": 148.67890835596862, + "y": -127.43601957429132, + "z": 0.0 + }, + { + "x": 147.67343760430902, + "y": -127.43557033628261, + "z": 0.0 + }, + { + "x": 146.66796685264944, + "y": -127.4351210982739, + "z": 0.0 + }, + { + "x": 145.66249610098987, + "y": -127.43467186026518, + "z": 0.0 + }, + { + "x": 144.65702534933027, + "y": -127.43422262225647, + "z": 0.0 + }, + { + "x": 143.6515545976707, + "y": -127.43377338424776, + "z": 0.0 + }, + { + "x": 142.64608384601098, + "y": -127.43332414623907, + "z": 0.0 + }, + { + "x": 141.64061309435152, + "y": -127.43287490823036, + "z": 0.0 + }, + { + "x": 140.63514234269192, + "y": -127.43242567022165, + "z": 0.0 + }, + { + "x": 139.62967159103235, + "y": -127.43197643221293, + "z": 0.0 + }, + { + "x": 138.62420083937278, + "y": -127.43152719420422, + "z": 0.0 + }, + { + "x": 137.61873008771317, + "y": -127.43107795619551, + "z": 0.0 + }, + { + "x": 136.6132593360536, + "y": -127.4306287181868, + "z": 0.0 + }, + { + "x": 135.607788584394, + "y": -127.43017948017808, + "z": 0.0 + }, + { + "x": 134.60231783273431, + "y": -127.4297302421694, + "z": 0.0 + }, + { + "x": 133.59684708107486, + "y": -127.42928100416069, + "z": 0.0 + }, + { + "x": 132.59137632941525, + "y": -127.42883176615197, + "z": 0.0 + }, + { + "x": 131.58590557775568, + "y": -127.42838252814326, + "z": 0.0 + }, + { + "x": 130.58043482609608, + "y": -127.42793329013455, + "z": 0.0 + }, + { + "x": 129.5749640744365, + "y": -127.42748405212583, + "z": 0.0 + }, + { + "x": 128.5694933227769, + "y": -127.42703481411712, + "z": 0.0 + }, + { + "x": 127.56402257111719, + "y": -127.42658557610844, + "z": 0.0 + }, + { + "x": 126.55855181945772, + "y": -127.42613633809972, + "z": 0.0 + }, + { + "x": 125.55308106779813, + "y": -127.42568710009101, + "z": 0.0 + }, + { + "x": 124.54761031613855, + "y": -127.4252378620823, + "z": 0.0 + }, + { + "x": 123.54213956447896, + "y": -127.42478862407359, + "z": 0.0 + }, + { + "x": 122.53666881281937, + "y": -127.42433938606487, + "z": 0.0 + }, + { + "x": 121.53119806115978, + "y": -127.42389014805616, + "z": 0.0 + }, + { + "x": 120.5257273095002, + "y": -127.42344091004745, + "z": 0.0 + }, + { + "x": 119.52025655784048, + "y": -127.42299167203876, + "z": 0.0 + }, + { + "x": 118.51478580618101, + "y": -127.42254243403005, + "z": 0.0 + }, + { + "x": 117.50931505452142, + "y": -127.42209319602134, + "z": 0.0 + }, + { + "x": 116.50384430286184, + "y": -127.42164395801262, + "z": 0.0 + }, + { + "x": 115.49837355120225, + "y": -127.42119472000391, + "z": 0.0 + }, + { + "x": 114.49290279954266, + "y": -127.4207454819952, + "z": 0.0 + }, + { + "x": 113.48743204788308, + "y": -127.42029624398648, + "z": 0.0 + }, + { + "x": 112.48196129622337, + "y": -127.4198470059778, + "z": 0.0 + }, + { + "x": 111.4764905445639, + "y": -127.41939776796909, + "z": 0.0 + }, + { + "x": 110.47101979290431, + "y": -127.41894852996037, + "z": 0.0 + }, + { + "x": 109.46554904124473, + "y": -127.41849929195166, + "z": 0.0 + }, + { + "x": 108.46007828958514, + "y": -127.41805005394295, + "z": 0.0 + }, + { + "x": 107.45460753792555, + "y": -127.41760081593424, + "z": 0.0 + }, + { + "x": 106.44913678626597, + "y": -127.41715157792552, + "z": 0.0 + }, + { + "x": 105.44366603460638, + "y": -127.41670233991681, + "z": 0.0 + }, + { + "x": 104.43819528294668, + "y": -127.41625310190813, + "z": 0.0 + }, + { + "x": 103.4327245312872, + "y": -127.41580386389941, + "z": 0.0 + }, + { + "x": 102.42725377962762, + "y": -127.4153546258907, + "z": 0.0 + }, + { + "x": 101.42178302796803, + "y": -127.41490538788199, + "z": 0.0 + } + ] + }, + { + "id": 21, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 101.4182086786346, + "y": -135.4149045893836, + "z": 0.0 + }, + { + "x": 102.42367943029419, + "y": -135.41535382739232, + "z": 0.0 + }, + { + "x": 103.42915018195377, + "y": -135.41580306540104, + "z": 0.0 + }, + { + "x": 104.43462093361347, + "y": -135.41625230340975, + "z": 0.0 + }, + { + "x": 105.44009168527295, + "y": -135.41670154141843, + "z": 0.0 + }, + { + "x": 106.44556243693253, + "y": -135.41715077942715, + "z": 0.0 + }, + { + "x": 107.45103318859212, + "y": -135.41760001743586, + "z": 0.0 + }, + { + "x": 108.45650394025171, + "y": -135.41804925544457, + "z": 0.0 + }, + { + "x": 109.4619746919113, + "y": -135.41849849345328, + "z": 0.0 + }, + { + "x": 110.46744544357088, + "y": -135.418947731462, + "z": 0.0 + }, + { + "x": 111.47291619523047, + "y": -135.4193969694707, + "z": 0.0 + }, + { + "x": 112.47838694689017, + "y": -135.41984620747942, + "z": 0.0 + }, + { + "x": 113.48385769854964, + "y": -135.4202954454881, + "z": 0.0 + }, + { + "x": 114.48932845020923, + "y": -135.42074468349682, + "z": 0.0 + }, + { + "x": 115.49479920186882, + "y": -135.42119392150553, + "z": 0.0 + }, + { + "x": 116.5002699535284, + "y": -135.42164315951425, + "z": 0.0 + }, + { + "x": 117.50574070518799, + "y": -135.42209239752296, + "z": 0.0 + }, + { + "x": 118.51121145684758, + "y": -135.42254163553167, + "z": 0.0 + }, + { + "x": 119.51668220850728, + "y": -135.42299087354039, + "z": 0.0 + }, + { + "x": 120.52215296016676, + "y": -135.42344011154907, + "z": 0.0 + }, + { + "x": 121.52762371182635, + "y": -135.42388934955778, + "z": 0.0 + }, + { + "x": 122.53309446348594, + "y": -135.4243385875665, + "z": 0.0 + }, + { + "x": 123.53856521514552, + "y": -135.4247878255752, + "z": 0.0 + }, + { + "x": 124.54403596680511, + "y": -135.42523706358392, + "z": 0.0 + }, + { + "x": 125.5495067184647, + "y": -135.42568630159263, + "z": 0.0 + }, + { + "x": 126.55497747012429, + "y": -135.42613553960135, + "z": 0.0 + }, + { + "x": 127.56044822178399, + "y": -135.42658477761006, + "z": 0.0 + }, + { + "x": 128.56591897344344, + "y": -135.42703401561874, + "z": 0.0 + }, + { + "x": 129.57138972510305, + "y": -135.42748325362746, + "z": 0.0 + }, + { + "x": 130.57686047676262, + "y": -135.42793249163617, + "z": 0.0 + }, + { + "x": 131.58233122842222, + "y": -135.42838172964488, + "z": 0.0 + }, + { + "x": 132.5878019800818, + "y": -135.4288309676536, + "z": 0.0 + }, + { + "x": 133.5932727317414, + "y": -135.4292802056623, + "z": 0.0 + }, + { + "x": 134.59874348340108, + "y": -135.42972944367102, + "z": 0.0 + }, + { + "x": 135.60421423506054, + "y": -135.4301786816797, + "z": 0.0 + }, + { + "x": 136.60968498672014, + "y": -135.43062791968842, + "z": 0.0 + }, + { + "x": 137.6151557383797, + "y": -135.43107715769713, + "z": 0.0 + }, + { + "x": 138.6206264900393, + "y": -135.43152639570584, + "z": 0.0 + }, + { + "x": 139.6260972416989, + "y": -135.43197563371456, + "z": 0.0 + }, + { + "x": 140.63156799335846, + "y": -135.43242487172327, + "z": 0.0 + }, + { + "x": 141.63703874501806, + "y": -135.43287410973198, + "z": 0.0 + }, + { + "x": 142.64250949667775, + "y": -135.4333233477407, + "z": 0.0 + }, + { + "x": 143.64798024833723, + "y": -135.43377258574938, + "z": 0.0 + }, + { + "x": 144.6534509999968, + "y": -135.4342218237581, + "z": 0.0 + }, + { + "x": 145.6589217516564, + "y": -135.4346710617668, + "z": 0.0 + }, + { + "x": 146.66439250331598, + "y": -135.43512029977552, + "z": 0.0 + }, + { + "x": 147.66986325497555, + "y": -135.43556953778423, + "z": 0.0 + }, + { + "x": 148.67533400663515, + "y": -135.43601877579295, + "z": 0.0 + }, + { + "x": 149.68080475829484, + "y": -135.43646801380166, + "z": 0.0 + }, + { + "x": 150.68627550995433, + "y": -135.43691725181034, + "z": 0.0 + }, + { + "x": 151.6917462616139, + "y": -135.43736648981906, + "z": 0.0 + }, + { + "x": 152.69721701327347, + "y": -135.43781572782777, + "z": 0.0 + }, + { + "x": 153.70268776493307, + "y": -135.43826496583648, + "z": 0.0 + }, + { + "x": 154.70815851659265, + "y": -135.4387142038452, + "z": 0.0 + }, + { + "x": 155.71362926825225, + "y": -135.4391634418539, + "z": 0.0 + }, + { + "x": 156.71910001991182, + "y": -135.43961267986262, + "z": 0.0 + }, + { + "x": 157.7245707715715, + "y": -135.44006191787133, + "z": 0.0 + }, + { + "x": 158.730041523231, + "y": -135.44051115588002, + "z": 0.0 + }, + { + "x": 159.73551227489057, + "y": -135.44096039388873, + "z": 0.0 + }, + { + "x": 160.74098302655017, + "y": -135.44140963189744, + "z": 0.0 + }, + { + "x": 161.74645377820974, + "y": -135.44185886990616, + "z": 0.0 + }, + { + "x": 162.7519245298693, + "y": -135.44230810791487, + "z": 0.0 + }, + { + "x": 163.75739528152891, + "y": -135.44275734592358, + "z": 0.0 + }, + { + "x": 164.7628660331886, + "y": -135.4432065839323, + "z": 0.0 + }, + { + "x": 165.7683367848481, + "y": -135.44365582194098, + "z": 0.0 + }, + { + "x": 166.77380753650766, + "y": -135.4441050599497, + "z": 0.0 + }, + { + "x": 167.77927828816726, + "y": -135.4445542979584, + "z": 0.0 + }, + { + "x": 168.78474903982686, + "y": -135.44500353596712, + "z": 0.0 + }, + { + "x": 169.79021979148644, + "y": -135.44545277397583, + "z": 0.0 + }, + { + "x": 170.79569054314604, + "y": -135.44590201198454, + "z": 0.0 + }, + { + "x": 171.80116129480564, + "y": -135.44635124999326, + "z": 0.0 + }, + { + "x": 172.80663204646532, + "y": -135.44680048800197, + "z": 0.0 + }, + { + "x": 173.8121027981248, + "y": -135.44724972601065, + "z": 0.0 + }, + { + "x": 174.8175735497844, + "y": -135.44769896401937, + "z": 0.0 + }, + { + "x": 175.82304430144399, + "y": -135.44814820202808, + "z": 0.0 + }, + { + "x": 176.8285150531036, + "y": -135.4485974400368, + "z": 0.0 + }, + { + "x": 177.8339858047632, + "y": -135.4490466780455, + "z": 0.0 + }, + { + "x": 178.83945655642276, + "y": -135.44949591605422, + "z": 0.0 + }, + { + "x": 179.84492730808248, + "y": -135.44994515406293, + "z": 0.0 + }, + { + "x": 180.85039805974196, + "y": -135.45039439207162, + "z": 0.0 + }, + { + "x": 181.85586881140154, + "y": -135.45084363008033, + "z": 0.0 + }, + { + "x": 182.86133956306114, + "y": -135.45129286808904, + "z": 0.0 + }, + { + "x": 183.86681031472074, + "y": -135.45174210609775, + "z": 0.0 + }, + { + "x": 184.8722810663803, + "y": -135.45219134410647, + "z": 0.0 + }, + { + "x": 185.8777518180399, + "y": -135.45264058211518, + "z": 0.0 + }, + { + "x": 186.8832225696995, + "y": -135.4530898201239, + "z": 0.0 + }, + { + "x": 187.8886933213592, + "y": -135.4535390581326, + "z": 0.0 + }, + { + "x": 188.8941640730187, + "y": -135.4539882961413, + "z": 0.0 + }, + { + "x": 189.8996348246783, + "y": -135.45443753415, + "z": 0.0 + }, + { + "x": 190.90510557633786, + "y": -135.45488677215872, + "z": 0.0 + }, + { + "x": 191.91057632799746, + "y": -135.45533601016743, + "z": 0.0 + }, + { + "x": 192.91604707965703, + "y": -135.45578524817614, + "z": 0.0 + }, + { + "x": 193.92151783131663, + "y": -135.45623448618485, + "z": 0.0 + }, + { + "x": 194.92698858297635, + "y": -135.45668372419357, + "z": 0.0 + }, + { + "x": 195.9324593346358, + "y": -135.45713296220225, + "z": 0.0 + }, + { + "x": 196.9379300862954, + "y": -135.45758220021096, + "z": 0.0 + }, + { + "x": 197.943400837955, + "y": -135.45803143821968, + "z": 0.0 + }, + { + "x": 198.94887158961458, + "y": -135.4584806762284, + "z": 0.0 + }, + { + "x": 199.95434234127418, + "y": -135.4589299142371, + "z": 0.0 + }, + { + "x": 200.95981309293379, + "y": -135.45937915224582, + "z": 0.0 + }, + { + "x": 201.96528384459336, + "y": -135.45982839025453, + "z": 0.0 + }, + { + "x": 202.97075459625307, + "y": -135.46027762826324, + "z": 0.0 + }, + { + "x": 203.97622534791256, + "y": -135.46072686627193, + "z": 0.0 + }, + { + "x": 204.98169609957213, + "y": -135.46117610428064, + "z": 0.0 + }, + { + "x": 205.98716685123173, + "y": -135.46162534228935, + "z": 0.0 + }, + { + "x": 206.99263760289134, + "y": -135.46207458029807, + "z": 0.0 + }, + { + "x": 207.9981083545509, + "y": -135.46252381830678, + "z": 0.0 + }, + { + "x": 209.0035791062105, + "y": -135.4629730563155, + "z": 0.0 + }, + { + "x": 210.00904985787022, + "y": -135.4634222943242, + "z": 0.0 + }, + { + "x": 211.01452060952968, + "y": -135.4638715323329, + "z": 0.0 + }, + { + "x": 212.01999136118928, + "y": -135.4643207703416, + "z": 0.0 + }, + { + "x": 213.02546211284888, + "y": -135.4647700083503, + "z": 0.0 + }, + { + "x": 214.03093286450846, + "y": -135.46521924635903, + "z": 0.0 + }, + { + "x": 215.03640361616806, + "y": -135.46566848436774, + "z": 0.0 + }, + { + "x": 216.04187436782766, + "y": -135.46611772237645, + "z": 0.0 + }, + { + "x": 217.04734511948723, + "y": -135.46656696038517, + "z": 0.0 + }, + { + "x": 218.05281587114695, + "y": -135.46701619839388, + "z": 0.0 + }, + { + "x": 219.05828662280643, + "y": -135.46746543640256, + "z": 0.0 + }, + { + "x": 220.063757374466, + "y": -135.46791467441128, + "z": 0.0 + }, + { + "x": 221.0692281261256, + "y": -135.46836391242, + "z": 0.0 + }, + { + "x": 222.0746988777852, + "y": -135.4688131504287, + "z": 0.0 + }, + { + "x": 223.08016962944478, + "y": -135.46926238843741, + "z": 0.0 + }, + { + "x": 224.08564038110438, + "y": -135.46971162644613, + "z": 0.0 + }, + { + "x": 225.09111113276407, + "y": -135.47016086445484, + "z": 0.0 + }, + { + "x": 226.09658188442356, + "y": -135.47061010246352, + "z": 0.0 + }, + { + "x": 227.10205263608316, + "y": -135.47105934047224, + "z": 0.0 + }, + { + "x": 228.10752338774273, + "y": -135.47150857848095, + "z": 0.0 + }, + { + "x": 229.11299413940233, + "y": -135.47195781648966, + "z": 0.0 + }, + { + "x": 230.11846489106193, + "y": -135.47240705449838, + "z": 0.0 + }, + { + "x": 231.1239356427215, + "y": -135.4728562925071, + "z": 0.0 + }, + { + "x": 232.12940639438108, + "y": -135.4733055305158, + "z": 0.0 + }, + { + "x": 233.13487714604076, + "y": -135.47375476852451, + "z": 0.0 + }, + { + "x": 234.14034789770025, + "y": -135.4742040065332, + "z": 0.0 + }, + { + "x": 235.14581864935982, + "y": -135.4746532445419, + "z": 0.0 + }, + { + "x": 236.1512894010194, + "y": -135.47510248255062, + "z": 0.0 + }, + { + "x": 237.15676015267897, + "y": -135.47555172055934, + "z": 0.0 + }, + { + "x": 238.16223090433854, + "y": -135.47600095856805, + "z": 0.0 + }, + { + "x": 239.16770165599812, + "y": -135.47645019657676, + "z": 0.0 + }, + { + "x": 240.17317240765783, + "y": -135.47689943458548, + "z": 0.0 + }, + { + "x": 241.1786431593173, + "y": -135.47734867259416, + "z": 0.0 + }, + { + "x": 242.18411391097686, + "y": -135.47779791060287, + "z": 0.0 + }, + { + "x": 243.18958466263643, + "y": -135.4782471486116, + "z": 0.0 + }, + { + "x": 244.195055414296, + "y": -135.4786963866203, + "z": 0.0 + }, + { + "x": 245.20052616595558, + "y": -135.479145624629, + "z": 0.0 + }, + { + "x": 246.20599691761515, + "y": -135.47959486263773, + "z": 0.0 + }, + { + "x": 247.21146766927475, + "y": -135.48004410064644, + "z": 0.0 + }, + { + "x": 248.21693842093444, + "y": -135.48049333865515, + "z": 0.0 + }, + { + "x": 249.2224091725939, + "y": -135.48094257666384, + "z": 0.0 + }, + { + "x": 250.22787992425347, + "y": -135.48139181467255, + "z": 0.0 + }, + { + "x": 251.23335067591304, + "y": -135.48184105268126, + "z": 0.0 + }, + { + "x": 252.23882142757262, + "y": -135.48229029068997, + "z": 0.0 + }, + { + "x": 253.24429217923222, + "y": -135.4827395286987, + "z": 0.0 + }, + { + "x": 254.2497629308918, + "y": -135.4831887667074, + "z": 0.0 + }, + { + "x": 255.25523368255148, + "y": -135.4836380047161, + "z": 0.0 + }, + { + "x": 256.26070443421094, + "y": -135.4840872427248, + "z": 0.0 + }, + { + "x": 257.2661751858705, + "y": -135.4845364807335, + "z": 0.0 + }, + { + "x": 258.2716459375301, + "y": -135.48498571874222, + "z": 0.0 + }, + { + "x": 259.27711668918965, + "y": -135.48543495675094, + "z": 0.0 + }, + { + "x": 260.2825874408492, + "y": -135.48588419475965, + "z": 0.0 + }, + { + "x": 261.2880581925088, + "y": -135.48633343276836, + "z": 0.0 + }, + { + "x": 262.2935289441684, + "y": -135.48678267077707, + "z": 0.0 + }, + { + "x": 263.29899969582806, + "y": -135.4872319087858, + "z": 0.0 + }, + { + "x": 264.3044704474875, + "y": -135.48768114679447, + "z": 0.0 + }, + { + "x": 265.3099411991471, + "y": -135.48813038480318, + "z": 0.0 + }, + { + "x": 266.3154119508067, + "y": -135.4885796228119, + "z": 0.0 + }, + { + "x": 267.3208827024663, + "y": -135.4890288608206, + "z": 0.0 + }, + { + "x": 268.32635345412587, + "y": -135.48947809882932, + "z": 0.0 + }, + { + "x": 269.33182420578544, + "y": -135.48992733683804, + "z": 0.0 + }, + { + "x": 270.3372949574451, + "y": -135.49037657484675, + "z": 0.0 + }, + { + "x": 271.3427657091046, + "y": -135.49082581285543, + "z": 0.0 + }, + { + "x": 272.34823646076416, + "y": -135.49127505086415, + "z": 0.0 + }, + { + "x": 273.3537072124237, + "y": -135.49172428887286, + "z": 0.0 + }, + { + "x": 274.3591779640833, + "y": -135.49217352688157, + "z": 0.0 + }, + { + "x": 275.3646487157429, + "y": -135.49262276489029, + "z": 0.0 + }, + { + "x": 276.37011946740245, + "y": -135.493072002899, + "z": 0.0 + }, + { + "x": 277.375590219062, + "y": -135.4935212409077, + "z": 0.0 + }, + { + "x": 278.38106097072176, + "y": -135.49397047891642, + "z": 0.0 + }, + { + "x": 279.3865317223812, + "y": -135.4944197169251, + "z": 0.0 + }, + { + "x": 280.3920024740408, + "y": -135.49486895493382, + "z": 0.0 + }, + { + "x": 281.39747322570037, + "y": -135.49531819294253, + "z": 0.0 + }, + { + "x": 282.40294397735994, + "y": -135.49576743095125, + "z": 0.0 + }, + { + "x": 283.4084147290195, + "y": -135.49621666895996, + "z": 0.0 + }, + { + "x": 284.4138854806791, + "y": -135.49666590696867, + "z": 0.0 + }, + { + "x": 285.41935623233877, + "y": -135.49711514497739, + "z": 0.0 + }, + { + "x": 286.42482698399823, + "y": -135.49756438298607, + "z": 0.0 + }, + { + "x": 287.4302977356578, + "y": -135.49801362099478, + "z": 0.0 + }, + { + "x": 288.4357684873174, + "y": -135.4984628590035, + "z": 0.0 + }, + { + "x": 289.44123923897695, + "y": -135.4989120970122, + "z": 0.0 + }, + { + "x": 290.4467099906365, + "y": -135.49936133502092, + "z": 0.0 + }, + { + "x": 291.45218074229615, + "y": -135.49981057302963, + "z": 0.0 + }, + { + "x": 292.4576514939557, + "y": -135.50025981103835, + "z": 0.0 + }, + { + "x": 293.4631222456154, + "y": -135.50070904904706, + "z": 0.0 + }, + { + "x": 294.46859299727487, + "y": -135.50115828705574, + "z": 0.0 + }, + { + "x": 295.47406374893444, + "y": -135.50160752506446, + "z": 0.0 + }, + { + "x": 296.479534500594, + "y": -135.50205676307317, + "z": 0.0 + }, + { + "x": 297.4850052522536, + "y": -135.50250600108188, + "z": 0.0 + }, + { + "x": 298.49047600391316, + "y": -135.5029552390906, + "z": 0.0 + }, + { + "x": 299.49594675557273, + "y": -135.5034044770993, + "z": 0.0 + }, + { + "x": 300.5014175072324, + "y": -135.50385371510802, + "z": 0.0 + }, + { + "x": 301.5068882588919, + "y": -135.5043029531167, + "z": 0.0 + }, + { + "x": 302.51235901055145, + "y": -135.50475219112542, + "z": 0.0 + }, + { + "x": 303.517829762211, + "y": -135.50520142913413, + "z": 0.0 + }, + { + "x": 304.52330051387065, + "y": -135.50565066714285, + "z": 0.0 + }, + { + "x": 305.5287712655302, + "y": -135.50609990515156, + "z": 0.0 + }, + { + "x": 306.5342420171898, + "y": -135.50654914316027, + "z": 0.0 + }, + { + "x": 307.53971276884937, + "y": -135.50699838116898, + "z": 0.0 + }, + { + "x": 308.54518352050906, + "y": -135.5074476191777, + "z": 0.0 + }, + { + "x": 309.5506542721685, + "y": -135.50789685718638, + "z": 0.0 + }, + { + "x": 310.5561250238281, + "y": -135.5083460951951, + "z": 0.0 + }, + { + "x": 311.56159577548766, + "y": -135.5087953332038, + "z": 0.0 + }, + { + "x": 312.56706652714723, + "y": -135.50924457121252, + "z": 0.0 + }, + { + "x": 313.5725372788068, + "y": -135.50969380922123, + "z": 0.0 + }, + { + "x": 314.5780080304664, + "y": -135.51014304722995, + "z": 0.0 + }, + { + "x": 315.58347878212606, + "y": -135.51059228523866, + "z": 0.0 + }, + { + "x": 316.5889495337855, + "y": -135.51104152324734, + "z": 0.0 + }, + { + "x": 317.59442028544515, + "y": -135.51149076125606, + "z": 0.0 + }, + { + "x": 318.5998910371047, + "y": -135.51193999926477, + "z": 0.0 + }, + { + "x": 319.6053617887643, + "y": -135.51238923727348, + "z": 0.0 + }, + { + "x": 320.61083254042387, + "y": -135.5128384752822, + "z": 0.0 + }, + { + "x": 321.61630329208344, + "y": -135.5132877132909, + "z": 0.0 + }, + { + "x": 322.621774043743, + "y": -135.51373695129962, + "z": 0.0 + }, + { + "x": 323.6272447954027, + "y": -135.51418618930833, + "z": 0.0 + }, + { + "x": 324.63271554706216, + "y": -135.51463542731702, + "z": 0.0 + }, + { + "x": 325.63818629872173, + "y": -135.51508466532573, + "z": 0.0 + } + ] + }, + { + "id": 22, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 101.41999585330132, + "y": -131.4149049886328, + "z": 0.0 + }, + { + "x": 102.4254666049609, + "y": -131.4153542266415, + "z": 0.0 + }, + { + "x": 103.43093735662049, + "y": -131.41580346465022, + "z": 0.0 + }, + { + "x": 104.43640810828008, + "y": -131.41625270265894, + "z": 0.0 + }, + { + "x": 105.44187885993966, + "y": -131.41670194066762, + "z": 0.0 + }, + { + "x": 106.44734961159925, + "y": -131.41715117867633, + "z": 0.0 + }, + { + "x": 107.45282036325884, + "y": -131.41760041668505, + "z": 0.0 + }, + { + "x": 108.45829111491842, + "y": -131.41804965469376, + "z": 0.0 + }, + { + "x": 109.46376186657801, + "y": -131.41849889270247, + "z": 0.0 + }, + { + "x": 110.4692326182376, + "y": -131.4189481307112, + "z": 0.0 + }, + { + "x": 111.47470336989718, + "y": -131.4193973687199, + "z": 0.0 + }, + { + "x": 112.48017412155677, + "y": -131.4198466067286, + "z": 0.0 + }, + { + "x": 113.48564487321636, + "y": -131.4202958447373, + "z": 0.0 + }, + { + "x": 114.49111562487595, + "y": -131.420745082746, + "z": 0.0 + }, + { + "x": 115.49658637653553, + "y": -131.42119432075472, + "z": 0.0 + }, + { + "x": 116.50205712819512, + "y": -131.42164355876344, + "z": 0.0 + }, + { + "x": 117.5075278798547, + "y": -131.42209279677215, + "z": 0.0 + }, + { + "x": 118.5129986315143, + "y": -131.42254203478086, + "z": 0.0 + }, + { + "x": 119.51846938317388, + "y": -131.42299127278957, + "z": 0.0 + }, + { + "x": 120.52394013483348, + "y": -131.42344051079826, + "z": 0.0 + }, + { + "x": 121.52941088649307, + "y": -131.42388974880697, + "z": 0.0 + }, + { + "x": 122.53488163815265, + "y": -131.42433898681568, + "z": 0.0 + }, + { + "x": 123.54035238981224, + "y": -131.4247882248244, + "z": 0.0 + }, + { + "x": 124.54582314147183, + "y": -131.4252374628331, + "z": 0.0 + }, + { + "x": 125.55129389313142, + "y": -131.42568670084182, + "z": 0.0 + }, + { + "x": 126.556764644791, + "y": -131.42613593885054, + "z": 0.0 + }, + { + "x": 127.56223539645059, + "y": -131.42658517685925, + "z": 0.0 + }, + { + "x": 128.56770614811018, + "y": -131.42703441486793, + "z": 0.0 + }, + { + "x": 129.57317689976978, + "y": -131.42748365287665, + "z": 0.0 + }, + { + "x": 130.57864765142935, + "y": -131.42793289088536, + "z": 0.0 + }, + { + "x": 131.58411840308895, + "y": -131.42838212889407, + "z": 0.0 + }, + { + "x": 132.58958915474852, + "y": -131.42883136690278, + "z": 0.0 + }, + { + "x": 133.59505990640812, + "y": -131.4292806049115, + "z": 0.0 + }, + { + "x": 134.6005306580677, + "y": -131.4297298429202, + "z": 0.0 + }, + { + "x": 135.60600140972727, + "y": -131.4301790809289, + "z": 0.0 + }, + { + "x": 136.61147216138687, + "y": -131.4306283189376, + "z": 0.0 + }, + { + "x": 137.61694291304644, + "y": -131.43107755694632, + "z": 0.0 + }, + { + "x": 138.62241366470604, + "y": -131.43152679495503, + "z": 0.0 + }, + { + "x": 139.62788441636562, + "y": -131.43197603296375, + "z": 0.0 + }, + { + "x": 140.6333551680252, + "y": -131.43242527097246, + "z": 0.0 + }, + { + "x": 141.6388259196848, + "y": -131.43287450898117, + "z": 0.0 + }, + { + "x": 142.64429667134436, + "y": -131.43332374698988, + "z": 0.0 + }, + { + "x": 143.64976742300396, + "y": -131.43377298499857, + "z": 0.0 + }, + { + "x": 144.65523817466354, + "y": -131.43422222300728, + "z": 0.0 + }, + { + "x": 145.66070892632314, + "y": -131.434671461016, + "z": 0.0 + }, + { + "x": 146.6661796779827, + "y": -131.4351206990247, + "z": 0.0 + }, + { + "x": 147.67165042964228, + "y": -131.43556993703342, + "z": 0.0 + }, + { + "x": 148.67712118130189, + "y": -131.43601917504213, + "z": 0.0 + }, + { + "x": 149.68259193296146, + "y": -131.43646841305085, + "z": 0.0 + }, + { + "x": 150.68806268462106, + "y": -131.43691765105953, + "z": 0.0 + }, + { + "x": 151.69353343628063, + "y": -131.43736688906824, + "z": 0.0 + }, + { + "x": 152.6990041879402, + "y": -131.43781612707696, + "z": 0.0 + }, + { + "x": 153.7044749395998, + "y": -131.43826536508567, + "z": 0.0 + }, + { + "x": 154.70994569125938, + "y": -131.43871460309438, + "z": 0.0 + }, + { + "x": 155.71541644291898, + "y": -131.4391638411031, + "z": 0.0 + }, + { + "x": 156.72088719457855, + "y": -131.4396130791118, + "z": 0.0 + }, + { + "x": 157.72635794623812, + "y": -131.44006231712052, + "z": 0.0 + }, + { + "x": 158.73182869789773, + "y": -131.4405115551292, + "z": 0.0 + }, + { + "x": 159.7372994495573, + "y": -131.44096079313792, + "z": 0.0 + }, + { + "x": 160.7427702012169, + "y": -131.44141003114663, + "z": 0.0 + }, + { + "x": 161.74824095287647, + "y": -131.44185926915534, + "z": 0.0 + }, + { + "x": 162.75371170453604, + "y": -131.44230850716406, + "z": 0.0 + }, + { + "x": 163.75918245619565, + "y": -131.44275774517277, + "z": 0.0 + }, + { + "x": 164.76465320785522, + "y": -131.44320698318148, + "z": 0.0 + }, + { + "x": 165.77012395951482, + "y": -131.44365622119017, + "z": 0.0 + }, + { + "x": 166.7755947111744, + "y": -131.44410545919888, + "z": 0.0 + }, + { + "x": 167.781065462834, + "y": -131.4445546972076, + "z": 0.0 + }, + { + "x": 168.7865362144936, + "y": -131.4450039352163, + "z": 0.0 + }, + { + "x": 169.79200696615317, + "y": -131.44545317322502, + "z": 0.0 + }, + { + "x": 170.79747771781277, + "y": -131.44590241123373, + "z": 0.0 + }, + { + "x": 171.80294846947237, + "y": -131.44635164924244, + "z": 0.0 + }, + { + "x": 172.80841922113194, + "y": -131.44680088725116, + "z": 0.0 + }, + { + "x": 173.81388997279154, + "y": -131.44725012525984, + "z": 0.0 + }, + { + "x": 174.81936072445114, + "y": -131.44769936326855, + "z": 0.0 + }, + { + "x": 175.82483147611072, + "y": -131.44814860127727, + "z": 0.0 + }, + { + "x": 176.83030222777032, + "y": -131.44859783928598, + "z": 0.0 + }, + { + "x": 177.83577297942992, + "y": -131.4490470772947, + "z": 0.0 + }, + { + "x": 178.8412437310895, + "y": -131.4494963153034, + "z": 0.0 + }, + { + "x": 179.8467144827491, + "y": -131.44994555331212, + "z": 0.0 + }, + { + "x": 180.8521852344087, + "y": -131.4503947913208, + "z": 0.0 + }, + { + "x": 181.85765598606827, + "y": -131.45084402932952, + "z": 0.0 + }, + { + "x": 182.86312673772787, + "y": -131.45129326733823, + "z": 0.0 + }, + { + "x": 183.86859748938747, + "y": -131.45174250534694, + "z": 0.0 + }, + { + "x": 184.87406824104704, + "y": -131.45219174335566, + "z": 0.0 + }, + { + "x": 185.87953899270664, + "y": -131.45264098136437, + "z": 0.0 + }, + { + "x": 186.88500974436624, + "y": -131.45309021937308, + "z": 0.0 + }, + { + "x": 187.89048049602582, + "y": -131.4535394573818, + "z": 0.0 + }, + { + "x": 188.89595124768542, + "y": -131.45398869539048, + "z": 0.0 + }, + { + "x": 189.90142199934502, + "y": -131.4544379333992, + "z": 0.0 + }, + { + "x": 190.9068927510046, + "y": -131.4548871714079, + "z": 0.0 + }, + { + "x": 191.9123635026642, + "y": -131.45533640941662, + "z": 0.0 + }, + { + "x": 192.91783425432376, + "y": -131.45578564742533, + "z": 0.0 + }, + { + "x": 193.92330500598337, + "y": -131.45623488543404, + "z": 0.0 + }, + { + "x": 194.92877575764297, + "y": -131.45668412344276, + "z": 0.0 + }, + { + "x": 195.93424650930254, + "y": -131.45713336145144, + "z": 0.0 + }, + { + "x": 196.93971726096214, + "y": -131.45758259946015, + "z": 0.0 + }, + { + "x": 197.94518801262174, + "y": -131.45803183746887, + "z": 0.0 + }, + { + "x": 198.95065876428131, + "y": -131.45848107547758, + "z": 0.0 + }, + { + "x": 199.95612951594092, + "y": -131.4589303134863, + "z": 0.0 + }, + { + "x": 200.96160026760052, + "y": -131.459379551495, + "z": 0.0 + }, + { + "x": 201.9670710192601, + "y": -131.45982878950372, + "z": 0.0 + }, + { + "x": 202.9725417709197, + "y": -131.46027802751243, + "z": 0.0 + }, + { + "x": 203.9780125225793, + "y": -131.46072726552111, + "z": 0.0 + }, + { + "x": 204.98348327423886, + "y": -131.46117650352983, + "z": 0.0 + }, + { + "x": 205.98895402589847, + "y": -131.46162574153854, + "z": 0.0 + }, + { + "x": 206.99442477755807, + "y": -131.46207497954725, + "z": 0.0 + }, + { + "x": 207.99989552921764, + "y": -131.46252421755597, + "z": 0.0 + }, + { + "x": 209.00536628087724, + "y": -131.46297345556468, + "z": 0.0 + }, + { + "x": 210.01083703253684, + "y": -131.4634226935734, + "z": 0.0 + }, + { + "x": 211.0163077841964, + "y": -131.46387193158208, + "z": 0.0 + }, + { + "x": 212.02177853585601, + "y": -131.4643211695908, + "z": 0.0 + }, + { + "x": 213.02724928751562, + "y": -131.4647704075995, + "z": 0.0 + }, + { + "x": 214.0327200391752, + "y": -131.46521964560822, + "z": 0.0 + }, + { + "x": 215.0381907908348, + "y": -131.46566888361693, + "z": 0.0 + }, + { + "x": 216.0436615424944, + "y": -131.46611812162564, + "z": 0.0 + }, + { + "x": 217.04913229415396, + "y": -131.46656735963435, + "z": 0.0 + }, + { + "x": 218.05460304581356, + "y": -131.46701659764307, + "z": 0.0 + }, + { + "x": 219.06007379747317, + "y": -131.46746583565175, + "z": 0.0 + }, + { + "x": 220.06554454913274, + "y": -131.46791507366046, + "z": 0.0 + }, + { + "x": 221.07101530079234, + "y": -131.46836431166918, + "z": 0.0 + }, + { + "x": 222.07648605245194, + "y": -131.4688135496779, + "z": 0.0 + }, + { + "x": 223.0819568041115, + "y": -131.4692627876866, + "z": 0.0 + }, + { + "x": 224.08742755577111, + "y": -131.46971202569532, + "z": 0.0 + }, + { + "x": 225.0928983074307, + "y": -131.47016126370403, + "z": 0.0 + }, + { + "x": 226.0983690590903, + "y": -131.4706105017127, + "z": 0.0 + }, + { + "x": 227.1038398107499, + "y": -131.47105973972143, + "z": 0.0 + }, + { + "x": 228.10931056240946, + "y": -131.47150897773014, + "z": 0.0 + }, + { + "x": 229.11478131406906, + "y": -131.47195821573885, + "z": 0.0 + }, + { + "x": 230.12025206572866, + "y": -131.47240745374756, + "z": 0.0 + }, + { + "x": 231.12572281738824, + "y": -131.47285669175628, + "z": 0.0 + }, + { + "x": 232.1311935690478, + "y": -131.473305929765, + "z": 0.0 + }, + { + "x": 233.13666432070738, + "y": -131.4737551677737, + "z": 0.0 + }, + { + "x": 234.14213507236698, + "y": -131.4742044057824, + "z": 0.0 + }, + { + "x": 235.14760582402656, + "y": -131.4746536437911, + "z": 0.0 + }, + { + "x": 236.15307657568613, + "y": -131.4751028817998, + "z": 0.0 + }, + { + "x": 237.1585473273457, + "y": -131.47555211980853, + "z": 0.0 + }, + { + "x": 238.16401807900527, + "y": -131.47600135781724, + "z": 0.0 + }, + { + "x": 239.16948883066485, + "y": -131.47645059582595, + "z": 0.0 + }, + { + "x": 240.17495958232445, + "y": -131.47689983383466, + "z": 0.0 + }, + { + "x": 241.18043033398402, + "y": -131.47734907184335, + "z": 0.0 + }, + { + "x": 242.1859010856436, + "y": -131.47779830985206, + "z": 0.0 + }, + { + "x": 243.19137183730317, + "y": -131.47824754786078, + "z": 0.0 + }, + { + "x": 244.19684258896274, + "y": -131.4786967858695, + "z": 0.0 + }, + { + "x": 245.2023133406223, + "y": -131.4791460238782, + "z": 0.0 + }, + { + "x": 246.20778409228188, + "y": -131.4795952618869, + "z": 0.0 + }, + { + "x": 247.21325484394148, + "y": -131.48004449989563, + "z": 0.0 + }, + { + "x": 248.21872559560106, + "y": -131.48049373790434, + "z": 0.0 + }, + { + "x": 249.22419634726063, + "y": -131.48094297591302, + "z": 0.0 + }, + { + "x": 250.2296670989202, + "y": -131.48139221392174, + "z": 0.0 + }, + { + "x": 251.23513785057978, + "y": -131.48184145193045, + "z": 0.0 + }, + { + "x": 252.24060860223935, + "y": -131.48229068993916, + "z": 0.0 + }, + { + "x": 253.24607935389895, + "y": -131.48273992794788, + "z": 0.0 + }, + { + "x": 254.25155010555852, + "y": -131.4831891659566, + "z": 0.0 + }, + { + "x": 255.2570208572181, + "y": -131.4836384039653, + "z": 0.0 + }, + { + "x": 256.26249160887767, + "y": -131.48408764197399, + "z": 0.0 + }, + { + "x": 257.26796236053724, + "y": -131.4845368799827, + "z": 0.0 + }, + { + "x": 258.2734331121968, + "y": -131.4849861179914, + "z": 0.0 + }, + { + "x": 259.2789038638564, + "y": -131.48543535600012, + "z": 0.0 + }, + { + "x": 260.28437461551596, + "y": -131.48588459400884, + "z": 0.0 + }, + { + "x": 261.28984536717553, + "y": -131.48633383201755, + "z": 0.0 + }, + { + "x": 262.2953161188351, + "y": -131.48678307002626, + "z": 0.0 + }, + { + "x": 263.3007868704947, + "y": -131.48723230803498, + "z": 0.0 + }, + { + "x": 264.30625762215425, + "y": -131.48768154604366, + "z": 0.0 + }, + { + "x": 265.3117283738138, + "y": -131.48813078405237, + "z": 0.0 + }, + { + "x": 266.31719912547345, + "y": -131.4885800220611, + "z": 0.0 + }, + { + "x": 267.322669877133, + "y": -131.4890292600698, + "z": 0.0 + }, + { + "x": 268.3281406287926, + "y": -131.4894784980785, + "z": 0.0 + }, + { + "x": 269.33361138045217, + "y": -131.48992773608722, + "z": 0.0 + }, + { + "x": 270.33908213211174, + "y": -131.49037697409594, + "z": 0.0 + }, + { + "x": 271.3445528837713, + "y": -131.49082621210462, + "z": 0.0 + }, + { + "x": 272.3500236354309, + "y": -131.49127545011333, + "z": 0.0 + }, + { + "x": 273.35549438709046, + "y": -131.49172468812205, + "z": 0.0 + }, + { + "x": 274.36096513875003, + "y": -131.49217392613076, + "z": 0.0 + }, + { + "x": 275.3664358904096, + "y": -131.49262316413947, + "z": 0.0 + }, + { + "x": 276.3719066420692, + "y": -131.4930724021482, + "z": 0.0 + }, + { + "x": 277.37737739372875, + "y": -131.4935216401569, + "z": 0.0 + }, + { + "x": 278.3828481453884, + "y": -131.4939708781656, + "z": 0.0 + }, + { + "x": 279.38831889704795, + "y": -131.4944201161743, + "z": 0.0 + }, + { + "x": 280.3937896487075, + "y": -131.494869354183, + "z": 0.0 + }, + { + "x": 281.3992604003671, + "y": -131.49531859219172, + "z": 0.0 + }, + { + "x": 282.40473115202667, + "y": -131.49576783020044, + "z": 0.0 + }, + { + "x": 283.41020190368624, + "y": -131.49621706820915, + "z": 0.0 + }, + { + "x": 284.4156726553458, + "y": -131.49666630621786, + "z": 0.0 + }, + { + "x": 285.4211434070054, + "y": -131.49711554422657, + "z": 0.0 + }, + { + "x": 286.42661415866496, + "y": -131.49756478223526, + "z": 0.0 + }, + { + "x": 287.43208491032453, + "y": -131.49801402024397, + "z": 0.0 + }, + { + "x": 288.4375556619841, + "y": -131.49846325825268, + "z": 0.0 + }, + { + "x": 289.4430264136437, + "y": -131.4989124962614, + "z": 0.0 + }, + { + "x": 290.44849716530325, + "y": -131.4993617342701, + "z": 0.0 + }, + { + "x": 291.4539679169629, + "y": -131.49981097227882, + "z": 0.0 + }, + { + "x": 292.45943866862245, + "y": -131.50026021028754, + "z": 0.0 + }, + { + "x": 293.464909420282, + "y": -131.50070944829625, + "z": 0.0 + }, + { + "x": 294.4703801719416, + "y": -131.50115868630493, + "z": 0.0 + }, + { + "x": 295.4758509236012, + "y": -131.50160792431365, + "z": 0.0 + }, + { + "x": 296.48132167526074, + "y": -131.50205716232236, + "z": 0.0 + }, + { + "x": 297.4867924269203, + "y": -131.50250640033107, + "z": 0.0 + }, + { + "x": 298.4922631785799, + "y": -131.50295563833978, + "z": 0.0 + }, + { + "x": 299.49773393023946, + "y": -131.5034048763485, + "z": 0.0 + }, + { + "x": 300.50320468189904, + "y": -131.5038541143572, + "z": 0.0 + }, + { + "x": 301.5086754335586, + "y": -131.5043033523659, + "z": 0.0 + }, + { + "x": 302.5141461852182, + "y": -131.5047525903746, + "z": 0.0 + }, + { + "x": 303.51961693687775, + "y": -131.50520182838332, + "z": 0.0 + }, + { + "x": 304.5250876885374, + "y": -131.50565106639203, + "z": 0.0 + }, + { + "x": 305.53055844019696, + "y": -131.50610030440075, + "z": 0.0 + }, + { + "x": 306.5360291918565, + "y": -131.50654954240946, + "z": 0.0 + }, + { + "x": 307.5414999435161, + "y": -131.50699878041817, + "z": 0.0 + }, + { + "x": 308.5469706951757, + "y": -131.50744801842689, + "z": 0.0 + }, + { + "x": 309.55244144683525, + "y": -131.50789725643557, + "z": 0.0 + }, + { + "x": 310.5579121984948, + "y": -131.50834649444428, + "z": 0.0 + }, + { + "x": 311.5633829501544, + "y": -131.508795732453, + "z": 0.0 + }, + { + "x": 312.56885370181396, + "y": -131.5092449704617, + "z": 0.0 + }, + { + "x": 313.57432445347354, + "y": -131.50969420847042, + "z": 0.0 + }, + { + "x": 314.5797952051331, + "y": -131.51014344647913, + "z": 0.0 + }, + { + "x": 315.5852659567927, + "y": -131.51059268448785, + "z": 0.0 + }, + { + "x": 316.59073670845225, + "y": -131.51104192249653, + "z": 0.0 + }, + { + "x": 317.5962074601119, + "y": -131.51149116050524, + "z": 0.0 + }, + { + "x": 318.60167821177146, + "y": -131.51194039851396, + "z": 0.0 + }, + { + "x": 319.60714896343103, + "y": -131.51238963652267, + "z": 0.0 + }, + { + "x": 320.6126197150906, + "y": -131.51283887453138, + "z": 0.0 + }, + { + "x": 321.6180904667502, + "y": -131.5132881125401, + "z": 0.0 + }, + { + "x": 322.62356121840975, + "y": -131.5137373505488, + "z": 0.0 + }, + { + "x": 323.6290319700693, + "y": -131.51418658855752, + "z": 0.0 + }, + { + "x": 324.6345027217289, + "y": -131.5146358265662, + "z": 0.0 + }, + { + "x": 325.63997347338847, + "y": -131.51508506457492, + "z": 0.0 + } + ] + }, + { + "id": 23, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.6408670607218, + "y": -129.5150852641995, + "z": 0.0 + }, + { + "x": 324.63539630906223, + "y": -129.5146360261908, + "z": 0.0 + }, + { + "x": 323.62992555740266, + "y": -129.51418678818212, + "z": 0.0 + }, + { + "x": 322.6244548057431, + "y": -129.5137375501734, + "z": 0.0 + }, + { + "x": 321.6189840540835, + "y": -129.5132883121647, + "z": 0.0 + }, + { + "x": 320.61351330242394, + "y": -129.51283907415598, + "z": 0.0 + }, + { + "x": 319.60804255076437, + "y": -129.51238983614726, + "z": 0.0 + }, + { + "x": 318.6025717991048, + "y": -129.51194059813855, + "z": 0.0 + }, + { + "x": 317.5971010474452, + "y": -129.51149136012984, + "z": 0.0 + }, + { + "x": 316.59163029578565, + "y": -129.51104212212113, + "z": 0.0 + }, + { + "x": 315.58615954412596, + "y": -129.51059288411244, + "z": 0.0 + }, + { + "x": 314.5806887924665, + "y": -129.51014364610373, + "z": 0.0 + }, + { + "x": 313.57521804080693, + "y": -129.50969440809502, + "z": 0.0 + }, + { + "x": 312.56974728914736, + "y": -129.5092451700863, + "z": 0.0 + }, + { + "x": 311.5642765374878, + "y": -129.5087959320776, + "z": 0.0 + }, + { + "x": 310.5588057858282, + "y": -129.50834669406888, + "z": 0.0 + }, + { + "x": 309.55333503416864, + "y": -129.50789745606016, + "z": 0.0 + }, + { + "x": 308.54786428250895, + "y": -129.50744821805148, + "z": 0.0 + }, + { + "x": 307.5423935308495, + "y": -129.50699898004277, + "z": 0.0 + }, + { + "x": 306.5369227791899, + "y": -129.50654974203405, + "z": 0.0 + }, + { + "x": 305.53145202753035, + "y": -129.50610050402534, + "z": 0.0 + }, + { + "x": 304.5259812758708, + "y": -129.50565126601663, + "z": 0.0 + }, + { + "x": 303.5205105242111, + "y": -129.50520202800791, + "z": 0.0 + }, + { + "x": 302.5150397725515, + "y": -129.5047527899992, + "z": 0.0 + }, + { + "x": 301.50956902089195, + "y": -129.5043035519905, + "z": 0.0 + }, + { + "x": 300.5040982692324, + "y": -129.5038543139818, + "z": 0.0 + }, + { + "x": 299.4986275175728, + "y": -129.5034050759731, + "z": 0.0 + }, + { + "x": 298.4931567659132, + "y": -129.50295583796438, + "z": 0.0 + }, + { + "x": 297.48768601425365, + "y": -129.50250659995567, + "z": 0.0 + }, + { + "x": 296.4822152625941, + "y": -129.50205736194695, + "z": 0.0 + }, + { + "x": 295.4767445109345, + "y": -129.50160812393824, + "z": 0.0 + }, + { + "x": 294.47127375927494, + "y": -129.50115888592953, + "z": 0.0 + }, + { + "x": 293.46580300761536, + "y": -129.50070964792084, + "z": 0.0 + }, + { + "x": 292.4603322559558, + "y": -129.50026040991213, + "z": 0.0 + }, + { + "x": 291.4548615042962, + "y": -129.49981117190342, + "z": 0.0 + }, + { + "x": 290.44939075263665, + "y": -129.4993619338947, + "z": 0.0 + }, + { + "x": 289.4439200009771, + "y": -129.498912695886, + "z": 0.0 + }, + { + "x": 288.4384492493175, + "y": -129.49846345787728, + "z": 0.0 + }, + { + "x": 287.4329784976579, + "y": -129.49801421986857, + "z": 0.0 + }, + { + "x": 286.42750774599835, + "y": -129.49756498185985, + "z": 0.0 + }, + { + "x": 285.42203699433867, + "y": -129.49711574385117, + "z": 0.0 + }, + { + "x": 284.4165662426792, + "y": -129.49666650584246, + "z": 0.0 + }, + { + "x": 283.41109549101964, + "y": -129.49621726783374, + "z": 0.0 + }, + { + "x": 282.40562473936006, + "y": -129.49576802982503, + "z": 0.0 + }, + { + "x": 281.4001539877005, + "y": -129.49531879181632, + "z": 0.0 + }, + { + "x": 280.3946832360409, + "y": -129.4948695538076, + "z": 0.0 + }, + { + "x": 279.38921248438135, + "y": -129.4944203157989, + "z": 0.0 + }, + { + "x": 278.38374173272166, + "y": -129.4939710777902, + "z": 0.0 + }, + { + "x": 277.3782709810621, + "y": -129.4935218397815, + "z": 0.0 + }, + { + "x": 276.3728002294025, + "y": -129.49307260177278, + "z": 0.0 + }, + { + "x": 275.36732947774294, + "y": -129.49262336376407, + "z": 0.0 + }, + { + "x": 274.36185872608337, + "y": -129.49217412575535, + "z": 0.0 + }, + { + "x": 273.3563879744238, + "y": -129.49172488774664, + "z": 0.0 + }, + { + "x": 272.3509172227642, + "y": -129.49127564973793, + "z": 0.0 + }, + { + "x": 271.34544647110465, + "y": -129.49082641172922, + "z": 0.0 + }, + { + "x": 270.3399757194451, + "y": -129.49037717372053, + "z": 0.0 + }, + { + "x": 269.3345049677855, + "y": -129.48992793571182, + "z": 0.0 + }, + { + "x": 268.32903421612593, + "y": -129.4894786977031, + "z": 0.0 + }, + { + "x": 267.32356346446636, + "y": -129.4890294596944, + "z": 0.0 + }, + { + "x": 266.3180927128068, + "y": -129.48858022168568, + "z": 0.0 + }, + { + "x": 265.3126219611472, + "y": -129.48813098367697, + "z": 0.0 + }, + { + "x": 264.30715120948764, + "y": -129.48768174566825, + "z": 0.0 + }, + { + "x": 263.30168045782796, + "y": -129.48723250765957, + "z": 0.0 + }, + { + "x": 262.2962097061685, + "y": -129.48678326965086, + "z": 0.0 + }, + { + "x": 261.2907389545089, + "y": -129.48633403164214, + "z": 0.0 + }, + { + "x": 260.28526820284935, + "y": -129.48588479363343, + "z": 0.0 + }, + { + "x": 259.2797974511898, + "y": -129.48543555562472, + "z": 0.0 + }, + { + "x": 258.2743266995302, + "y": -129.484986317616, + "z": 0.0 + }, + { + "x": 257.26885594787063, + "y": -129.4845370796073, + "z": 0.0 + }, + { + "x": 256.26338519621106, + "y": -129.48408784159858, + "z": 0.0 + }, + { + "x": 255.2579144445514, + "y": -129.4836386035899, + "z": 0.0 + }, + { + "x": 254.2524436928919, + "y": -129.48318936558118, + "z": 0.0 + }, + { + "x": 253.24697294123231, + "y": -129.48274012757247, + "z": 0.0 + }, + { + "x": 252.2415021895727, + "y": -129.48229088956376, + "z": 0.0 + }, + { + "x": 251.23603143791314, + "y": -129.48184165155504, + "z": 0.0 + }, + { + "x": 250.23056068625357, + "y": -129.48139241354633, + "z": 0.0 + }, + { + "x": 249.225089934594, + "y": -129.48094317553762, + "z": 0.0 + }, + { + "x": 248.21961918293437, + "y": -129.48049393752893, + "z": 0.0 + }, + { + "x": 247.21414843127485, + "y": -129.48004469952022, + "z": 0.0 + }, + { + "x": 246.20867767961525, + "y": -129.4795954615115, + "z": 0.0 + }, + { + "x": 245.20320692795568, + "y": -129.4791462235028, + "z": 0.0 + }, + { + "x": 244.1977361762961, + "y": -129.47869698549408, + "z": 0.0 + }, + { + "x": 243.19226542463653, + "y": -129.47824774748537, + "z": 0.0 + }, + { + "x": 242.18679467297696, + "y": -129.47779850947666, + "z": 0.0 + }, + { + "x": 241.1813239213174, + "y": -129.47734927146794, + "z": 0.0 + }, + { + "x": 240.17585316965776, + "y": -129.47690003345926, + "z": 0.0 + }, + { + "x": 239.1703824179982, + "y": -129.47645079545055, + "z": 0.0 + }, + { + "x": 238.16491166633864, + "y": -129.47600155744183, + "z": 0.0 + }, + { + "x": 237.15944091467907, + "y": -129.47555231943312, + "z": 0.0 + }, + { + "x": 236.1539701630195, + "y": -129.4751030814244, + "z": 0.0 + }, + { + "x": 235.14849941135992, + "y": -129.4746538434157, + "z": 0.0 + }, + { + "x": 234.14302865970035, + "y": -129.47420460540698, + "z": 0.0 + }, + { + "x": 233.1375579080407, + "y": -129.4737553673983, + "z": 0.0 + }, + { + "x": 232.13208715638117, + "y": -129.47330612938958, + "z": 0.0 + }, + { + "x": 231.1266164047216, + "y": -129.47285689138087, + "z": 0.0 + }, + { + "x": 230.12114565306203, + "y": -129.47240765337216, + "z": 0.0 + }, + { + "x": 229.11567490140243, + "y": -129.47195841536345, + "z": 0.0 + }, + { + "x": 228.11020414974283, + "y": -129.47150917735473, + "z": 0.0 + }, + { + "x": 227.10473339808325, + "y": -129.47105993934602, + "z": 0.0 + }, + { + "x": 226.09926264642365, + "y": -129.4706107013373, + "z": 0.0 + }, + { + "x": 225.093791894764, + "y": -129.47016146332862, + "z": 0.0 + }, + { + "x": 224.08832114310448, + "y": -129.4697122253199, + "z": 0.0 + }, + { + "x": 223.08285039144488, + "y": -129.4692629873112, + "z": 0.0 + }, + { + "x": 222.0773796397853, + "y": -129.46881374930248, + "z": 0.0 + }, + { + "x": 221.0719088881257, + "y": -129.46836451129377, + "z": 0.0 + }, + { + "x": 220.0664381364661, + "y": -129.46791527328506, + "z": 0.0 + }, + { + "x": 219.06096738480653, + "y": -129.46746603527635, + "z": 0.0 + }, + { + "x": 218.05549663314687, + "y": -129.46701679726766, + "z": 0.0 + }, + { + "x": 217.05002588148733, + "y": -129.46656755925895, + "z": 0.0 + }, + { + "x": 216.04455512982776, + "y": -129.46611832125024, + "z": 0.0 + }, + { + "x": 215.03908437816816, + "y": -129.46566908324152, + "z": 0.0 + }, + { + "x": 214.03361362650855, + "y": -129.4652198452328, + "z": 0.0 + }, + { + "x": 213.02814287484898, + "y": -129.4647706072241, + "z": 0.0 + }, + { + "x": 212.02267212318938, + "y": -129.46432136921538, + "z": 0.0 + }, + { + "x": 211.01720137152978, + "y": -129.46387213120667, + "z": 0.0 + }, + { + "x": 210.01173061987015, + "y": -129.463422893198, + "z": 0.0 + }, + { + "x": 209.0062598682106, + "y": -129.46297365518927, + "z": 0.0 + }, + { + "x": 208.000789116551, + "y": -129.46252441718056, + "z": 0.0 + }, + { + "x": 206.99531836489143, + "y": -129.46207517917185, + "z": 0.0 + }, + { + "x": 205.98984761323183, + "y": -129.46162594116313, + "z": 0.0 + }, + { + "x": 204.98437686157223, + "y": -129.46117670315442, + "z": 0.0 + }, + { + "x": 203.97890610991266, + "y": -129.4607274651457, + "z": 0.0 + }, + { + "x": 202.973435358253, + "y": -129.46027822713702, + "z": 0.0 + }, + { + "x": 201.96796460659345, + "y": -129.4598289891283, + "z": 0.0 + }, + { + "x": 200.96249385493388, + "y": -129.4593797511196, + "z": 0.0 + }, + { + "x": 199.95702310327428, + "y": -129.4589305131109, + "z": 0.0 + }, + { + "x": 198.95155235161468, + "y": -129.45848127510217, + "z": 0.0 + }, + { + "x": 197.9460815999551, + "y": -129.45803203709346, + "z": 0.0 + }, + { + "x": 196.9406108482955, + "y": -129.45758279908475, + "z": 0.0 + }, + { + "x": 195.9351400966359, + "y": -129.45713356107603, + "z": 0.0 + }, + { + "x": 194.92966934497628, + "y": -129.45668432306735, + "z": 0.0 + }, + { + "x": 193.92419859331673, + "y": -129.45623508505864, + "z": 0.0 + }, + { + "x": 192.91872784165713, + "y": -129.45578584704992, + "z": 0.0 + }, + { + "x": 191.91325708999756, + "y": -129.4553366090412, + "z": 0.0 + }, + { + "x": 190.90778633833796, + "y": -129.4548873710325, + "z": 0.0 + }, + { + "x": 189.90231558667838, + "y": -129.45443813302379, + "z": 0.0 + }, + { + "x": 188.89684483501878, + "y": -129.45398889501507, + "z": 0.0 + }, + { + "x": 187.89137408335912, + "y": -129.4535396570064, + "z": 0.0 + }, + { + "x": 186.8859033316996, + "y": -129.45309041899768, + "z": 0.0 + }, + { + "x": 185.88043258004, + "y": -129.45264118098896, + "z": 0.0 + }, + { + "x": 184.8749618283804, + "y": -129.45219194298025, + "z": 0.0 + }, + { + "x": 183.86949107672083, + "y": -129.45174270497154, + "z": 0.0 + }, + { + "x": 182.86402032506123, + "y": -129.45129346696282, + "z": 0.0 + }, + { + "x": 181.85854957340163, + "y": -129.4508442289541, + "z": 0.0 + }, + { + "x": 180.85307882174206, + "y": -129.4503949909454, + "z": 0.0 + }, + { + "x": 179.8476080700824, + "y": -129.4499457529367, + "z": 0.0 + }, + { + "x": 178.84213731842286, + "y": -129.449496514928, + "z": 0.0 + }, + { + "x": 177.83666656676328, + "y": -129.4490472769193, + "z": 0.0 + }, + { + "x": 176.83119581510368, + "y": -129.44859803891057, + "z": 0.0 + }, + { + "x": 175.82572506344408, + "y": -129.44814880090186, + "z": 0.0 + }, + { + "x": 174.8202543117845, + "y": -129.44769956289315, + "z": 0.0 + }, + { + "x": 173.8147835601249, + "y": -129.44725032488444, + "z": 0.0 + }, + { + "x": 172.80931280846525, + "y": -129.44680108687575, + "z": 0.0 + }, + { + "x": 171.80384205680573, + "y": -129.44635184886704, + "z": 0.0 + }, + { + "x": 170.79837130514613, + "y": -129.44590261085833, + "z": 0.0 + }, + { + "x": 169.79290055348653, + "y": -129.4454533728496, + "z": 0.0 + }, + { + "x": 168.78742980182696, + "y": -129.4450041348409, + "z": 0.0 + }, + { + "x": 167.78195905016736, + "y": -129.4445548968322, + "z": 0.0 + }, + { + "x": 166.77648829850776, + "y": -129.44410565882347, + "z": 0.0 + }, + { + "x": 165.77101754684819, + "y": -129.44365642081476, + "z": 0.0 + }, + { + "x": 164.76554679518853, + "y": -129.44320718280608, + "z": 0.0 + }, + { + "x": 163.760076043529, + "y": -129.44275794479736, + "z": 0.0 + }, + { + "x": 162.7546052918694, + "y": -129.44230870678865, + "z": 0.0 + }, + { + "x": 161.74913454020984, + "y": -129.44185946877994, + "z": 0.0 + }, + { + "x": 160.74366378855026, + "y": -129.44141023077123, + "z": 0.0 + }, + { + "x": 159.73819303689066, + "y": -129.4409609927625, + "z": 0.0 + }, + { + "x": 158.7327222852311, + "y": -129.4405117547538, + "z": 0.0 + }, + { + "x": 157.72725153357143, + "y": -129.44006251674512, + "z": 0.0 + }, + { + "x": 156.72178078191192, + "y": -129.4396132787364, + "z": 0.0 + }, + { + "x": 155.71631003025234, + "y": -129.4391640407277, + "z": 0.0 + }, + { + "x": 154.71083927859274, + "y": -129.43871480271898, + "z": 0.0 + }, + { + "x": 153.70536852693317, + "y": -129.43826556471026, + "z": 0.0 + }, + { + "x": 152.69989777527357, + "y": -129.43781632670155, + "z": 0.0 + }, + { + "x": 151.694427023614, + "y": -129.43736708869284, + "z": 0.0 + }, + { + "x": 150.68895627195442, + "y": -129.43691785068413, + "z": 0.0 + }, + { + "x": 149.68348552029477, + "y": -129.43646861267544, + "z": 0.0 + }, + { + "x": 148.67801476863525, + "y": -129.43601937466673, + "z": 0.0 + }, + { + "x": 147.67254401697565, + "y": -129.43557013665801, + "z": 0.0 + }, + { + "x": 146.66707326531608, + "y": -129.4351208986493, + "z": 0.0 + }, + { + "x": 145.6616025136565, + "y": -129.4346716606406, + "z": 0.0 + }, + { + "x": 144.6561317619969, + "y": -129.43422242263188, + "z": 0.0 + }, + { + "x": 143.65066101033733, + "y": -129.43377318462316, + "z": 0.0 + }, + { + "x": 142.64519025867767, + "y": -129.43332394661448, + "z": 0.0 + }, + { + "x": 141.63971950701816, + "y": -129.43287470860577, + "z": 0.0 + }, + { + "x": 140.63424875535856, + "y": -129.43242547059705, + "z": 0.0 + }, + { + "x": 139.62877800369898, + "y": -129.43197623258834, + "z": 0.0 + }, + { + "x": 138.6233072520394, + "y": -129.43152699457963, + "z": 0.0 + }, + { + "x": 137.6178365003798, + "y": -129.43107775657091, + "z": 0.0 + }, + { + "x": 136.61236574872024, + "y": -129.4306285185622, + "z": 0.0 + }, + { + "x": 135.60689499706064, + "y": -129.4301792805535, + "z": 0.0 + }, + { + "x": 134.601424245401, + "y": -129.4297300425448, + "z": 0.0 + }, + { + "x": 133.5959534937415, + "y": -129.4292808045361, + "z": 0.0 + }, + { + "x": 132.5904827420819, + "y": -129.42883156652738, + "z": 0.0 + }, + { + "x": 131.58501199042232, + "y": -129.42838232851867, + "z": 0.0 + }, + { + "x": 130.57954123876272, + "y": -129.42793309050995, + "z": 0.0 + }, + { + "x": 129.57407048710314, + "y": -129.42748385250124, + "z": 0.0 + }, + { + "x": 128.56859973544354, + "y": -129.42703461449253, + "z": 0.0 + }, + { + "x": 127.56312898378388, + "y": -129.42658537648384, + "z": 0.0 + }, + { + "x": 126.55765823212437, + "y": -129.42613613847513, + "z": 0.0 + }, + { + "x": 125.55218748046477, + "y": -129.42568690046642, + "z": 0.0 + }, + { + "x": 124.5467167288052, + "y": -129.4252376624577, + "z": 0.0 + }, + { + "x": 123.54124597714559, + "y": -129.424788424449, + "z": 0.0 + }, + { + "x": 122.53577522548602, + "y": -129.42433918644028, + "z": 0.0 + }, + { + "x": 121.53030447382642, + "y": -129.42388994843157, + "z": 0.0 + }, + { + "x": 120.52483372216685, + "y": -129.42344071042285, + "z": 0.0 + }, + { + "x": 119.51936297050719, + "y": -129.42299147241417, + "z": 0.0 + }, + { + "x": 118.51389221884764, + "y": -129.42254223440546, + "z": 0.0 + }, + { + "x": 117.50842146718807, + "y": -129.42209299639674, + "z": 0.0 + }, + { + "x": 116.50295071552847, + "y": -129.42164375838803, + "z": 0.0 + }, + { + "x": 115.4974799638689, + "y": -129.42119452037932, + "z": 0.0 + }, + { + "x": 114.4920092122093, + "y": -129.4207452823706, + "z": 0.0 + }, + { + "x": 113.48653846054972, + "y": -129.4202960443619, + "z": 0.0 + }, + { + "x": 112.48106770889007, + "y": -129.4198468063532, + "z": 0.0 + }, + { + "x": 111.47559695723055, + "y": -129.4193975683445, + "z": 0.0 + }, + { + "x": 110.47012620557095, + "y": -129.41894833033578, + "z": 0.0 + }, + { + "x": 109.46465545391138, + "y": -129.41849909232707, + "z": 0.0 + }, + { + "x": 108.45918470225178, + "y": -129.41804985431835, + "z": 0.0 + }, + { + "x": 107.4537139505922, + "y": -129.41760061630964, + "z": 0.0 + }, + { + "x": 106.4482431989326, + "y": -129.41715137830093, + "z": 0.0 + }, + { + "x": 105.44277244727303, + "y": -129.41670214029222, + "z": 0.0 + }, + { + "x": 104.43730169561337, + "y": -129.41625290228353, + "z": 0.0 + }, + { + "x": 103.43183094395386, + "y": -129.41580366427482, + "z": 0.0 + }, + { + "x": 102.42636019229425, + "y": -129.4153544262661, + "z": 0.0 + }, + { + "x": 101.42088944063468, + "y": -129.4149051882574, + "z": 0.0 + } + ] + }, + { + "id": 24, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 101.41910226596795, + "y": -133.4149047890082, + "z": 0.0 + }, + { + "x": 102.42457301762755, + "y": -133.41535402701692, + "z": 0.0 + }, + { + "x": 103.43004376928712, + "y": -133.41580326502563, + "z": 0.0 + }, + { + "x": 104.43551452094678, + "y": -133.41625250303434, + "z": 0.0 + }, + { + "x": 105.4409852726063, + "y": -133.41670174104303, + "z": 0.0 + }, + { + "x": 106.4464560242659, + "y": -133.41715097905174, + "z": 0.0 + }, + { + "x": 107.45192677592547, + "y": -133.41760021706045, + "z": 0.0 + }, + { + "x": 108.45739752758507, + "y": -133.41804945506917, + "z": 0.0 + }, + { + "x": 109.46286827924465, + "y": -133.41849869307788, + "z": 0.0 + }, + { + "x": 110.46833903090425, + "y": -133.4189479310866, + "z": 0.0 + }, + { + "x": 111.47380978256382, + "y": -133.4193971690953, + "z": 0.0 + }, + { + "x": 112.47928053422348, + "y": -133.41984640710402, + "z": 0.0 + }, + { + "x": 113.484751285883, + "y": -133.4202956451127, + "z": 0.0 + }, + { + "x": 114.4902220375426, + "y": -133.42074488312142, + "z": 0.0 + }, + { + "x": 115.49569278920217, + "y": -133.42119412113013, + "z": 0.0 + }, + { + "x": 116.50116354086177, + "y": -133.42164335913884, + "z": 0.0 + }, + { + "x": 117.50663429252134, + "y": -133.42209259714755, + "z": 0.0 + }, + { + "x": 118.51210504418094, + "y": -133.42254183515627, + "z": 0.0 + }, + { + "x": 119.51757579584057, + "y": -133.42299107316498, + "z": 0.0 + }, + { + "x": 120.52304654750012, + "y": -133.42344031117366, + "z": 0.0 + }, + { + "x": 121.52851729915972, + "y": -133.42388954918238, + "z": 0.0 + }, + { + "x": 122.53398805081929, + "y": -133.4243387871911, + "z": 0.0 + }, + { + "x": 123.53945880247889, + "y": -133.4247880251998, + "z": 0.0 + }, + { + "x": 124.54492955413846, + "y": -133.42523726320852, + "z": 0.0 + }, + { + "x": 125.55040030579806, + "y": -133.42568650121723, + "z": 0.0 + }, + { + "x": 126.55587105745764, + "y": -133.42613573922594, + "z": 0.0 + }, + { + "x": 127.5613418091173, + "y": -133.42658497723465, + "z": 0.0 + }, + { + "x": 128.5668125607768, + "y": -133.42703421524334, + "z": 0.0 + }, + { + "x": 129.5722833124364, + "y": -133.42748345325205, + "z": 0.0 + }, + { + "x": 130.57775406409598, + "y": -133.42793269126076, + "z": 0.0 + }, + { + "x": 131.58322481575559, + "y": -133.42838192926948, + "z": 0.0 + }, + { + "x": 132.58869556741516, + "y": -133.4288311672782, + "z": 0.0 + }, + { + "x": 133.59416631907476, + "y": -133.4292804052869, + "z": 0.0 + }, + { + "x": 134.5996370707344, + "y": -133.42972964329562, + "z": 0.0 + }, + { + "x": 135.6051078223939, + "y": -133.4301788813043, + "z": 0.0 + }, + { + "x": 136.6105785740535, + "y": -133.430628119313, + "z": 0.0 + }, + { + "x": 137.61604932571308, + "y": -133.43107735732173, + "z": 0.0 + }, + { + "x": 138.62152007737268, + "y": -133.43152659533044, + "z": 0.0 + }, + { + "x": 139.62699082903225, + "y": -133.43197583333915, + "z": 0.0 + }, + { + "x": 140.63246158069182, + "y": -133.43242507134786, + "z": 0.0 + }, + { + "x": 141.63793233235143, + "y": -133.43287430935658, + "z": 0.0 + }, + { + "x": 142.64340308401106, + "y": -133.4333235473653, + "z": 0.0 + }, + { + "x": 143.6488738356706, + "y": -133.43377278537398, + "z": 0.0 + }, + { + "x": 144.65434458733017, + "y": -133.4342220233827, + "z": 0.0 + }, + { + "x": 145.65981533898977, + "y": -133.4346712613914, + "z": 0.0 + }, + { + "x": 146.66528609064935, + "y": -133.4351204994001, + "z": 0.0 + }, + { + "x": 147.67075684230892, + "y": -133.43556973740883, + "z": 0.0 + }, + { + "x": 148.67622759396852, + "y": -133.43601897541754, + "z": 0.0 + }, + { + "x": 149.68169834562815, + "y": -133.43646821342625, + "z": 0.0 + }, + { + "x": 150.6871690972877, + "y": -133.43691745143494, + "z": 0.0 + }, + { + "x": 151.69263984894727, + "y": -133.43736668944365, + "z": 0.0 + }, + { + "x": 152.69811060060684, + "y": -133.43781592745236, + "z": 0.0 + }, + { + "x": 153.70358135226644, + "y": -133.43826516546108, + "z": 0.0 + }, + { + "x": 154.709052103926, + "y": -133.4387144034698, + "z": 0.0 + }, + { + "x": 155.7145228555856, + "y": -133.4391636414785, + "z": 0.0 + }, + { + "x": 156.7199936072452, + "y": -133.4396128794872, + "z": 0.0 + }, + { + "x": 157.72546435890482, + "y": -133.44006211749593, + "z": 0.0 + }, + { + "x": 158.73093511056436, + "y": -133.4405113555046, + "z": 0.0 + }, + { + "x": 159.73640586222393, + "y": -133.44096059351332, + "z": 0.0 + }, + { + "x": 160.74187661388353, + "y": -133.44140983152204, + "z": 0.0 + }, + { + "x": 161.7473473655431, + "y": -133.44185906953075, + "z": 0.0 + }, + { + "x": 162.75281811720268, + "y": -133.44230830753946, + "z": 0.0 + }, + { + "x": 163.75828886886228, + "y": -133.44275754554818, + "z": 0.0 + }, + { + "x": 164.7637596205219, + "y": -133.4432067835569, + "z": 0.0 + }, + { + "x": 165.76923037218145, + "y": -133.44365602156557, + "z": 0.0 + }, + { + "x": 166.77470112384103, + "y": -133.4441052595743, + "z": 0.0 + }, + { + "x": 167.78017187550063, + "y": -133.444554497583, + "z": 0.0 + }, + { + "x": 168.78564262716023, + "y": -133.4450037355917, + "z": 0.0 + }, + { + "x": 169.7911133788198, + "y": -133.44545297360042, + "z": 0.0 + }, + { + "x": 170.7965841304794, + "y": -133.44590221160914, + "z": 0.0 + }, + { + "x": 171.802054882139, + "y": -133.44635144961785, + "z": 0.0 + }, + { + "x": 172.80752563379863, + "y": -133.44680068762656, + "z": 0.0 + }, + { + "x": 173.81299638545818, + "y": -133.44724992563525, + "z": 0.0 + }, + { + "x": 174.81846713711778, + "y": -133.44769916364396, + "z": 0.0 + }, + { + "x": 175.82393788877735, + "y": -133.44814840165267, + "z": 0.0 + }, + { + "x": 176.82940864043695, + "y": -133.4485976396614, + "z": 0.0 + }, + { + "x": 177.83487939209655, + "y": -133.4490468776701, + "z": 0.0 + }, + { + "x": 178.84035014375613, + "y": -133.4494961156788, + "z": 0.0 + }, + { + "x": 179.84582089541578, + "y": -133.44994535368753, + "z": 0.0 + }, + { + "x": 180.85129164707533, + "y": -133.4503945916962, + "z": 0.0 + }, + { + "x": 181.8567623987349, + "y": -133.45084382970492, + "z": 0.0 + }, + { + "x": 182.8622331503945, + "y": -133.45129306771364, + "z": 0.0 + }, + { + "x": 183.8677039020541, + "y": -133.45174230572235, + "z": 0.0 + }, + { + "x": 184.87317465371368, + "y": -133.45219154373106, + "z": 0.0 + }, + { + "x": 185.87864540537328, + "y": -133.45264078173977, + "z": 0.0 + }, + { + "x": 186.88411615703288, + "y": -133.4530900197485, + "z": 0.0 + }, + { + "x": 187.8895869086925, + "y": -133.4535392577572, + "z": 0.0 + }, + { + "x": 188.89505766035205, + "y": -133.45398849576588, + "z": 0.0 + }, + { + "x": 189.90052841201165, + "y": -133.4544377337746, + "z": 0.0 + }, + { + "x": 190.90599916367123, + "y": -133.4548869717833, + "z": 0.0 + }, + { + "x": 191.91146991533083, + "y": -133.45533620979202, + "z": 0.0 + }, + { + "x": 192.9169406669904, + "y": -133.45578544780074, + "z": 0.0 + }, + { + "x": 193.92241141865, + "y": -133.45623468580945, + "z": 0.0 + }, + { + "x": 194.92788217030966, + "y": -133.45668392381816, + "z": 0.0 + }, + { + "x": 195.93335292196917, + "y": -133.45713316182685, + "z": 0.0 + }, + { + "x": 196.93882367362878, + "y": -133.45758239983556, + "z": 0.0 + }, + { + "x": 197.94429442528838, + "y": -133.45803163784427, + "z": 0.0 + }, + { + "x": 198.94976517694795, + "y": -133.45848087585298, + "z": 0.0 + }, + { + "x": 199.95523592860755, + "y": -133.4589301138617, + "z": 0.0 + }, + { + "x": 200.96070668026715, + "y": -133.4593793518704, + "z": 0.0 + }, + { + "x": 201.96617743192672, + "y": -133.45982858987912, + "z": 0.0 + }, + { + "x": 202.97164818358638, + "y": -133.46027782788784, + "z": 0.0 + }, + { + "x": 203.97711893524593, + "y": -133.46072706589652, + "z": 0.0 + }, + { + "x": 204.9825896869055, + "y": -133.46117630390523, + "z": 0.0 + }, + { + "x": 205.9880604385651, + "y": -133.46162554191395, + "z": 0.0 + }, + { + "x": 206.9935311902247, + "y": -133.46207477992266, + "z": 0.0 + }, + { + "x": 207.99900194188427, + "y": -133.46252401793137, + "z": 0.0 + }, + { + "x": 209.00447269354387, + "y": -133.46297325594008, + "z": 0.0 + }, + { + "x": 210.00994344520353, + "y": -133.4634224939488, + "z": 0.0 + }, + { + "x": 211.01541419686305, + "y": -133.46387173195748, + "z": 0.0 + }, + { + "x": 212.02088494852265, + "y": -133.4643209699662, + "z": 0.0 + }, + { + "x": 213.02635570018225, + "y": -133.4647702079749, + "z": 0.0 + }, + { + "x": 214.03182645184182, + "y": -133.46521944598362, + "z": 0.0 + }, + { + "x": 215.03729720350142, + "y": -133.46566868399233, + "z": 0.0 + }, + { + "x": 216.04276795516103, + "y": -133.46611792200105, + "z": 0.0 + }, + { + "x": 217.0482387068206, + "y": -133.46656716000976, + "z": 0.0 + }, + { + "x": 218.05370945848026, + "y": -133.46701639801847, + "z": 0.0 + }, + { + "x": 219.0591802101398, + "y": -133.46746563602716, + "z": 0.0 + }, + { + "x": 220.06465096179937, + "y": -133.46791487403587, + "z": 0.0 + }, + { + "x": 221.07012171345897, + "y": -133.46836411204458, + "z": 0.0 + }, + { + "x": 222.07559246511858, + "y": -133.4688133500533, + "z": 0.0 + }, + { + "x": 223.08106321677815, + "y": -133.469262588062, + "z": 0.0 + }, + { + "x": 224.08653396843775, + "y": -133.46971182607072, + "z": 0.0 + }, + { + "x": 225.09200472009738, + "y": -133.47016106407943, + "z": 0.0 + }, + { + "x": 226.09747547175692, + "y": -133.47061030208812, + "z": 0.0 + }, + { + "x": 227.10294622341652, + "y": -133.47105954009683, + "z": 0.0 + }, + { + "x": 228.1084169750761, + "y": -133.47150877810554, + "z": 0.0 + }, + { + "x": 229.1138877267357, + "y": -133.47195801611426, + "z": 0.0 + }, + { + "x": 230.1193584783953, + "y": -133.47240725412297, + "z": 0.0 + }, + { + "x": 231.12482923005487, + "y": -133.47285649213168, + "z": 0.0 + }, + { + "x": 232.13029998171444, + "y": -133.4733057301404, + "z": 0.0 + }, + { + "x": 233.13577073337407, + "y": -133.4737549681491, + "z": 0.0 + }, + { + "x": 234.14124148503362, + "y": -133.4742042061578, + "z": 0.0 + }, + { + "x": 235.1467122366932, + "y": -133.4746534441665, + "z": 0.0 + }, + { + "x": 236.15218298835276, + "y": -133.47510268217522, + "z": 0.0 + }, + { + "x": 237.15765374001234, + "y": -133.47555192018393, + "z": 0.0 + }, + { + "x": 238.1631244916719, + "y": -133.47600115819264, + "z": 0.0 + }, + { + "x": 239.16859524333148, + "y": -133.47645039620136, + "z": 0.0 + }, + { + "x": 240.17406599499114, + "y": -133.47689963421007, + "z": 0.0 + }, + { + "x": 241.17953674665065, + "y": -133.47734887221876, + "z": 0.0 + }, + { + "x": 242.18500749831023, + "y": -133.47779811022747, + "z": 0.0 + }, + { + "x": 243.1904782499698, + "y": -133.47824734823618, + "z": 0.0 + }, + { + "x": 244.19594900162937, + "y": -133.4786965862449, + "z": 0.0 + }, + { + "x": 245.20141975328895, + "y": -133.4791458242536, + "z": 0.0 + }, + { + "x": 246.20689050494852, + "y": -133.47959506226232, + "z": 0.0 + }, + { + "x": 247.21236125660812, + "y": -133.48004430027103, + "z": 0.0 + }, + { + "x": 248.21783200826775, + "y": -133.48049353827975, + "z": 0.0 + }, + { + "x": 249.22330275992726, + "y": -133.48094277628843, + "z": 0.0 + }, + { + "x": 250.22877351158684, + "y": -133.48139201429714, + "z": 0.0 + }, + { + "x": 251.2342442632464, + "y": -133.48184125230586, + "z": 0.0 + }, + { + "x": 252.23971501490598, + "y": -133.48229049031457, + "z": 0.0 + }, + { + "x": 253.24518576656558, + "y": -133.48273972832328, + "z": 0.0 + }, + { + "x": 254.25065651822516, + "y": -133.483188966332, + "z": 0.0 + }, + { + "x": 255.2561272698848, + "y": -133.4836382043407, + "z": 0.0 + }, + { + "x": 256.2615980215443, + "y": -133.4840874423494, + "z": 0.0 + }, + { + "x": 257.26706877320385, + "y": -133.4845366803581, + "z": 0.0 + }, + { + "x": 258.2725395248634, + "y": -133.48498591836682, + "z": 0.0 + }, + { + "x": 259.278010276523, + "y": -133.48543515637553, + "z": 0.0 + }, + { + "x": 260.28348102818256, + "y": -133.48588439438424, + "z": 0.0 + }, + { + "x": 261.28895177984214, + "y": -133.48633363239296, + "z": 0.0 + }, + { + "x": 262.2944225315017, + "y": -133.48678287040167, + "z": 0.0 + }, + { + "x": 263.2998932831614, + "y": -133.48723210841038, + "z": 0.0 + }, + { + "x": 264.30536403482085, + "y": -133.48768134641907, + "z": 0.0 + }, + { + "x": 265.3108347864804, + "y": -133.48813058442778, + "z": 0.0 + }, + { + "x": 266.3163055381401, + "y": -133.4885798224365, + "z": 0.0 + }, + { + "x": 267.3217762897997, + "y": -133.4890290604452, + "z": 0.0 + }, + { + "x": 268.32724704145926, + "y": -133.48947829845392, + "z": 0.0 + }, + { + "x": 269.33271779311883, + "y": -133.48992753646263, + "z": 0.0 + }, + { + "x": 270.3381885447784, + "y": -133.49037677447134, + "z": 0.0 + }, + { + "x": 271.343659296438, + "y": -133.49082601248003, + "z": 0.0 + }, + { + "x": 272.34913004809755, + "y": -133.49127525048874, + "z": 0.0 + }, + { + "x": 273.3546007997571, + "y": -133.49172448849745, + "z": 0.0 + }, + { + "x": 274.3600715514167, + "y": -133.49217372650617, + "z": 0.0 + }, + { + "x": 275.36554230307627, + "y": -133.49262296451488, + "z": 0.0 + }, + { + "x": 276.37101305473584, + "y": -133.4930722025236, + "z": 0.0 + }, + { + "x": 277.3764838063954, + "y": -133.4935214405323, + "z": 0.0 + }, + { + "x": 278.3819545580551, + "y": -133.49397067854102, + "z": 0.0 + }, + { + "x": 279.38742530971456, + "y": -133.4944199165497, + "z": 0.0 + }, + { + "x": 280.39289606137413, + "y": -133.49486915455842, + "z": 0.0 + }, + { + "x": 281.3983668130337, + "y": -133.49531839256713, + "z": 0.0 + }, + { + "x": 282.4038375646933, + "y": -133.49576763057584, + "z": 0.0 + }, + { + "x": 283.40930831635285, + "y": -133.49621686858455, + "z": 0.0 + }, + { + "x": 284.4147790680124, + "y": -133.49666610659327, + "z": 0.0 + }, + { + "x": 285.4202498196721, + "y": -133.49711534460198, + "z": 0.0 + }, + { + "x": 286.42572057133157, + "y": -133.49756458261066, + "z": 0.0 + }, + { + "x": 287.43119132299114, + "y": -133.49801382061938, + "z": 0.0 + }, + { + "x": 288.4366620746507, + "y": -133.4984630586281, + "z": 0.0 + }, + { + "x": 289.4421328263103, + "y": -133.4989122966368, + "z": 0.0 + }, + { + "x": 290.44760357796986, + "y": -133.49936153464552, + "z": 0.0 + }, + { + "x": 291.45307432962954, + "y": -133.49981077265423, + "z": 0.0 + }, + { + "x": 292.4585450812891, + "y": -133.50026001066294, + "z": 0.0 + }, + { + "x": 293.4640158329487, + "y": -133.50070924867165, + "z": 0.0 + }, + { + "x": 294.46948658460826, + "y": -133.50115848668034, + "z": 0.0 + }, + { + "x": 295.47495733626783, + "y": -133.50160772468905, + "z": 0.0 + }, + { + "x": 296.4804280879274, + "y": -133.50205696269776, + "z": 0.0 + }, + { + "x": 297.485898839587, + "y": -133.50250620070648, + "z": 0.0 + }, + { + "x": 298.49136959124655, + "y": -133.5029554387152, + "z": 0.0 + }, + { + "x": 299.4968403429061, + "y": -133.5034046767239, + "z": 0.0 + }, + { + "x": 300.5023110945657, + "y": -133.50385391473262, + "z": 0.0 + }, + { + "x": 301.50778184622527, + "y": -133.5043031527413, + "z": 0.0 + }, + { + "x": 302.51325259788484, + "y": -133.50475239075, + "z": 0.0 + }, + { + "x": 303.5187233495444, + "y": -133.50520162875873, + "z": 0.0 + }, + { + "x": 304.524194101204, + "y": -133.50565086676744, + "z": 0.0 + }, + { + "x": 305.52966485286356, + "y": -133.50610010477615, + "z": 0.0 + }, + { + "x": 306.53513560452313, + "y": -133.50654934278487, + "z": 0.0 + }, + { + "x": 307.5406063561827, + "y": -133.50699858079358, + "z": 0.0 + }, + { + "x": 308.5460771078424, + "y": -133.5074478188023, + "z": 0.0 + }, + { + "x": 309.55154785950185, + "y": -133.50789705681098, + "z": 0.0 + }, + { + "x": 310.5570186111614, + "y": -133.5083462948197, + "z": 0.0 + }, + { + "x": 311.562489362821, + "y": -133.5087955328284, + "z": 0.0 + }, + { + "x": 312.56796011448057, + "y": -133.5092447708371, + "z": 0.0 + }, + { + "x": 313.57343086614014, + "y": -133.50969400884583, + "z": 0.0 + }, + { + "x": 314.5789016177997, + "y": -133.51014324685454, + "z": 0.0 + }, + { + "x": 315.5843723694594, + "y": -133.51059248486325, + "z": 0.0 + }, + { + "x": 316.58984312111886, + "y": -133.51104172287194, + "z": 0.0 + }, + { + "x": 317.59531387277855, + "y": -133.51149096088065, + "z": 0.0 + }, + { + "x": 318.6007846244381, + "y": -133.51194019888936, + "z": 0.0 + }, + { + "x": 319.6062553760977, + "y": -133.51238943689808, + "z": 0.0 + }, + { + "x": 320.61172612775727, + "y": -133.5128386749068, + "z": 0.0 + }, + { + "x": 321.61719687941684, + "y": -133.5132879129155, + "z": 0.0 + }, + { + "x": 322.6226676310764, + "y": -133.51373715092421, + "z": 0.0 + }, + { + "x": 323.628138382736, + "y": -133.51418638893293, + "z": 0.0 + }, + { + "x": 324.63360913439556, + "y": -133.5146356269416, + "z": 0.0 + }, + { + "x": 325.63907988605513, + "y": -133.51508486495032, + "z": 0.0 + } + ] + }, + { + "id": 25, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 79.64213303769317, + "y": -324.57727938928275, + "z": 0.0 + }, + { + "x": 78.6330027477079, + "y": -324.5767387981524, + "z": 0.0 + }, + { + "x": 77.62387245772217, + "y": -324.5761982070222, + "z": 0.0 + }, + { + "x": 76.61474216773736, + "y": -324.5756576158918, + "z": 0.0 + }, + { + "x": 75.60561187775163, + "y": -324.5751170247616, + "z": 0.0 + }, + { + "x": 74.59648158776682, + "y": -324.57457643363125, + "z": 0.0 + }, + { + "x": 73.58735129778131, + "y": -324.57403584250096, + "z": 0.0 + }, + { + "x": 72.57822100779582, + "y": -324.57349525137073, + "z": 0.0 + }, + { + "x": 71.569090717811, + "y": -324.5729546602404, + "z": 0.0 + }, + { + "x": 70.5599604278255, + "y": -324.5724140691101, + "z": 0.0 + }, + { + "x": 69.55083013784022, + "y": -324.5718734779798, + "z": 0.0 + }, + { + "x": 68.54169984785494, + "y": -324.5713328868495, + "z": 0.0 + }, + { + "x": 67.53256955786968, + "y": -324.57079229571923, + "z": 0.0 + }, + { + "x": 66.5234392678844, + "y": -324.57025170458894, + "z": 0.0 + }, + { + "x": 65.51430897789913, + "y": -324.56971111345865, + "z": 0.0 + }, + { + "x": 64.50517868791385, + "y": -324.56917052232836, + "z": 0.0 + }, + { + "x": 63.496048397928575, + "y": -324.5686299311981, + "z": 0.0 + }, + { + "x": 62.486918107943296, + "y": -324.5680893400678, + "z": 0.0 + }, + { + "x": 61.477787817958024, + "y": -324.5675487489375, + "z": 0.0 + }, + { + "x": 60.468657527972745, + "y": -324.5670081578072, + "z": 0.0 + }, + { + "x": 59.45952723798747, + "y": -324.5664675666769, + "z": 0.0 + }, + { + "x": 58.450396948002194, + "y": -324.56592697554663, + "z": 0.0 + }, + { + "x": 57.441266658016914, + "y": -324.56538638441634, + "z": 0.0 + }, + { + "x": 56.43213636803164, + "y": -324.56484579328605, + "z": 0.0 + }, + { + "x": 55.42300607804658, + "y": -324.5643052021557, + "z": 0.0 + }, + { + "x": 54.41387578806109, + "y": -324.5637646110254, + "z": 0.0 + }, + { + "x": 53.404745498075584, + "y": -324.5632240198952, + "z": 0.0 + }, + { + "x": 52.39561520809054, + "y": -324.5626834287649, + "z": 0.0 + }, + { + "x": 51.38648491810525, + "y": -324.5621428376346, + "z": 0.0 + }, + { + "x": 50.37735462812019, + "y": -324.56160224650426, + "z": 0.0 + }, + { + "x": 49.368224338134695, + "y": -324.561061655374, + "z": 0.0 + }, + { + "x": 48.35909404814919, + "y": -324.56052106424374, + "z": 0.0 + }, + { + "x": 47.349963758164144, + "y": -324.55998047311346, + "z": 0.0 + }, + { + "x": 46.340833468179085, + "y": -324.5594398819831, + "z": 0.0 + }, + { + "x": 45.33170317819359, + "y": -324.5588992908528, + "z": 0.0 + }, + { + "x": 44.32257288820831, + "y": -324.55835869972253, + "z": 0.0 + }, + { + "x": 43.31344259822304, + "y": -324.55781810859224, + "z": 0.0 + }, + { + "x": 42.30431230823776, + "y": -324.55727751746196, + "z": 0.0 + }, + { + "x": 41.29518201825249, + "y": -324.55673692633167, + "z": 0.0 + }, + { + "x": 40.28605172826721, + "y": -324.5561963352014, + "z": 0.0 + }, + { + "x": 39.27692143828194, + "y": -324.5556557440711, + "z": 0.0 + }, + { + "x": 38.26779114829666, + "y": -324.5551151529408, + "z": 0.0 + }, + { + "x": 37.25866085831138, + "y": -324.5545745618105, + "z": 0.0 + }, + { + "x": 36.24953056832611, + "y": -324.5540339706802, + "z": 0.0 + }, + { + "x": 35.24040027834083, + "y": -324.55349337954993, + "z": 0.0 + }, + { + "x": 34.23126998835556, + "y": -324.55295278841965, + "z": 0.0 + }, + { + "x": 33.22213969837028, + "y": -324.55241219728936, + "z": 0.0 + }, + { + "x": 32.213009408385, + "y": -324.55187160615907, + "z": 0.0 + }, + { + "x": 31.203879118399723, + "y": -324.5513310150288, + "z": 0.0 + }, + { + "x": 30.19474882841467, + "y": -324.55079042389843, + "z": 0.0 + }, + { + "x": 29.185618538428944, + "y": -324.5502498327682, + "z": 0.0 + }, + { + "x": 28.176488248443892, + "y": -324.5497092416379, + "z": 0.0 + }, + { + "x": 27.167357958458613, + "y": -324.5491686505076, + "z": 0.0 + }, + { + "x": 26.158227668473337, + "y": -324.54862805937734, + "z": 0.0 + }, + { + "x": 25.14909737848829, + "y": -324.548087468247, + "z": 0.0 + }, + { + "x": 24.139967088502562, + "y": -324.54754687711676, + "z": 0.0 + }, + { + "x": 23.130836798517738, + "y": -324.5470062859864, + "z": 0.0 + }, + { + "x": 22.121706508532235, + "y": -324.5464656948561, + "z": 0.0 + }, + { + "x": 21.11257621854673, + "y": -324.5459251037259, + "z": 0.0 + }, + { + "x": 20.103445928561907, + "y": -324.54538451259555, + "z": 0.0 + }, + { + "x": 19.094315638576404, + "y": -324.54484392146526, + "z": 0.0 + }, + { + "x": 18.08518534859113, + "y": -324.54430333033497, + "z": 0.0 + }, + { + "x": 17.076055058605853, + "y": -324.5437627392047, + "z": 0.0 + }, + { + "x": 16.06692476862035, + "y": -324.54322214807445, + "z": 0.0 + }, + { + "x": 15.057794478635525, + "y": -324.5426815569441, + "z": 0.0 + }, + { + "x": 14.048664188650024, + "y": -324.5421409658138, + "z": 0.0 + }, + { + "x": 13.039533898664747, + "y": -324.5416003746835, + "z": 0.0 + }, + { + "x": 12.030403608679471, + "y": -324.54105978355324, + "z": 0.0 + }, + { + "x": 11.021273318694194, + "y": -324.54051919242295, + "z": 0.0 + }, + { + "x": 10.012143028708918, + "y": -324.53997860129266, + "z": 0.0 + } + ] + }, + { + "id": 26, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 10.007857429054754, + "y": -332.53997745339484, + "z": 0.0 + }, + { + "x": 11.01698771904003, + "y": -332.54051804452513, + "z": 0.0 + }, + { + "x": 12.026118009025307, + "y": -332.5410586356554, + "z": 0.0 + }, + { + "x": 13.035248299010583, + "y": -332.5415992267857, + "z": 0.0 + }, + { + "x": 14.04437858899586, + "y": -332.542139817916, + "z": 0.0 + }, + { + "x": 15.05350887898091, + "y": -332.5426804090463, + "z": 0.0 + }, + { + "x": 16.062639168966637, + "y": -332.54322100017663, + "z": 0.0 + }, + { + "x": 17.071769458951692, + "y": -332.54376159130686, + "z": 0.0 + }, + { + "x": 18.080899748936968, + "y": -332.54430218243715, + "z": 0.0 + }, + { + "x": 19.090030038922244, + "y": -332.54484277356744, + "z": 0.0 + }, + { + "x": 20.099160328907292, + "y": -332.5453833646977, + "z": 0.0 + }, + { + "x": 21.10829061889302, + "y": -332.5459239558281, + "z": 0.0 + }, + { + "x": 22.117420908878074, + "y": -332.5464645469583, + "z": 0.0 + }, + { + "x": 23.126551198863122, + "y": -332.5470051380886, + "z": 0.0 + }, + { + "x": 24.13568148884885, + "y": -332.54754572921894, + "z": 0.0 + }, + { + "x": 25.144811778833674, + "y": -332.54808632034917, + "z": 0.0 + }, + { + "x": 26.153942068819177, + "y": -332.5486269114795, + "z": 0.0 + }, + { + "x": 27.163072358804452, + "y": -332.5491675026098, + "z": 0.0 + }, + { + "x": 28.17220264878973, + "y": -332.5497080937401, + "z": 0.0 + }, + { + "x": 29.18133293877523, + "y": -332.5502486848704, + "z": 0.0 + }, + { + "x": 30.190463228760056, + "y": -332.5507892760006, + "z": 0.0 + }, + { + "x": 31.199593518745562, + "y": -332.55132986713096, + "z": 0.0 + }, + { + "x": 32.20872380873083, + "y": -332.55187045826125, + "z": 0.0 + }, + { + "x": 33.21785409871611, + "y": -332.55241104939154, + "z": 0.0 + }, + { + "x": 34.22698438870139, + "y": -332.5529516405218, + "z": 0.0 + }, + { + "x": 35.23611467868666, + "y": -332.5534922316521, + "z": 0.0 + }, + { + "x": 36.24524496867194, + "y": -332.5540328227824, + "z": 0.0 + }, + { + "x": 37.25437525865721, + "y": -332.5545734139127, + "z": 0.0 + }, + { + "x": 38.26350554864249, + "y": -332.555114005043, + "z": 0.0 + }, + { + "x": 39.27263583862777, + "y": -332.55565459617327, + "z": 0.0 + }, + { + "x": 40.28176612861304, + "y": -332.55619518730356, + "z": 0.0 + }, + { + "x": 41.29089641859832, + "y": -332.55673577843385, + "z": 0.0 + }, + { + "x": 42.300026708583594, + "y": -332.55727636956414, + "z": 0.0 + }, + { + "x": 43.309156998568874, + "y": -332.5578169606944, + "z": 0.0 + }, + { + "x": 44.318287288554146, + "y": -332.5583575518247, + "z": 0.0 + }, + { + "x": 45.327417578539425, + "y": -332.558898142955, + "z": 0.0 + }, + { + "x": 46.33654786852448, + "y": -332.5594387340853, + "z": 0.0 + }, + { + "x": 47.345678158509976, + "y": -332.55997932521564, + "z": 0.0 + }, + { + "x": 48.354808448495476, + "y": -332.5605199163459, + "z": 0.0 + }, + { + "x": 49.36393873848053, + "y": -332.56106050747616, + "z": 0.0 + }, + { + "x": 50.37306902846558, + "y": -332.56160109860645, + "z": 0.0 + }, + { + "x": 51.382199318451086, + "y": -332.5621416897368, + "z": 0.0 + }, + { + "x": 52.39132960843637, + "y": -332.5626822808671, + "z": 0.0 + }, + { + "x": 53.40045989842187, + "y": -332.56322287199737, + "z": 0.0 + }, + { + "x": 54.40959018840692, + "y": -332.5637634631276, + "z": 0.0 + }, + { + "x": 55.418720478391975, + "y": -332.5643040542579, + "z": 0.0 + }, + { + "x": 56.427850768377475, + "y": -332.56484464538823, + "z": 0.0 + }, + { + "x": 57.43698105836275, + "y": -332.5653852365185, + "z": 0.0 + }, + { + "x": 58.446111348348026, + "y": -332.5659258276488, + "z": 0.0 + }, + { + "x": 59.455241638333305, + "y": -332.5664664187791, + "z": 0.0 + }, + { + "x": 60.46437192831858, + "y": -332.5670070099094, + "z": 0.0 + }, + { + "x": 61.47350221830386, + "y": -332.5675476010397, + "z": 0.0 + }, + { + "x": 62.48263250828913, + "y": -332.56808819216997, + "z": 0.0 + }, + { + "x": 63.49176279827441, + "y": -332.56862878330026, + "z": 0.0 + }, + { + "x": 64.50089308825969, + "y": -332.56916937443054, + "z": 0.0 + }, + { + "x": 65.51002337824497, + "y": -332.56970996556083, + "z": 0.0 + }, + { + "x": 66.51915366823023, + "y": -332.5702505566911, + "z": 0.0 + }, + { + "x": 67.52828395821551, + "y": -332.5707911478214, + "z": 0.0 + }, + { + "x": 68.53741424820078, + "y": -332.5713317389517, + "z": 0.0 + }, + { + "x": 69.54654453818605, + "y": -332.571872330082, + "z": 0.0 + }, + { + "x": 70.55567482817133, + "y": -332.5724129212123, + "z": 0.0 + }, + { + "x": 71.56480511815637, + "y": -332.57295351234256, + "z": 0.0 + }, + { + "x": 72.5739354081421, + "y": -332.5734941034729, + "z": 0.0 + }, + { + "x": 73.58306569812714, + "y": -332.57403469460314, + "z": 0.0 + }, + { + "x": 74.5921959881122, + "y": -332.57457528573343, + "z": 0.0 + }, + { + "x": 75.60132627809791, + "y": -332.5751158768638, + "z": 0.0 + }, + { + "x": 76.61045656808274, + "y": -332.575656467994, + "z": 0.0 + }, + { + "x": 77.61958685806846, + "y": -332.57619705912435, + "z": 0.0 + }, + { + "x": 78.62871714805328, + "y": -332.5767376502546, + "z": 0.0 + }, + { + "x": 79.63784743803855, + "y": -332.57727824138493, + "z": 0.0 + } + ] + }, + { + "id": 27, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 10.010000228881836, + "y": -328.53997802734375, + "z": 0.0 + }, + { + "x": 11.019130518867112, + "y": -328.54051861847404, + "z": 0.0 + }, + { + "x": 12.028260808852389, + "y": -328.5410592096043, + "z": 0.0 + }, + { + "x": 13.037391098837665, + "y": -328.5415998007346, + "z": 0.0 + }, + { + "x": 14.046521388822942, + "y": -328.5421403918649, + "z": 0.0 + }, + { + "x": 15.055651678808218, + "y": -328.5426809829952, + "z": 0.0 + }, + { + "x": 16.064781968793493, + "y": -328.54322157412554, + "z": 0.0 + }, + { + "x": 17.073912258778773, + "y": -328.54376216525577, + "z": 0.0 + }, + { + "x": 18.08304254876405, + "y": -328.54430275638606, + "z": 0.0 + }, + { + "x": 19.092172838749324, + "y": -328.54484334751635, + "z": 0.0 + }, + { + "x": 20.1013031287346, + "y": -328.54538393864664, + "z": 0.0 + }, + { + "x": 21.110433418719875, + "y": -328.545924529777, + "z": 0.0 + }, + { + "x": 22.119563708705154, + "y": -328.5464651209072, + "z": 0.0 + }, + { + "x": 23.12869399869043, + "y": -328.5470057120375, + "z": 0.0 + }, + { + "x": 24.137824288675706, + "y": -328.54754630316785, + "z": 0.0 + }, + { + "x": 25.14695457866098, + "y": -328.5480868942981, + "z": 0.0 + }, + { + "x": 26.156084868646257, + "y": -328.5486274854284, + "z": 0.0 + }, + { + "x": 27.165215158631533, + "y": -328.5491680765587, + "z": 0.0 + }, + { + "x": 28.174345448616812, + "y": -328.549708667689, + "z": 0.0 + }, + { + "x": 29.183475738602088, + "y": -328.5502492588193, + "z": 0.0 + }, + { + "x": 30.192606028587363, + "y": -328.5507898499495, + "z": 0.0 + }, + { + "x": 31.201736318572642, + "y": -328.55133044107987, + "z": 0.0 + }, + { + "x": 32.210866608557915, + "y": -328.55187103221016, + "z": 0.0 + }, + { + "x": 33.219996898543194, + "y": -328.55241162334045, + "z": 0.0 + }, + { + "x": 34.22912718852847, + "y": -328.55295221447074, + "z": 0.0 + }, + { + "x": 35.238257478513745, + "y": -328.553492805601, + "z": 0.0 + }, + { + "x": 36.247387768499024, + "y": -328.5540333967313, + "z": 0.0 + }, + { + "x": 37.256518058484296, + "y": -328.5545739878616, + "z": 0.0 + }, + { + "x": 38.265648348469576, + "y": -328.5551145789919, + "z": 0.0 + }, + { + "x": 39.274778638454855, + "y": -328.5556551701222, + "z": 0.0 + }, + { + "x": 40.28390892844013, + "y": -328.55619576125247, + "z": 0.0 + }, + { + "x": 41.293039218425406, + "y": -328.55673635238276, + "z": 0.0 + }, + { + "x": 42.30216950841068, + "y": -328.55727694351305, + "z": 0.0 + }, + { + "x": 43.31129979839596, + "y": -328.55781753464333, + "z": 0.0 + }, + { + "x": 44.32043008838123, + "y": -328.5583581257736, + "z": 0.0 + }, + { + "x": 45.32956037836651, + "y": -328.5588987169039, + "z": 0.0 + }, + { + "x": 46.33869066835178, + "y": -328.5594393080342, + "z": 0.0 + }, + { + "x": 47.34782095833706, + "y": -328.55997989916455, + "z": 0.0 + }, + { + "x": 48.35695124832233, + "y": -328.56052049029483, + "z": 0.0 + }, + { + "x": 49.36608153830761, + "y": -328.56106108142507, + "z": 0.0 + }, + { + "x": 50.37521182829288, + "y": -328.56160167255535, + "z": 0.0 + }, + { + "x": 51.38434211827817, + "y": -328.5621422636857, + "z": 0.0 + }, + { + "x": 52.393472408263456, + "y": -328.562682854816, + "z": 0.0 + }, + { + "x": 53.40260269824873, + "y": -328.5632234459463, + "z": 0.0 + }, + { + "x": 54.41173298823401, + "y": -328.5637640370765, + "z": 0.0 + }, + { + "x": 55.42086327821928, + "y": -328.5643046282068, + "z": 0.0 + }, + { + "x": 56.42999356820456, + "y": -328.56484521933714, + "z": 0.0 + }, + { + "x": 57.43912385818983, + "y": -328.56538581046743, + "z": 0.0 + }, + { + "x": 58.44825414817511, + "y": -328.5659264015977, + "z": 0.0 + }, + { + "x": 59.45738443816039, + "y": -328.566466992728, + "z": 0.0 + }, + { + "x": 60.46651472814566, + "y": -328.5670075838583, + "z": 0.0 + }, + { + "x": 61.47564501813094, + "y": -328.5675481749886, + "z": 0.0 + }, + { + "x": 62.48477530811621, + "y": -328.5680887661189, + "z": 0.0 + }, + { + "x": 63.49390559810149, + "y": -328.56862935724916, + "z": 0.0 + }, + { + "x": 64.50303588808677, + "y": -328.56916994837945, + "z": 0.0 + }, + { + "x": 65.51216617807205, + "y": -328.56971053950974, + "z": 0.0 + }, + { + "x": 66.52129646805732, + "y": -328.57025113064003, + "z": 0.0 + }, + { + "x": 67.5304267580426, + "y": -328.5707917217703, + "z": 0.0 + }, + { + "x": 68.53955704802786, + "y": -328.5713323129006, + "z": 0.0 + }, + { + "x": 69.54868733801314, + "y": -328.5718729040309, + "z": 0.0 + }, + { + "x": 70.55781762799842, + "y": -328.5724134951612, + "z": 0.0 + }, + { + "x": 71.56694791798368, + "y": -328.5729540862915, + "z": 0.0 + }, + { + "x": 72.57607820796896, + "y": -328.5734946774218, + "z": 0.0 + }, + { + "x": 73.58520849795423, + "y": -328.57403526855205, + "z": 0.0 + }, + { + "x": 74.5943387879395, + "y": -328.57457585968234, + "z": 0.0 + }, + { + "x": 75.60346907792477, + "y": -328.5751164508127, + "z": 0.0 + }, + { + "x": 76.61259936791005, + "y": -328.5756570419429, + "z": 0.0 + }, + { + "x": 77.62172965789532, + "y": -328.57619763307326, + "z": 0.0 + }, + { + "x": 78.6308599478806, + "y": -328.5767382242035, + "z": 0.0 + }, + { + "x": 79.63999023786586, + "y": -328.57727881533384, + "z": 0.0 + } + ] + }, + { + "id": 28, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 79.64106163777952, + "y": -326.5772791023083, + "z": 0.0 + }, + { + "x": 78.63193134779425, + "y": -326.57673851117795, + "z": 0.0 + }, + { + "x": 77.62280105780874, + "y": -326.5761979200477, + "z": 0.0 + }, + { + "x": 76.6136707678237, + "y": -326.5756573289174, + "z": 0.0 + }, + { + "x": 75.6045404778382, + "y": -326.57511673778714, + "z": 0.0 + }, + { + "x": 74.59541018785316, + "y": -326.5745761466568, + "z": 0.0 + }, + { + "x": 73.58627989786777, + "y": -326.5740355555265, + "z": 0.0 + }, + { + "x": 72.57714960788239, + "y": -326.5734949643963, + "z": 0.0 + }, + { + "x": 71.56801931789734, + "y": -326.57295437326593, + "z": 0.0 + }, + { + "x": 70.55888902791196, + "y": -326.57241378213564, + "z": 0.0 + }, + { + "x": 69.54975873792668, + "y": -326.57187319100535, + "z": 0.0 + }, + { + "x": 68.5406284479414, + "y": -326.57133259987506, + "z": 0.0 + }, + { + "x": 67.53149815795614, + "y": -326.5707920087448, + "z": 0.0 + }, + { + "x": 66.52236786797086, + "y": -326.5702514176145, + "z": 0.0 + }, + { + "x": 65.51323757798559, + "y": -326.5697108264842, + "z": 0.0 + }, + { + "x": 64.50410728800031, + "y": -326.5691702353539, + "z": 0.0 + }, + { + "x": 63.494976998015034, + "y": -326.5686296442236, + "z": 0.0 + }, + { + "x": 62.485846708029754, + "y": -326.56808905309333, + "z": 0.0 + }, + { + "x": 61.47671641804448, + "y": -326.56754846196304, + "z": 0.0 + }, + { + "x": 60.4675861280592, + "y": -326.56700787083275, + "z": 0.0 + }, + { + "x": 59.45845583807393, + "y": -326.56646727970247, + "z": 0.0 + }, + { + "x": 58.44932554808865, + "y": -326.5659266885722, + "z": 0.0 + }, + { + "x": 57.44019525810337, + "y": -326.5653860974419, + "z": 0.0 + }, + { + "x": 56.4310649681181, + "y": -326.5648455063116, + "z": 0.0 + }, + { + "x": 55.42193467813293, + "y": -326.56430491518125, + "z": 0.0 + }, + { + "x": 54.41280438814755, + "y": -326.56376432405096, + "z": 0.0 + }, + { + "x": 53.403674098162156, + "y": -326.56322373292073, + "z": 0.0 + }, + { + "x": 52.394543808177, + "y": -326.56268314179044, + "z": 0.0 + }, + { + "x": 51.38541351819171, + "y": -326.56214255066016, + "z": 0.0 + }, + { + "x": 50.37628322820653, + "y": -326.5616019595298, + "z": 0.0 + }, + { + "x": 49.36715293822115, + "y": -326.5610613683995, + "z": 0.0 + }, + { + "x": 48.35802264823576, + "y": -326.5605207772693, + "z": 0.0 + }, + { + "x": 47.3488923582506, + "y": -326.559980186139, + "z": 0.0 + }, + { + "x": 46.33976206826543, + "y": -326.55943959500866, + "z": 0.0 + }, + { + "x": 45.33063177828005, + "y": -326.55889900387837, + "z": 0.0 + }, + { + "x": 44.32150148829477, + "y": -326.5583584127481, + "z": 0.0 + }, + { + "x": 43.3123711983095, + "y": -326.5578178216178, + "z": 0.0 + }, + { + "x": 42.30324090832422, + "y": -326.5572772304875, + "z": 0.0 + }, + { + "x": 41.29411061833895, + "y": -326.5567366393572, + "z": 0.0 + }, + { + "x": 40.28498032835367, + "y": -326.5561960482269, + "z": 0.0 + }, + { + "x": 39.2758500383684, + "y": -326.55565545709663, + "z": 0.0 + }, + { + "x": 38.26671974838312, + "y": -326.55511486596635, + "z": 0.0 + }, + { + "x": 37.25758945839784, + "y": -326.55457427483606, + "z": 0.0 + }, + { + "x": 36.248459168412566, + "y": -326.55403368370577, + "z": 0.0 + }, + { + "x": 35.23932887842729, + "y": -326.5534930925755, + "z": 0.0 + }, + { + "x": 34.230198588442015, + "y": -326.5529525014452, + "z": 0.0 + }, + { + "x": 33.221068298456736, + "y": -326.5524119103149, + "z": 0.0 + }, + { + "x": 32.211938008471456, + "y": -326.5518713191846, + "z": 0.0 + }, + { + "x": 31.202807718486184, + "y": -326.5513307280543, + "z": 0.0 + }, + { + "x": 30.19367742850102, + "y": -326.550790136924, + "z": 0.0 + }, + { + "x": 29.184547138515516, + "y": -326.55024954579375, + "z": 0.0 + }, + { + "x": 28.175416848530354, + "y": -326.54970895466346, + "z": 0.0 + }, + { + "x": 27.166286558545075, + "y": -326.54916836353317, + "z": 0.0 + }, + { + "x": 26.157156268559795, + "y": -326.5486277724029, + "z": 0.0 + }, + { + "x": 25.148025978574637, + "y": -326.54808718127254, + "z": 0.0 + }, + { + "x": 24.138895688589134, + "y": -326.5475465901423, + "z": 0.0 + }, + { + "x": 23.129765398604086, + "y": -326.54700599901196, + "z": 0.0 + }, + { + "x": 22.120635108618693, + "y": -326.54646540788167, + "z": 0.0 + }, + { + "x": 21.111504818633303, + "y": -326.54592481675144, + "z": 0.0 + }, + { + "x": 20.102374528648255, + "y": -326.5453842256211, + "z": 0.0 + }, + { + "x": 19.093244238662862, + "y": -326.5448436344908, + "z": 0.0 + }, + { + "x": 18.08411394867759, + "y": -326.5443030433605, + "z": 0.0 + }, + { + "x": 17.07498365869231, + "y": -326.5437624522302, + "z": 0.0 + }, + { + "x": 16.06585336870692, + "y": -326.5432218611, + "z": 0.0 + }, + { + "x": 15.056723078721872, + "y": -326.54268126996965, + "z": 0.0 + }, + { + "x": 14.047592788736484, + "y": -326.54214067883936, + "z": 0.0 + }, + { + "x": 13.038462498751205, + "y": -326.54160008770907, + "z": 0.0 + }, + { + "x": 12.02933220876593, + "y": -326.5410594965788, + "z": 0.0 + }, + { + "x": 11.020201918780653, + "y": -326.5405189054485, + "z": 0.0 + }, + { + "x": 10.011071628795378, + "y": -326.5399783143182, + "z": 0.0 + } + ] + }, + { + "id": 29, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 10.008928828968294, + "y": -330.5399777403693, + "z": 0.0 + }, + { + "x": 11.01805911895357, + "y": -330.5405183314996, + "z": 0.0 + }, + { + "x": 12.027189408938849, + "y": -330.5410589226299, + "z": 0.0 + }, + { + "x": 13.036319698924125, + "y": -330.54159951376016, + "z": 0.0 + }, + { + "x": 14.0454499889094, + "y": -330.54214010489045, + "z": 0.0 + }, + { + "x": 15.054580278894564, + "y": -330.54268069602074, + "z": 0.0 + }, + { + "x": 16.063710568880065, + "y": -330.5432212871511, + "z": 0.0 + }, + { + "x": 17.072840858865234, + "y": -330.5437618782813, + "z": 0.0 + }, + { + "x": 18.081971148850506, + "y": -330.5443024694116, + "z": 0.0 + }, + { + "x": 19.091101438835786, + "y": -330.5448430605419, + "z": 0.0 + }, + { + "x": 20.100231728820944, + "y": -330.5453836516722, + "z": 0.0 + }, + { + "x": 21.109362018806447, + "y": -330.5459242428025, + "z": 0.0 + }, + { + "x": 22.118492308791616, + "y": -330.54646483393276, + "z": 0.0 + }, + { + "x": 23.127622598776775, + "y": -330.54700542506305, + "z": 0.0 + }, + { + "x": 24.136752888762278, + "y": -330.5475460161934, + "z": 0.0 + }, + { + "x": 25.145883178747326, + "y": -330.5480866073236, + "z": 0.0 + }, + { + "x": 26.15501346873272, + "y": -330.54862719845397, + "z": 0.0 + }, + { + "x": 27.16414375871799, + "y": -330.54916778958426, + "z": 0.0 + }, + { + "x": 28.17327404870327, + "y": -330.54970838071455, + "z": 0.0 + }, + { + "x": 29.18240433868866, + "y": -330.55024897184484, + "z": 0.0 + }, + { + "x": 30.191534628673708, + "y": -330.55078956297507, + "z": 0.0 + }, + { + "x": 31.2006649186591, + "y": -330.5513301541054, + "z": 0.0 + }, + { + "x": 32.20979520864437, + "y": -330.5518707452357, + "z": 0.0 + }, + { + "x": 33.21892549862965, + "y": -330.552411336366, + "z": 0.0 + }, + { + "x": 34.22805578861493, + "y": -330.5529519274963, + "z": 0.0 + }, + { + "x": 35.2371860786002, + "y": -330.55349251862657, + "z": 0.0 + }, + { + "x": 36.24631636858548, + "y": -330.55403310975686, + "z": 0.0 + }, + { + "x": 37.255446658570754, + "y": -330.55457370088715, + "z": 0.0 + }, + { + "x": 38.264576948556034, + "y": -330.55511429201744, + "z": 0.0 + }, + { + "x": 39.27370723854131, + "y": -330.5556548831477, + "z": 0.0 + }, + { + "x": 40.282837528526585, + "y": -330.556195474278, + "z": 0.0 + }, + { + "x": 41.291967818511864, + "y": -330.5567360654083, + "z": 0.0 + }, + { + "x": 42.301098108497136, + "y": -330.5572766565386, + "z": 0.0 + }, + { + "x": 43.310228398482415, + "y": -330.5578172476689, + "z": 0.0 + }, + { + "x": 44.31935868846769, + "y": -330.55835783879917, + "z": 0.0 + }, + { + "x": 45.32848897845297, + "y": -330.55889842992946, + "z": 0.0 + }, + { + "x": 46.33761926843813, + "y": -330.55943902105975, + "z": 0.0 + }, + { + "x": 47.34674955842352, + "y": -330.5599796121901, + "z": 0.0 + }, + { + "x": 48.355879848408904, + "y": -330.5605202033204, + "z": 0.0 + }, + { + "x": 49.36501013839407, + "y": -330.5610607944506, + "z": 0.0 + }, + { + "x": 50.374140428379235, + "y": -330.5616013855809, + "z": 0.0 + }, + { + "x": 51.38327071836463, + "y": -330.56214197671125, + "z": 0.0 + }, + { + "x": 52.392401008349914, + "y": -330.56268256784153, + "z": 0.0 + }, + { + "x": 53.4015312983353, + "y": -330.5632231589718, + "z": 0.0 + }, + { + "x": 54.410661588320465, + "y": -330.56376375010205, + "z": 0.0 + }, + { + "x": 55.41979187830563, + "y": -330.56430434123234, + "z": 0.0 + }, + { + "x": 56.42892216829102, + "y": -330.5648449323627, + "z": 0.0 + }, + { + "x": 57.43805245827629, + "y": -330.565385523493, + "z": 0.0 + }, + { + "x": 58.44718274826157, + "y": -330.56592611462327, + "z": 0.0 + }, + { + "x": 59.45631303824685, + "y": -330.56646670575356, + "z": 0.0 + }, + { + "x": 60.46544332823212, + "y": -330.56700729688384, + "z": 0.0 + }, + { + "x": 61.4745736182174, + "y": -330.56754788801413, + "z": 0.0 + }, + { + "x": 62.48370390820267, + "y": -330.5680884791444, + "z": 0.0 + }, + { + "x": 63.49283419818795, + "y": -330.5686290702747, + "z": 0.0 + }, + { + "x": 64.50196448817323, + "y": -330.569169661405, + "z": 0.0 + }, + { + "x": 65.51109477815851, + "y": -330.5697102525353, + "z": 0.0 + }, + { + "x": 66.52022506814377, + "y": -330.5702508436656, + "z": 0.0 + }, + { + "x": 67.52935535812905, + "y": -330.57079143479586, + "z": 0.0 + }, + { + "x": 68.53848564811432, + "y": -330.57133202592615, + "z": 0.0 + }, + { + "x": 69.5476159380996, + "y": -330.57187261705644, + "z": 0.0 + }, + { + "x": 70.55674622808488, + "y": -330.57241320818673, + "z": 0.0 + }, + { + "x": 71.56587651807003, + "y": -330.572953799317, + "z": 0.0 + }, + { + "x": 72.57500680805553, + "y": -330.57349439044737, + "z": 0.0 + }, + { + "x": 73.58413709804069, + "y": -330.5740349815776, + "z": 0.0 + }, + { + "x": 74.59326738802585, + "y": -330.5745755727079, + "z": 0.0 + }, + { + "x": 75.60239767801134, + "y": -330.57511616383823, + "z": 0.0 + }, + { + "x": 76.6115279679964, + "y": -330.57565675496846, + "z": 0.0 + }, + { + "x": 77.62065825798189, + "y": -330.5761973460988, + "z": 0.0 + }, + { + "x": 78.62978854796694, + "y": -330.57673793722904, + "z": 0.0 + }, + { + "x": 79.6389188379522, + "y": -330.5772785283594, + "z": 0.0 + } + ] + }, + { + "id": 30, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 325.71998576749917, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 324.7150530320806, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 323.7101202966621, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 322.70518756124363, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 321.7002548258251, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 320.69532209040653, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 319.69038935498804, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 318.6854566195695, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 317.68052388415094, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 316.67559114873245, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 315.67065841331396, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 314.6657256778954, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 313.66079294247686, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 312.65586020705837, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 311.6509274716398, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 310.64599473622127, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 309.6410620008028, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 308.6361292653843, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 307.63119652996573, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 306.6262637945472, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 305.6213310591287, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 304.61639832371014, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 303.6114655882916, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 302.6065328528731, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 301.6016001174546, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 300.59666738203606, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 299.5917346466175, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 298.586801911199, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 297.58186917578047, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 296.5769364403619, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 295.5720037049434, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 294.56707096952493, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 293.5621382341064, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 292.55720549868784, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 291.55227276326934, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 290.54734839213904, + "y": -324.6099832501986, + "z": 0.0 + }, + { + "x": 289.54283147550484, + "y": -324.6098767052554, + "z": 0.0 + }, + { + "x": 288.53790172978063, + "y": -324.60976938847693, + "z": 0.0 + }, + { + "x": 287.5329690000928, + "y": -324.6096620713808, + "z": 0.0 + }, + { + "x": 286.528036270404, + "y": -324.6095547542848, + "z": 0.0 + }, + { + "x": 285.52310354071574, + "y": -324.60944743718875, + "z": 0.0 + }, + { + "x": 284.5181708110277, + "y": -324.60934012009267, + "z": 0.0 + }, + { + "x": 283.51323808133935, + "y": -324.6092328029966, + "z": 0.0 + }, + { + "x": 282.5083053516508, + "y": -324.60912548590056, + "z": 0.0 + }, + { + "x": 281.50337262196274, + "y": -324.6090181688045, + "z": 0.0 + }, + { + "x": 280.49843989227446, + "y": -324.6089108517084, + "z": 0.0 + }, + { + "x": 279.4935071625859, + "y": -324.6088035346124, + "z": 0.0 + }, + { + "x": 278.48857443289785, + "y": -324.6086962175163, + "z": 0.0 + }, + { + "x": 277.48364170320957, + "y": -324.6085889004202, + "z": 0.0 + }, + { + "x": 276.478708973521, + "y": -324.6084815833242, + "z": 0.0 + }, + { + "x": 275.4737762438329, + "y": -324.6083742662281, + "z": 0.0 + }, + { + "x": 274.4688435141444, + "y": -324.6082669491321, + "z": 0.0 + }, + { + "x": 273.46391078445635, + "y": -324.608159632036, + "z": 0.0 + }, + { + "x": 272.4589780547678, + "y": -324.60805231494, + "z": 0.0 + }, + { + "x": 271.45404532507973, + "y": -324.6079449978439, + "z": 0.0 + }, + { + "x": 270.44911259539145, + "y": -324.6078376807478, + "z": 0.0 + }, + { + "x": 269.4441798657029, + "y": -324.6077303636518, + "z": 0.0 + }, + { + "x": 268.4392471360148, + "y": -324.6076230465557, + "z": 0.0 + }, + { + "x": 267.4343144063265, + "y": -324.60751572945964, + "z": 0.0 + }, + { + "x": 266.429381676638, + "y": -324.6074084123636, + "z": 0.0 + }, + { + "x": 265.4244489469499, + "y": -324.60730109526753, + "z": 0.0 + }, + { + "x": 264.4195162172616, + "y": -324.60719377817145, + "z": 0.0 + }, + { + "x": 263.4145834875731, + "y": -324.6070864610754, + "z": 0.0 + }, + { + "x": 262.409650757885, + "y": -324.60697914397934, + "z": 0.0 + }, + { + "x": 261.40471802819644, + "y": -324.6068718268833, + "z": 0.0 + }, + { + "x": 260.3997852985084, + "y": -324.60676450978724, + "z": 0.0 + }, + { + "x": 259.3948525688201, + "y": -324.60665719269116, + "z": 0.0 + }, + { + "x": 258.38991983913155, + "y": -324.60654987559514, + "z": 0.0 + }, + { + "x": 257.3849871094435, + "y": -324.60644255849905, + "z": 0.0 + }, + { + "x": 256.380054379755, + "y": -324.60633524140303, + "z": 0.0 + }, + { + "x": 255.37512165006692, + "y": -324.60622792430695, + "z": 0.0 + }, + { + "x": 254.37018892037858, + "y": -324.60612060721087, + "z": 0.0 + }, + { + "x": 253.36525619069005, + "y": -324.60601329011484, + "z": 0.0 + }, + { + "x": 252.360323461002, + "y": -324.60590597301876, + "z": 0.0 + }, + { + "x": 251.35539073131346, + "y": -324.60579865592274, + "z": 0.0 + }, + { + "x": 250.35045800162538, + "y": -324.60569133882666, + "z": 0.0 + }, + { + "x": 249.3455252719371, + "y": -324.6055840217306, + "z": 0.0 + }, + { + "x": 248.34059254224857, + "y": -324.60547670463455, + "z": 0.0 + }, + { + "x": 247.33565981256046, + "y": -324.6053693875385, + "z": 0.0 + }, + { + "x": 246.3307270828722, + "y": -324.6052620704424, + "z": 0.0 + }, + { + "x": 245.32579435318365, + "y": -324.60515475334637, + "z": 0.0 + }, + { + "x": 244.32086162349557, + "y": -324.6050474362503, + "z": 0.0 + }, + { + "x": 243.31592889380727, + "y": -324.6049401191542, + "z": 0.0 + }, + { + "x": 242.31099616411876, + "y": -324.6048328020582, + "z": 0.0 + }, + { + "x": 241.30606343443046, + "y": -324.60472548496216, + "z": 0.0 + }, + { + "x": 240.30113070474235, + "y": -324.6046181678661, + "z": 0.0 + }, + { + "x": 239.29619797505407, + "y": -324.60451085077, + "z": 0.0 + }, + { + "x": 238.29126524536554, + "y": -324.604403533674, + "z": 0.0 + }, + { + "x": 237.28633251567746, + "y": -324.6042962165779, + "z": 0.0 + }, + { + "x": 236.28139978598918, + "y": -324.6041888994818, + "z": 0.0 + }, + { + "x": 235.27646705630065, + "y": -324.6040815823858, + "z": 0.0 + }, + { + "x": 234.27153432661257, + "y": -324.6039742652897, + "z": 0.0 + }, + { + "x": 233.26660159692423, + "y": -324.6038669481936, + "z": 0.0 + }, + { + "x": 232.26166886723573, + "y": -324.6037596310976, + "z": 0.0 + }, + { + "x": 231.25673613754742, + "y": -324.6036523140016, + "z": 0.0 + }, + { + "x": 230.25180340785957, + "y": -324.60354499690544, + "z": 0.0 + }, + { + "x": 229.24687067817084, + "y": -324.6034376798094, + "z": 0.0 + }, + { + "x": 228.2419379484825, + "y": -324.6033303627134, + "z": 0.0 + }, + { + "x": 227.23700521879465, + "y": -324.60322304561726, + "z": 0.0 + }, + { + "x": 226.2320724891059, + "y": -324.60311572852123, + "z": 0.0 + }, + { + "x": 225.22713975941755, + "y": -324.6030084114252, + "z": 0.0 + }, + { + "x": 224.22220702972947, + "y": -324.6029010943291, + "z": 0.0 + }, + { + "x": 223.21727430004114, + "y": -324.60279377723305, + "z": 0.0 + }, + { + "x": 222.2123415703526, + "y": -324.602686460137, + "z": 0.0 + }, + { + "x": 221.20740884066453, + "y": -324.60257914304094, + "z": 0.0 + }, + { + "x": 220.2024761109762, + "y": -324.60247182594486, + "z": 0.0 + }, + { + "x": 219.19754338128766, + "y": -324.60236450884884, + "z": 0.0 + }, + { + "x": 218.19261065159935, + "y": -324.6022571917528, + "z": 0.0 + }, + { + "x": 217.18767792191147, + "y": -324.6021498746567, + "z": 0.0 + }, + { + "x": 216.1827451922227, + "y": -324.60204255756065, + "z": 0.0 + }, + { + "x": 215.1778124625344, + "y": -324.6019352404646, + "z": 0.0 + }, + { + "x": 214.17287973284655, + "y": -324.6018279233685, + "z": 0.0 + }, + { + "x": 213.16794700315776, + "y": -324.60172060627247, + "z": 0.0 + }, + { + "x": 212.16301427346946, + "y": -324.60161328917644, + "z": 0.0 + }, + { + "x": 211.15808154378138, + "y": -324.60150597208036, + "z": 0.0 + }, + { + "x": 210.15314881409304, + "y": -324.6013986549843, + "z": 0.0 + }, + { + "x": 209.1482160844045, + "y": -324.60129133788826, + "z": 0.0 + }, + { + "x": 208.1432833547162, + "y": -324.60118402079223, + "z": 0.0 + }, + { + "x": 207.13835062502832, + "y": -324.6010767036961, + "z": 0.0 + }, + { + "x": 206.13341789533956, + "y": -324.60096938660007, + "z": 0.0 + }, + { + "x": 205.12848516565123, + "y": -324.60086206950405, + "z": 0.0 + }, + { + "x": 204.12355243596338, + "y": -324.6007547524079, + "z": 0.0 + }, + { + "x": 203.11861970627461, + "y": -324.6006474353119, + "z": 0.0 + }, + { + "x": 202.11368697658628, + "y": -324.60054011821586, + "z": 0.0 + }, + { + "x": 201.1087542468982, + "y": -324.6004328011198, + "z": 0.0 + }, + { + "x": 200.1038215172099, + "y": -324.6003254840237, + "z": 0.0 + }, + { + "x": 199.09888878752133, + "y": -324.6002181669277, + "z": 0.0 + }, + { + "x": 198.09395605783325, + "y": -324.6001108498316, + "z": 0.0 + }, + { + "x": 197.08902332814495, + "y": -324.6000035327355, + "z": 0.0 + }, + { + "x": 196.08409059845638, + "y": -324.5998962156395, + "z": 0.0 + }, + { + "x": 195.0791578687683, + "y": -324.5997888985434, + "z": 0.0 + }, + { + "x": 194.07422513908, + "y": -324.5996815814473, + "z": 0.0 + }, + { + "x": 193.06929240939147, + "y": -324.5995742643513, + "z": 0.0 + }, + { + "x": 192.06435967970313, + "y": -324.5994669472553, + "z": 0.0 + }, + { + "x": 191.05942695001505, + "y": -324.5993596301592, + "z": 0.0 + }, + { + "x": 190.05449422032672, + "y": -324.5992523130631, + "z": 0.0 + }, + { + "x": 189.04956149063818, + "y": -324.5991449959671, + "z": 0.0 + }, + { + "x": 188.0446287609501, + "y": -324.599037678871, + "z": 0.0 + }, + { + "x": 187.03969603126177, + "y": -324.59893036177493, + "z": 0.0 + }, + { + "x": 186.03476330157324, + "y": -324.5988230446789, + "z": 0.0 + }, + { + "x": 185.02983057188513, + "y": -324.5987157275828, + "z": 0.0 + }, + { + "x": 184.02489784219682, + "y": -324.59860841048675, + "z": 0.0 + }, + { + "x": 183.0199651125083, + "y": -324.5985010933907, + "z": 0.0 + }, + { + "x": 182.01503238282018, + "y": -324.59839377629464, + "z": 0.0 + }, + { + "x": 181.01009965313187, + "y": -324.59828645919856, + "z": 0.0 + }, + { + "x": 180.00516692344334, + "y": -324.59817914210254, + "z": 0.0 + }, + { + "x": 179.00023419375526, + "y": -324.59807182500646, + "z": 0.0 + }, + { + "x": 177.99530146406693, + "y": -324.5979645079104, + "z": 0.0 + }, + { + "x": 176.9903687343784, + "y": -324.59785719081435, + "z": 0.0 + }, + { + "x": 175.9854360046901, + "y": -324.5977498737183, + "z": 0.0 + }, + { + "x": 174.98050327500198, + "y": -324.59764255662225, + "z": 0.0 + }, + { + "x": 173.97557054531367, + "y": -324.59753523952617, + "z": 0.0 + }, + { + "x": 172.97063781562514, + "y": -324.59742792243014, + "z": 0.0 + }, + { + "x": 171.96570508593703, + "y": -324.59732060533406, + "z": 0.0 + }, + { + "x": 170.96077235624873, + "y": -324.597213288238, + "z": 0.0 + }, + { + "x": 169.95583962656016, + "y": -324.59710597114196, + "z": 0.0 + }, + { + "x": 168.95090689687208, + "y": -324.5969986540459, + "z": 0.0 + }, + { + "x": 167.94597416718378, + "y": -324.5968913369498, + "z": 0.0 + }, + { + "x": 166.94104143749522, + "y": -324.59678401985377, + "z": 0.0 + }, + { + "x": 165.93610870780714, + "y": -324.5966767027577, + "z": 0.0 + }, + { + "x": 164.9311759781186, + "y": -324.59656938566167, + "z": 0.0 + }, + { + "x": 163.92624324843052, + "y": -324.5964620685656, + "z": 0.0 + }, + { + "x": 162.92131051874222, + "y": -324.5963547514695, + "z": 0.0 + }, + { + "x": 161.91637778905368, + "y": -324.5962474343735, + "z": 0.0 + }, + { + "x": 160.9114450593656, + "y": -324.5961401172774, + "z": 0.0 + }, + { + "x": 159.90651232967707, + "y": -324.5960328001814, + "z": 0.0 + }, + { + "x": 158.901579599989, + "y": -324.5959254830853, + "z": 0.0 + }, + { + "x": 157.89664687030069, + "y": -324.5958181659892, + "z": 0.0 + }, + { + "x": 156.89171414061212, + "y": -324.5957108488932, + "z": 0.0 + }, + { + "x": 155.88678141092404, + "y": -324.5956035317971, + "z": 0.0 + }, + { + "x": 154.8818486812355, + "y": -324.5954962147011, + "z": 0.0 + }, + { + "x": 153.87691595154743, + "y": -324.595388897605, + "z": 0.0 + }, + { + "x": 152.87198322185913, + "y": -324.5952815805089, + "z": 0.0 + }, + { + "x": 151.8670504921706, + "y": -324.5951742634129, + "z": 0.0 + }, + { + "x": 150.8621177624825, + "y": -324.5950669463168, + "z": 0.0 + }, + { + "x": 149.8571850327942, + "y": -324.59495962922074, + "z": 0.0 + }, + { + "x": 148.85225230310567, + "y": -324.5948523121247, + "z": 0.0 + }, + { + "x": 147.8473195734176, + "y": -324.59474499502863, + "z": 0.0 + }, + { + "x": 146.84238684372926, + "y": -324.59463767793255, + "z": 0.0 + }, + { + "x": 145.83745411404072, + "y": -324.59453036083653, + "z": 0.0 + }, + { + "x": 144.83252138435242, + "y": -324.5944230437405, + "z": 0.0 + }, + { + "x": 143.82758865466434, + "y": -324.5943157266444, + "z": 0.0 + }, + { + "x": 142.82265592497603, + "y": -324.59420840954834, + "z": 0.0 + }, + { + "x": 141.8177231952875, + "y": -324.5941010924523, + "z": 0.0 + }, + { + "x": 140.81279046559942, + "y": -324.59399377535624, + "z": 0.0 + }, + { + "x": 139.8078577359111, + "y": -324.59388645826016, + "z": 0.0 + }, + { + "x": 138.80292500622258, + "y": -324.59377914116413, + "z": 0.0 + }, + { + "x": 137.7979922765345, + "y": -324.59367182406805, + "z": 0.0 + }, + { + "x": 136.7930595468462, + "y": -324.593564506972, + "z": 0.0 + }, + { + "x": 135.78812681715763, + "y": -324.59345718987595, + "z": 0.0 + }, + { + "x": 134.78319408746958, + "y": -324.59334987277987, + "z": 0.0 + }, + { + "x": 133.77826135778125, + "y": -324.5932425556838, + "z": 0.0 + }, + { + "x": 132.7733286280927, + "y": -324.59313523858776, + "z": 0.0 + }, + { + "x": 131.7683958984044, + "y": -324.59302792149174, + "z": 0.0 + }, + { + "x": 130.76346316871656, + "y": -324.5929206043956, + "z": 0.0 + }, + { + "x": 129.7585304390278, + "y": -324.5928132872996, + "z": 0.0 + }, + { + "x": 128.75359770933946, + "y": -324.59270597020355, + "z": 0.0 + }, + { + "x": 127.74866497965138, + "y": -324.5925986531075, + "z": 0.0 + }, + { + "x": 126.74373224996307, + "y": -324.5924913360114, + "z": 0.0 + }, + { + "x": 125.73879952027453, + "y": -324.59238401891537, + "z": 0.0 + }, + { + "x": 124.73386679058645, + "y": -324.5922767018193, + "z": 0.0 + }, + { + "x": 123.72893406089814, + "y": -324.5921693847232, + "z": 0.0 + }, + { + "x": 122.72400133120959, + "y": -324.5920620676272, + "z": 0.0 + }, + { + "x": 121.71906860152127, + "y": -324.59195475053116, + "z": 0.0 + }, + { + "x": 120.71413587183342, + "y": -324.591847433435, + "z": 0.0 + }, + { + "x": 119.70920314214466, + "y": -324.591740116339, + "z": 0.0 + }, + { + "x": 118.70427041245634, + "y": -324.591632799243, + "z": 0.0 + }, + { + "x": 117.69933768276849, + "y": -324.59152548214684, + "z": 0.0 + }, + { + "x": 116.69440495307973, + "y": -324.5914181650508, + "z": 0.0 + }, + { + "x": 115.6894722233914, + "y": -324.5913108479548, + "z": 0.0 + }, + { + "x": 114.68453949370333, + "y": -324.5912035308587, + "z": 0.0 + }, + { + "x": 113.67960676401502, + "y": -324.5910962137626, + "z": 0.0 + }, + { + "x": 112.67467403432649, + "y": -324.5909888966666, + "z": 0.0 + }, + { + "x": 111.66974130463817, + "y": -324.5908815795706, + "z": 0.0 + }, + { + "x": 110.66480857495031, + "y": -324.59077426247444, + "z": 0.0 + }, + { + "x": 109.65987584526155, + "y": -324.5906669453784, + "z": 0.0 + }, + { + "x": 108.65494311557323, + "y": -324.5905596282824, + "z": 0.0 + }, + { + "x": 107.65001038588538, + "y": -324.59045231118625, + "z": 0.0 + }, + { + "x": 106.64507765619662, + "y": -324.59034499409023, + "z": 0.0 + }, + { + "x": 105.6401449265083, + "y": -324.5902376769942, + "z": 0.0 + }, + { + "x": 104.63521219682022, + "y": -324.5901303598981, + "z": 0.0 + }, + { + "x": 103.63027946713191, + "y": -324.59002304280204, + "z": 0.0 + }, + { + "x": 102.62663591823683, + "y": -324.58959221099286, + "z": 0.0 + }, + { + "x": 101.62212988384367, + "y": -324.5890540743326, + "z": 0.0 + } + ] + }, + { + "id": 31, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 101.61784428418933, + "y": -332.58905292643476, + "z": 0.0 + }, + { + "x": 102.62320343224319, + "y": -332.58959147462036, + "z": 0.0 + }, + { + "x": 103.62942514451072, + "y": -332.5900229971853, + "z": 0.0 + }, + { + "x": 104.63435787419903, + "y": -332.5901303142814, + "z": 0.0 + }, + { + "x": 105.63929060388756, + "y": -332.5902376313775, + "z": 0.0 + }, + { + "x": 106.64422333357588, + "y": -332.5903449484735, + "z": 0.0 + }, + { + "x": 107.64915606326373, + "y": -332.5904522655695, + "z": 0.0 + }, + { + "x": 108.65408879295249, + "y": -332.59055958266566, + "z": 0.0 + }, + { + "x": 109.65902152264081, + "y": -332.5906668997617, + "z": 0.0 + }, + { + "x": 110.66395425232867, + "y": -332.5907742168577, + "z": 0.0 + }, + { + "x": 111.66888698201743, + "y": -332.59088153395385, + "z": 0.0 + }, + { + "x": 112.67381971170575, + "y": -332.5909888510499, + "z": 0.0 + }, + { + "x": 113.67875244139383, + "y": -332.5910961681459, + "z": 0.0 + }, + { + "x": 114.68368517108213, + "y": -332.591203485242, + "z": 0.0 + }, + { + "x": 115.68861790077067, + "y": -332.59131080233806, + "z": 0.0 + }, + { + "x": 116.69355063045899, + "y": -332.5914181194341, + "z": 0.0 + }, + { + "x": 117.69848336014684, + "y": -332.5915254365301, + "z": 0.0 + }, + { + "x": 118.7034160898356, + "y": -332.59163275362624, + "z": 0.0 + }, + { + "x": 119.70834881952392, + "y": -332.59174007072227, + "z": 0.0 + }, + { + "x": 120.71328154921177, + "y": -332.5918473878183, + "z": 0.0 + }, + { + "x": 121.71821427890053, + "y": -332.59195470491443, + "z": 0.0 + }, + { + "x": 122.72314700858885, + "y": -332.59206202201045, + "z": 0.0 + }, + { + "x": 123.72807973827695, + "y": -332.5921693391065, + "z": 0.0 + }, + { + "x": 124.73301246796525, + "y": -332.59227665620256, + "z": 0.0 + }, + { + "x": 125.73794519765379, + "y": -332.59238397329864, + "z": 0.0 + }, + { + "x": 126.74287792734188, + "y": -332.59249129039466, + "z": 0.0 + }, + { + "x": 127.74781065703019, + "y": -332.59259860749074, + "z": 0.0 + }, + { + "x": 128.75274338671872, + "y": -332.5927059245868, + "z": 0.0 + }, + { + "x": 129.75767611640705, + "y": -332.59281324168285, + "z": 0.0 + }, + { + "x": 130.7626088460949, + "y": -332.59292055877887, + "z": 0.0 + }, + { + "x": 131.76754157578367, + "y": -332.593027875875, + "z": 0.0 + }, + { + "x": 132.77247430547197, + "y": -332.59313519297103, + "z": 0.0 + }, + { + "x": 133.77740703516005, + "y": -332.59324251006706, + "z": 0.0 + }, + { + "x": 134.7823397648484, + "y": -332.59334982716314, + "z": 0.0 + }, + { + "x": 135.7872724945369, + "y": -332.5934571442592, + "z": 0.0 + }, + { + "x": 136.792205224225, + "y": -332.59356446135524, + "z": 0.0 + }, + { + "x": 137.7971379539133, + "y": -332.5936717784513, + "z": 0.0 + }, + { + "x": 138.80207068360184, + "y": -332.5937790955474, + "z": 0.0 + }, + { + "x": 139.80700341328992, + "y": -332.5938864126434, + "z": 0.0 + }, + { + "x": 140.81193614297823, + "y": -332.5939937297395, + "z": 0.0 + }, + { + "x": 141.81686887266676, + "y": -332.5941010468356, + "z": 0.0 + }, + { + "x": 142.82180160235484, + "y": -332.5942083639316, + "z": 0.0 + }, + { + "x": 143.82673433204315, + "y": -332.5943156810277, + "z": 0.0 + }, + { + "x": 144.83166706173168, + "y": -332.5944229981238, + "z": 0.0 + }, + { + "x": 145.83659979141999, + "y": -332.5945303152198, + "z": 0.0 + }, + { + "x": 146.84153252110806, + "y": -332.5946376323158, + "z": 0.0 + }, + { + "x": 147.8464652507964, + "y": -332.5947449494119, + "z": 0.0 + }, + { + "x": 148.85139798048493, + "y": -332.594852266508, + "z": 0.0 + }, + { + "x": 149.856330710173, + "y": -332.594959583604, + "z": 0.0 + }, + { + "x": 150.86126343986132, + "y": -332.5950669007001, + "z": 0.0 + }, + { + "x": 151.86619616954985, + "y": -332.59517421779617, + "z": 0.0 + }, + { + "x": 152.87112889923793, + "y": -332.5952815348922, + "z": 0.0 + }, + { + "x": 153.87606162892624, + "y": -332.5953888519883, + "z": 0.0 + }, + { + "x": 154.88099435861477, + "y": -332.59549616908436, + "z": 0.0 + }, + { + "x": 155.88592708830285, + "y": -332.5956034861804, + "z": 0.0 + }, + { + "x": 156.89085981799138, + "y": -332.59571080327646, + "z": 0.0 + }, + { + "x": 157.8957925476795, + "y": -332.5958181203725, + "z": 0.0 + }, + { + "x": 158.9007252773678, + "y": -332.59592543746857, + "z": 0.0 + }, + { + "x": 159.90565800705633, + "y": -332.59603275456465, + "z": 0.0 + }, + { + "x": 160.9105907367444, + "y": -332.59614007166067, + "z": 0.0 + }, + { + "x": 161.91552346643294, + "y": -332.59624738875675, + "z": 0.0 + }, + { + "x": 162.92045619612102, + "y": -332.5963547058528, + "z": 0.0 + }, + { + "x": 163.92538892580933, + "y": -332.59646202294886, + "z": 0.0 + }, + { + "x": 164.93032165549786, + "y": -332.59656934004494, + "z": 0.0 + }, + { + "x": 165.93525438518594, + "y": -332.59667665714096, + "z": 0.0 + }, + { + "x": 166.94018711487448, + "y": -332.59678397423704, + "z": 0.0 + }, + { + "x": 167.94511984456258, + "y": -332.59689129133307, + "z": 0.0 + }, + { + "x": 168.9500525742509, + "y": -332.59699860842915, + "z": 0.0 + }, + { + "x": 169.95498530393942, + "y": -332.5971059255252, + "z": 0.0 + }, + { + "x": 170.95991803362753, + "y": -332.59721324262125, + "z": 0.0 + }, + { + "x": 171.96485076331584, + "y": -332.59732055971733, + "z": 0.0 + }, + { + "x": 172.9697834930044, + "y": -332.5974278768134, + "z": 0.0 + }, + { + "x": 173.97471622269248, + "y": -332.59753519390944, + "z": 0.0 + }, + { + "x": 174.97964895238078, + "y": -332.5976425110055, + "z": 0.0 + }, + { + "x": 175.98458168206935, + "y": -332.5977498281016, + "z": 0.0 + }, + { + "x": 176.98951441175765, + "y": -332.5978571451976, + "z": 0.0 + }, + { + "x": 177.99444714144573, + "y": -332.59796446229365, + "z": 0.0 + }, + { + "x": 178.99937987113407, + "y": -332.5980717793897, + "z": 0.0 + }, + { + "x": 180.0043126008226, + "y": -332.5981790964858, + "z": 0.0 + }, + { + "x": 181.00924533051068, + "y": -332.59828641358183, + "z": 0.0 + }, + { + "x": 182.014178060199, + "y": -332.5983937306779, + "z": 0.0 + }, + { + "x": 183.01911078988755, + "y": -332.598501047774, + "z": 0.0 + }, + { + "x": 184.02404351957563, + "y": -332.59860836487, + "z": 0.0 + }, + { + "x": 185.02897624926393, + "y": -332.5987156819661, + "z": 0.0 + }, + { + "x": 186.0339089789525, + "y": -332.5988229990622, + "z": 0.0 + }, + { + "x": 187.03884170864058, + "y": -332.5989303161582, + "z": 0.0 + }, + { + "x": 188.0437744383289, + "y": -332.5990376332543, + "z": 0.0 + }, + { + "x": 189.04870716801744, + "y": -332.59914495035036, + "z": 0.0 + }, + { + "x": 190.05363989770552, + "y": -332.5992522674464, + "z": 0.0 + }, + { + "x": 191.05857262739386, + "y": -332.59935958454247, + "z": 0.0 + }, + { + "x": 192.0635053570824, + "y": -332.59946690163855, + "z": 0.0 + }, + { + "x": 193.06843808677073, + "y": -332.5995742187346, + "z": 0.0 + }, + { + "x": 194.0733708164588, + "y": -332.5996815358306, + "z": 0.0 + }, + { + "x": 195.0783035461471, + "y": -332.5997888529267, + "z": 0.0 + }, + { + "x": 196.08323627583565, + "y": -332.59989617002276, + "z": 0.0 + }, + { + "x": 197.08816900552375, + "y": -332.6000034871188, + "z": 0.0 + }, + { + "x": 198.09310173521206, + "y": -332.60011080421486, + "z": 0.0 + }, + { + "x": 199.0980344649006, + "y": -332.60021812131095, + "z": 0.0 + }, + { + "x": 200.1029671945887, + "y": -332.60032543840697, + "z": 0.0 + }, + { + "x": 201.107899924277, + "y": -332.60043275550305, + "z": 0.0 + }, + { + "x": 202.11283265396554, + "y": -332.60054007259913, + "z": 0.0 + }, + { + "x": 203.11776538365388, + "y": -332.60064738969515, + "z": 0.0 + }, + { + "x": 204.12269811334173, + "y": -332.6007547067912, + "z": 0.0 + }, + { + "x": 205.1276308430305, + "y": -332.6008620238873, + "z": 0.0 + }, + { + "x": 206.13256357271882, + "y": -332.60096934098334, + "z": 0.0 + }, + { + "x": 207.13749630240667, + "y": -332.60107665807936, + "z": 0.0 + }, + { + "x": 208.14242903209546, + "y": -332.6011839751755, + "z": 0.0 + }, + { + "x": 209.14736176178377, + "y": -332.6012912922715, + "z": 0.0 + }, + { + "x": 210.15229449147185, + "y": -332.60139860936755, + "z": 0.0 + }, + { + "x": 211.15722722116018, + "y": -332.60150592646363, + "z": 0.0 + }, + { + "x": 212.16215995084872, + "y": -332.6016132435597, + "z": 0.0 + }, + { + "x": 213.16709268053702, + "y": -332.60172056065574, + "z": 0.0 + }, + { + "x": 214.1720254102249, + "y": -332.60182787775176, + "z": 0.0 + }, + { + "x": 215.17695813991367, + "y": -332.6019351948479, + "z": 0.0 + }, + { + "x": 216.18189086960197, + "y": -332.6020425119439, + "z": 0.0 + }, + { + "x": 217.18682359928982, + "y": -332.60214982903994, + "z": 0.0 + }, + { + "x": 218.1917563289786, + "y": -332.6022571461361, + "z": 0.0 + }, + { + "x": 219.19668905866692, + "y": -332.6023644632321, + "z": 0.0 + }, + { + "x": 220.201621788355, + "y": -332.60247178032813, + "z": 0.0 + }, + { + "x": 221.20655451804333, + "y": -332.6025790974242, + "z": 0.0 + }, + { + "x": 222.21148724773187, + "y": -332.6026864145203, + "z": 0.0 + }, + { + "x": 223.21641997741995, + "y": -332.6027937316163, + "z": 0.0 + }, + { + "x": 224.22135270710828, + "y": -332.6029010487124, + "z": 0.0 + }, + { + "x": 225.22628543679681, + "y": -332.6030083658085, + "z": 0.0 + }, + { + "x": 226.23121816648515, + "y": -332.6031156829045, + "z": 0.0 + }, + { + "x": 227.236150896173, + "y": -332.6032230000005, + "z": 0.0 + }, + { + "x": 228.24108362586176, + "y": -332.60333031709666, + "z": 0.0 + }, + { + "x": 229.2460163555501, + "y": -332.6034376341927, + "z": 0.0 + }, + { + "x": 230.25094908523792, + "y": -332.6035449512887, + "z": 0.0 + }, + { + "x": 231.25588181492668, + "y": -332.60365226838485, + "z": 0.0 + }, + { + "x": 232.260814544615, + "y": -332.6037595854809, + "z": 0.0 + }, + { + "x": 233.26574727430304, + "y": -332.6038669025769, + "z": 0.0 + }, + { + "x": 234.27068000399137, + "y": -332.603974219673, + "z": 0.0 + }, + { + "x": 235.2756127336799, + "y": -332.60408153676906, + "z": 0.0 + }, + { + "x": 236.280545463368, + "y": -332.6041888538651, + "z": 0.0 + }, + { + "x": 237.28547819305626, + "y": -332.60429617096116, + "z": 0.0 + }, + { + "x": 238.2904109227448, + "y": -332.60440348805724, + "z": 0.0 + }, + { + "x": 239.29534365243288, + "y": -332.60451080515327, + "z": 0.0 + }, + { + "x": 240.30027638212115, + "y": -332.60461812224935, + "z": 0.0 + }, + { + "x": 241.30520911180972, + "y": -332.60472543934543, + "z": 0.0 + }, + { + "x": 242.31014184149802, + "y": -332.60483275644145, + "z": 0.0 + }, + { + "x": 243.31507457118607, + "y": -332.6049400735375, + "z": 0.0 + }, + { + "x": 244.32000730087438, + "y": -332.60504739063356, + "z": 0.0 + }, + { + "x": 245.3249400305629, + "y": -332.60515470772964, + "z": 0.0 + }, + { + "x": 246.329872760251, + "y": -332.60526202482566, + "z": 0.0 + }, + { + "x": 247.33480548993927, + "y": -332.60536934192174, + "z": 0.0 + }, + { + "x": 248.33973821962783, + "y": -332.6054766590178, + "z": 0.0 + }, + { + "x": 249.3446709493159, + "y": -332.60558397611385, + "z": 0.0 + }, + { + "x": 250.3496036790042, + "y": -332.60569129320993, + "z": 0.0 + }, + { + "x": 251.35453640869272, + "y": -332.605798610306, + "z": 0.0 + }, + { + "x": 252.3594691383808, + "y": -332.60590592740203, + "z": 0.0 + }, + { + "x": 253.3644018680693, + "y": -332.6060132444981, + "z": 0.0 + }, + { + "x": 254.3693345977574, + "y": -332.60612056159414, + "z": 0.0 + }, + { + "x": 255.37426732744572, + "y": -332.6062278786902, + "z": 0.0 + }, + { + "x": 256.37920005713426, + "y": -332.6063351957863, + "z": 0.0 + }, + { + "x": 257.3841327868223, + "y": -332.6064425128823, + "z": 0.0 + }, + { + "x": 258.3890655165108, + "y": -332.6065498299784, + "z": 0.0 + }, + { + "x": 259.3939982461989, + "y": -332.60665714707443, + "z": 0.0 + }, + { + "x": 260.3989309758872, + "y": -332.6067644641705, + "z": 0.0 + }, + { + "x": 261.4038637055757, + "y": -332.6068717812666, + "z": 0.0 + }, + { + "x": 262.4087964352638, + "y": -332.6069790983626, + "z": 0.0 + }, + { + "x": 263.4137291649524, + "y": -332.6070864154587, + "z": 0.0 + }, + { + "x": 264.4186618946404, + "y": -332.6071937325547, + "z": 0.0 + }, + { + "x": 265.4235946243287, + "y": -332.6073010496508, + "z": 0.0 + }, + { + "x": 266.42852735401726, + "y": -332.6074083667469, + "z": 0.0 + }, + { + "x": 267.4334600837053, + "y": -332.6075156838429, + "z": 0.0 + }, + { + "x": 268.4383928133936, + "y": -332.607623000939, + "z": 0.0 + }, + { + "x": 269.44332554308215, + "y": -332.60773031803507, + "z": 0.0 + }, + { + "x": 270.44825827277026, + "y": -332.6078376351311, + "z": 0.0 + }, + { + "x": 271.45319100245854, + "y": -332.6079449522272, + "z": 0.0 + }, + { + "x": 272.45812373214704, + "y": -332.60805226932325, + "z": 0.0 + }, + { + "x": 273.46305646183515, + "y": -332.6081595864193, + "z": 0.0 + }, + { + "x": 274.46798919152366, + "y": -332.60826690351536, + "z": 0.0 + }, + { + "x": 275.4729219212117, + "y": -332.6083742206114, + "z": 0.0 + }, + { + "x": 276.47785465090027, + "y": -332.60848153770746, + "z": 0.0 + }, + { + "x": 277.4827873805884, + "y": -332.6085888548035, + "z": 0.0 + }, + { + "x": 278.48772011027665, + "y": -332.60869617189957, + "z": 0.0 + }, + { + "x": 279.49265283996516, + "y": -332.60880348899565, + "z": 0.0 + }, + { + "x": 280.49758556965327, + "y": -332.60891080609167, + "z": 0.0 + }, + { + "x": 281.50251829934155, + "y": -332.60901812318775, + "z": 0.0 + }, + { + "x": 282.50745102903005, + "y": -332.60912544028383, + "z": 0.0 + }, + { + "x": 283.51238375871816, + "y": -332.60923275737986, + "z": 0.0 + }, + { + "x": 284.5173164884065, + "y": -332.60934007447594, + "z": 0.0 + }, + { + "x": 285.522249218095, + "y": -332.609447391572, + "z": 0.0 + }, + { + "x": 286.5271819477833, + "y": -332.60955470866804, + "z": 0.0 + }, + { + "x": 287.53211467747116, + "y": -332.60966202576407, + "z": 0.0 + }, + { + "x": 288.5370474071599, + "y": -332.6097693428602, + "z": 0.0 + }, + { + "x": 289.54198312081223, + "y": -332.6098766602738, + "z": 0.0 + }, + { + "x": 290.54733166367475, + "y": -332.6099832501811, + "z": 0.0 + }, + { + "x": 291.55227276326934, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 292.55720549868784, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 293.5621382341064, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 294.56707096952493, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 295.5720037049434, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 296.5769364403619, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 297.58186917578047, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 298.586801911199, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 299.5917346466175, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 300.59666738203606, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 301.6016001174546, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 302.6065328528731, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 303.6114655882916, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 304.61639832371014, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 305.6213310591287, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 306.6262637945472, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 307.63119652996573, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 308.6361292653843, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 309.6410620008028, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 310.64599473622127, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 311.6509274716398, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 312.65586020705837, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 313.66079294247686, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 314.6657256778954, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 315.67065841331396, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 316.67559114873245, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 317.68052388415094, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 318.6854566195695, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 319.69038935498804, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 320.69532209040653, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 321.7002548258251, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 322.70518756124363, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 323.7101202966621, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 324.7150530320806, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 325.71998576749917, + "y": -332.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 32, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 101.6199870840165, + "y": -328.58905350038367, + "z": 0.0 + }, + { + "x": 102.62491967524001, + "y": -328.5895918428066, + "z": 0.0 + }, + { + "x": 103.62985230582132, + "y": -328.5900230199937, + "z": 0.0 + }, + { + "x": 104.63478503550962, + "y": -328.59013033708976, + "z": 0.0 + }, + { + "x": 105.63971776519793, + "y": -328.59023765418584, + "z": 0.0 + }, + { + "x": 106.64465049488625, + "y": -328.59034497128187, + "z": 0.0 + }, + { + "x": 107.64958322457456, + "y": -328.5904522883779, + "z": 0.0 + }, + { + "x": 108.65451595426286, + "y": -328.590559605474, + "z": 0.0 + }, + { + "x": 109.65944868395118, + "y": -328.59066692257005, + "z": 0.0 + }, + { + "x": 110.66438141363949, + "y": -328.5907742396661, + "z": 0.0 + }, + { + "x": 111.6693141433278, + "y": -328.5908815567622, + "z": 0.0 + }, + { + "x": 112.67424687301612, + "y": -328.59098887385824, + "z": 0.0 + }, + { + "x": 113.67917960270442, + "y": -328.59109619095426, + "z": 0.0 + }, + { + "x": 114.68411233239273, + "y": -328.59120350805034, + "z": 0.0 + }, + { + "x": 115.68904506208104, + "y": -328.5913108251464, + "z": 0.0 + }, + { + "x": 116.69397779176936, + "y": -328.59141814224245, + "z": 0.0 + }, + { + "x": 117.69891052145766, + "y": -328.59152545933847, + "z": 0.0 + }, + { + "x": 118.70384325114597, + "y": -328.5916327764346, + "z": 0.0 + }, + { + "x": 119.70877598083429, + "y": -328.59174009353063, + "z": 0.0 + }, + { + "x": 120.7137087105226, + "y": -328.59184741062666, + "z": 0.0 + }, + { + "x": 121.7186414402109, + "y": -328.5919547277228, + "z": 0.0 + }, + { + "x": 122.72357416989922, + "y": -328.5920620448188, + "z": 0.0 + }, + { + "x": 123.72850689958754, + "y": -328.59216936191484, + "z": 0.0 + }, + { + "x": 124.73343962927585, + "y": -328.5922766790109, + "z": 0.0 + }, + { + "x": 125.73837235896416, + "y": -328.592383996107, + "z": 0.0 + }, + { + "x": 126.74330508865248, + "y": -328.592491313203, + "z": 0.0 + }, + { + "x": 127.74823781834078, + "y": -328.5925986302991, + "z": 0.0 + }, + { + "x": 128.7531705480291, + "y": -328.5927059473952, + "z": 0.0 + }, + { + "x": 129.75810327771742, + "y": -328.5928132644912, + "z": 0.0 + }, + { + "x": 130.76303600740573, + "y": -328.59292058158724, + "z": 0.0 + }, + { + "x": 131.76796873709404, + "y": -328.5930278986834, + "z": 0.0 + }, + { + "x": 132.77290146678234, + "y": -328.5931352157794, + "z": 0.0 + }, + { + "x": 133.77783419647065, + "y": -328.5932425328754, + "z": 0.0 + }, + { + "x": 134.78276692615898, + "y": -328.5933498499715, + "z": 0.0 + }, + { + "x": 135.78769965584726, + "y": -328.5934571670676, + "z": 0.0 + }, + { + "x": 136.7926323855356, + "y": -328.5935644841636, + "z": 0.0 + }, + { + "x": 137.7975651152239, + "y": -328.5936718012597, + "z": 0.0 + }, + { + "x": 138.8024978449122, + "y": -328.59377911835577, + "z": 0.0 + }, + { + "x": 139.80743057460052, + "y": -328.5938864354518, + "z": 0.0 + }, + { + "x": 140.81236330428882, + "y": -328.5939937525479, + "z": 0.0 + }, + { + "x": 141.81729603397713, + "y": -328.59410106964395, + "z": 0.0 + }, + { + "x": 142.82222876366544, + "y": -328.59420838674, + "z": 0.0 + }, + { + "x": 143.82716149335374, + "y": -328.59431570383606, + "z": 0.0 + }, + { + "x": 144.83209422304205, + "y": -328.59442302093214, + "z": 0.0 + }, + { + "x": 145.83702695273035, + "y": -328.59453033802816, + "z": 0.0 + }, + { + "x": 146.84195968241866, + "y": -328.5946376551242, + "z": 0.0 + }, + { + "x": 147.846892412107, + "y": -328.59474497222027, + "z": 0.0 + }, + { + "x": 148.8518251417953, + "y": -328.59485228931635, + "z": 0.0 + }, + { + "x": 149.8567578714836, + "y": -328.5949596064124, + "z": 0.0 + }, + { + "x": 150.86169060117192, + "y": -328.59506692350845, + "z": 0.0 + }, + { + "x": 151.86662333086022, + "y": -328.59517424060454, + "z": 0.0 + }, + { + "x": 152.87155606054853, + "y": -328.59528155770056, + "z": 0.0 + }, + { + "x": 153.87648879023683, + "y": -328.59538887479664, + "z": 0.0 + }, + { + "x": 154.88142151992514, + "y": -328.5954961918927, + "z": 0.0 + }, + { + "x": 155.88635424961345, + "y": -328.59560350898875, + "z": 0.0 + }, + { + "x": 156.89128697930175, + "y": -328.5957108260848, + "z": 0.0 + }, + { + "x": 157.8962197089901, + "y": -328.59581814318085, + "z": 0.0 + }, + { + "x": 158.9011524386784, + "y": -328.59592546027693, + "z": 0.0 + }, + { + "x": 159.9060851683667, + "y": -328.596032777373, + "z": 0.0 + }, + { + "x": 160.911017898055, + "y": -328.59614009446904, + "z": 0.0 + }, + { + "x": 161.9159506277433, + "y": -328.5962474115651, + "z": 0.0 + }, + { + "x": 162.92088335743162, + "y": -328.59635472866114, + "z": 0.0 + }, + { + "x": 163.92581608711993, + "y": -328.5964620457572, + "z": 0.0 + }, + { + "x": 164.93074881680823, + "y": -328.5965693628533, + "z": 0.0 + }, + { + "x": 165.93568154649654, + "y": -328.5966766799493, + "z": 0.0 + }, + { + "x": 166.94061427618485, + "y": -328.5967839970454, + "z": 0.0 + }, + { + "x": 167.94554700587318, + "y": -328.59689131414143, + "z": 0.0 + }, + { + "x": 168.9504797355615, + "y": -328.5969986312375, + "z": 0.0 + }, + { + "x": 169.9554124652498, + "y": -328.5971059483336, + "z": 0.0 + }, + { + "x": 170.96034519493813, + "y": -328.5972132654296, + "z": 0.0 + }, + { + "x": 171.96527792462643, + "y": -328.5973205825257, + "z": 0.0 + }, + { + "x": 172.97021065431477, + "y": -328.5974278996218, + "z": 0.0 + }, + { + "x": 173.97514338400308, + "y": -328.5975352167178, + "z": 0.0 + }, + { + "x": 174.98007611369138, + "y": -328.5976425338139, + "z": 0.0 + }, + { + "x": 175.98500884337972, + "y": -328.59774985090996, + "z": 0.0 + }, + { + "x": 176.98994157306802, + "y": -328.597857168006, + "z": 0.0 + }, + { + "x": 177.99487430275633, + "y": -328.597964485102, + "z": 0.0 + }, + { + "x": 178.99980703244466, + "y": -328.5980718021981, + "z": 0.0 + }, + { + "x": 180.00473976213297, + "y": -328.5981791192942, + "z": 0.0 + }, + { + "x": 181.00967249182128, + "y": -328.5982864363902, + "z": 0.0 + }, + { + "x": 182.01460522150958, + "y": -328.5983937534863, + "z": 0.0 + }, + { + "x": 183.01953795119792, + "y": -328.59850107058236, + "z": 0.0 + }, + { + "x": 184.02447068088622, + "y": -328.5986083876784, + "z": 0.0 + }, + { + "x": 185.02940341057453, + "y": -328.59871570477446, + "z": 0.0 + }, + { + "x": 186.03433614026287, + "y": -328.59882302187054, + "z": 0.0 + }, + { + "x": 187.03926886995117, + "y": -328.59893033896657, + "z": 0.0 + }, + { + "x": 188.0442015996395, + "y": -328.59903765606265, + "z": 0.0 + }, + { + "x": 189.0491343293278, + "y": -328.59914497315873, + "z": 0.0 + }, + { + "x": 190.05406705901612, + "y": -328.59925229025475, + "z": 0.0 + }, + { + "x": 191.05899978870445, + "y": -328.59935960735083, + "z": 0.0 + }, + { + "x": 192.06393251839276, + "y": -328.5994669244469, + "z": 0.0 + }, + { + "x": 193.0688652480811, + "y": -328.59957424154294, + "z": 0.0 + }, + { + "x": 194.0737979777694, + "y": -328.59968155863896, + "z": 0.0 + }, + { + "x": 195.0787307074577, + "y": -328.59978887573504, + "z": 0.0 + }, + { + "x": 196.08366343714601, + "y": -328.5998961928311, + "z": 0.0 + }, + { + "x": 197.08859616683435, + "y": -328.60000350992715, + "z": 0.0 + }, + { + "x": 198.09352889652266, + "y": -328.60011082702323, + "z": 0.0 + }, + { + "x": 199.09846162621096, + "y": -328.6002181441193, + "z": 0.0 + }, + { + "x": 200.1033943558993, + "y": -328.60032546121533, + "z": 0.0 + }, + { + "x": 201.1083270855876, + "y": -328.6004327783114, + "z": 0.0 + }, + { + "x": 202.1132598152759, + "y": -328.6005400954075, + "z": 0.0 + }, + { + "x": 203.11819254496424, + "y": -328.6006474125035, + "z": 0.0 + }, + { + "x": 204.12312527465255, + "y": -328.60075472959954, + "z": 0.0 + }, + { + "x": 205.12805800434086, + "y": -328.6008620466957, + "z": 0.0 + }, + { + "x": 206.1329907340292, + "y": -328.6009693637917, + "z": 0.0 + }, + { + "x": 207.1379234637175, + "y": -328.60107668088773, + "z": 0.0 + }, + { + "x": 208.14285619340583, + "y": -328.60118399798387, + "z": 0.0 + }, + { + "x": 209.14778892309414, + "y": -328.6012913150799, + "z": 0.0 + }, + { + "x": 210.15272165278245, + "y": -328.6013986321759, + "z": 0.0 + }, + { + "x": 211.15765438247078, + "y": -328.601505949272, + "z": 0.0 + }, + { + "x": 212.1625871121591, + "y": -328.6016132663681, + "z": 0.0 + }, + { + "x": 213.1675198418474, + "y": -328.6017205834641, + "z": 0.0 + }, + { + "x": 214.17245257153573, + "y": -328.6018279005601, + "z": 0.0 + }, + { + "x": 215.17738530122404, + "y": -328.60193521765626, + "z": 0.0 + }, + { + "x": 216.18231803091234, + "y": -328.6020425347523, + "z": 0.0 + }, + { + "x": 217.18725076060065, + "y": -328.6021498518483, + "z": 0.0 + }, + { + "x": 218.19218349028898, + "y": -328.60225716894445, + "z": 0.0 + }, + { + "x": 219.1971162199773, + "y": -328.60236448604047, + "z": 0.0 + }, + { + "x": 220.2020489496656, + "y": -328.6024718031365, + "z": 0.0 + }, + { + "x": 221.20698167935393, + "y": -328.6025791202326, + "z": 0.0 + }, + { + "x": 222.21191440904224, + "y": -328.60268643732866, + "z": 0.0 + }, + { + "x": 223.21684713873054, + "y": -328.6027937544247, + "z": 0.0 + }, + { + "x": 224.22177986841888, + "y": -328.60290107152076, + "z": 0.0 + }, + { + "x": 225.22671259810718, + "y": -328.60300838861684, + "z": 0.0 + }, + { + "x": 226.23164532779552, + "y": -328.60311570571287, + "z": 0.0 + }, + { + "x": 227.23657805748383, + "y": -328.6032230228089, + "z": 0.0 + }, + { + "x": 228.24151078717213, + "y": -328.603330339905, + "z": 0.0 + }, + { + "x": 229.24644351686047, + "y": -328.60343765700105, + "z": 0.0 + }, + { + "x": 230.25137624654874, + "y": -328.6035449740971, + "z": 0.0 + }, + { + "x": 231.25630897623705, + "y": -328.6036522911932, + "z": 0.0 + }, + { + "x": 232.26124170592536, + "y": -328.60375960828924, + "z": 0.0 + }, + { + "x": 233.26617443561364, + "y": -328.60386692538526, + "z": 0.0 + }, + { + "x": 234.27110716530197, + "y": -328.60397424248134, + "z": 0.0 + }, + { + "x": 235.27603989499028, + "y": -328.6040815595774, + "z": 0.0 + }, + { + "x": 236.28097262467858, + "y": -328.60418887667345, + "z": 0.0 + }, + { + "x": 237.28590535436686, + "y": -328.6042961937695, + "z": 0.0 + }, + { + "x": 238.29083808405517, + "y": -328.6044035108656, + "z": 0.0 + }, + { + "x": 239.29577081374347, + "y": -328.60451082796163, + "z": 0.0 + }, + { + "x": 240.30070354343175, + "y": -328.6046181450577, + "z": 0.0 + }, + { + "x": 241.3056362731201, + "y": -328.6047254621538, + "z": 0.0 + }, + { + "x": 242.3105690028084, + "y": -328.6048327792498, + "z": 0.0 + }, + { + "x": 243.31550173249667, + "y": -328.60494009634584, + "z": 0.0 + }, + { + "x": 244.32043446218498, + "y": -328.6050474134419, + "z": 0.0 + }, + { + "x": 245.32536719187328, + "y": -328.605154730538, + "z": 0.0 + }, + { + "x": 246.3302999215616, + "y": -328.605262047634, + "z": 0.0 + }, + { + "x": 247.33523265124987, + "y": -328.6053693647301, + "z": 0.0 + }, + { + "x": 248.3401653809382, + "y": -328.6054766818262, + "z": 0.0 + }, + { + "x": 249.3450981106265, + "y": -328.6055839989222, + "z": 0.0 + }, + { + "x": 250.3500308403148, + "y": -328.6056913160183, + "z": 0.0 + }, + { + "x": 251.3549635700031, + "y": -328.6057986331144, + "z": 0.0 + }, + { + "x": 252.3598962996914, + "y": -328.6059059502104, + "z": 0.0 + }, + { + "x": 253.36482902937968, + "y": -328.6060132673065, + "z": 0.0 + }, + { + "x": 254.36976175906798, + "y": -328.6061205844025, + "z": 0.0 + }, + { + "x": 255.37469448875632, + "y": -328.6062279014986, + "z": 0.0 + }, + { + "x": 256.3796272184446, + "y": -328.60633521859467, + "z": 0.0 + }, + { + "x": 257.3845599481329, + "y": -328.6064425356907, + "z": 0.0 + }, + { + "x": 258.3894926778212, + "y": -328.60654985278677, + "z": 0.0 + }, + { + "x": 259.3944254075095, + "y": -328.6066571698828, + "z": 0.0 + }, + { + "x": 260.3993581371978, + "y": -328.6067644869789, + "z": 0.0 + }, + { + "x": 261.4042908668861, + "y": -328.60687180407496, + "z": 0.0 + }, + { + "x": 262.4092235965744, + "y": -328.606979121171, + "z": 0.0 + }, + { + "x": 263.41415632626274, + "y": -328.60708643826706, + "z": 0.0 + }, + { + "x": 264.419089055951, + "y": -328.6071937553631, + "z": 0.0 + }, + { + "x": 265.4240217856393, + "y": -328.60730107245917, + "z": 0.0 + }, + { + "x": 266.42895451532763, + "y": -328.60740838955525, + "z": 0.0 + }, + { + "x": 267.4338872450159, + "y": -328.60751570665127, + "z": 0.0 + }, + { + "x": 268.4388199747042, + "y": -328.60762302374735, + "z": 0.0 + }, + { + "x": 269.4437527043925, + "y": -328.60773034084343, + "z": 0.0 + }, + { + "x": 270.44868543408086, + "y": -328.60783765793946, + "z": 0.0 + }, + { + "x": 271.45361816376914, + "y": -328.60794497503554, + "z": 0.0 + }, + { + "x": 272.4585508934574, + "y": -328.6080522921316, + "z": 0.0 + }, + { + "x": 273.46348362314575, + "y": -328.60815960922764, + "z": 0.0 + }, + { + "x": 274.468416352834, + "y": -328.6082669263237, + "z": 0.0 + }, + { + "x": 275.4733490825223, + "y": -328.60837424341975, + "z": 0.0 + }, + { + "x": 276.47828181221064, + "y": -328.6084815605158, + "z": 0.0 + }, + { + "x": 277.483214541899, + "y": -328.60858887761185, + "z": 0.0 + }, + { + "x": 278.48814727158725, + "y": -328.60869619470793, + "z": 0.0 + }, + { + "x": 279.49308000127553, + "y": -328.608803511804, + "z": 0.0 + }, + { + "x": 280.49801273096386, + "y": -328.60891082890004, + "z": 0.0 + }, + { + "x": 281.50294546065214, + "y": -328.6090181459961, + "z": 0.0 + }, + { + "x": 282.5078781903404, + "y": -328.6091254630922, + "z": 0.0 + }, + { + "x": 283.51281092002876, + "y": -328.6092327801882, + "z": 0.0 + }, + { + "x": 284.5177436497171, + "y": -328.6093400972843, + "z": 0.0 + }, + { + "x": 285.52267637940537, + "y": -328.6094474143804, + "z": 0.0 + }, + { + "x": 286.52760910909365, + "y": -328.6095547314764, + "z": 0.0 + }, + { + "x": 287.532541838782, + "y": -328.60966204857243, + "z": 0.0 + }, + { + "x": 288.53747456847026, + "y": -328.60976936566857, + "z": 0.0 + }, + { + "x": 289.54240729815854, + "y": -328.6098766827646, + "z": 0.0 + }, + { + "x": 290.5473400279069, + "y": -328.6099832501898, + "z": 0.0 + }, + { + "x": 291.55227276326934, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 292.55720549868784, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 293.5621382341064, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 294.56707096952493, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 295.5720037049434, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 296.5769364403619, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 297.58186917578047, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 298.586801911199, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 299.5917346466175, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 300.59666738203606, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 301.6016001174546, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 302.6065328528731, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 303.6114655882916, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 304.61639832371014, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 305.6213310591287, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 306.6262637945472, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 307.63119652996573, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 308.6361292653843, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 309.6410620008028, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 310.64599473622127, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 311.6509274716398, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 312.65586020705837, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 313.66079294247686, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 314.6657256778954, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 315.67065841331396, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 316.67559114873245, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 317.68052388415094, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 318.6854566195695, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 319.69038935498804, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 320.69532209040653, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 321.7002548258251, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 322.70518756124363, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 323.7101202966621, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 324.7150530320806, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 325.71998576749917, + "y": -328.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 33, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.71998576749917, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 324.7150530320806, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 323.7101202966621, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 322.70518756124363, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 321.7002548258251, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 320.69532209040653, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 319.69038935498804, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 318.6854566195695, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 317.68052388415094, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 316.67559114873245, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 315.67065841331396, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 314.6657256778954, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 313.66079294247686, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 312.65586020705837, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 311.6509274716398, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 310.64599473622127, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 309.6410620008028, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 308.6361292653843, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 307.63119652996573, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 306.6262637945472, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 305.6213310591287, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 304.61639832371014, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 303.6114655882916, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 302.6065328528731, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 301.6016001174546, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 300.59666738203606, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 299.5917346466175, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 298.586801911199, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 297.58186917578047, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 296.5769364403619, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 295.5720037049434, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 294.56707096952493, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 293.5621382341064, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 292.55720549868784, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 291.55227276326934, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 290.54734421002297, + "y": -326.6099832501942, + "z": 0.0 + }, + { + "x": 289.5426193868317, + "y": -326.60987669401, + "z": 0.0 + }, + { + "x": 288.5376881491254, + "y": -326.6097693770728, + "z": 0.0 + }, + { + "x": 287.5327554194374, + "y": -326.6096620599766, + "z": 0.0 + }, + { + "x": 286.52782268974886, + "y": -326.6095547428806, + "z": 0.0 + }, + { + "x": 285.5228899600605, + "y": -326.60944742578454, + "z": 0.0 + }, + { + "x": 284.5179572303724, + "y": -326.60934010868846, + "z": 0.0 + }, + { + "x": 283.5130245006841, + "y": -326.6092327915924, + "z": 0.0 + }, + { + "x": 282.50809177099563, + "y": -326.6091254744964, + "z": 0.0 + }, + { + "x": 281.5031590413074, + "y": -326.6090181574003, + "z": 0.0 + }, + { + "x": 280.4982263116192, + "y": -326.60891084030425, + "z": 0.0 + }, + { + "x": 279.49329358193074, + "y": -326.60880352320817, + "z": 0.0 + }, + { + "x": 278.4883608522425, + "y": -326.6086962061121, + "z": 0.0 + }, + { + "x": 277.4834281225543, + "y": -326.608588889016, + "z": 0.0 + }, + { + "x": 276.47849539286585, + "y": -326.60848157192004, + "z": 0.0 + }, + { + "x": 275.47356266317763, + "y": -326.60837425482396, + "z": 0.0 + }, + { + "x": 274.4686299334892, + "y": -326.6082669377279, + "z": 0.0 + }, + { + "x": 273.4636972038011, + "y": -326.6081596206318, + "z": 0.0 + }, + { + "x": 272.4587644741126, + "y": -326.6080523035358, + "z": 0.0 + }, + { + "x": 271.4538317444244, + "y": -326.60794498643975, + "z": 0.0 + }, + { + "x": 270.4488990147362, + "y": -326.60783766934367, + "z": 0.0 + }, + { + "x": 269.44396628504774, + "y": -326.6077303522476, + "z": 0.0 + }, + { + "x": 268.4390335553595, + "y": -326.6076230351515, + "z": 0.0 + }, + { + "x": 267.4341008256712, + "y": -326.6075157180554, + "z": 0.0 + }, + { + "x": 266.42916809598285, + "y": -326.60740840095946, + "z": 0.0 + }, + { + "x": 265.4242353662946, + "y": -326.6073010838634, + "z": 0.0 + }, + { + "x": 264.4193026366063, + "y": -326.6071937667673, + "z": 0.0 + }, + { + "x": 263.41436990691795, + "y": -326.6070864496712, + "z": 0.0 + }, + { + "x": 262.40943717722973, + "y": -326.60697913257513, + "z": 0.0 + }, + { + "x": 261.4045044475413, + "y": -326.60687181547917, + "z": 0.0 + }, + { + "x": 260.39957171785306, + "y": -326.6067644983831, + "z": 0.0 + }, + { + "x": 259.39463898816484, + "y": -326.606657181287, + "z": 0.0 + }, + { + "x": 258.3897062584764, + "y": -326.6065498641909, + "z": 0.0 + }, + { + "x": 257.3847735287882, + "y": -326.60644254709484, + "z": 0.0 + }, + { + "x": 256.37984079909984, + "y": -326.6063352299989, + "z": 0.0 + }, + { + "x": 255.37490806941162, + "y": -326.6062279129028, + "z": 0.0 + }, + { + "x": 254.36997533972328, + "y": -326.6061205958067, + "z": 0.0 + }, + { + "x": 253.36504261003486, + "y": -326.60601327871063, + "z": 0.0 + }, + { + "x": 252.3601098803467, + "y": -326.60590596161455, + "z": 0.0 + }, + { + "x": 251.35517715065828, + "y": -326.6057986445186, + "z": 0.0 + }, + { + "x": 250.35024442097009, + "y": -326.6056913274225, + "z": 0.0 + }, + { + "x": 249.3453116912818, + "y": -326.6055840103264, + "z": 0.0 + }, + { + "x": 248.3403789615934, + "y": -326.60547669323034, + "z": 0.0 + }, + { + "x": 247.33544623190517, + "y": -326.60536937613426, + "z": 0.0 + }, + { + "x": 246.3305135022169, + "y": -326.6052620590382, + "z": 0.0 + }, + { + "x": 245.32558077252847, + "y": -326.6051547419422, + "z": 0.0 + }, + { + "x": 244.32064804284028, + "y": -326.60504742484613, + "z": 0.0 + }, + { + "x": 243.31571531315197, + "y": -326.60494010775005, + "z": 0.0 + }, + { + "x": 242.31078258346358, + "y": -326.604832790654, + "z": 0.0 + }, + { + "x": 241.30584985377527, + "y": -326.604725473558, + "z": 0.0 + }, + { + "x": 240.30091712408705, + "y": -326.6046181564619, + "z": 0.0 + }, + { + "x": 239.29598439439877, + "y": -326.60451083936584, + "z": 0.0 + }, + { + "x": 238.29105166471035, + "y": -326.60440352226976, + "z": 0.0 + }, + { + "x": 237.28611893502216, + "y": -326.6042962051737, + "z": 0.0 + }, + { + "x": 236.28118620533388, + "y": -326.6041888880776, + "z": 0.0 + }, + { + "x": 235.27625347564546, + "y": -326.60408157098163, + "z": 0.0 + }, + { + "x": 234.27132074595727, + "y": -326.60397425388555, + "z": 0.0 + }, + { + "x": 233.26638801626893, + "y": -326.6038669367895, + "z": 0.0 + }, + { + "x": 232.26145528658054, + "y": -326.6037596196934, + "z": 0.0 + }, + { + "x": 231.25652255689224, + "y": -326.6036523025974, + "z": 0.0 + }, + { + "x": 230.25158982720416, + "y": -326.60354498550123, + "z": 0.0 + }, + { + "x": 229.24665709751565, + "y": -326.60343766840526, + "z": 0.0 + }, + { + "x": 228.24172436782732, + "y": -326.6033303513092, + "z": 0.0 + }, + { + "x": 227.23679163813924, + "y": -326.6032230342131, + "z": 0.0 + }, + { + "x": 226.2318589084507, + "y": -326.603115717117, + "z": 0.0 + }, + { + "x": 225.22692617876237, + "y": -326.60300840002105, + "z": 0.0 + }, + { + "x": 224.22199344907418, + "y": -326.602901082925, + "z": 0.0 + }, + { + "x": 223.21706071938584, + "y": -326.6027937658289, + "z": 0.0 + }, + { + "x": 222.21212798969742, + "y": -326.6026864487328, + "z": 0.0 + }, + { + "x": 221.20719526000923, + "y": -326.60257913163673, + "z": 0.0 + }, + { + "x": 220.2022625303209, + "y": -326.60247181454065, + "z": 0.0 + }, + { + "x": 219.19732980063247, + "y": -326.6023644974447, + "z": 0.0 + }, + { + "x": 218.19239707094417, + "y": -326.6022571803486, + "z": 0.0 + }, + { + "x": 217.18746434125606, + "y": -326.6021498632525, + "z": 0.0 + }, + { + "x": 216.18253161156753, + "y": -326.60204254615644, + "z": 0.0 + }, + { + "x": 215.17759888187922, + "y": -326.6019352290605, + "z": 0.0 + }, + { + "x": 214.17266615219114, + "y": -326.6018279119643, + "z": 0.0 + }, + { + "x": 213.16773342250258, + "y": -326.6017205948683, + "z": 0.0 + }, + { + "x": 212.16280069281427, + "y": -326.60161327777223, + "z": 0.0 + }, + { + "x": 211.15786796312608, + "y": -326.60150596067615, + "z": 0.0 + }, + { + "x": 210.15293523343774, + "y": -326.60139864358007, + "z": 0.0 + }, + { + "x": 209.14800250374932, + "y": -326.6012913264841, + "z": 0.0 + }, + { + "x": 208.14306977406102, + "y": -326.601184009388, + "z": 0.0 + }, + { + "x": 207.1381370443729, + "y": -326.60107669229194, + "z": 0.0 + }, + { + "x": 206.13320431468438, + "y": -326.60096937519586, + "z": 0.0 + }, + { + "x": 205.12827158499604, + "y": -326.6008620580999, + "z": 0.0 + }, + { + "x": 204.12333885530796, + "y": -326.6007547410037, + "z": 0.0 + }, + { + "x": 203.11840612561943, + "y": -326.60064742390773, + "z": 0.0 + }, + { + "x": 202.1134733959311, + "y": -326.60054010681165, + "z": 0.0 + }, + { + "x": 201.1085406662429, + "y": -326.60043278971557, + "z": 0.0 + }, + { + "x": 200.1036079365546, + "y": -326.6003254726195, + "z": 0.0 + }, + { + "x": 199.09867520686615, + "y": -326.6002181555235, + "z": 0.0 + }, + { + "x": 198.09374247717795, + "y": -326.60011083842744, + "z": 0.0 + }, + { + "x": 197.08880974748965, + "y": -326.60000352133136, + "z": 0.0 + }, + { + "x": 196.0838770178012, + "y": -326.5998962042353, + "z": 0.0 + }, + { + "x": 195.078944288113, + "y": -326.5997888871392, + "z": 0.0 + }, + { + "x": 194.0740115584247, + "y": -326.5996815700431, + "z": 0.0 + }, + { + "x": 193.06907882873628, + "y": -326.59957425294715, + "z": 0.0 + }, + { + "x": 192.06414609904795, + "y": -326.59946693585107, + "z": 0.0 + }, + { + "x": 191.05921336935975, + "y": -326.599359618755, + "z": 0.0 + }, + { + "x": 190.05428063967142, + "y": -326.5992523016589, + "z": 0.0 + }, + { + "x": 189.049347909983, + "y": -326.59914498456294, + "z": 0.0 + }, + { + "x": 188.0444151802948, + "y": -326.59903766746686, + "z": 0.0 + }, + { + "x": 187.03948245060647, + "y": -326.5989303503708, + "z": 0.0 + }, + { + "x": 186.03454972091805, + "y": -326.5988230332747, + "z": 0.0 + }, + { + "x": 185.02961699122983, + "y": -326.5987157161786, + "z": 0.0 + }, + { + "x": 184.02468426154152, + "y": -326.59860839908254, + "z": 0.0 + }, + { + "x": 183.0197515318531, + "y": -326.59850108198657, + "z": 0.0 + }, + { + "x": 182.01481880216488, + "y": -326.5983937648905, + "z": 0.0 + }, + { + "x": 181.00988607247658, + "y": -326.5982864477944, + "z": 0.0 + }, + { + "x": 180.00495334278816, + "y": -326.5981791306983, + "z": 0.0 + }, + { + "x": 179.00002061309996, + "y": -326.59807181360225, + "z": 0.0 + }, + { + "x": 177.99508788341163, + "y": -326.59796449650617, + "z": 0.0 + }, + { + "x": 176.9901551537232, + "y": -326.5978571794102, + "z": 0.0 + }, + { + "x": 175.9852224240349, + "y": -326.5977498623141, + "z": 0.0 + }, + { + "x": 174.98028969434668, + "y": -326.59764254521804, + "z": 0.0 + }, + { + "x": 173.97535696465837, + "y": -326.59753522812196, + "z": 0.0 + }, + { + "x": 172.97042423496995, + "y": -326.597427911026, + "z": 0.0 + }, + { + "x": 171.96549150528173, + "y": -326.5973205939299, + "z": 0.0 + }, + { + "x": 170.96055877559343, + "y": -326.5972132768338, + "z": 0.0 + }, + { + "x": 169.95562604590498, + "y": -326.59710595973775, + "z": 0.0 + }, + { + "x": 168.95069331621679, + "y": -326.59699864264167, + "z": 0.0 + }, + { + "x": 167.94576058652848, + "y": -326.5968913255456, + "z": 0.0 + }, + { + "x": 166.94082785684003, + "y": -326.5967840084496, + "z": 0.0 + }, + { + "x": 165.93589512715184, + "y": -326.59667669135354, + "z": 0.0 + }, + { + "x": 164.93096239746342, + "y": -326.59656937425746, + "z": 0.0 + }, + { + "x": 163.92602966777523, + "y": -326.5964620571614, + "z": 0.0 + }, + { + "x": 162.92109693808692, + "y": -326.5963547400653, + "z": 0.0 + }, + { + "x": 161.9161642083985, + "y": -326.5962474229693, + "z": 0.0 + }, + { + "x": 160.9112314787103, + "y": -326.59614010587325, + "z": 0.0 + }, + { + "x": 159.9062987490219, + "y": -326.59603278877717, + "z": 0.0 + }, + { + "x": 158.9013660193337, + "y": -326.5959254716811, + "z": 0.0 + }, + { + "x": 157.8964332896454, + "y": -326.595818154585, + "z": 0.0 + }, + { + "x": 156.89150055995694, + "y": -326.59571083748904, + "z": 0.0 + }, + { + "x": 155.88656783026875, + "y": -326.59560352039296, + "z": 0.0 + }, + { + "x": 154.88163510058033, + "y": -326.5954962032969, + "z": 0.0 + }, + { + "x": 153.87670237089213, + "y": -326.5953888862008, + "z": 0.0 + }, + { + "x": 152.87176964120383, + "y": -326.5952815691047, + "z": 0.0 + }, + { + "x": 151.8668369115154, + "y": -326.59517425200875, + "z": 0.0 + }, + { + "x": 150.8619041818272, + "y": -326.59506693491267, + "z": 0.0 + }, + { + "x": 149.8569714521389, + "y": -326.5949596178166, + "z": 0.0 + }, + { + "x": 148.8520387224505, + "y": -326.5948523007205, + "z": 0.0 + }, + { + "x": 147.8471059927623, + "y": -326.5947449836244, + "z": 0.0 + }, + { + "x": 146.84217326307396, + "y": -326.59463766652834, + "z": 0.0 + }, + { + "x": 145.83724053338554, + "y": -326.5945303494324, + "z": 0.0 + }, + { + "x": 144.83230780369723, + "y": -326.5944230323363, + "z": 0.0 + }, + { + "x": 143.82737507400904, + "y": -326.5943157152402, + "z": 0.0 + }, + { + "x": 142.82244234432073, + "y": -326.59420839814413, + "z": 0.0 + }, + { + "x": 141.8175096146323, + "y": -326.59410108104817, + "z": 0.0 + }, + { + "x": 140.81257688494412, + "y": -326.5939937639521, + "z": 0.0 + }, + { + "x": 139.80764415525582, + "y": -326.593886446856, + "z": 0.0 + }, + { + "x": 138.8027114255674, + "y": -326.5937791297599, + "z": 0.0 + }, + { + "x": 137.7977786958792, + "y": -326.59367181266384, + "z": 0.0 + }, + { + "x": 136.7928459661909, + "y": -326.59356449556776, + "z": 0.0 + }, + { + "x": 135.78791323650245, + "y": -326.5934571784718, + "z": 0.0 + }, + { + "x": 134.78298050681428, + "y": -326.5933498613757, + "z": 0.0 + }, + { + "x": 133.77804777712595, + "y": -326.59324254427963, + "z": 0.0 + }, + { + "x": 132.77311504743753, + "y": -326.59313522718355, + "z": 0.0 + }, + { + "x": 131.76818231774922, + "y": -326.5930279100876, + "z": 0.0 + }, + { + "x": 130.76324958806114, + "y": -326.5929205929914, + "z": 0.0 + }, + { + "x": 129.7583168583726, + "y": -326.5928132758954, + "z": 0.0 + }, + { + "x": 128.75338412868427, + "y": -326.59270595879934, + "z": 0.0 + }, + { + "x": 127.74845139899608, + "y": -326.59259864170326, + "z": 0.0 + }, + { + "x": 126.74351866930778, + "y": -326.5924913246072, + "z": 0.0 + }, + { + "x": 125.73858593961934, + "y": -326.5923840075112, + "z": 0.0 + }, + { + "x": 124.73365320993115, + "y": -326.59227669041513, + "z": 0.0 + }, + { + "x": 123.72872048024284, + "y": -326.59216937331905, + "z": 0.0 + }, + { + "x": 122.72378775055441, + "y": -326.59206205622297, + "z": 0.0 + }, + { + "x": 121.71885502086609, + "y": -326.591954739127, + "z": 0.0 + }, + { + "x": 120.71392229117801, + "y": -326.5918474220308, + "z": 0.0 + }, + { + "x": 119.70898956148947, + "y": -326.59174010493484, + "z": 0.0 + }, + { + "x": 118.70405683180115, + "y": -326.59163278783876, + "z": 0.0 + }, + { + "x": 117.69912410211307, + "y": -326.5915254707427, + "z": 0.0 + }, + { + "x": 116.69419137242454, + "y": -326.5914181536466, + "z": 0.0 + }, + { + "x": 115.68925864273622, + "y": -326.59131083655063, + "z": 0.0 + }, + { + "x": 114.68432591304803, + "y": -326.59120351945455, + "z": 0.0 + }, + { + "x": 113.67939318335972, + "y": -326.5910962023585, + "z": 0.0 + }, + { + "x": 112.6744604536713, + "y": -326.5909888852624, + "z": 0.0 + }, + { + "x": 111.66952772398298, + "y": -326.5908815681664, + "z": 0.0 + }, + { + "x": 110.6645949942949, + "y": -326.59077425107023, + "z": 0.0 + }, + { + "x": 109.65966226460637, + "y": -326.59066693397426, + "z": 0.0 + }, + { + "x": 108.65472953491805, + "y": -326.5905596168782, + "z": 0.0 + }, + { + "x": 107.64979680522997, + "y": -326.5904522997821, + "z": 0.0 + }, + { + "x": 106.64486407554143, + "y": -326.590344982686, + "z": 0.0 + }, + { + "x": 105.63993134585311, + "y": -326.59023766559005, + "z": 0.0 + }, + { + "x": 104.63499861616492, + "y": -326.590130348494, + "z": 0.0 + }, + { + "x": 103.63006588647661, + "y": -326.5900230313979, + "z": 0.0 + }, + { + "x": 102.62577779673842, + "y": -326.5895920268997, + "z": 0.0 + }, + { + "x": 101.62105848393009, + "y": -326.5890537873581, + "z": 0.0 + } + ] + }, + { + "id": 34, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 101.61891568410292, + "y": -330.5890532134092, + "z": 0.0 + }, + { + "x": 102.6240615537416, + "y": -330.5895916587135, + "z": 0.0 + }, + { + "x": 103.62963872516602, + "y": -330.59002300858947, + "z": 0.0 + }, + { + "x": 104.63457145485432, + "y": -330.59013032568555, + "z": 0.0 + }, + { + "x": 105.63950418454274, + "y": -330.59023764278163, + "z": 0.0 + }, + { + "x": 106.64443691423106, + "y": -330.5903449598777, + "z": 0.0 + }, + { + "x": 107.64936964391914, + "y": -330.5904522769737, + "z": 0.0 + }, + { + "x": 108.65430237360768, + "y": -330.5905595940699, + "z": 0.0 + }, + { + "x": 109.659235103296, + "y": -330.59066691116584, + "z": 0.0 + }, + { + "x": 110.66416783298408, + "y": -330.5907742282619, + "z": 0.0 + }, + { + "x": 111.66910056267261, + "y": -330.590881545358, + "z": 0.0 + }, + { + "x": 112.67403329236093, + "y": -330.5909888624541, + "z": 0.0 + }, + { + "x": 113.67896602204912, + "y": -330.59109617955005, + "z": 0.0 + }, + { + "x": 114.68389875173743, + "y": -330.59120349664613, + "z": 0.0 + }, + { + "x": 115.68883148142585, + "y": -330.5913108137422, + "z": 0.0 + }, + { + "x": 116.69376421111417, + "y": -330.5914181308383, + "z": 0.0 + }, + { + "x": 117.69869694080225, + "y": -330.59152544793426, + "z": 0.0 + }, + { + "x": 118.70362967049078, + "y": -330.59163276503045, + "z": 0.0 + }, + { + "x": 119.7085624001791, + "y": -330.5917400821264, + "z": 0.0 + }, + { + "x": 120.71349512986718, + "y": -330.5918473992225, + "z": 0.0 + }, + { + "x": 121.71842785955572, + "y": -330.5919547163186, + "z": 0.0 + }, + { + "x": 122.72336058924404, + "y": -330.59206203341466, + "z": 0.0 + }, + { + "x": 123.72829331893224, + "y": -330.59216935051063, + "z": 0.0 + }, + { + "x": 124.73322604862055, + "y": -330.5922766676067, + "z": 0.0 + }, + { + "x": 125.73815877830897, + "y": -330.5923839847028, + "z": 0.0 + }, + { + "x": 126.74309150799718, + "y": -330.5924913017989, + "z": 0.0 + }, + { + "x": 127.74802423768548, + "y": -330.59259861889495, + "z": 0.0 + }, + { + "x": 128.7529569673739, + "y": -330.59270593599103, + "z": 0.0 + }, + { + "x": 129.75788969706224, + "y": -330.592813253087, + "z": 0.0 + }, + { + "x": 130.76282242675032, + "y": -330.5929205701831, + "z": 0.0 + }, + { + "x": 131.76775515643885, + "y": -330.59302788727916, + "z": 0.0 + }, + { + "x": 132.77268788612716, + "y": -330.59313520437524, + "z": 0.0 + }, + { + "x": 133.77762061581535, + "y": -330.5932425214712, + "z": 0.0 + }, + { + "x": 134.7825533455037, + "y": -330.5933498385673, + "z": 0.0 + }, + { + "x": 135.78748607519208, + "y": -330.5934571556634, + "z": 0.0 + }, + { + "x": 136.7924188048803, + "y": -330.59356447275945, + "z": 0.0 + }, + { + "x": 137.7973515345686, + "y": -330.59367178985553, + "z": 0.0 + }, + { + "x": 138.80228426425703, + "y": -330.5937791069516, + "z": 0.0 + }, + { + "x": 139.80721699394522, + "y": -330.5938864240476, + "z": 0.0 + }, + { + "x": 140.81214972363352, + "y": -330.59399374114366, + "z": 0.0 + }, + { + "x": 141.81708245332194, + "y": -330.59410105823974, + "z": 0.0 + }, + { + "x": 142.82201518301014, + "y": -330.5942083753358, + "z": 0.0 + }, + { + "x": 143.82694791269844, + "y": -330.5943156924319, + "z": 0.0 + }, + { + "x": 144.83188064238686, + "y": -330.594423009528, + "z": 0.0 + }, + { + "x": 145.83681337207517, + "y": -330.59453032662395, + "z": 0.0 + }, + { + "x": 146.84174610176336, + "y": -330.59463764372003, + "z": 0.0 + }, + { + "x": 147.8466788314517, + "y": -330.5947449608161, + "z": 0.0 + }, + { + "x": 148.85161156114012, + "y": -330.5948522779122, + "z": 0.0 + }, + { + "x": 149.8565442908283, + "y": -330.59495959500816, + "z": 0.0 + }, + { + "x": 150.86147702051662, + "y": -330.59506691210424, + "z": 0.0 + }, + { + "x": 151.86640975020504, + "y": -330.5951742292003, + "z": 0.0 + }, + { + "x": 152.87134247989323, + "y": -330.5952815462964, + "z": 0.0 + }, + { + "x": 153.87627520958154, + "y": -330.5953888633925, + "z": 0.0 + }, + { + "x": 154.88120793926996, + "y": -330.59549618048857, + "z": 0.0 + }, + { + "x": 155.88614066895815, + "y": -330.59560349758453, + "z": 0.0 + }, + { + "x": 156.89107339864657, + "y": -330.5957108146806, + "z": 0.0 + }, + { + "x": 157.8960061283348, + "y": -330.5958181317767, + "z": 0.0 + }, + { + "x": 158.9009388580231, + "y": -330.5959254488728, + "z": 0.0 + }, + { + "x": 159.90587158771152, + "y": -330.59603276596886, + "z": 0.0 + }, + { + "x": 160.9108043173997, + "y": -330.5961400830648, + "z": 0.0 + }, + { + "x": 161.91573704708813, + "y": -330.5962474001609, + "z": 0.0 + }, + { + "x": 162.92066977677632, + "y": -330.596354717257, + "z": 0.0 + }, + { + "x": 163.92560250646463, + "y": -330.59646203435307, + "z": 0.0 + }, + { + "x": 164.93053523615305, + "y": -330.59656935144915, + "z": 0.0 + }, + { + "x": 165.93546796584124, + "y": -330.5966766685451, + "z": 0.0 + }, + { + "x": 166.94040069552966, + "y": -330.5967839856412, + "z": 0.0 + }, + { + "x": 167.94533342521788, + "y": -330.5968913027373, + "z": 0.0 + }, + { + "x": 168.9502661549062, + "y": -330.59699861983336, + "z": 0.0 + }, + { + "x": 169.9551988845946, + "y": -330.59710593692944, + "z": 0.0 + }, + { + "x": 170.96013161428283, + "y": -330.5972132540254, + "z": 0.0 + }, + { + "x": 171.96506434397114, + "y": -330.5973205711215, + "z": 0.0 + }, + { + "x": 172.96999707365958, + "y": -330.59742788821757, + "z": 0.0 + }, + { + "x": 173.97492980334778, + "y": -330.59753520531365, + "z": 0.0 + }, + { + "x": 174.97986253303608, + "y": -330.5976425224097, + "z": 0.0 + }, + { + "x": 175.98479526272453, + "y": -330.5977498395058, + "z": 0.0 + }, + { + "x": 176.98972799241284, + "y": -330.5978571566018, + "z": 0.0 + }, + { + "x": 177.99466072210103, + "y": -330.59796447369786, + "z": 0.0 + }, + { + "x": 178.99959345178937, + "y": -330.59807179079394, + "z": 0.0 + }, + { + "x": 180.0045261814778, + "y": -330.59817910789, + "z": 0.0 + }, + { + "x": 181.00945891116598, + "y": -330.598286424986, + "z": 0.0 + }, + { + "x": 182.01439164085429, + "y": -330.59839374208207, + "z": 0.0 + }, + { + "x": 183.01932437054273, + "y": -330.59850105917815, + "z": 0.0 + }, + { + "x": 184.02425710023093, + "y": -330.5986083762742, + "z": 0.0 + }, + { + "x": 185.02918982991923, + "y": -330.5987156933703, + "z": 0.0 + }, + { + "x": 186.03412255960768, + "y": -330.5988230104664, + "z": 0.0 + }, + { + "x": 187.03905528929587, + "y": -330.59893032756236, + "z": 0.0 + }, + { + "x": 188.0439880189842, + "y": -330.59903764465844, + "z": 0.0 + }, + { + "x": 189.04892074867263, + "y": -330.5991449617545, + "z": 0.0 + }, + { + "x": 190.05385347836082, + "y": -330.5992522788506, + "z": 0.0 + }, + { + "x": 191.05878620804916, + "y": -330.5993595959467, + "z": 0.0 + }, + { + "x": 192.06371893773758, + "y": -330.59946691304276, + "z": 0.0 + }, + { + "x": 193.0686516674259, + "y": -330.5995742301387, + "z": 0.0 + }, + { + "x": 194.0735843971141, + "y": -330.5996815472348, + "z": 0.0 + }, + { + "x": 195.0785171268024, + "y": -330.5997888643309, + "z": 0.0 + }, + { + "x": 196.08344985649083, + "y": -330.59989618142697, + "z": 0.0 + }, + { + "x": 197.08838258617905, + "y": -330.60000349852294, + "z": 0.0 + }, + { + "x": 198.09331531586736, + "y": -330.600110815619, + "z": 0.0 + }, + { + "x": 199.09824804555578, + "y": -330.6002181327151, + "z": 0.0 + }, + { + "x": 200.103180775244, + "y": -330.6003254498112, + "z": 0.0 + }, + { + "x": 201.1081135049323, + "y": -330.60043276690726, + "z": 0.0 + }, + { + "x": 202.11304623462073, + "y": -330.60054008400334, + "z": 0.0 + }, + { + "x": 203.11797896430906, + "y": -330.6006474010993, + "z": 0.0 + }, + { + "x": 204.12291169399714, + "y": -330.6007547181954, + "z": 0.0 + }, + { + "x": 205.12784442368567, + "y": -330.60086203529147, + "z": 0.0 + }, + { + "x": 206.132777153374, + "y": -330.60096935238755, + "z": 0.0 + }, + { + "x": 207.1377098830621, + "y": -330.6010766694835, + "z": 0.0 + }, + { + "x": 208.14264261275065, + "y": -330.6011839865797, + "z": 0.0 + }, + { + "x": 209.14757534243896, + "y": -330.6012913036757, + "z": 0.0 + }, + { + "x": 210.15250807212715, + "y": -330.60139862077176, + "z": 0.0 + }, + { + "x": 211.15744080181548, + "y": -330.60150593786784, + "z": 0.0 + }, + { + "x": 212.1623735315039, + "y": -330.6016132549639, + "z": 0.0 + }, + { + "x": 213.1673062611922, + "y": -330.6017205720599, + "z": 0.0 + }, + { + "x": 214.17223899088032, + "y": -330.60182788915597, + "z": 0.0 + }, + { + "x": 215.17717172056885, + "y": -330.60193520625205, + "z": 0.0 + }, + { + "x": 216.18210445025716, + "y": -330.60204252334813, + "z": 0.0 + }, + { + "x": 217.18703717994524, + "y": -330.6021498404441, + "z": 0.0 + }, + { + "x": 218.1919699096338, + "y": -330.6022571575403, + "z": 0.0 + }, + { + "x": 219.1969026393221, + "y": -330.60236447463626, + "z": 0.0 + }, + { + "x": 220.2018353690103, + "y": -330.60247179173234, + "z": 0.0 + }, + { + "x": 221.20676809869863, + "y": -330.6025791088284, + "z": 0.0 + }, + { + "x": 222.21170082838705, + "y": -330.6026864259245, + "z": 0.0 + }, + { + "x": 223.21663355807524, + "y": -330.60279374302047, + "z": 0.0 + }, + { + "x": 224.22156628776358, + "y": -330.60290106011655, + "z": 0.0 + }, + { + "x": 225.226499017452, + "y": -330.60300837721263, + "z": 0.0 + }, + { + "x": 226.23143174714033, + "y": -330.6031156943087, + "z": 0.0 + }, + { + "x": 227.2363644768284, + "y": -330.6032230114047, + "z": 0.0 + }, + { + "x": 228.24129720651695, + "y": -330.6033303285009, + "z": 0.0 + }, + { + "x": 229.24622993620528, + "y": -330.60343764559684, + "z": 0.0 + }, + { + "x": 230.25116266589333, + "y": -330.6035449626929, + "z": 0.0 + }, + { + "x": 231.25609539558187, + "y": -330.603652279789, + "z": 0.0 + }, + { + "x": 232.26102812527017, + "y": -330.6037595968851, + "z": 0.0 + }, + { + "x": 233.26596085495834, + "y": -330.60386691398105, + "z": 0.0 + }, + { + "x": 234.27089358464667, + "y": -330.60397423107713, + "z": 0.0 + }, + { + "x": 235.2758263143351, + "y": -330.6040815481732, + "z": 0.0 + }, + { + "x": 236.28075904402328, + "y": -330.6041888652693, + "z": 0.0 + }, + { + "x": 237.28569177371156, + "y": -330.6042961823654, + "z": 0.0 + }, + { + "x": 238.29062450339998, + "y": -330.60440349946145, + "z": 0.0 + }, + { + "x": 239.29555723308818, + "y": -330.6045108165574, + "z": 0.0 + }, + { + "x": 240.30048996277645, + "y": -330.6046181336535, + "z": 0.0 + }, + { + "x": 241.3054226924649, + "y": -330.6047254507496, + "z": 0.0 + }, + { + "x": 242.3103554221532, + "y": -330.60483276784566, + "z": 0.0 + }, + { + "x": 243.31528815184137, + "y": -330.60494008494163, + "z": 0.0 + }, + { + "x": 244.32022088152968, + "y": -330.6050474020377, + "z": 0.0 + }, + { + "x": 245.3251536112181, + "y": -330.6051547191338, + "z": 0.0 + }, + { + "x": 246.3300863409063, + "y": -330.6052620362299, + "z": 0.0 + }, + { + "x": 247.33501907059457, + "y": -330.60536935332595, + "z": 0.0 + }, + { + "x": 248.33995180028302, + "y": -330.60547667042204, + "z": 0.0 + }, + { + "x": 249.3448845299712, + "y": -330.605583987518, + "z": 0.0 + }, + { + "x": 250.3498172596595, + "y": -330.6056913046141, + "z": 0.0 + }, + { + "x": 251.3547499893479, + "y": -330.60579862171016, + "z": 0.0 + }, + { + "x": 252.3596827190361, + "y": -330.60590593880625, + "z": 0.0 + }, + { + "x": 253.3646154487245, + "y": -330.6060132559023, + "z": 0.0 + }, + { + "x": 254.36954817841269, + "y": -330.6061205729983, + "z": 0.0 + }, + { + "x": 255.37448090810102, + "y": -330.6062278900944, + "z": 0.0 + }, + { + "x": 256.3794136377894, + "y": -330.60633520719045, + "z": 0.0 + }, + { + "x": 257.38434636747763, + "y": -330.60644252428654, + "z": 0.0 + }, + { + "x": 258.38927909716597, + "y": -330.6065498413826, + "z": 0.0 + }, + { + "x": 259.3942118268542, + "y": -330.6066571584786, + "z": 0.0 + }, + { + "x": 260.3991445565425, + "y": -330.60676447557466, + "z": 0.0 + }, + { + "x": 261.40407728623086, + "y": -330.60687179267074, + "z": 0.0 + }, + { + "x": 262.4090100159191, + "y": -330.6069791097668, + "z": 0.0 + }, + { + "x": 263.4139427456075, + "y": -330.6070864268629, + "z": 0.0 + }, + { + "x": 264.41887547529575, + "y": -330.6071937439589, + "z": 0.0 + }, + { + "x": 265.42380820498397, + "y": -330.60730106105495, + "z": 0.0 + }, + { + "x": 266.4287409346724, + "y": -330.60740837815104, + "z": 0.0 + }, + { + "x": 267.43367366436064, + "y": -330.6075156952471, + "z": 0.0 + }, + { + "x": 268.43860639404886, + "y": -330.6076230123432, + "z": 0.0 + }, + { + "x": 269.4435391237373, + "y": -330.6077303294393, + "z": 0.0 + }, + { + "x": 270.44847185342553, + "y": -330.60783764653524, + "z": 0.0 + }, + { + "x": 271.45340458311387, + "y": -330.6079449636313, + "z": 0.0 + }, + { + "x": 272.4583373128022, + "y": -330.6080522807274, + "z": 0.0 + }, + { + "x": 273.4632700424904, + "y": -330.6081595978235, + "z": 0.0 + }, + { + "x": 274.46820277217887, + "y": -330.60826691491957, + "z": 0.0 + }, + { + "x": 275.473135501867, + "y": -330.60837423201554, + "z": 0.0 + }, + { + "x": 276.4780682315554, + "y": -330.6084815491116, + "z": 0.0 + }, + { + "x": 277.48300096124365, + "y": -330.6085888662077, + "z": 0.0 + }, + { + "x": 278.487933690932, + "y": -330.6086961833038, + "z": 0.0 + }, + { + "x": 279.4928664206203, + "y": -330.60880350039986, + "z": 0.0 + }, + { + "x": 280.49779915030854, + "y": -330.6089108174958, + "z": 0.0 + }, + { + "x": 281.5027318799969, + "y": -330.6090181345919, + "z": 0.0 + }, + { + "x": 282.5076646096852, + "y": -330.609125451688, + "z": 0.0 + }, + { + "x": 283.51259733937343, + "y": -330.60923276878407, + "z": 0.0 + }, + { + "x": 284.51753006906176, + "y": -330.60934008588015, + "z": 0.0 + }, + { + "x": 285.5224627987502, + "y": -330.60944740297623, + "z": 0.0 + }, + { + "x": 286.52739552843843, + "y": -330.6095547200722, + "z": 0.0 + }, + { + "x": 287.53232825812654, + "y": -330.6096620371683, + "z": 0.0 + }, + { + "x": 288.5372609878151, + "y": -330.60976935426436, + "z": 0.0 + }, + { + "x": 289.5421952094854, + "y": -330.6098766715192, + "z": 0.0 + }, + { + "x": 290.5473358457908, + "y": -330.60998325018545, + "z": 0.0 + }, + { + "x": 291.55227276326934, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 292.55720549868784, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 293.5621382341064, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 294.56707096952493, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 295.5720037049434, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 296.5769364403619, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 297.58186917578047, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 298.586801911199, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 299.5917346466175, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 300.59666738203606, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 301.6016001174546, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 302.6065328528731, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 303.6114655882916, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 304.61639832371014, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 305.6213310591287, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 306.6262637945472, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 307.63119652996573, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 308.6361292653843, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 309.6410620008028, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 310.64599473622127, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 311.6509274716398, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 312.65586020705837, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 313.66079294247686, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 314.6657256778954, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 315.67065841331396, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 316.67559114873245, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 317.68052388415094, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 318.6854566195695, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 319.69038935498804, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 320.69532209040653, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 321.7002548258251, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 322.70518756124363, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 323.7101202966621, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 324.7150530320806, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 325.71998576749917, + "y": -330.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 35, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 384.07998657059636, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 383.0414151190793, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 382.0028436675622, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 380.9642722160452, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 379.92570076452813, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 378.88712931301103, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 377.848557861494, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 376.80998640997694, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 375.77141495845984, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 374.7328435069428, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 373.69427205542576, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 372.6557006039087, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 371.6171291523916, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 370.57855770087457, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 369.5399862493575, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 368.5014147978404, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 367.4628433463234, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 366.42427189480634, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 365.38570044328924, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 364.3471289917722, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 363.30855754025515, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 362.26998608873805, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 361.231414637221, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 360.19284318570396, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 359.15427173418686, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 358.1157002826698, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 357.0771288311528, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 356.0385573796357, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 354.99998592811863, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 353.9614144766016, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 352.92284302508455, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 351.88427157356745, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 350.8457001220504, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 349.80712867053336, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 348.76855721901626, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 347.7299857674992, + "y": -324.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 36, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 347.7299857674992, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 348.76855721901626, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 349.80712867053336, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 350.8457001220504, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 351.88427157356745, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 352.92284302508455, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 353.9614144766016, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 354.99998592811863, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 356.0385573796357, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 357.0771288311528, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 358.1157002826698, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 359.15427173418686, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 360.19284318570396, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 361.231414637221, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 362.26998608873805, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 363.30855754025515, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 364.3471289917722, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 365.38570044328924, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 366.42427189480634, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 367.4628433463234, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 368.5014147978404, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 369.5399862493575, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 370.57855770087457, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 371.6171291523916, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 372.6557006039087, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 373.69427205542576, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 374.7328435069428, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 375.77141495845984, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 376.80998640997694, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 377.848557861494, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 378.88712931301103, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 379.92570076452813, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 380.9642722160452, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 382.0028436675622, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 383.0414151190793, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 384.07998657059636, + "y": -332.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 37, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 347.7299857674992, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 348.76855721901626, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 349.80712867053336, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 350.8457001220504, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 351.88427157356745, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 352.92284302508455, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 353.9614144766016, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 354.99998592811863, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 356.0385573796357, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 357.0771288311528, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 358.1157002826698, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 359.15427173418686, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 360.19284318570396, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 361.231414637221, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 362.26998608873805, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 363.30855754025515, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 364.3471289917722, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 365.38570044328924, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 366.42427189480634, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 367.4628433463234, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 368.5014147978404, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 369.5399862493575, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 370.57855770087457, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 371.6171291523916, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 372.6557006039087, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 373.69427205542576, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 374.7328435069428, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 375.77141495845984, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 376.80998640997694, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 377.848557861494, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 378.88712931301103, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 379.92570076452813, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 380.9642722160452, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 382.0028436675622, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 383.0414151190793, + "y": -328.6099853515625, + "z": 0.0 + }, + { + "x": 384.07998657059636, + "y": -328.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 38, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 384.07998657059636, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 383.0414151190793, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 382.0028436675622, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 380.9642722160452, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 379.92570076452813, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 378.88712931301103, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 377.848557861494, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 376.80998640997694, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 375.77141495845984, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 374.7328435069428, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 373.69427205542576, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 372.6557006039087, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 371.6171291523916, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 370.57855770087457, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 369.5399862493575, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 368.5014147978404, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 367.4628433463234, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 366.42427189480634, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 365.38570044328924, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 364.3471289917722, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 363.30855754025515, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 362.26998608873805, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 361.231414637221, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 360.19284318570396, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 359.15427173418686, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 358.1157002826698, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 357.0771288311528, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 356.0385573796357, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 354.99998592811863, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 353.9614144766016, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 352.92284302508455, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 351.88427157356745, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 350.8457001220504, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 349.80712867053336, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 348.76855721901626, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 347.7299857674992, + "y": -326.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 39, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 347.7299857674992, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 348.76855721901626, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 349.80712867053336, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 350.8457001220504, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 351.88427157356745, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 352.92284302508455, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 353.9614144766016, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 354.99998592811863, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 356.0385573796357, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 357.0771288311528, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 358.1157002826698, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 359.15427173418686, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 360.19284318570396, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 361.231414637221, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 362.26998608873805, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 363.30855754025515, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 364.3471289917722, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 365.38570044328924, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 366.42427189480634, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 367.4628433463234, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 368.5014147978404, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 369.5399862493575, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 370.57855770087457, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 371.6171291523916, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 372.6557006039087, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 373.69427205542576, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 374.7328435069428, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 375.77141495845984, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 376.80998640997694, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 377.848557861494, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 378.88712931301103, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 379.92570076452813, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 380.9642722160452, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 382.0028436675622, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 383.0414151190793, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 384.07998657059636, + "y": -330.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 40, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 390.380007762646, + "y": -9.845199567387848, + "z": 0.0 + }, + { + "x": 390.3788050944489, + "y": -10.847439245752769, + "z": 0.0 + }, + { + "x": 390.3776024262517, + "y": -11.849678924117207, + "z": 0.0 + }, + { + "x": 390.3763997580546, + "y": -12.85191860248258, + "z": 0.0 + }, + { + "x": 390.3751970898575, + "y": -13.854158280847502, + "z": 0.0 + }, + { + "x": 390.3739944216603, + "y": -14.856397959211929, + "z": 0.0 + }, + { + "x": 390.3727917534632, + "y": -15.8586376375773, + "z": 0.0 + }, + { + "x": 390.37158908526607, + "y": -16.860877315941995, + "z": 0.0 + }, + { + "x": 390.3703864170689, + "y": -17.86311699430688, + "z": 0.0 + }, + { + "x": 390.3691837488718, + "y": -18.865356672671986, + "z": 0.0 + }, + { + "x": 390.36798108067467, + "y": -19.86759635103667, + "z": 0.0 + }, + { + "x": 390.3667784124775, + "y": -20.86983602940159, + "z": 0.0 + }, + { + "x": 390.36557574428036, + "y": -21.872075707766566, + "z": 0.0 + }, + { + "x": 390.36437307608327, + "y": -22.87431538613169, + "z": 0.0 + }, + { + "x": 390.3631704078861, + "y": -23.876555064496372, + "z": 0.0 + }, + { + "x": 390.36196773968896, + "y": -24.87879474286126, + "z": 0.0 + }, + { + "x": 390.36076507149187, + "y": -25.88103442122636, + "z": 0.0 + }, + { + "x": 390.3595624032947, + "y": -26.883274099591002, + "z": 0.0 + }, + { + "x": 390.35835973509757, + "y": -27.885513777955907, + "z": 0.0 + }, + { + "x": 390.35715706690047, + "y": -28.887753456321025, + "z": 0.0 + }, + { + "x": 390.3559543987033, + "y": -29.889993134685668, + "z": 0.0 + }, + { + "x": 390.35475173050617, + "y": -30.89223281305054, + "z": 0.0 + }, + { + "x": 390.35354906230907, + "y": -31.89447249141564, + "z": 0.0 + }, + { + "x": 390.3523463941119, + "y": -32.89671216978028, + "z": 0.0 + }, + { + "x": 390.35114372591477, + "y": -33.89895184814515, + "z": 0.0 + }, + { + "x": 390.3499410577176, + "y": -34.90119152651005, + "z": 0.0 + }, + { + "x": 390.34873838952046, + "y": -35.90343120487495, + "z": 0.0 + }, + { + "x": 390.34753572132337, + "y": -36.90567088324007, + "z": 0.0 + }, + { + "x": 390.3463330531262, + "y": -37.907910561604744, + "z": 0.0 + }, + { + "x": 390.34513038492906, + "y": -38.91015023996968, + "z": 0.0 + }, + { + "x": 390.34392771673197, + "y": -39.912389918334775, + "z": 0.0 + }, + { + "x": 390.3427250485348, + "y": -40.91462959669942, + "z": 0.0 + }, + { + "x": 390.34152238033766, + "y": -41.91686927506429, + "z": 0.0 + }, + { + "x": 390.34031971214057, + "y": -42.919108953429394, + "z": 0.0 + }, + { + "x": 390.3391170439434, + "y": -43.92134863179405, + "z": 0.0 + }, + { + "x": 390.33791437574627, + "y": -44.923588310158955, + "z": 0.0 + }, + { + "x": 390.33671170754917, + "y": -45.92582798852408, + "z": 0.0 + }, + { + "x": 390.335509039352, + "y": -46.92806766688876, + "z": 0.0 + }, + { + "x": 390.33430637115487, + "y": -47.93030734525364, + "z": 0.0 + }, + { + "x": 390.3331037029577, + "y": -48.93254702361856, + "z": 0.0 + }, + { + "x": 390.3319010347606, + "y": -49.934786701983654, + "z": 0.0 + }, + { + "x": 390.33069836656347, + "y": -50.93702638034831, + "z": 0.0 + }, + { + "x": 390.3294956983663, + "y": -51.93926605871323, + "z": 0.0 + }, + { + "x": 390.3282930301692, + "y": -52.94150573707833, + "z": 0.0 + }, + { + "x": 390.327090361972, + "y": -53.94374541544286, + "z": 0.0 + }, + { + "x": 390.3258876937749, + "y": -54.94598509380819, + "z": 0.0 + }, + { + "x": 390.3246850255778, + "y": -55.948224772173106, + "z": 0.0 + }, + { + "x": 390.3234823573806, + "y": -56.95046445053753, + "z": 0.0 + }, + { + "x": 390.3222796891835, + "y": -57.95270412890285, + "z": 0.0 + }, + { + "x": 390.32107702098637, + "y": -58.954943807267554, + "z": 0.0 + }, + { + "x": 390.3198743527892, + "y": -59.95718348563243, + "z": 0.0 + }, + { + "x": 390.3186716845921, + "y": -60.95942316399757, + "z": 0.0 + }, + { + "x": 390.31746901639497, + "y": -61.961662842362216, + "z": 0.0 + }, + { + "x": 390.3162663481978, + "y": -62.96390252072709, + "z": 0.0 + }, + { + "x": 390.3150636800007, + "y": -63.96614219909221, + "z": 0.0 + }, + { + "x": 390.31386101180357, + "y": -64.96838187745689, + "z": 0.0 + }, + { + "x": 390.3126583436064, + "y": -65.9706215558218, + "z": 0.0 + }, + { + "x": 390.31145567540926, + "y": -66.97286123418672, + "z": 0.0 + }, + { + "x": 390.31025300721217, + "y": -67.97510091255184, + "z": 0.0 + }, + { + "x": 390.309050339015, + "y": -68.97734059091651, + "z": 0.0 + }, + { + "x": 390.30784767081786, + "y": -69.97958026928141, + "z": 0.0 + }, + { + "x": 390.30664500262077, + "y": -70.98181994764653, + "z": 0.0 + }, + { + "x": 390.3054423344236, + "y": -71.98405962601122, + "z": 0.0 + }, + { + "x": 390.30423966622647, + "y": -72.9862993043761, + "z": 0.0 + }, + { + "x": 390.30303699802937, + "y": -73.98853898274126, + "z": 0.0 + }, + { + "x": 390.3018343298322, + "y": -74.99077866110594, + "z": 0.0 + }, + { + "x": 390.30063166163507, + "y": -75.99301833947084, + "z": 0.0 + }, + { + "x": 390.2994289934379, + "y": -76.99525801783574, + "z": 0.0 + }, + { + "x": 390.29822632524076, + "y": -77.99749769620063, + "z": 0.0 + }, + { + "x": 390.29702365704367, + "y": -78.99973737456575, + "z": 0.0 + }, + { + "x": 390.2958209888465, + "y": -80.00197705293043, + "z": 0.0 + }, + { + "x": 390.29461832064936, + "y": -81.00421673129533, + "z": 0.0 + }, + { + "x": 390.29341565245227, + "y": -82.00645640966046, + "z": 0.0 + }, + { + "x": 390.2922129842551, + "y": -83.00869608802516, + "z": 0.0 + }, + { + "x": 390.29101031605796, + "y": -84.01093576639005, + "z": 0.0 + }, + { + "x": 390.28980764786087, + "y": -85.01317544475518, + "z": 0.0 + }, + { + "x": 390.2886049796637, + "y": -86.01541512311985, + "z": 0.0 + }, + { + "x": 390.2876623789813, + "y": -87.01869741734455, + "z": 0.0 + }, + { + "x": 390.2876355630676, + "y": -88.0245953007731, + "z": 0.0 + }, + { + "x": 390.28784715222, + "y": -89.02777977775638, + "z": 0.0 + }, + { + "x": 390.28805865355594, + "y": -90.03002015539369, + "z": 0.0 + }, + { + "x": 390.28827015489185, + "y": -91.03226053303119, + "z": 0.0 + }, + { + "x": 390.28848165622776, + "y": -92.0345009106687, + "z": 0.0 + }, + { + "x": 390.2886931575636, + "y": -93.03674128830598, + "z": 0.0 + }, + { + "x": 390.2889046588996, + "y": -94.03898166594394, + "z": 0.0 + }, + { + "x": 390.2891161602355, + "y": -95.04122204358121, + "z": 0.0 + }, + { + "x": 390.2893276615714, + "y": -96.04346242121872, + "z": 0.0 + }, + { + "x": 390.28953916290726, + "y": -97.045702798856, + "z": 0.0 + }, + { + "x": 390.28975066424323, + "y": -98.04794317649396, + "z": 0.0 + }, + { + "x": 390.28996216557914, + "y": -99.05018355413127, + "z": 0.0 + }, + { + "x": 390.29017366691505, + "y": -100.05242393176877, + "z": 0.0 + }, + { + "x": 390.29038516825096, + "y": -101.05466430940628, + "z": 0.0 + }, + { + "x": 390.2905966695868, + "y": -102.05690468704356, + "z": 0.0 + }, + { + "x": 390.2908081709228, + "y": -103.05914506468152, + "z": 0.0 + }, + { + "x": 390.2910196722587, + "y": -104.06138544231878, + "z": 0.0 + }, + { + "x": 390.2912311735946, + "y": -105.06362581995629, + "z": 0.0 + }, + { + "x": 390.29144267493047, + "y": -106.06586619759359, + "z": 0.0 + }, + { + "x": 390.2916541762664, + "y": -107.06810657523133, + "z": 0.0 + }, + { + "x": 390.2918656776023, + "y": -108.07034695286883, + "z": 0.0 + }, + { + "x": 390.29207717893826, + "y": -109.07258733050656, + "z": 0.0 + }, + { + "x": 390.2922886802741, + "y": -110.07482770814362, + "z": 0.0 + }, + { + "x": 390.29250018161, + "y": -111.07706808578135, + "z": 0.0 + }, + { + "x": 390.29271168294594, + "y": -112.07930846341885, + "z": 0.0 + }, + { + "x": 390.2929231842819, + "y": -113.08154884105659, + "z": 0.0 + }, + { + "x": 390.2931346856178, + "y": -114.08378921869385, + "z": 0.0 + }, + { + "x": 390.29334618695367, + "y": -115.08602959633114, + "z": 0.0 + }, + { + "x": 390.2935576882896, + "y": -116.08826997396886, + "z": 0.0 + }, + { + "x": 390.2937691896255, + "y": -117.09051035160635, + "z": 0.0 + }, + { + "x": 390.29398069096146, + "y": -118.09275072924407, + "z": 0.0 + }, + { + "x": 390.2941921922973, + "y": -119.09499110688111, + "z": 0.0 + }, + { + "x": 390.2944036936332, + "y": -120.09723148451884, + "z": 0.0 + }, + { + "x": 390.29461519496914, + "y": -121.09947186215635, + "z": 0.0 + }, + { + "x": 390.29482669630505, + "y": -122.10171223979387, + "z": 0.0 + }, + { + "x": 390.295038197641, + "y": -123.1039526174316, + "z": 0.0 + }, + { + "x": 390.2952496989769, + "y": -124.10619299506864, + "z": 0.0 + }, + { + "x": 390.2954612003128, + "y": -125.10843337270637, + "z": 0.0 + }, + { + "x": 390.2956727016487, + "y": -126.11067375034386, + "z": 0.0 + }, + { + "x": 390.29588420298467, + "y": -127.11291412798158, + "z": 0.0 + }, + { + "x": 390.2960957043205, + "y": -128.11515450561862, + "z": 0.0 + }, + { + "x": 390.29630720565643, + "y": -129.11739488325634, + "z": 0.0 + }, + { + "x": 390.29651870699234, + "y": -130.11963526089386, + "z": 0.0 + }, + { + "x": 390.29673020832826, + "y": -131.12187563853138, + "z": 0.0 + }, + { + "x": 390.29694170966417, + "y": -132.1241160161689, + "z": 0.0 + }, + { + "x": 390.2971532110001, + "y": -133.1263563938064, + "z": 0.0 + }, + { + "x": 390.297364712336, + "y": -134.1285967714439, + "z": 0.0 + }, + { + "x": 390.2975762136719, + "y": -135.1308371490814, + "z": 0.0 + }, + { + "x": 390.29778771500787, + "y": -136.13307752671915, + "z": 0.0 + }, + { + "x": 390.2979992163437, + "y": -137.13531790435619, + "z": 0.0 + }, + { + "x": 390.29821071767964, + "y": -138.13755828199396, + "z": 0.0 + }, + { + "x": 390.29842221901555, + "y": -139.13979865963145, + "z": 0.0 + }, + { + "x": 390.29863372035146, + "y": -140.14203903726897, + "z": 0.0 + }, + { + "x": 390.2988452216874, + "y": -141.14427941490646, + "z": 0.0 + }, + { + "x": 390.2990567230233, + "y": -142.14651979254398, + "z": 0.0 + }, + { + "x": 390.2992682243592, + "y": -143.14876017018148, + "z": 0.0 + }, + { + "x": 390.2994797256951, + "y": -144.151000547819, + "z": 0.0 + }, + { + "x": 390.299691227031, + "y": -145.1532409254565, + "z": 0.0 + }, + { + "x": 390.29990272836693, + "y": -146.155481303094, + "z": 0.0 + }, + { + "x": 390.30011422970284, + "y": -147.15772168073153, + "z": 0.0 + }, + { + "x": 390.30032573103875, + "y": -148.15996205836905, + "z": 0.0 + }, + { + "x": 390.30053723237467, + "y": -149.16220243600654, + "z": 0.0 + }, + { + "x": 390.3007487337106, + "y": -150.16444281364403, + "z": 0.0 + }, + { + "x": 390.3009602350465, + "y": -151.16668319128155, + "z": 0.0 + }, + { + "x": 390.3011717363824, + "y": -152.16892356891904, + "z": 0.0 + }, + { + "x": 390.3013832377183, + "y": -153.17116394655656, + "z": 0.0 + }, + { + "x": 390.30159473905417, + "y": -154.17340432419385, + "z": 0.0 + }, + { + "x": 390.30180624039014, + "y": -155.17564470183183, + "z": 0.0 + }, + { + "x": 390.30201774172605, + "y": -156.1778850794691, + "z": 0.0 + }, + { + "x": 390.30222924306196, + "y": -157.1801254571066, + "z": 0.0 + }, + { + "x": 390.30244074439787, + "y": -158.1823658347441, + "z": 0.0 + }, + { + "x": 390.3026522457337, + "y": -159.1846062123814, + "z": 0.0 + }, + { + "x": 390.3028637470697, + "y": -160.18684659001934, + "z": 0.0 + }, + { + "x": 390.3030752484056, + "y": -161.18908696765664, + "z": 0.0 + }, + { + "x": 390.3032867497415, + "y": -162.19132734529413, + "z": 0.0 + }, + { + "x": 390.3034982510774, + "y": -163.19356772293145, + "z": 0.0 + }, + { + "x": 390.30370975241334, + "y": -164.1958081005694, + "z": 0.0 + }, + { + "x": 390.30392125374925, + "y": -165.1980484782067, + "z": 0.0 + }, + { + "x": 390.30413275508516, + "y": -166.20028885584418, + "z": 0.0 + }, + { + "x": 390.3043442564211, + "y": -167.2025292334817, + "z": 0.0 + }, + { + "x": 390.30455575775693, + "y": -168.20476961111896, + "z": 0.0 + }, + { + "x": 390.3047672590929, + "y": -169.20700998875694, + "z": 0.0 + }, + { + "x": 390.3049787604288, + "y": -170.20925036639423, + "z": 0.0 + }, + { + "x": 390.3051902617647, + "y": -171.21149074403175, + "z": 0.0 + }, + { + "x": 390.3054017631006, + "y": -172.213731121669, + "z": 0.0 + }, + { + "x": 390.30561326443654, + "y": -173.215971499307, + "z": 0.0 + }, + { + "x": 390.30582476577246, + "y": -174.21821187694425, + "z": 0.0 + }, + { + "x": 390.30603626710837, + "y": -175.22045225458177, + "z": 0.0 + }, + { + "x": 390.3062477684443, + "y": -176.22269263221926, + "z": 0.0 + }, + { + "x": 390.30645926978013, + "y": -177.22493300985656, + "z": 0.0 + }, + { + "x": 390.3066707711161, + "y": -178.2271733874945, + "z": 0.0 + }, + { + "x": 390.306882272452, + "y": -179.22941376513182, + "z": 0.0 + }, + { + "x": 390.3070937737879, + "y": -180.23165414276932, + "z": 0.0 + }, + { + "x": 390.3073052751238, + "y": -181.23389452040658, + "z": 0.0 + }, + { + "x": 390.3075167764597, + "y": -182.23613489804433, + "z": 0.0 + }, + { + "x": 390.30772827779566, + "y": -183.23837527568205, + "z": 0.0 + }, + { + "x": 390.3079397791316, + "y": -184.24061565331934, + "z": 0.0 + }, + { + "x": 390.3081512804674, + "y": -185.2428560309566, + "z": 0.0 + }, + { + "x": 390.30836278180334, + "y": -186.24509640859438, + "z": 0.0 + }, + { + "x": 390.3085742831393, + "y": -187.2473367862321, + "z": 0.0 + }, + { + "x": 390.3087857844752, + "y": -188.2495771638694, + "z": 0.0 + }, + { + "x": 390.30899728581113, + "y": -189.25181754150688, + "z": 0.0 + }, + { + "x": 390.309208787147, + "y": -190.25405791914417, + "z": 0.0 + }, + { + "x": 390.3094202884829, + "y": -191.2562982967819, + "z": 0.0 + }, + { + "x": 390.3096317898188, + "y": -192.25853867441938, + "z": 0.0 + }, + { + "x": 390.3098432911548, + "y": -193.2607790520571, + "z": 0.0 + }, + { + "x": 390.31005479249063, + "y": -194.26301942969414, + "z": 0.0 + }, + { + "x": 390.31026629382654, + "y": -195.26525980733186, + "z": 0.0 + }, + { + "x": 390.31047779516246, + "y": -196.26750018496938, + "z": 0.0 + }, + { + "x": 390.31068929649837, + "y": -197.26974056260687, + "z": 0.0 + }, + { + "x": 390.31090079783434, + "y": -198.2719809402446, + "z": 0.0 + }, + { + "x": 390.3111122991702, + "y": -199.27422131788163, + "z": 0.0 + }, + { + "x": 390.3113238005061, + "y": -200.27646169551934, + "z": 0.0 + }, + { + "x": 390.311535301842, + "y": -201.27870207315684, + "z": 0.0 + }, + { + "x": 390.311746803178, + "y": -202.28094245079456, + "z": 0.0 + }, + { + "x": 390.31195830451384, + "y": -203.2831828284316, + "z": 0.0 + }, + { + "x": 390.31216980584975, + "y": -204.28542320606934, + "z": 0.0 + }, + { + "x": 390.31238130718566, + "y": -205.28766358370683, + "z": 0.0 + }, + { + "x": 390.3125928085216, + "y": -206.28990396134432, + "z": 0.0 + }, + { + "x": 390.3128043098575, + "y": -207.2921443389818, + "z": 0.0 + }, + { + "x": 390.3130158111934, + "y": -208.2943847166193, + "z": 0.0 + }, + { + "x": 390.3132273125293, + "y": -209.2966250942568, + "z": 0.0 + }, + { + "x": 390.3134388138652, + "y": -210.2988654718943, + "z": 0.0 + }, + { + "x": 390.3136503152012, + "y": -211.301105849532, + "z": 0.0 + }, + { + "x": 390.31386181653704, + "y": -212.30334622716907, + "z": 0.0 + }, + { + "x": 390.31407331787295, + "y": -213.3055866048068, + "z": 0.0 + }, + { + "x": 390.31428481920886, + "y": -214.30782698244428, + "z": 0.0 + }, + { + "x": 390.3144963205448, + "y": -215.31006736008177, + "z": 0.0 + }, + { + "x": 390.3147078218807, + "y": -216.31230773771927, + "z": 0.0 + }, + { + "x": 390.3149193232166, + "y": -217.31454811535676, + "z": 0.0 + }, + { + "x": 390.3151308245525, + "y": -218.31678849299425, + "z": 0.0 + }, + { + "x": 390.3153423258884, + "y": -219.31902887063174, + "z": 0.0 + }, + { + "x": 390.31555382722433, + "y": -220.32126924826926, + "z": 0.0 + }, + { + "x": 390.31576532856025, + "y": -221.32350962590675, + "z": 0.0 + }, + { + "x": 390.31597682989616, + "y": -222.32575000354424, + "z": 0.0 + }, + { + "x": 390.31618833123207, + "y": -223.32799038118173, + "z": 0.0 + }, + { + "x": 390.316399832568, + "y": -224.33023075881923, + "z": 0.0 + }, + { + "x": 390.3166113339039, + "y": -225.33247113645672, + "z": 0.0 + }, + { + "x": 390.3168228352398, + "y": -226.3347115140942, + "z": 0.0 + }, + { + "x": 390.3170343365757, + "y": -227.3369518917317, + "z": 0.0 + }, + { + "x": 390.3172458379116, + "y": -228.33919226936922, + "z": 0.0 + }, + { + "x": 390.31745733924754, + "y": -229.3414326470067, + "z": 0.0 + }, + { + "x": 390.31766884058345, + "y": -230.3436730246442, + "z": 0.0 + }, + { + "x": 390.31788034191936, + "y": -231.3459134022817, + "z": 0.0 + }, + { + "x": 390.3180918432553, + "y": -232.3481537799192, + "z": 0.0 + }, + { + "x": 390.3183033445912, + "y": -233.35039415755668, + "z": 0.0 + }, + { + "x": 390.3185148459271, + "y": -234.35263453519417, + "z": 0.0 + }, + { + "x": 390.318726347263, + "y": -235.35487491283166, + "z": 0.0 + }, + { + "x": 390.3189378485989, + "y": -236.35711529046915, + "z": 0.0 + }, + { + "x": 390.31914934993483, + "y": -237.35935566810664, + "z": 0.0 + }, + { + "x": 390.31936085127074, + "y": -238.36159604574414, + "z": 0.0 + }, + { + "x": 390.31957235260666, + "y": -239.36383642338163, + "z": 0.0 + }, + { + "x": 390.31978385394257, + "y": -240.36607680101912, + "z": 0.0 + }, + { + "x": 390.3200109086524, + "y": -241.36837919461823, + "z": 0.0 + }, + { + "x": 390.32040065747765, + "y": -242.3712680984976, + "z": 0.0 + }, + { + "x": 390.3207902067958, + "y": -243.37350842274657, + "z": 0.0 + }, + { + "x": 390.3211797561139, + "y": -244.37574874699575, + "z": 0.0 + }, + { + "x": 390.3215693054321, + "y": -245.37798907124514, + "z": 0.0 + }, + { + "x": 390.3219588547503, + "y": -246.38022939549433, + "z": 0.0 + }, + { + "x": 390.3223484040684, + "y": -247.38246971974326, + "z": 0.0 + }, + { + "x": 390.3227379533866, + "y": -248.38471004399267, + "z": 0.0 + }, + { + "x": 390.3231275027047, + "y": -249.38695036824163, + "z": 0.0 + }, + { + "x": 390.32351705202285, + "y": -250.38919069249079, + "z": 0.0 + }, + { + "x": 390.32390660134104, + "y": -251.3914310167402, + "z": 0.0 + }, + { + "x": 390.3242961506592, + "y": -252.39367134098939, + "z": 0.0 + }, + { + "x": 390.32468569997735, + "y": -253.39591166523832, + "z": 0.0 + }, + { + "x": 390.32507524929554, + "y": -254.39815198948773, + "z": 0.0 + }, + { + "x": 390.32546479861367, + "y": -255.40039231373666, + "z": 0.0 + }, + { + "x": 390.3258543479318, + "y": -256.40263263798585, + "z": 0.0 + }, + { + "x": 390.32624389725, + "y": -257.4048729622353, + "z": 0.0 + }, + { + "x": 390.32663344656817, + "y": -258.40711328648445, + "z": 0.0 + }, + { + "x": 390.3270229958863, + "y": -259.4093536107334, + "z": 0.0 + }, + { + "x": 390.3274125452044, + "y": -260.41159393498253, + "z": 0.0 + }, + { + "x": 390.3278020945226, + "y": -261.413834259232, + "z": 0.0 + }, + { + "x": 390.3281916438408, + "y": -262.41607458348113, + "z": 0.0 + }, + { + "x": 390.3285811931589, + "y": -263.41831490773006, + "z": 0.0 + }, + { + "x": 390.3289707424771, + "y": -264.4205552319795, + "z": 0.0 + }, + { + "x": 390.3293602917953, + "y": -265.42279555622866, + "z": 0.0 + }, + { + "x": 390.3297498411134, + "y": -266.4250358804776, + "z": 0.0 + }, + { + "x": 390.33013939043155, + "y": -267.4272762047268, + "z": 0.0 + }, + { + "x": 390.33052893974974, + "y": -268.4295165289762, + "z": 0.0 + }, + { + "x": 390.33091848906787, + "y": -269.4317568532251, + "z": 0.0 + }, + { + "x": 390.33130803838606, + "y": -270.43399717747457, + "z": 0.0 + }, + { + "x": 390.3316975877042, + "y": -271.4362375017235, + "z": 0.0 + }, + { + "x": 390.3320871370223, + "y": -272.43847782597265, + "z": 0.0 + }, + { + "x": 390.3324766863405, + "y": -273.4407181502221, + "z": 0.0 + }, + { + "x": 390.3328662356587, + "y": -274.44295847447125, + "z": 0.0 + }, + { + "x": 390.3332557849768, + "y": -275.4451987987202, + "z": 0.0 + }, + { + "x": 390.333645334295, + "y": -276.4474391229696, + "z": 0.0 + }, + { + "x": 390.3340348836131, + "y": -277.44967944721856, + "z": 0.0 + }, + { + "x": 390.3344244329313, + "y": -278.45191977146794, + "z": 0.0 + }, + { + "x": 390.33481398224944, + "y": -279.4541600957169, + "z": 0.0 + }, + { + "x": 390.33520353156763, + "y": -280.4564004199663, + "z": 0.0 + }, + { + "x": 390.3355930808858, + "y": -281.4586407442155, + "z": 0.0 + }, + { + "x": 390.33598263020394, + "y": -282.46088106846446, + "z": 0.0 + }, + { + "x": 390.3363721795221, + "y": -283.4631213927136, + "z": 0.0 + }, + { + "x": 390.33676172884026, + "y": -284.465361716963, + "z": 0.0 + }, + { + "x": 390.3371512781584, + "y": -285.467602041212, + "z": 0.0 + }, + { + "x": 390.3375408274766, + "y": -286.4698423654614, + "z": 0.0 + }, + { + "x": 390.33793037679476, + "y": -287.47208268971053, + "z": 0.0 + }, + { + "x": 390.3383199261129, + "y": -288.4743230139595, + "z": 0.0 + }, + { + "x": 390.338709475431, + "y": -289.4765633382087, + "z": 0.0 + }, + { + "x": 390.3390990247492, + "y": -290.47880366245806, + "z": 0.0 + }, + { + "x": 390.33948857406733, + "y": -291.48104398670705, + "z": 0.0 + }, + { + "x": 390.3398781233855, + "y": -292.48328431095644, + "z": 0.0 + }, + { + "x": 390.34026767270365, + "y": -293.4855246352054, + "z": 0.0 + }, + { + "x": 390.34065722202183, + "y": -294.4877649594548, + "z": 0.0 + }, + { + "x": 390.34104677133996, + "y": -295.49000528370374, + "z": 0.0 + }, + { + "x": 390.34143632065815, + "y": -296.4922456079532, + "z": 0.0 + }, + { + "x": 390.34182586997633, + "y": -297.49448593220234, + "z": 0.0 + }, + { + "x": 390.34221541929446, + "y": -298.49672625645127, + "z": 0.0 + }, + { + "x": 390.3426049686126, + "y": -299.4989665807005, + "z": 0.0 + }, + { + "x": 390.3429945179308, + "y": -300.50120690494987, + "z": 0.0 + }, + { + "x": 390.3433840672489, + "y": -301.50344722919885, + "z": 0.0 + }, + { + "x": 390.3437736165671, + "y": -302.50568755344824, + "z": 0.0 + }, + { + "x": 390.3441631658853, + "y": -303.5079278776974, + "z": 0.0 + }, + { + "x": 390.3445527152034, + "y": -304.5101682019464, + "z": 0.0 + }, + { + "x": 390.34494226452153, + "y": -305.51240852619554, + "z": 0.0 + }, + { + "x": 390.3453318138397, + "y": -306.5146488504449, + "z": 0.0 + }, + { + "x": 390.34572136315785, + "y": -307.5168891746939, + "z": 0.0 + }, + { + "x": 390.34611091247604, + "y": -308.5191294989433, + "z": 0.0 + }, + { + "x": 390.3465004617942, + "y": -309.5213698231925, + "z": 0.0 + }, + { + "x": 390.34689001111235, + "y": -310.52361014744145, + "z": 0.0 + }, + { + "x": 390.3472795604305, + "y": -311.5258504716906, + "z": 0.0 + }, + { + "x": 390.34766910974867, + "y": -312.52809079594005, + "z": 0.0 + }, + { + "x": 390.34805865906685, + "y": -313.5303311201892, + "z": 0.0 + }, + { + "x": 390.348448208385, + "y": -314.5325714444382, + "z": 0.0 + }, + { + "x": 390.34883775770317, + "y": -315.5348117686876, + "z": 0.0 + }, + { + "x": 390.3492273070213, + "y": -316.5370520929365, + "z": 0.0 + }, + { + "x": 390.3496168563394, + "y": -317.5392924171857, + "z": 0.0 + }, + { + "x": 390.3500064056576, + "y": -318.5415327414351, + "z": 0.0 + } + ] + }, + { + "id": 41, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 398.35000580137364, + "y": -318.5384233132524, + "z": 0.0 + }, + { + "x": 398.34961625205545, + "y": -317.53618298900346, + "z": 0.0 + }, + { + "x": 398.3492267027373, + "y": -316.53394266475425, + "z": 0.0 + }, + { + "x": 398.3488371534192, + "y": -315.53170234050486, + "z": 0.0 + }, + { + "x": 398.348447604101, + "y": -314.52946201625593, + "z": 0.0 + }, + { + "x": 398.3480580547829, + "y": -313.5272216920065, + "z": 0.0 + }, + { + "x": 398.3476685054647, + "y": -312.52498136775733, + "z": 0.0 + }, + { + "x": 398.3472789561465, + "y": -311.52274104350835, + "z": 0.0 + }, + { + "x": 398.3468894068284, + "y": -310.5205007192592, + "z": 0.0 + }, + { + "x": 398.34649985751025, + "y": -309.5182603950098, + "z": 0.0 + }, + { + "x": 398.34611030819207, + "y": -308.5160200707606, + "z": 0.0 + }, + { + "x": 398.3457207588739, + "y": -307.51377974651166, + "z": 0.0 + }, + { + "x": 398.34533120955575, + "y": -306.5115394222622, + "z": 0.0 + }, + { + "x": 398.34494166023757, + "y": -305.5092990980133, + "z": 0.0 + }, + { + "x": 398.34455211091944, + "y": -304.50705877376413, + "z": 0.0 + }, + { + "x": 398.3441625616013, + "y": -303.5048184495147, + "z": 0.0 + }, + { + "x": 398.3437730122831, + "y": -302.50257812526553, + "z": 0.0 + }, + { + "x": 398.34338346296494, + "y": -301.5003378010166, + "z": 0.0 + }, + { + "x": 398.3429939136468, + "y": -300.49809747676716, + "z": 0.0 + }, + { + "x": 398.3426043643286, + "y": -299.4958571525182, + "z": 0.0 + }, + { + "x": 398.3422148150105, + "y": -298.493616828269, + "z": 0.0 + }, + { + "x": 398.34182526569236, + "y": -297.4913765040196, + "z": 0.0 + }, + { + "x": 398.3414357163742, + "y": -296.48913617977047, + "z": 0.0 + }, + { + "x": 398.341046167056, + "y": -295.4868958555215, + "z": 0.0 + }, + { + "x": 398.34065661773786, + "y": -294.4846555312721, + "z": 0.0 + }, + { + "x": 398.3402670684197, + "y": -293.48241520702317, + "z": 0.0 + }, + { + "x": 398.33987751910155, + "y": -292.4801748827737, + "z": 0.0 + }, + { + "x": 398.33948796978336, + "y": -291.4779345585248, + "z": 0.0 + }, + { + "x": 398.33909842046523, + "y": -290.47569423427535, + "z": 0.0 + }, + { + "x": 398.33870887114705, + "y": -289.4734539100264, + "z": 0.0 + }, + { + "x": 398.3383193218289, + "y": -288.47121358577726, + "z": 0.0 + }, + { + "x": 398.3379297725108, + "y": -287.4689732615278, + "z": 0.0 + }, + { + "x": 398.3375402231926, + "y": -286.46673293727866, + "z": 0.0 + }, + { + "x": 398.3371506738744, + "y": -285.46449261302973, + "z": 0.0 + }, + { + "x": 398.3367611245563, + "y": -284.4622522887803, + "z": 0.0 + }, + { + "x": 398.3363715752381, + "y": -283.46001196453136, + "z": 0.0 + }, + { + "x": 398.33598202592, + "y": -282.4577716402822, + "z": 0.0 + }, + { + "x": 398.33559247660185, + "y": -281.45553131603276, + "z": 0.0 + }, + { + "x": 398.33520292728366, + "y": -280.4532909917836, + "z": 0.0 + }, + { + "x": 398.3348133779655, + "y": -279.4510506675346, + "z": 0.0 + }, + { + "x": 398.33442382864735, + "y": -278.44881034328523, + "z": 0.0 + }, + { + "x": 398.33403427932916, + "y": -277.4465700190363, + "z": 0.0 + }, + { + "x": 398.33364473001103, + "y": -276.4443296947869, + "z": 0.0 + }, + { + "x": 398.33325518069284, + "y": -275.44208937053793, + "z": 0.0 + }, + { + "x": 398.3328656313747, + "y": -274.43984904628854, + "z": 0.0 + }, + { + "x": 398.33247608205653, + "y": -273.4376087220394, + "z": 0.0 + }, + { + "x": 398.33208653273834, + "y": -272.4353683977904, + "z": 0.0 + }, + { + "x": 398.3316969834202, + "y": -271.43312807354124, + "z": 0.0 + }, + { + "x": 398.3313074341021, + "y": -270.43088774929186, + "z": 0.0 + }, + { + "x": 398.3309178847839, + "y": -269.42864742504287, + "z": 0.0 + }, + { + "x": 398.3305283354658, + "y": -268.4264071007935, + "z": 0.0 + }, + { + "x": 398.3301387861476, + "y": -267.42416677654455, + "z": 0.0 + }, + { + "x": 398.32974923682946, + "y": -266.42192645229534, + "z": 0.0 + }, + { + "x": 398.3293596875113, + "y": -265.41968612804595, + "z": 0.0 + }, + { + "x": 398.32897013819314, + "y": -264.4174458037968, + "z": 0.0 + }, + { + "x": 398.32858058887496, + "y": -263.4152054795478, + "z": 0.0 + }, + { + "x": 398.3281910395568, + "y": -262.4129651552984, + "z": 0.0 + }, + { + "x": 398.32780149023864, + "y": -261.41072483104927, + "z": 0.0 + }, + { + "x": 398.32741194092046, + "y": -260.4084845068003, + "z": 0.0 + }, + { + "x": 398.3270223916023, + "y": -259.4062441825511, + "z": 0.0 + }, + { + "x": 398.3266328422842, + "y": -258.40400385830173, + "z": 0.0 + }, + { + "x": 398.326243292966, + "y": -257.4017635340526, + "z": 0.0 + }, + { + "x": 398.3258537436478, + "y": -256.3995232098036, + "z": 0.0 + }, + { + "x": 398.3254641943297, + "y": -255.3972828855544, + "z": 0.0 + }, + { + "x": 398.32507464501157, + "y": -254.39504256130502, + "z": 0.0 + }, + { + "x": 398.3246850956934, + "y": -253.39280223705606, + "z": 0.0 + }, + { + "x": 398.32429554637525, + "y": -252.39056191280667, + "z": 0.0 + }, + { + "x": 398.32390599705707, + "y": -251.3883215885575, + "z": 0.0 + }, + { + "x": 398.3235164477389, + "y": -250.38608126430853, + "z": 0.0 + }, + { + "x": 398.32312689842075, + "y": -249.38384094005937, + "z": 0.0 + }, + { + "x": 398.3227373491026, + "y": -248.38160061580996, + "z": 0.0 + }, + { + "x": 398.32234779978444, + "y": -247.379360291561, + "z": 0.0 + }, + { + "x": 398.3219582504663, + "y": -246.37711996731161, + "z": 0.0 + }, + { + "x": 398.3215687011481, + "y": -245.37487964306243, + "z": 0.0 + }, + { + "x": 398.32117915182994, + "y": -244.3726393188135, + "z": 0.0 + }, + { + "x": 398.3207896025118, + "y": -243.3703989945643, + "z": 0.0 + }, + { + "x": 398.3204000531937, + "y": -242.3681586703149, + "z": 0.0 + }, + { + "x": 398.32001070338254, + "y": -241.3665669256959, + "z": 0.0 + }, + { + "x": 398.3197836758104, + "y": -240.36438857263863, + "z": 0.0 + }, + { + "x": 398.3195721744745, + "y": -239.36214819500114, + "z": 0.0 + }, + { + "x": 398.3193606731386, + "y": -238.35990781736365, + "z": 0.0 + }, + { + "x": 398.3191491718027, + "y": -237.35766743972616, + "z": 0.0 + }, + { + "x": 398.31893767046677, + "y": -236.35542706208867, + "z": 0.0 + }, + { + "x": 398.31872616913085, + "y": -235.35318668445117, + "z": 0.0 + }, + { + "x": 398.31851466779494, + "y": -234.35094630681368, + "z": 0.0 + }, + { + "x": 398.31830316645903, + "y": -233.3487059291762, + "z": 0.0 + }, + { + "x": 398.3180916651231, + "y": -232.3464655515387, + "z": 0.0 + }, + { + "x": 398.3178801637872, + "y": -231.3442251739012, + "z": 0.0 + }, + { + "x": 398.3176686624513, + "y": -230.34198479626372, + "z": 0.0 + }, + { + "x": 398.3174571611154, + "y": -229.33974441862622, + "z": 0.0 + }, + { + "x": 398.3172456597795, + "y": -228.33750404098873, + "z": 0.0 + }, + { + "x": 398.31703415844356, + "y": -227.3352636633512, + "z": 0.0 + }, + { + "x": 398.31682265710765, + "y": -226.33302328571372, + "z": 0.0 + }, + { + "x": 398.31661115577174, + "y": -225.33078290807623, + "z": 0.0 + }, + { + "x": 398.3163996544358, + "y": -224.32854253043874, + "z": 0.0 + }, + { + "x": 398.3161881530999, + "y": -223.32630215280125, + "z": 0.0 + }, + { + "x": 398.315976651764, + "y": -222.32406177516376, + "z": 0.0 + }, + { + "x": 398.3157651504281, + "y": -221.32182139752626, + "z": 0.0 + }, + { + "x": 398.3155536490922, + "y": -220.31958101988877, + "z": 0.0 + }, + { + "x": 398.31534214775627, + "y": -219.31734064225125, + "z": 0.0 + }, + { + "x": 398.31513064642036, + "y": -218.31510026461376, + "z": 0.0 + }, + { + "x": 398.31491914508445, + "y": -217.31285988697627, + "z": 0.0 + }, + { + "x": 398.31470764374853, + "y": -216.31061950933878, + "z": 0.0 + }, + { + "x": 398.3144961424126, + "y": -215.3083791317013, + "z": 0.0 + }, + { + "x": 398.3142846410767, + "y": -214.3061387540638, + "z": 0.0 + }, + { + "x": 398.3140731397408, + "y": -213.3038983764263, + "z": 0.0 + }, + { + "x": 398.3138616384049, + "y": -212.30165799878904, + "z": 0.0 + }, + { + "x": 398.31365013706903, + "y": -211.29941762115106, + "z": 0.0 + }, + { + "x": 398.31343863573306, + "y": -210.2971772435138, + "z": 0.0 + }, + { + "x": 398.31322713439715, + "y": -209.2949368658763, + "z": 0.0 + }, + { + "x": 398.31301563306124, + "y": -208.29269648823882, + "z": 0.0 + }, + { + "x": 398.31280413172533, + "y": -207.29045611060133, + "z": 0.0 + }, + { + "x": 398.3125926303894, + "y": -206.28821573296383, + "z": 0.0 + }, + { + "x": 398.3123811290535, + "y": -205.28597535532634, + "z": 0.0 + }, + { + "x": 398.3121696277176, + "y": -204.28373497768885, + "z": 0.0 + }, + { + "x": 398.3119581263817, + "y": -203.28149460005156, + "z": 0.0 + }, + { + "x": 398.3117466250458, + "y": -202.2792542224136, + "z": 0.0 + }, + { + "x": 398.31153512370986, + "y": -201.27701384477635, + "z": 0.0 + }, + { + "x": 398.31132362237395, + "y": -200.27477346713886, + "z": 0.0 + }, + { + "x": 398.31111212103804, + "y": -199.2725330895016, + "z": 0.0 + }, + { + "x": 398.3109006197022, + "y": -198.27029271186365, + "z": 0.0 + }, + { + "x": 398.3106891183662, + "y": -197.26805233422638, + "z": 0.0 + }, + { + "x": 398.3104776170303, + "y": -196.2658119565889, + "z": 0.0 + }, + { + "x": 398.3102661156944, + "y": -195.26357157895137, + "z": 0.0 + }, + { + "x": 398.3100546143585, + "y": -194.2613312013141, + "z": 0.0 + }, + { + "x": 398.3098431130226, + "y": -193.25909082367616, + "z": 0.0 + }, + { + "x": 398.30963161168665, + "y": -192.2568504460389, + "z": 0.0 + }, + { + "x": 398.30942011035074, + "y": -191.2546100684014, + "z": 0.0 + }, + { + "x": 398.30920860901483, + "y": -190.25236969076414, + "z": 0.0 + }, + { + "x": 398.308997107679, + "y": -189.2501293131264, + "z": 0.0 + }, + { + "x": 398.30878560634306, + "y": -188.2478889354889, + "z": 0.0 + }, + { + "x": 398.30857410500715, + "y": -187.24564855785115, + "z": 0.0 + }, + { + "x": 398.3083626036712, + "y": -186.2434081802139, + "z": 0.0 + }, + { + "x": 398.3081511023353, + "y": -185.24116780257657, + "z": 0.0 + }, + { + "x": 398.3079396009994, + "y": -184.23892742493885, + "z": 0.0 + }, + { + "x": 398.3077280996635, + "y": -183.2366870473011, + "z": 0.0 + }, + { + "x": 398.30751659832754, + "y": -182.23444666966384, + "z": 0.0 + }, + { + "x": 398.3073050969916, + "y": -181.23220629202655, + "z": 0.0 + }, + { + "x": 398.3070935956558, + "y": -180.22996591438883, + "z": 0.0 + }, + { + "x": 398.30688209431986, + "y": -179.22772553675134, + "z": 0.0 + }, + { + "x": 398.30667059298395, + "y": -178.22548515911356, + "z": 0.0 + }, + { + "x": 398.306459091648, + "y": -177.22324478147652, + "z": 0.0 + }, + { + "x": 398.3062475903121, + "y": -176.22100440383878, + "z": 0.0 + }, + { + "x": 398.3060360889762, + "y": -175.21876402620128, + "z": 0.0 + }, + { + "x": 398.3058245876403, + "y": -174.21652364856376, + "z": 0.0 + }, + { + "x": 398.3056130863044, + "y": -173.21428327092605, + "z": 0.0 + }, + { + "x": 398.3054015849684, + "y": -172.21204289328898, + "z": 0.0 + }, + { + "x": 398.30519008363257, + "y": -171.20980251565126, + "z": 0.0 + }, + { + "x": 398.30497858229666, + "y": -170.20756213801374, + "z": 0.0 + }, + { + "x": 398.30476708096074, + "y": -169.205321760376, + "z": 0.0 + }, + { + "x": 398.3045555796248, + "y": -168.20308138273893, + "z": 0.0 + }, + { + "x": 398.3043440782889, + "y": -167.2008410051012, + "z": 0.0 + }, + { + "x": 398.304132576953, + "y": -166.1986006274637, + "z": 0.0 + }, + { + "x": 398.3039210756171, + "y": -165.1963602498262, + "z": 0.0 + }, + { + "x": 398.3037095742812, + "y": -164.19411987218845, + "z": 0.0 + }, + { + "x": 398.3034980729452, + "y": -163.19187949455142, + "z": 0.0 + }, + { + "x": 398.30328657160936, + "y": -162.18963911691364, + "z": 0.0 + }, + { + "x": 398.30307507027345, + "y": -161.18739873927615, + "z": 0.0 + }, + { + "x": 398.30286356893754, + "y": -160.1851583616384, + "z": 0.0 + }, + { + "x": 398.30265206760157, + "y": -159.18291798400136, + "z": 0.0 + }, + { + "x": 398.3024405662657, + "y": -158.18067760636362, + "z": 0.0 + }, + { + "x": 398.3022290649298, + "y": -157.17843722872612, + "z": 0.0 + }, + { + "x": 398.3020175635939, + "y": -156.1761968510886, + "z": 0.0 + }, + { + "x": 398.301806062258, + "y": -155.1739564734509, + "z": 0.0 + }, + { + "x": 398.301594560922, + "y": -154.17171609581382, + "z": 0.0 + }, + { + "x": 398.30138305958616, + "y": -153.16947571817607, + "z": 0.0 + }, + { + "x": 398.30117155825025, + "y": -152.16723534053855, + "z": 0.0 + }, + { + "x": 398.30096005691433, + "y": -151.16499496290106, + "z": 0.0 + }, + { + "x": 398.3007485555784, + "y": -150.16275458526354, + "z": 0.0 + }, + { + "x": 398.3005370542425, + "y": -149.16051420762605, + "z": 0.0 + }, + { + "x": 398.3003255529066, + "y": -148.15827382998856, + "z": 0.0 + }, + { + "x": 398.3001140515707, + "y": -147.15603345235104, + "z": 0.0 + }, + { + "x": 398.2999025502348, + "y": -146.15379307471352, + "z": 0.0 + }, + { + "x": 398.29969104889886, + "y": -145.151552697076, + "z": 0.0 + }, + { + "x": 398.29947954756295, + "y": -144.1493123194385, + "z": 0.0 + }, + { + "x": 398.29926804622704, + "y": -143.147071941801, + "z": 0.0 + }, + { + "x": 398.29905654489113, + "y": -142.1448315641635, + "z": 0.0 + }, + { + "x": 398.2988450435552, + "y": -141.14259118652598, + "z": 0.0 + }, + { + "x": 398.2986335422193, + "y": -140.14035080888848, + "z": 0.0 + }, + { + "x": 398.2984220408834, + "y": -139.13811043125096, + "z": 0.0 + }, + { + "x": 398.2982105395475, + "y": -138.13587005361347, + "z": 0.0 + }, + { + "x": 398.2979990382116, + "y": -137.13362967597615, + "z": 0.0 + }, + { + "x": 398.2977875368757, + "y": -136.1313892983382, + "z": 0.0 + }, + { + "x": 398.29757603553975, + "y": -135.1291489207009, + "z": 0.0 + }, + { + "x": 398.29736453420384, + "y": -134.12690854306342, + "z": 0.0 + }, + { + "x": 398.2971530328679, + "y": -133.1246681654259, + "z": 0.0 + }, + { + "x": 398.296941531532, + "y": -132.1224277877884, + "z": 0.0 + }, + { + "x": 398.2967300301961, + "y": -131.1201874101509, + "z": 0.0 + }, + { + "x": 398.2965185288602, + "y": -130.11794703251337, + "z": 0.0 + }, + { + "x": 398.2963070275243, + "y": -129.11570665487585, + "z": 0.0 + }, + { + "x": 398.29609552618837, + "y": -128.1134662772386, + "z": 0.0 + }, + { + "x": 398.2958840248525, + "y": -127.11122589960061, + "z": 0.0 + }, + { + "x": 398.29567252351654, + "y": -126.10898552196335, + "z": 0.0 + }, + { + "x": 398.29546102218063, + "y": -125.10674514432586, + "z": 0.0 + }, + { + "x": 398.2952495208447, + "y": -124.10450476668858, + "z": 0.0 + }, + { + "x": 398.29503801950887, + "y": -123.10226438905063, + "z": 0.0 + }, + { + "x": 398.2948265181729, + "y": -122.10002401141335, + "z": 0.0 + }, + { + "x": 398.294615016837, + "y": -121.09778363377583, + "z": 0.0 + }, + { + "x": 398.2944035155011, + "y": -120.09554325613833, + "z": 0.0 + }, + { + "x": 398.29419201416516, + "y": -119.09330287850105, + "z": 0.0 + }, + { + "x": 398.2939805128293, + "y": -118.0910625008631, + "z": 0.0 + }, + { + "x": 398.29376901149334, + "y": -117.08882212322584, + "z": 0.0 + }, + { + "x": 398.2935575101574, + "y": -116.08658174558835, + "z": 0.0 + }, + { + "x": 398.2933460088215, + "y": -115.08434136795108, + "z": 0.0 + }, + { + "x": 398.29313450748566, + "y": -114.08210099031334, + "z": 0.0 + }, + { + "x": 398.29292300614975, + "y": -113.07986061267562, + "z": 0.0 + }, + { + "x": 398.2927115048138, + "y": -112.07762023503834, + "z": 0.0 + }, + { + "x": 398.29250000347787, + "y": -111.07537985740083, + "z": 0.0 + }, + { + "x": 398.29228850214196, + "y": -110.07313947976355, + "z": 0.0 + }, + { + "x": 398.2920770008061, + "y": -109.0708991021256, + "z": 0.0 + }, + { + "x": 398.29186549947013, + "y": -108.06865872448832, + "z": 0.0 + }, + { + "x": 398.2916539981342, + "y": -107.06641834685081, + "z": 0.0 + }, + { + "x": 398.2914424967983, + "y": -106.06417796921353, + "z": 0.0 + }, + { + "x": 398.29123099546246, + "y": -105.06193759157577, + "z": 0.0 + }, + { + "x": 398.29101949412654, + "y": -104.05969721393826, + "z": 0.0 + }, + { + "x": 398.29080799279063, + "y": -103.05745683630055, + "z": 0.0 + }, + { + "x": 398.29059649145466, + "y": -102.0552164586635, + "z": 0.0 + }, + { + "x": 398.2903849901188, + "y": -101.05297608102576, + "z": 0.0 + }, + { + "x": 398.2901734887829, + "y": -100.05073570338826, + "z": 0.0 + }, + { + "x": 398.289961987447, + "y": -99.04849532575075, + "z": 0.0 + }, + { + "x": 398.2897504861111, + "y": -98.04625494811299, + "z": 0.0 + }, + { + "x": 398.2895389847751, + "y": -97.04401457047594, + "z": 0.0 + }, + { + "x": 398.28932748343925, + "y": -96.0417741928382, + "z": 0.0 + }, + { + "x": 398.28911598210334, + "y": -95.0395338152007, + "z": 0.0 + }, + { + "x": 398.2889044807674, + "y": -94.03729343756297, + "z": 0.0 + }, + { + "x": 398.28869297943146, + "y": -93.03505305992591, + "z": 0.0 + }, + { + "x": 398.2884814780956, + "y": -92.03281268228818, + "z": 0.0 + }, + { + "x": 398.2882699767597, + "y": -91.03057230465068, + "z": 0.0 + }, + { + "x": 398.2880584754238, + "y": -90.02833192701317, + "z": 0.0 + }, + { + "x": 398.28784697408787, + "y": -89.02609154937541, + "z": 0.0 + }, + { + "x": 398.28763556056833, + "y": -88.02479527108368, + "z": 0.0 + }, + { + "x": 398.2876588492329, + "y": -87.02621246628772, + "z": 0.0 + }, + { + "x": 398.28859921985594, + "y": -86.02501496122022, + "z": 0.0 + }, + { + "x": 398.2898018880531, + "y": -85.0227752828551, + "z": 0.0 + }, + { + "x": 398.2910045562502, + "y": -84.02053560449042, + "z": 0.0 + }, + { + "x": 398.29220722444734, + "y": -83.01829592612553, + "z": 0.0 + }, + { + "x": 398.2934098926445, + "y": -82.01605624776037, + "z": 0.0 + }, + { + "x": 398.2946125608416, + "y": -81.0138165693957, + "z": 0.0 + }, + { + "x": 398.29581522903874, + "y": -80.0115768910308, + "z": 0.0 + }, + { + "x": 398.2970178972359, + "y": -79.00933721266567, + "z": 0.0 + }, + { + "x": 398.298220565433, + "y": -78.007097534301, + "z": 0.0 + }, + { + "x": 398.29942323363014, + "y": -77.00485785593611, + "z": 0.0 + }, + { + "x": 398.3006259018273, + "y": -76.00261817757121, + "z": 0.0 + }, + { + "x": 398.30182857002444, + "y": -75.0003784992063, + "z": 0.0 + }, + { + "x": 398.3030312382216, + "y": -73.99813882084118, + "z": 0.0 + }, + { + "x": 398.3042339064187, + "y": -72.99589914247647, + "z": 0.0 + }, + { + "x": 398.30543657461584, + "y": -71.99365946411159, + "z": 0.0 + }, + { + "x": 398.306639242813, + "y": -70.99141978574644, + "z": 0.0 + }, + { + "x": 398.3078419110101, + "y": -69.98918010738178, + "z": 0.0 + }, + { + "x": 398.30904457920724, + "y": -68.98694042901688, + "z": 0.0 + }, + { + "x": 398.3102472474044, + "y": -67.98470075065175, + "z": 0.0 + }, + { + "x": 398.3114499156015, + "y": -66.9824610722871, + "z": 0.0 + }, + { + "x": 398.31265258379864, + "y": -65.98022139392216, + "z": 0.0 + }, + { + "x": 398.3138552519958, + "y": -64.97798171555726, + "z": 0.0 + }, + { + "x": 398.31505792019294, + "y": -63.97574203719214, + "z": 0.0 + }, + { + "x": 398.31626058839004, + "y": -62.973502358827474, + "z": 0.0 + }, + { + "x": 398.3174632565872, + "y": -61.9712626804626, + "z": 0.0 + }, + { + "x": 398.31866592478434, + "y": -60.9690230020975, + "z": 0.0 + }, + { + "x": 398.31986859298144, + "y": -59.96678332373281, + "z": 0.0 + }, + { + "x": 398.3210712611786, + "y": -58.964543645367925, + "z": 0.0 + }, + { + "x": 398.32227392937574, + "y": -57.96230396700278, + "z": 0.0 + }, + { + "x": 398.32347659757284, + "y": -56.96006428863836, + "z": 0.0 + }, + { + "x": 398.32467926577004, + "y": -55.957824610273036, + "z": 0.0 + }, + { + "x": 398.32588193396714, + "y": -54.95558493190812, + "z": 0.0 + }, + { + "x": 398.32708460216423, + "y": -53.95334525354369, + "z": 0.0 + }, + { + "x": 398.32828727036144, + "y": -52.95110557517826, + "z": 0.0 + }, + { + "x": 398.32948993855854, + "y": -51.9488658968136, + "z": 0.0 + }, + { + "x": 398.3306926067557, + "y": -50.94662621844869, + "z": 0.0 + }, + { + "x": 398.33189527495284, + "y": -49.944386540083585, + "z": 0.0 + }, + { + "x": 398.33309794314994, + "y": -48.94214686171893, + "z": 0.0 + }, + { + "x": 398.3343006113471, + "y": -47.93990718335402, + "z": 0.0 + }, + { + "x": 398.33550327954424, + "y": -46.93766750498914, + "z": 0.0 + }, + { + "x": 398.3367059477414, + "y": -45.93542782662401, + "z": 0.0 + }, + { + "x": 398.3379086159385, + "y": -44.93318814825934, + "z": 0.0 + }, + { + "x": 398.33911128413564, + "y": -43.93094846989443, + "z": 0.0 + }, + { + "x": 398.3403139523328, + "y": -42.928708791529324, + "z": 0.0 + }, + { + "x": 398.3415166205299, + "y": -41.92646911316468, + "z": 0.0 + }, + { + "x": 398.34271928872704, + "y": -40.924229434799805, + "z": 0.0 + }, + { + "x": 398.3439219569242, + "y": -39.921989756434705, + "z": 0.0 + }, + { + "x": 398.3451246251213, + "y": -38.91975007807005, + "z": 0.0 + }, + { + "x": 398.34632729331844, + "y": -37.91751039970513, + "z": 0.0 + }, + { + "x": 398.3475299615156, + "y": -36.91527072134, + "z": 0.0 + }, + { + "x": 398.3487326297127, + "y": -35.913031042975334, + "z": 0.0 + }, + { + "x": 398.34993529790984, + "y": -34.91079136461043, + "z": 0.0 + }, + { + "x": 398.351137966107, + "y": -33.90855168624554, + "z": 0.0 + }, + { + "x": 398.35234063430414, + "y": -32.906312007880665, + "z": 0.0 + }, + { + "x": 398.3535433025013, + "y": -31.904072329515564, + "z": 0.0 + }, + { + "x": 398.3547459706984, + "y": -30.90183265115092, + "z": 0.0 + }, + { + "x": 398.35594863889554, + "y": -29.899592972786046, + "z": 0.0 + }, + { + "x": 398.3571513070927, + "y": -28.89735329442095, + "z": 0.0 + }, + { + "x": 398.3583539752898, + "y": -27.895113616056285, + "z": 0.0 + }, + { + "x": 398.35955664348694, + "y": -26.89287393769138, + "z": 0.0 + }, + { + "x": 398.3607593116841, + "y": -25.890634259326283, + "z": 0.0 + }, + { + "x": 398.3619619798812, + "y": -24.888394580961638, + "z": 0.0 + }, + { + "x": 398.36316464807834, + "y": -23.88615490259675, + "z": 0.0 + }, + { + "x": 398.3643673162755, + "y": -22.883915224231615, + "z": 0.0 + }, + { + "x": 398.3655699844726, + "y": -21.881675545866944, + "z": 0.0 + }, + { + "x": 398.36677265266974, + "y": -20.879435867501968, + "z": 0.0 + }, + { + "x": 398.3679753208669, + "y": -19.87719618913705, + "z": 0.0 + }, + { + "x": 398.36917798906404, + "y": -18.87495651077191, + "z": 0.0 + }, + { + "x": 398.37038065726114, + "y": -17.872716832407257, + "z": 0.0 + }, + { + "x": 398.3715833254583, + "y": -16.870477154042373, + "z": 0.0 + }, + { + "x": 398.37278599365544, + "y": -15.868237475677223, + "z": 0.0 + }, + { + "x": 398.37398866185254, + "y": -14.865997797312762, + "z": 0.0 + }, + { + "x": 398.37519133004974, + "y": -13.863758118947425, + "z": 0.0 + }, + { + "x": 398.37639399824684, + "y": -12.861518440582504, + "z": 0.0 + }, + { + "x": 398.37759666644394, + "y": -11.85927876221804, + "z": 0.0 + }, + { + "x": 398.37879933464114, + "y": -10.857039083852692, + "z": 0.0 + }, + { + "x": 398.38000200283824, + "y": -9.854799405487771, + "z": 0.0 + } + ] + }, + { + "id": 42, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 394.3500061035156, + "y": -318.53997802734375, + "z": 0.0 + }, + { + "x": 394.34961655419744, + "y": -317.5377377030946, + "z": 0.0 + }, + { + "x": 394.3492270048793, + "y": -316.5354973788454, + "z": 0.0 + }, + { + "x": 394.3488374555612, + "y": -315.5332570545962, + "z": 0.0 + }, + { + "x": 394.348447906243, + "y": -314.53101673034706, + "z": 0.0 + }, + { + "x": 394.34805835692487, + "y": -313.52877640609785, + "z": 0.0 + }, + { + "x": 394.3476688076067, + "y": -312.5265360818487, + "z": 0.0 + }, + { + "x": 394.3472792582885, + "y": -311.5242957575995, + "z": 0.0 + }, + { + "x": 394.34688970897037, + "y": -310.5220554333503, + "z": 0.0 + }, + { + "x": 394.34650015965224, + "y": -309.51981510910116, + "z": 0.0 + }, + { + "x": 394.34611061033405, + "y": -308.51757478485194, + "z": 0.0 + }, + { + "x": 394.34572106101587, + "y": -307.5153344606028, + "z": 0.0 + }, + { + "x": 394.34533151169774, + "y": -306.5130941363536, + "z": 0.0 + }, + { + "x": 394.34494196237955, + "y": -305.5108538121044, + "z": 0.0 + }, + { + "x": 394.3445524130614, + "y": -304.50861348785526, + "z": 0.0 + }, + { + "x": 394.3441628637433, + "y": -303.50637316360604, + "z": 0.0 + }, + { + "x": 394.3437733144251, + "y": -302.5041328393569, + "z": 0.0 + }, + { + "x": 394.3433837651069, + "y": -301.5018925151077, + "z": 0.0 + }, + { + "x": 394.3429942157888, + "y": -300.4996521908585, + "z": 0.0 + }, + { + "x": 394.3426046664706, + "y": -299.49741186660935, + "z": 0.0 + }, + { + "x": 394.3422151171525, + "y": -298.49517154236014, + "z": 0.0 + }, + { + "x": 394.34182556783435, + "y": -297.492931218111, + "z": 0.0 + }, + { + "x": 394.34143601851616, + "y": -296.4906908938618, + "z": 0.0 + }, + { + "x": 394.341046469198, + "y": -295.4884505696126, + "z": 0.0 + }, + { + "x": 394.34065691987985, + "y": -294.48621024536345, + "z": 0.0 + }, + { + "x": 394.34026737056166, + "y": -293.4839699211143, + "z": 0.0 + }, + { + "x": 394.33987782124353, + "y": -292.4817295968651, + "z": 0.0 + }, + { + "x": 394.33948827192535, + "y": -291.4794892726159, + "z": 0.0 + }, + { + "x": 394.3390987226072, + "y": -290.4772489483667, + "z": 0.0 + }, + { + "x": 394.33870917328903, + "y": -289.47500862411755, + "z": 0.0 + }, + { + "x": 394.3383196239709, + "y": -288.4727682998684, + "z": 0.0 + }, + { + "x": 394.3379300746528, + "y": -287.4705279756192, + "z": 0.0 + }, + { + "x": 394.3375405253346, + "y": -286.46828765137, + "z": 0.0 + }, + { + "x": 394.3371509760164, + "y": -285.46604732712086, + "z": 0.0 + }, + { + "x": 394.3367614266983, + "y": -284.46380700287165, + "z": 0.0 + }, + { + "x": 394.3363718773801, + "y": -283.4615666786225, + "z": 0.0 + }, + { + "x": 394.33598232806196, + "y": -282.45932635437333, + "z": 0.0 + }, + { + "x": 394.33559277874383, + "y": -281.4570860301241, + "z": 0.0 + }, + { + "x": 394.33520322942564, + "y": -280.45484570587496, + "z": 0.0 + }, + { + "x": 394.33481368010746, + "y": -279.45260538162574, + "z": 0.0 + }, + { + "x": 394.33442413078933, + "y": -278.4503650573766, + "z": 0.0 + }, + { + "x": 394.33403458147114, + "y": -277.44812473312743, + "z": 0.0 + }, + { + "x": 394.333645032153, + "y": -276.44588440887827, + "z": 0.0 + }, + { + "x": 394.33325548283483, + "y": -275.44364408462906, + "z": 0.0 + }, + { + "x": 394.3328659335167, + "y": -274.4414037603799, + "z": 0.0 + }, + { + "x": 394.3324763841985, + "y": -273.43916343613074, + "z": 0.0 + }, + { + "x": 394.33208683488033, + "y": -272.4369231118815, + "z": 0.0 + }, + { + "x": 394.3316972855622, + "y": -271.43468278763237, + "z": 0.0 + }, + { + "x": 394.33130773624407, + "y": -270.4324424633832, + "z": 0.0 + }, + { + "x": 394.3309181869259, + "y": -269.430202139134, + "z": 0.0 + }, + { + "x": 394.33052863760776, + "y": -268.42796181488484, + "z": 0.0 + }, + { + "x": 394.33013908828957, + "y": -267.4257214906357, + "z": 0.0 + }, + { + "x": 394.32974953897144, + "y": -266.42348116638647, + "z": 0.0 + }, + { + "x": 394.3293599896533, + "y": -265.4212408421373, + "z": 0.0 + }, + { + "x": 394.3289704403351, + "y": -264.41900051788815, + "z": 0.0 + }, + { + "x": 394.32858089101694, + "y": -263.41676019363894, + "z": 0.0 + }, + { + "x": 394.3281913416988, + "y": -262.4145198693898, + "z": 0.0 + }, + { + "x": 394.3278017923806, + "y": -261.4122795451406, + "z": 0.0 + }, + { + "x": 394.32741224306244, + "y": -260.4100392208914, + "z": 0.0 + }, + { + "x": 394.3270226937443, + "y": -259.40779889664225, + "z": 0.0 + }, + { + "x": 394.3266331444262, + "y": -258.4055585723931, + "z": 0.0 + }, + { + "x": 394.326243595108, + "y": -257.40331824814393, + "z": 0.0 + }, + { + "x": 394.3258540457898, + "y": -256.4010779238947, + "z": 0.0 + }, + { + "x": 394.3254644964717, + "y": -255.39883759964553, + "z": 0.0 + }, + { + "x": 394.32507494715355, + "y": -254.39659727539637, + "z": 0.0 + }, + { + "x": 394.32468539783537, + "y": -253.3943569511472, + "z": 0.0 + }, + { + "x": 394.32429584851724, + "y": -252.39211662689803, + "z": 0.0 + }, + { + "x": 394.32390629919905, + "y": -251.38987630264884, + "z": 0.0 + }, + { + "x": 394.32351674988087, + "y": -250.38763597839966, + "z": 0.0 + }, + { + "x": 394.32312720056274, + "y": -249.3853956541505, + "z": 0.0 + }, + { + "x": 394.3227376512446, + "y": -248.3831553299013, + "z": 0.0 + }, + { + "x": 394.3223481019264, + "y": -247.38091500565213, + "z": 0.0 + }, + { + "x": 394.3219585526083, + "y": -246.37867468140297, + "z": 0.0 + }, + { + "x": 394.3215690032901, + "y": -245.37643435715378, + "z": 0.0 + }, + { + "x": 394.3211794539719, + "y": -244.37419403290463, + "z": 0.0 + }, + { + "x": 394.3207899046538, + "y": -243.37195370865544, + "z": 0.0 + }, + { + "x": 394.32040035533566, + "y": -242.36971338440625, + "z": 0.0 + }, + { + "x": 394.3200108060175, + "y": -241.36747306015707, + "z": 0.0 + }, + { + "x": 394.3197837648765, + "y": -240.36523268682888, + "z": 0.0 + }, + { + "x": 394.3195722635406, + "y": -239.36299230919138, + "z": 0.0 + }, + { + "x": 394.31936076220467, + "y": -238.3607519315539, + "z": 0.0 + }, + { + "x": 394.31914926086876, + "y": -237.3585115539164, + "z": 0.0 + }, + { + "x": 394.31893775953284, + "y": -236.3562711762789, + "z": 0.0 + }, + { + "x": 394.31872625819693, + "y": -235.35403079864142, + "z": 0.0 + }, + { + "x": 394.318514756861, + "y": -234.35179042100393, + "z": 0.0 + }, + { + "x": 394.3183032555251, + "y": -233.34955004336643, + "z": 0.0 + }, + { + "x": 394.3180917541892, + "y": -232.34730966572894, + "z": 0.0 + }, + { + "x": 394.3178802528533, + "y": -231.34506928809145, + "z": 0.0 + }, + { + "x": 394.3176687515174, + "y": -230.34282891045396, + "z": 0.0 + }, + { + "x": 394.31745725018146, + "y": -229.34058853281647, + "z": 0.0 + }, + { + "x": 394.31724574884555, + "y": -228.33834815517898, + "z": 0.0 + }, + { + "x": 394.31703424750964, + "y": -227.33610777754146, + "z": 0.0 + }, + { + "x": 394.3168227461737, + "y": -226.33386739990397, + "z": 0.0 + }, + { + "x": 394.3166112448378, + "y": -225.33162702226647, + "z": 0.0 + }, + { + "x": 394.3163997435019, + "y": -224.32938664462898, + "z": 0.0 + }, + { + "x": 394.316188242166, + "y": -223.3271462669915, + "z": 0.0 + }, + { + "x": 394.3159767408301, + "y": -222.324905889354, + "z": 0.0 + }, + { + "x": 394.31576523949417, + "y": -221.3226655117165, + "z": 0.0 + }, + { + "x": 394.31555373815826, + "y": -220.32042513407902, + "z": 0.0 + }, + { + "x": 394.31534223682235, + "y": -219.3181847564415, + "z": 0.0 + }, + { + "x": 394.31513073548643, + "y": -218.315944378804, + "z": 0.0 + }, + { + "x": 394.3149192341505, + "y": -217.3137040011665, + "z": 0.0 + }, + { + "x": 394.3147077328146, + "y": -216.31146362352902, + "z": 0.0 + }, + { + "x": 394.3144962314787, + "y": -215.30922324589153, + "z": 0.0 + }, + { + "x": 394.3142847301428, + "y": -214.30698286825404, + "z": 0.0 + }, + { + "x": 394.3140732288069, + "y": -213.30474249061655, + "z": 0.0 + }, + { + "x": 394.31386172747096, + "y": -212.30250211297906, + "z": 0.0 + }, + { + "x": 394.3136502261351, + "y": -211.30026173534154, + "z": 0.0 + }, + { + "x": 394.31343872479914, + "y": -210.29802135770404, + "z": 0.0 + }, + { + "x": 394.31322722346323, + "y": -209.29578098006655, + "z": 0.0 + }, + { + "x": 394.3130157221273, + "y": -208.29354060242906, + "z": 0.0 + }, + { + "x": 394.3128042207914, + "y": -207.29130022479157, + "z": 0.0 + }, + { + "x": 394.3125927194555, + "y": -206.28905984715408, + "z": 0.0 + }, + { + "x": 394.3123812181196, + "y": -205.2868194695166, + "z": 0.0 + }, + { + "x": 394.31216971678367, + "y": -204.2845790918791, + "z": 0.0 + }, + { + "x": 394.31195821544776, + "y": -203.28233871424158, + "z": 0.0 + }, + { + "x": 394.3117467141119, + "y": -202.28009833660408, + "z": 0.0 + }, + { + "x": 394.31153521277594, + "y": -201.2778579589666, + "z": 0.0 + }, + { + "x": 394.31132371144, + "y": -200.2756175813291, + "z": 0.0 + }, + { + "x": 394.3111122101041, + "y": -199.2733772036916, + "z": 0.0 + }, + { + "x": 394.31090070876826, + "y": -198.27113682605412, + "z": 0.0 + }, + { + "x": 394.3106892074323, + "y": -197.26889644841663, + "z": 0.0 + }, + { + "x": 394.3104777060964, + "y": -196.26665607077913, + "z": 0.0 + }, + { + "x": 394.31026620476047, + "y": -195.26441569314161, + "z": 0.0 + }, + { + "x": 394.31005470342456, + "y": -194.26217531550412, + "z": 0.0 + }, + { + "x": 394.3098432020887, + "y": -193.25993493786663, + "z": 0.0 + }, + { + "x": 394.30963170075273, + "y": -192.25769456022914, + "z": 0.0 + }, + { + "x": 394.3094201994168, + "y": -191.25545418259165, + "z": 0.0 + }, + { + "x": 394.3092086980809, + "y": -190.25321380495416, + "z": 0.0 + }, + { + "x": 394.30899719674505, + "y": -189.25097342731664, + "z": 0.0 + }, + { + "x": 394.30878569540914, + "y": -188.24873304967915, + "z": 0.0 + }, + { + "x": 394.30857419407323, + "y": -187.24649267204163, + "z": 0.0 + }, + { + "x": 394.30836269273726, + "y": -186.24425229440413, + "z": 0.0 + }, + { + "x": 394.30815119140135, + "y": -185.2420119167666, + "z": 0.0 + }, + { + "x": 394.3079396900655, + "y": -184.2397715391291, + "z": 0.0 + }, + { + "x": 394.3077281887296, + "y": -183.23753116149157, + "z": 0.0 + }, + { + "x": 394.3075166873936, + "y": -182.23529078385408, + "z": 0.0 + }, + { + "x": 394.3073051860577, + "y": -181.23305040621656, + "z": 0.0 + }, + { + "x": 394.30709368472185, + "y": -180.23081002857907, + "z": 0.0 + }, + { + "x": 394.30688218338594, + "y": -179.22856965094158, + "z": 0.0 + }, + { + "x": 394.30667068205, + "y": -178.22632927330403, + "z": 0.0 + }, + { + "x": 394.30645918071406, + "y": -177.22408889566654, + "z": 0.0 + }, + { + "x": 394.3062476793782, + "y": -176.22184851802902, + "z": 0.0 + }, + { + "x": 394.3060361780423, + "y": -175.21960814039153, + "z": 0.0 + }, + { + "x": 394.3058246767064, + "y": -174.217367762754, + "z": 0.0 + }, + { + "x": 394.30561317537047, + "y": -173.21512738511652, + "z": 0.0 + }, + { + "x": 394.3054016740345, + "y": -172.212887007479, + "z": 0.0 + }, + { + "x": 394.30519017269864, + "y": -171.2106466298415, + "z": 0.0 + }, + { + "x": 394.30497867136273, + "y": -170.20840625220399, + "z": 0.0 + }, + { + "x": 394.3047671700268, + "y": -169.20616587456647, + "z": 0.0 + }, + { + "x": 394.30455566869085, + "y": -168.20392549692895, + "z": 0.0 + }, + { + "x": 394.304344167355, + "y": -167.20168511929145, + "z": 0.0 + }, + { + "x": 394.3041326660191, + "y": -166.19944474165393, + "z": 0.0 + }, + { + "x": 394.3039211646832, + "y": -165.19720436401644, + "z": 0.0 + }, + { + "x": 394.30370966334726, + "y": -164.19496398637892, + "z": 0.0 + }, + { + "x": 394.3034981620113, + "y": -163.19272360874143, + "z": 0.0 + }, + { + "x": 394.30328666067544, + "y": -162.19048323110388, + "z": 0.0 + }, + { + "x": 394.3030751593395, + "y": -161.1882428534664, + "z": 0.0 + }, + { + "x": 394.3028636580036, + "y": -160.18600247582887, + "z": 0.0 + }, + { + "x": 394.30265215666765, + "y": -159.18376209819138, + "z": 0.0 + }, + { + "x": 394.3024406553318, + "y": -158.18152172055386, + "z": 0.0 + }, + { + "x": 394.3022291539959, + "y": -157.17928134291637, + "z": 0.0 + }, + { + "x": 394.30201765265997, + "y": -156.17704096527885, + "z": 0.0 + }, + { + "x": 394.30180615132406, + "y": -155.17480058764136, + "z": 0.0 + }, + { + "x": 394.3015946499881, + "y": -154.17256021000384, + "z": 0.0 + }, + { + "x": 394.30138314865223, + "y": -153.17031983236632, + "z": 0.0 + }, + { + "x": 394.3011716473163, + "y": -152.1680794547288, + "z": 0.0 + }, + { + "x": 394.3009601459804, + "y": -151.1658390770913, + "z": 0.0 + }, + { + "x": 394.3007486446445, + "y": -150.1635986994538, + "z": 0.0 + }, + { + "x": 394.3005371433086, + "y": -149.1613583218163, + "z": 0.0 + }, + { + "x": 394.3003256419727, + "y": -148.1591179441788, + "z": 0.0 + }, + { + "x": 394.30011414063677, + "y": -147.15687756654128, + "z": 0.0 + }, + { + "x": 394.29990263930085, + "y": -146.15463718890376, + "z": 0.0 + }, + { + "x": 394.29969113796494, + "y": -145.15239681126624, + "z": 0.0 + }, + { + "x": 394.29947963662903, + "y": -144.15015643362875, + "z": 0.0 + }, + { + "x": 394.2992681352931, + "y": -143.14791605599123, + "z": 0.0 + }, + { + "x": 394.2990566339572, + "y": -142.14567567835374, + "z": 0.0 + }, + { + "x": 394.2988451326213, + "y": -141.14343530071622, + "z": 0.0 + }, + { + "x": 394.2986336312854, + "y": -140.14119492307873, + "z": 0.0 + }, + { + "x": 394.2984221299495, + "y": -139.1389545454412, + "z": 0.0 + }, + { + "x": 394.29821062861356, + "y": -138.13671416780372, + "z": 0.0 + }, + { + "x": 394.29799912727765, + "y": -137.13447379016617, + "z": 0.0 + }, + { + "x": 394.2977876259418, + "y": -136.13223341252868, + "z": 0.0 + }, + { + "x": 394.2975761246058, + "y": -135.12999303489116, + "z": 0.0 + }, + { + "x": 394.2973646232699, + "y": -134.12775265725367, + "z": 0.0 + }, + { + "x": 394.297153121934, + "y": -133.12551227961615, + "z": 0.0 + }, + { + "x": 394.2969416205981, + "y": -132.12327190197865, + "z": 0.0 + }, + { + "x": 394.2967301192622, + "y": -131.12103152434113, + "z": 0.0 + }, + { + "x": 394.29651861792627, + "y": -130.11879114670361, + "z": 0.0 + }, + { + "x": 394.29630711659036, + "y": -129.1165507690661, + "z": 0.0 + }, + { + "x": 394.29609561525444, + "y": -128.1143103914286, + "z": 0.0 + }, + { + "x": 394.2958841139186, + "y": -127.1120700137911, + "z": 0.0 + }, + { + "x": 394.2956726125826, + "y": -126.1098296361536, + "z": 0.0 + }, + { + "x": 394.2954611112467, + "y": -125.10758925851611, + "z": 0.0 + }, + { + "x": 394.2952496099108, + "y": -124.10534888087861, + "z": 0.0 + }, + { + "x": 394.29503810857494, + "y": -123.10310850324112, + "z": 0.0 + }, + { + "x": 394.294826607239, + "y": -122.10086812560361, + "z": 0.0 + }, + { + "x": 394.29461510590306, + "y": -121.09862774796609, + "z": 0.0 + }, + { + "x": 394.29440360456715, + "y": -120.09638737032859, + "z": 0.0 + }, + { + "x": 394.29419210323124, + "y": -119.09414699269108, + "z": 0.0 + }, + { + "x": 394.2939806018954, + "y": -118.09190661505359, + "z": 0.0 + }, + { + "x": 394.2937691005594, + "y": -117.0896662374161, + "z": 0.0 + }, + { + "x": 394.2935575992235, + "y": -116.0874258597786, + "z": 0.0 + }, + { + "x": 394.2933460978876, + "y": -115.08518548214111, + "z": 0.0 + }, + { + "x": 394.29313459655174, + "y": -114.0829451045036, + "z": 0.0 + }, + { + "x": 394.2929230952158, + "y": -113.0807047268661, + "z": 0.0 + }, + { + "x": 394.29271159387986, + "y": -112.0784643492286, + "z": 0.0 + }, + { + "x": 394.29250009254395, + "y": -111.07622397159109, + "z": 0.0 + }, + { + "x": 394.29228859120803, + "y": -110.07398359395359, + "z": 0.0 + }, + { + "x": 394.2920770898722, + "y": -109.07174321631608, + "z": 0.0 + }, + { + "x": 394.2918655885362, + "y": -108.06950283867857, + "z": 0.0 + }, + { + "x": 394.2916540872003, + "y": -107.06726246104107, + "z": 0.0 + }, + { + "x": 394.2914425858644, + "y": -106.06502208340356, + "z": 0.0 + }, + { + "x": 394.29123108452853, + "y": -105.06278170576603, + "z": 0.0 + }, + { + "x": 394.2910195831926, + "y": -104.06054132812852, + "z": 0.0 + }, + { + "x": 394.2908080818567, + "y": -103.05830095049103, + "z": 0.0 + }, + { + "x": 394.29059658052074, + "y": -102.05606057285353, + "z": 0.0 + }, + { + "x": 394.2903850791849, + "y": -101.05382019521602, + "z": 0.0 + }, + { + "x": 394.290173577849, + "y": -100.05157981757851, + "z": 0.0 + }, + { + "x": 394.28996207651306, + "y": -99.04933943994101, + "z": 0.0 + }, + { + "x": 394.28975057517715, + "y": -98.04709906230347, + "z": 0.0 + }, + { + "x": 394.2895390738412, + "y": -97.04485868466597, + "z": 0.0 + }, + { + "x": 394.28932757250533, + "y": -96.04261830702846, + "z": 0.0 + }, + { + "x": 394.2891160711694, + "y": -95.04037792939096, + "z": 0.0 + }, + { + "x": 394.2889045698335, + "y": -94.03813755175345, + "z": 0.0 + }, + { + "x": 394.28869306849754, + "y": -93.03589717411595, + "z": 0.0 + }, + { + "x": 394.2884815671617, + "y": -92.03365679647844, + "z": 0.0 + }, + { + "x": 394.28827006582577, + "y": -91.03141641884093, + "z": 0.0 + }, + { + "x": 394.28805856448986, + "y": -90.02917604120343, + "z": 0.0 + }, + { + "x": 394.28784706315395, + "y": -89.0269356635659, + "z": 0.0 + }, + { + "x": 394.287635561818, + "y": -88.02469528592839, + "z": 0.0 + }, + { + "x": 394.2876606141071, + "y": -87.02245494181614, + "z": 0.0 + }, + { + "x": 394.2886020997598, + "y": -86.02021504217004, + "z": 0.0 + }, + { + "x": 394.289804767957, + "y": -85.01797536380514, + "z": 0.0 + }, + { + "x": 394.2910074361541, + "y": -84.01573568544023, + "z": 0.0 + }, + { + "x": 394.2922101043512, + "y": -83.01349600707535, + "z": 0.0 + }, + { + "x": 394.2934127725484, + "y": -82.01125632871042, + "z": 0.0 + }, + { + "x": 394.2946154407455, + "y": -81.00901665034552, + "z": 0.0 + }, + { + "x": 394.2958181089426, + "y": -80.00677697198061, + "z": 0.0 + }, + { + "x": 394.2970207771398, + "y": -79.00453729361571, + "z": 0.0 + }, + { + "x": 394.2982234453369, + "y": -78.00229761525081, + "z": 0.0 + }, + { + "x": 394.299426113534, + "y": -77.00005793688592, + "z": 0.0 + }, + { + "x": 394.3006287817312, + "y": -75.99781825852102, + "z": 0.0 + }, + { + "x": 394.30183144992833, + "y": -74.99557858015612, + "z": 0.0 + }, + { + "x": 394.3030341181255, + "y": -73.99333890179122, + "z": 0.0 + }, + { + "x": 394.3042367863226, + "y": -72.99109922342629, + "z": 0.0 + }, + { + "x": 394.3054394545197, + "y": -71.9888595450614, + "z": 0.0 + }, + { + "x": 394.3066421227169, + "y": -70.98661986669649, + "z": 0.0 + }, + { + "x": 394.307844790914, + "y": -69.9843801883316, + "z": 0.0 + }, + { + "x": 394.3090474591111, + "y": -68.9821405099667, + "z": 0.0 + }, + { + "x": 394.3102501273083, + "y": -67.9799008316018, + "z": 0.0 + }, + { + "x": 394.3114527955054, + "y": -66.97766115323691, + "z": 0.0 + }, + { + "x": 394.3126554637025, + "y": -65.97542147487198, + "z": 0.0 + }, + { + "x": 394.3138581318997, + "y": -64.97318179650708, + "z": 0.0 + }, + { + "x": 394.31506080009683, + "y": -63.970942118142176, + "z": 0.0 + }, + { + "x": 394.3162634682939, + "y": -62.96870243977728, + "z": 0.0 + }, + { + "x": 394.3174661364911, + "y": -61.96646276141241, + "z": 0.0 + }, + { + "x": 394.31866880468823, + "y": -60.964223083047536, + "z": 0.0 + }, + { + "x": 394.3198714728853, + "y": -59.96198340468262, + "z": 0.0 + }, + { + "x": 394.3210741410825, + "y": -58.95974372631774, + "z": 0.0 + }, + { + "x": 394.32227680927963, + "y": -57.95750404795282, + "z": 0.0 + }, + { + "x": 394.3234794774767, + "y": -56.955264369587944, + "z": 0.0 + }, + { + "x": 394.32468214567393, + "y": -55.95302469122307, + "z": 0.0 + }, + { + "x": 394.325884813871, + "y": -54.950785012858155, + "z": 0.0 + }, + { + "x": 394.3270874820681, + "y": -53.948545334493275, + "z": 0.0 + }, + { + "x": 394.32829015026533, + "y": -52.946305656128295, + "z": 0.0 + }, + { + "x": 394.3294928184624, + "y": -51.944065977763415, + "z": 0.0 + }, + { + "x": 394.3306954866596, + "y": -50.9418262993985, + "z": 0.0 + }, + { + "x": 394.33189815485673, + "y": -49.93958662103362, + "z": 0.0 + }, + { + "x": 394.3331008230538, + "y": -48.937346942668746, + "z": 0.0 + }, + { + "x": 394.334303491251, + "y": -47.93510726430383, + "z": 0.0 + }, + { + "x": 394.33550615944813, + "y": -46.93286758593895, + "z": 0.0 + }, + { + "x": 394.3367088276453, + "y": -45.93062790757404, + "z": 0.0 + }, + { + "x": 394.3379114958424, + "y": -44.92838822920915, + "z": 0.0 + }, + { + "x": 394.33911416403953, + "y": -43.92614855084424, + "z": 0.0 + }, + { + "x": 394.3403168322367, + "y": -42.92390887247936, + "z": 0.0 + }, + { + "x": 394.3415195004338, + "y": -41.921669194114486, + "z": 0.0 + }, + { + "x": 394.3427221686309, + "y": -40.91942951574961, + "z": 0.0 + }, + { + "x": 394.3439248368281, + "y": -39.91718983738474, + "z": 0.0 + }, + { + "x": 394.3451275050252, + "y": -38.91495015901987, + "z": 0.0 + }, + { + "x": 394.3463301732223, + "y": -37.91271048065494, + "z": 0.0 + }, + { + "x": 394.3475328414195, + "y": -36.910470802290035, + "z": 0.0 + }, + { + "x": 394.3487355096166, + "y": -35.90823112392514, + "z": 0.0 + }, + { + "x": 394.3499381778137, + "y": -34.90599144556024, + "z": 0.0 + }, + { + "x": 394.3511408460109, + "y": -33.903751767195345, + "z": 0.0 + }, + { + "x": 394.35234351420803, + "y": -32.90151208883047, + "z": 0.0 + }, + { + "x": 394.3535461824052, + "y": -31.899272410465603, + "z": 0.0 + }, + { + "x": 394.3547488506023, + "y": -30.89703273210073, + "z": 0.0 + }, + { + "x": 394.35595151879943, + "y": -29.894793053735857, + "z": 0.0 + }, + { + "x": 394.3571541869966, + "y": -28.892553375370987, + "z": 0.0 + }, + { + "x": 394.3583568551937, + "y": -27.890313697006096, + "z": 0.0 + }, + { + "x": 394.3595595233908, + "y": -26.88807401864119, + "z": 0.0 + }, + { + "x": 394.360762191588, + "y": -25.885834340276322, + "z": 0.0 + }, + { + "x": 394.3619648597851, + "y": -24.88359466191145, + "z": 0.0 + }, + { + "x": 394.3631675279822, + "y": -23.88135498354656, + "z": 0.0 + }, + { + "x": 394.3643701961794, + "y": -22.879115305181653, + "z": 0.0 + }, + { + "x": 394.3655728643765, + "y": -21.876875626816755, + "z": 0.0 + }, + { + "x": 394.3667755325736, + "y": -20.87463594845178, + "z": 0.0 + }, + { + "x": 394.3679782007708, + "y": -19.87239627008686, + "z": 0.0 + }, + { + "x": 394.36918086896793, + "y": -18.870156591721948, + "z": 0.0 + }, + { + "x": 394.370383537165, + "y": -17.867916913357067, + "z": 0.0 + }, + { + "x": 394.3715862053622, + "y": -16.865677234992184, + "z": 0.0 + }, + { + "x": 394.37278887355933, + "y": -15.863437556627261, + "z": 0.0 + }, + { + "x": 394.3739915417564, + "y": -14.861197878262345, + "z": 0.0 + }, + { + "x": 394.37519420995363, + "y": -13.858958199897463, + "z": 0.0 + }, + { + "x": 394.37639687815073, + "y": -12.856718521532542, + "z": 0.0 + }, + { + "x": 394.3775995463478, + "y": -11.854478843167623, + "z": 0.0 + }, + { + "x": 394.37880221454503, + "y": -10.85223916480273, + "z": 0.0 + }, + { + "x": 394.3800048827421, + "y": -9.84999948643781, + "z": 0.0 + } + ] + }, + { + "id": 43, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 392.38000632269404, + "y": -9.847599526912829, + "z": 0.0 + }, + { + "x": 392.378803654497, + "y": -10.84983920527775, + "z": 0.0 + }, + { + "x": 392.37760098629974, + "y": -11.852078883642415, + "z": 0.0 + }, + { + "x": 392.3763983181027, + "y": -12.854318562007562, + "z": 0.0 + }, + { + "x": 392.37519564990555, + "y": -13.856558240372483, + "z": 0.0 + }, + { + "x": 392.3739929817084, + "y": -14.858797918737137, + "z": 0.0 + }, + { + "x": 392.37279031351125, + "y": -15.86103759710228, + "z": 0.0 + }, + { + "x": 392.3715876453141, + "y": -16.86327727546709, + "z": 0.0 + }, + { + "x": 392.37038497711694, + "y": -17.86551695383197, + "z": 0.0 + }, + { + "x": 392.3691823089199, + "y": -18.867756632196965, + "z": 0.0 + }, + { + "x": 392.36797964072275, + "y": -19.869996310561767, + "z": 0.0 + }, + { + "x": 392.3667769725256, + "y": -20.872235988926683, + "z": 0.0 + }, + { + "x": 392.36557430432845, + "y": -21.874475667291662, + "z": 0.0 + }, + { + "x": 392.3643716361313, + "y": -22.87671534565667, + "z": 0.0 + }, + { + "x": 392.36316896793414, + "y": -23.878955024021465, + "z": 0.0 + }, + { + "x": 392.361966299737, + "y": -24.881194702386352, + "z": 0.0 + }, + { + "x": 392.36076363153995, + "y": -25.88343438075134, + "z": 0.0 + }, + { + "x": 392.3595609633428, + "y": -26.8856740591161, + "z": 0.0 + }, + { + "x": 392.35835829514565, + "y": -27.887913737481, + "z": 0.0 + }, + { + "x": 392.3571556269485, + "y": -28.890153415846008, + "z": 0.0 + }, + { + "x": 392.35595295875135, + "y": -29.89239309421076, + "z": 0.0 + }, + { + "x": 392.3547502905542, + "y": -30.894632772575633, + "z": 0.0 + }, + { + "x": 392.35354762235715, + "y": -31.89687245094062, + "z": 0.0 + }, + { + "x": 392.35234495416, + "y": -32.89911212930538, + "z": 0.0 + }, + { + "x": 392.35114228596285, + "y": -33.90135180767025, + "z": 0.0 + }, + { + "x": 392.3499396177657, + "y": -34.90359148603514, + "z": 0.0 + }, + { + "x": 392.34873694956855, + "y": -35.90583116440004, + "z": 0.0 + }, + { + "x": 392.3475342813714, + "y": -36.908070842765056, + "z": 0.0 + }, + { + "x": 392.34633161317424, + "y": -37.910310521129844, + "z": 0.0 + }, + { + "x": 392.3451289449771, + "y": -38.912550199494774, + "z": 0.0 + }, + { + "x": 392.34392627678005, + "y": -39.91478987785976, + "z": 0.0 + }, + { + "x": 392.3427236085829, + "y": -40.91702955622452, + "z": 0.0 + }, + { + "x": 392.34152094038575, + "y": -41.91926923458939, + "z": 0.0 + }, + { + "x": 392.3403182721886, + "y": -42.92150891295438, + "z": 0.0 + }, + { + "x": 392.33911560399144, + "y": -43.92374859131914, + "z": 0.0 + }, + { + "x": 392.3379129357943, + "y": -44.925988269684055, + "z": 0.0 + }, + { + "x": 392.33671026759725, + "y": -45.928227948049056, + "z": 0.0 + }, + { + "x": 392.3355075994001, + "y": -46.93046762641386, + "z": 0.0 + }, + { + "x": 392.33430493120295, + "y": -47.93270730477873, + "z": 0.0 + }, + { + "x": 392.3331022630058, + "y": -48.934946983143654, + "z": 0.0 + }, + { + "x": 392.33189959480865, + "y": -49.93718666150863, + "z": 0.0 + }, + { + "x": 392.3306969266115, + "y": -50.93942633987341, + "z": 0.0 + }, + { + "x": 392.32949425841434, + "y": -51.94166601823832, + "z": 0.0 + }, + { + "x": 392.3282915902173, + "y": -52.94390569660331, + "z": 0.0 + }, + { + "x": 392.32708892202004, + "y": -53.94614537496807, + "z": 0.0 + }, + { + "x": 392.325886253823, + "y": -54.94838505333317, + "z": 0.0 + }, + { + "x": 392.32468358562585, + "y": -55.950624731698085, + "z": 0.0 + }, + { + "x": 392.3234809174287, + "y": -56.95286441006274, + "z": 0.0 + }, + { + "x": 392.32227824923154, + "y": -57.95510408842783, + "z": 0.0 + }, + { + "x": 392.3210755810344, + "y": -58.95734376679265, + "z": 0.0 + }, + { + "x": 392.31987291283724, + "y": -59.95958344515752, + "z": 0.0 + }, + { + "x": 392.3186702446402, + "y": -60.96182312352255, + "z": 0.0 + }, + { + "x": 392.31746757644305, + "y": -61.96406280188731, + "z": 0.0 + }, + { + "x": 392.3162649082459, + "y": -62.96630248025218, + "z": 0.0 + }, + { + "x": 392.31506224004875, + "y": -63.9685421586172, + "z": 0.0 + }, + { + "x": 392.3138595718516, + "y": -64.97078183698198, + "z": 0.0 + }, + { + "x": 392.31265690365444, + "y": -65.97302151534689, + "z": 0.0 + }, + { + "x": 392.3114542354573, + "y": -66.97526119371182, + "z": 0.0 + }, + { + "x": 392.31025156726025, + "y": -67.97750087207682, + "z": 0.0 + }, + { + "x": 392.3090488990631, + "y": -68.9797405504416, + "z": 0.0 + }, + { + "x": 392.30784623086595, + "y": -69.9819802288065, + "z": 0.0 + }, + { + "x": 392.3066435626688, + "y": -70.98421990717151, + "z": 0.0 + }, + { + "x": 392.30544089447164, + "y": -71.98645958553631, + "z": 0.0 + }, + { + "x": 392.3042382262745, + "y": -72.9886992639012, + "z": 0.0 + }, + { + "x": 392.30303555807745, + "y": -73.99093894226624, + "z": 0.0 + }, + { + "x": 392.3018328898803, + "y": -74.99317862063103, + "z": 0.0 + }, + { + "x": 392.30063022168315, + "y": -75.99541829899593, + "z": 0.0 + }, + { + "x": 392.299427553486, + "y": -76.99765797736083, + "z": 0.0 + }, + { + "x": 392.29822488528885, + "y": -77.99989765572572, + "z": 0.0 + }, + { + "x": 392.2970222170917, + "y": -79.00213733409073, + "z": 0.0 + }, + { + "x": 392.29581954889454, + "y": -80.00437701245552, + "z": 0.0 + }, + { + "x": 392.2946168806974, + "y": -81.00661669082042, + "z": 0.0 + }, + { + "x": 392.29341421250035, + "y": -82.00885636918544, + "z": 0.0 + }, + { + "x": 392.2922115443032, + "y": -83.01109604755025, + "z": 0.0 + }, + { + "x": 392.29100887610605, + "y": -84.01333572591514, + "z": 0.0 + }, + { + "x": 392.2898062079089, + "y": -85.01557540428016, + "z": 0.0 + }, + { + "x": 392.28860353971174, + "y": -86.01781508264494, + "z": 0.0 + }, + { + "x": 392.28766149654416, + "y": -87.02057617958035, + "z": 0.0 + }, + { + "x": 392.2876355624428, + "y": -88.02464529335074, + "z": 0.0 + }, + { + "x": 392.28784710768696, + "y": -89.02735772066114, + "z": 0.0 + }, + { + "x": 392.28805860902287, + "y": -90.02959809829855, + "z": 0.0 + }, + { + "x": 392.2882701103588, + "y": -91.03183847593607, + "z": 0.0 + }, + { + "x": 392.2884816116947, + "y": -92.03407885357356, + "z": 0.0 + }, + { + "x": 392.2886931130306, + "y": -93.03631923121097, + "z": 0.0 + }, + { + "x": 392.2889046143665, + "y": -94.03855960884869, + "z": 0.0 + }, + { + "x": 392.2891161157024, + "y": -95.04079998648609, + "z": 0.0 + }, + { + "x": 392.28932761703834, + "y": -96.04304036412358, + "z": 0.0 + }, + { + "x": 392.28953911837425, + "y": -97.04528074176099, + "z": 0.0 + }, + { + "x": 392.28975061971016, + "y": -98.04752111939871, + "z": 0.0 + }, + { + "x": 392.2899621210461, + "y": -99.04976149703614, + "z": 0.0 + }, + { + "x": 392.290173622382, + "y": -100.05200187467364, + "z": 0.0 + }, + { + "x": 392.2903851237179, + "y": -101.05424225231116, + "z": 0.0 + }, + { + "x": 392.2905966250538, + "y": -102.05648262994853, + "z": 0.0 + }, + { + "x": 392.2908081263897, + "y": -103.05872300758628, + "z": 0.0 + }, + { + "x": 392.29101962772563, + "y": -104.06096338522366, + "z": 0.0 + }, + { + "x": 392.29123112906154, + "y": -105.06320376286115, + "z": 0.0 + }, + { + "x": 392.29144263039746, + "y": -106.06544414049858, + "z": 0.0 + }, + { + "x": 392.29165413173337, + "y": -107.06768451813619, + "z": 0.0 + }, + { + "x": 392.2918656330693, + "y": -108.06992489577371, + "z": 0.0 + }, + { + "x": 392.2920771344052, + "y": -109.07216527341131, + "z": 0.0 + }, + { + "x": 392.2922886357411, + "y": -110.07440565104861, + "z": 0.0 + }, + { + "x": 392.292500137077, + "y": -111.07664602868621, + "z": 0.0 + }, + { + "x": 392.2927116384129, + "y": -112.07888640632373, + "z": 0.0 + }, + { + "x": 392.29292313974884, + "y": -113.08112678396134, + "z": 0.0 + }, + { + "x": 392.29313464108475, + "y": -114.08336716159872, + "z": 0.0 + }, + { + "x": 392.29334614242066, + "y": -115.08560753923612, + "z": 0.0 + }, + { + "x": 392.29355764375657, + "y": -116.08784791687373, + "z": 0.0 + }, + { + "x": 392.2937691450925, + "y": -117.09008829451122, + "z": 0.0 + }, + { + "x": 392.2939806464284, + "y": -118.09232867214882, + "z": 0.0 + }, + { + "x": 392.2941921477643, + "y": -119.09456904978609, + "z": 0.0 + }, + { + "x": 392.2944036491002, + "y": -120.09680942742372, + "z": 0.0 + }, + { + "x": 392.29461515043613, + "y": -121.09904980506121, + "z": 0.0 + }, + { + "x": 392.29482665177204, + "y": -122.10129018269873, + "z": 0.0 + }, + { + "x": 392.29503815310795, + "y": -123.10353056033637, + "z": 0.0 + }, + { + "x": 392.29524965444386, + "y": -124.10577093797363, + "z": 0.0 + }, + { + "x": 392.2954611557798, + "y": -125.10801131561124, + "z": 0.0 + }, + { + "x": 392.2956726571157, + "y": -126.11025169324873, + "z": 0.0 + }, + { + "x": 392.2958841584516, + "y": -127.11249207088633, + "z": 0.0 + }, + { + "x": 392.2960956597875, + "y": -128.11473244852363, + "z": 0.0 + }, + { + "x": 392.2963071611234, + "y": -129.1169728261612, + "z": 0.0 + }, + { + "x": 392.29651866245933, + "y": -130.11921320379872, + "z": 0.0 + }, + { + "x": 392.29673016379525, + "y": -131.12145358143624, + "z": 0.0 + }, + { + "x": 392.29694166513116, + "y": -132.12369395907376, + "z": 0.0 + }, + { + "x": 392.29715316646707, + "y": -133.12593433671128, + "z": 0.0 + }, + { + "x": 392.297364667803, + "y": -134.1281747143488, + "z": 0.0 + }, + { + "x": 392.2975761691389, + "y": -135.13041509198626, + "z": 0.0 + }, + { + "x": 392.2977876704748, + "y": -136.1326554696239, + "z": 0.0 + }, + { + "x": 392.2979991718107, + "y": -137.1348958472612, + "z": 0.0 + }, + { + "x": 392.2982106731466, + "y": -138.13713622489882, + "z": 0.0 + }, + { + "x": 392.29842217448254, + "y": -139.13937660253634, + "z": 0.0 + }, + { + "x": 392.29863367581845, + "y": -140.14161698017386, + "z": 0.0 + }, + { + "x": 392.29884517715436, + "y": -141.14385735781133, + "z": 0.0 + }, + { + "x": 392.2990566784903, + "y": -142.14609773544885, + "z": 0.0 + }, + { + "x": 392.2992681798262, + "y": -143.14833811308637, + "z": 0.0 + }, + { + "x": 392.2994796811621, + "y": -144.1505784907239, + "z": 0.0 + }, + { + "x": 392.299691182498, + "y": -145.15281886836135, + "z": 0.0 + }, + { + "x": 392.2999026838339, + "y": -146.15505924599887, + "z": 0.0 + }, + { + "x": 392.30011418516983, + "y": -147.1572996236364, + "z": 0.0 + }, + { + "x": 392.30032568650574, + "y": -148.1595400012739, + "z": 0.0 + }, + { + "x": 392.30053718784166, + "y": -149.16178037891143, + "z": 0.0 + }, + { + "x": 392.30074868917757, + "y": -150.1640207565489, + "z": 0.0 + }, + { + "x": 392.3009601905135, + "y": -151.1662611341864, + "z": 0.0 + }, + { + "x": 392.3011716918494, + "y": -152.16850151182393, + "z": 0.0 + }, + { + "x": 392.3013831931853, + "y": -153.17074188946145, + "z": 0.0 + }, + { + "x": 392.3015946945211, + "y": -154.17298226709886, + "z": 0.0 + }, + { + "x": 392.3018061958571, + "y": -155.1752226447366, + "z": 0.0 + }, + { + "x": 392.30201769719304, + "y": -156.17746302237396, + "z": 0.0 + }, + { + "x": 392.30222919852895, + "y": -157.17970340001148, + "z": 0.0 + }, + { + "x": 392.30244069986486, + "y": -158.181943777649, + "z": 0.0 + }, + { + "x": 392.30265220120066, + "y": -159.1841841552864, + "z": 0.0 + }, + { + "x": 392.3028637025367, + "y": -160.1864245329241, + "z": 0.0 + }, + { + "x": 392.3030752038726, + "y": -161.1886649105615, + "z": 0.0 + }, + { + "x": 392.3032867052085, + "y": -162.19090528819902, + "z": 0.0 + }, + { + "x": 392.3034982065443, + "y": -163.19314566583643, + "z": 0.0 + }, + { + "x": 392.30370970788033, + "y": -164.19538604347417, + "z": 0.0 + }, + { + "x": 392.30392120921624, + "y": -165.19762642111158, + "z": 0.0 + }, + { + "x": 392.30413271055215, + "y": -166.19986679874904, + "z": 0.0 + }, + { + "x": 392.30434421188806, + "y": -167.20210717638656, + "z": 0.0 + }, + { + "x": 392.30455571322386, + "y": -168.20434755402397, + "z": 0.0 + }, + { + "x": 392.3047672145599, + "y": -169.20658793166172, + "z": 0.0 + }, + { + "x": 392.3049787158958, + "y": -170.20882830929912, + "z": 0.0 + }, + { + "x": 392.3051902172317, + "y": -171.21106868693664, + "z": 0.0 + }, + { + "x": 392.3054017185675, + "y": -172.213309064574, + "z": 0.0 + }, + { + "x": 392.30561321990353, + "y": -173.21554944221174, + "z": 0.0 + }, + { + "x": 392.30582472123945, + "y": -174.21778981984914, + "z": 0.0 + }, + { + "x": 392.30603622257536, + "y": -175.22003019748666, + "z": 0.0 + }, + { + "x": 392.30624772391127, + "y": -176.22227057512413, + "z": 0.0 + }, + { + "x": 392.30645922524707, + "y": -177.22451095276153, + "z": 0.0 + }, + { + "x": 392.3066707265831, + "y": -178.22675133039928, + "z": 0.0 + }, + { + "x": 392.306882227919, + "y": -179.2289917080367, + "z": 0.0 + }, + { + "x": 392.3070937292549, + "y": -180.2312320856742, + "z": 0.0 + }, + { + "x": 392.3073052305907, + "y": -181.23347246331156, + "z": 0.0 + }, + { + "x": 392.3075167319266, + "y": -182.2357128409492, + "z": 0.0 + }, + { + "x": 392.30772823326265, + "y": -183.23795321858682, + "z": 0.0 + }, + { + "x": 392.30793973459856, + "y": -184.24019359622423, + "z": 0.0 + }, + { + "x": 392.30815123593436, + "y": -185.24243397386158, + "z": 0.0 + }, + { + "x": 392.3083627372703, + "y": -186.24467435149927, + "z": 0.0 + }, + { + "x": 392.3085742386063, + "y": -187.24691472913685, + "z": 0.0 + }, + { + "x": 392.3087857399422, + "y": -188.24915510677425, + "z": 0.0 + }, + { + "x": 392.3089972412781, + "y": -189.25139548441177, + "z": 0.0 + }, + { + "x": 392.3092087426139, + "y": -190.25363586204918, + "z": 0.0 + }, + { + "x": 392.30942024394983, + "y": -191.25587623968676, + "z": 0.0 + }, + { + "x": 392.30963174528574, + "y": -192.25811661732428, + "z": 0.0 + }, + { + "x": 392.30984324662177, + "y": -193.26035699496185, + "z": 0.0 + }, + { + "x": 392.31005474795757, + "y": -194.26259737259915, + "z": 0.0 + }, + { + "x": 392.3102662492935, + "y": -195.26483775023672, + "z": 0.0 + }, + { + "x": 392.3104777506294, + "y": -196.26707812787424, + "z": 0.0 + }, + { + "x": 392.3106892519653, + "y": -197.26931850551176, + "z": 0.0 + }, + { + "x": 392.3109007533013, + "y": -198.27155888314934, + "z": 0.0 + }, + { + "x": 392.3111122546371, + "y": -199.27379926078663, + "z": 0.0 + }, + { + "x": 392.31132375597304, + "y": -200.2760396384242, + "z": 0.0 + }, + { + "x": 392.31153525730895, + "y": -201.27828001606173, + "z": 0.0 + }, + { + "x": 392.311746758645, + "y": -202.2805203936993, + "z": 0.0 + }, + { + "x": 392.31195825998077, + "y": -203.2827607713366, + "z": 0.0 + }, + { + "x": 392.3121697613167, + "y": -204.28500114897423, + "z": 0.0 + }, + { + "x": 392.3123812626526, + "y": -205.2872415266117, + "z": 0.0 + }, + { + "x": 392.3125927639885, + "y": -206.28948190424921, + "z": 0.0 + }, + { + "x": 392.3128042653244, + "y": -207.29172228188668, + "z": 0.0 + }, + { + "x": 392.3130157666603, + "y": -208.2939626595242, + "z": 0.0 + }, + { + "x": 392.31322726799624, + "y": -209.29620303716166, + "z": 0.0 + }, + { + "x": 392.31343876933215, + "y": -210.29844341479918, + "z": 0.0 + }, + { + "x": 392.3136502706682, + "y": -211.30068379243676, + "z": 0.0 + }, + { + "x": 392.313861772004, + "y": -212.30292417007405, + "z": 0.0 + }, + { + "x": 392.3140732733399, + "y": -213.30516454771168, + "z": 0.0 + }, + { + "x": 392.3142847746758, + "y": -214.30740492534915, + "z": 0.0 + }, + { + "x": 392.3144962760117, + "y": -215.30964530298667, + "z": 0.0 + }, + { + "x": 392.3147077773476, + "y": -216.31188568062413, + "z": 0.0 + }, + { + "x": 392.31491927868353, + "y": -217.31412605826165, + "z": 0.0 + }, + { + "x": 392.31513078001944, + "y": -218.3163664358991, + "z": 0.0 + }, + { + "x": 392.31534228135536, + "y": -219.31860681353663, + "z": 0.0 + }, + { + "x": 392.31555378269127, + "y": -220.32084719117415, + "z": 0.0 + }, + { + "x": 392.3157652840272, + "y": -221.32308756881162, + "z": 0.0 + }, + { + "x": 392.3159767853631, + "y": -222.32532794644914, + "z": 0.0 + }, + { + "x": 392.316188286699, + "y": -223.3275683240866, + "z": 0.0 + }, + { + "x": 392.3163997880349, + "y": -224.32980870172412, + "z": 0.0 + }, + { + "x": 392.3166112893708, + "y": -225.33204907936158, + "z": 0.0 + }, + { + "x": 392.31682279070674, + "y": -226.3342894569991, + "z": 0.0 + }, + { + "x": 392.31703429204265, + "y": -227.33652983463656, + "z": 0.0 + }, + { + "x": 392.31724579337856, + "y": -228.33877021227408, + "z": 0.0 + }, + { + "x": 392.3174572947145, + "y": -229.3410105899116, + "z": 0.0 + }, + { + "x": 392.3176687960504, + "y": -230.34325096754907, + "z": 0.0 + }, + { + "x": 392.3178802973863, + "y": -231.3454913451866, + "z": 0.0 + }, + { + "x": 392.3180917987222, + "y": -232.34773172282405, + "z": 0.0 + }, + { + "x": 392.3183033000581, + "y": -233.34997210046157, + "z": 0.0 + }, + { + "x": 392.31851480139403, + "y": -234.35221247809903, + "z": 0.0 + }, + { + "x": 392.31872630272994, + "y": -235.35445285573655, + "z": 0.0 + }, + { + "x": 392.31893780406585, + "y": -236.35669323337402, + "z": 0.0 + }, + { + "x": 392.31914930540177, + "y": -237.35893361101154, + "z": 0.0 + }, + { + "x": 392.3193608067377, + "y": -238.361173988649, + "z": 0.0 + }, + { + "x": 392.3195723080736, + "y": -239.36341436628652, + "z": 0.0 + }, + { + "x": 392.3197838094095, + "y": -240.36565474392398, + "z": 0.0 + }, + { + "x": 392.320010857335, + "y": -241.36792612738765, + "z": 0.0 + }, + { + "x": 392.32040050640666, + "y": -242.37049074145193, + "z": 0.0 + }, + { + "x": 392.3207900557248, + "y": -243.372731065701, + "z": 0.0 + }, + { + "x": 392.3211796050429, + "y": -244.3749713899502, + "z": 0.0 + }, + { + "x": 392.3215691543611, + "y": -245.37721171419946, + "z": 0.0 + }, + { + "x": 392.3219587036793, + "y": -246.37945203844865, + "z": 0.0 + }, + { + "x": 392.3223482529974, + "y": -247.3816923626977, + "z": 0.0 + }, + { + "x": 392.3227378023156, + "y": -248.383932686947, + "z": 0.0 + }, + { + "x": 392.32312735163373, + "y": -249.38617301119606, + "z": 0.0 + }, + { + "x": 392.32351690095186, + "y": -250.38841333544522, + "z": 0.0 + }, + { + "x": 392.32390645027004, + "y": -251.39065365969452, + "z": 0.0 + }, + { + "x": 392.32429599958823, + "y": -252.3928939839437, + "z": 0.0 + }, + { + "x": 392.32468554890636, + "y": -253.39513430819275, + "z": 0.0 + }, + { + "x": 392.32507509822454, + "y": -254.39737463244205, + "z": 0.0 + }, + { + "x": 392.3254646475427, + "y": -255.3996149566911, + "z": 0.0 + }, + { + "x": 392.3258541968608, + "y": -256.40185528094025, + "z": 0.0 + }, + { + "x": 392.326243746179, + "y": -257.4040956051896, + "z": 0.0 + }, + { + "x": 392.3266332954972, + "y": -258.4063359294388, + "z": 0.0 + }, + { + "x": 392.3270228448153, + "y": -259.4085762536878, + "z": 0.0 + }, + { + "x": 392.32741239413343, + "y": -260.410816577937, + "z": 0.0 + }, + { + "x": 392.3278019434516, + "y": -261.4130569021863, + "z": 0.0 + }, + { + "x": 392.3281914927698, + "y": -262.4152972264354, + "z": 0.0 + }, + { + "x": 392.32858104208793, + "y": -263.41753755068453, + "z": 0.0 + }, + { + "x": 392.3289705914061, + "y": -264.41977787493386, + "z": 0.0 + }, + { + "x": 392.3293601407243, + "y": -265.42201819918296, + "z": 0.0 + }, + { + "x": 392.32974969004243, + "y": -266.42425852343206, + "z": 0.0 + }, + { + "x": 392.33013923936056, + "y": -267.4264988476813, + "z": 0.0 + }, + { + "x": 392.33052878867875, + "y": -268.4287391719305, + "z": 0.0 + }, + { + "x": 392.3309183379969, + "y": -269.4309794961796, + "z": 0.0 + }, + { + "x": 392.33130788731506, + "y": -270.4332198204289, + "z": 0.0 + }, + { + "x": 392.3316974366332, + "y": -271.4354601446779, + "z": 0.0 + }, + { + "x": 392.3320869859513, + "y": -272.4377004689271, + "z": 0.0 + }, + { + "x": 392.3324765352695, + "y": -273.43994079317645, + "z": 0.0 + }, + { + "x": 392.3328660845877, + "y": -274.44218111742555, + "z": 0.0 + }, + { + "x": 392.3332556339058, + "y": -275.44442144167465, + "z": 0.0 + }, + { + "x": 392.333645183224, + "y": -276.446661765924, + "z": 0.0 + }, + { + "x": 392.33403473254214, + "y": -277.44890209017296, + "z": 0.0 + }, + { + "x": 392.3344242818603, + "y": -278.4511424144223, + "z": 0.0 + }, + { + "x": 392.33481383117845, + "y": -279.4533827386713, + "z": 0.0 + }, + { + "x": 392.33520338049664, + "y": -280.4556230629206, + "z": 0.0 + }, + { + "x": 392.3355929298148, + "y": -281.4578633871698, + "z": 0.0 + }, + { + "x": 392.33598247913295, + "y": -282.4601037114189, + "z": 0.0 + }, + { + "x": 392.3363720284511, + "y": -283.462344035668, + "z": 0.0 + }, + { + "x": 392.33676157776927, + "y": -284.46458435991735, + "z": 0.0 + }, + { + "x": 392.3371511270874, + "y": -285.46682468416645, + "z": 0.0 + }, + { + "x": 392.3375406764056, + "y": -286.46906500841567, + "z": 0.0 + }, + { + "x": 392.33793022572377, + "y": -287.4713053326649, + "z": 0.0 + }, + { + "x": 392.3383197750419, + "y": -288.473545656914, + "z": 0.0 + }, + { + "x": 392.33870932436, + "y": -289.4757859811631, + "z": 0.0 + }, + { + "x": 392.3390988736782, + "y": -290.4780263054124, + "z": 0.0 + }, + { + "x": 392.33948842299634, + "y": -291.4802666296615, + "z": 0.0 + }, + { + "x": 392.3398779723145, + "y": -292.48250695391073, + "z": 0.0 + }, + { + "x": 392.34026752163265, + "y": -293.48474727815983, + "z": 0.0 + }, + { + "x": 392.34065707095084, + "y": -294.48698760240916, + "z": 0.0 + }, + { + "x": 392.34104662026897, + "y": -295.48922792665815, + "z": 0.0 + }, + { + "x": 392.34143616958715, + "y": -296.4914682509075, + "z": 0.0 + }, + { + "x": 392.34182571890534, + "y": -297.4937085751567, + "z": 0.0 + }, + { + "x": 392.34221526822347, + "y": -298.4959488994057, + "z": 0.0 + }, + { + "x": 392.3426048175416, + "y": -299.4981892236549, + "z": 0.0 + }, + { + "x": 392.3429943668598, + "y": -300.5004295479042, + "z": 0.0 + }, + { + "x": 392.3433839161779, + "y": -301.5026698721533, + "z": 0.0 + }, + { + "x": 392.3437734654961, + "y": -302.50491019640253, + "z": 0.0 + }, + { + "x": 392.3441630148143, + "y": -303.50715052065175, + "z": 0.0 + }, + { + "x": 392.3445525641324, + "y": -304.50939084490085, + "z": 0.0 + }, + { + "x": 392.34494211345054, + "y": -305.51163116914995, + "z": 0.0 + }, + { + "x": 392.34533166276873, + "y": -306.5138714933993, + "z": 0.0 + }, + { + "x": 392.34572121208686, + "y": -307.5161118176484, + "z": 0.0 + }, + { + "x": 392.34611076140504, + "y": -308.5183521418976, + "z": 0.0 + }, + { + "x": 392.34650031072323, + "y": -309.5205924661468, + "z": 0.0 + }, + { + "x": 392.34688986004136, + "y": -310.5228327903959, + "z": 0.0 + }, + { + "x": 392.3472794093595, + "y": -311.525073114645, + "z": 0.0 + }, + { + "x": 392.3476689586777, + "y": -312.52731343889434, + "z": 0.0 + }, + { + "x": 392.34805850799586, + "y": -313.52955376314355, + "z": 0.0 + }, + { + "x": 392.348448057314, + "y": -314.53179408739265, + "z": 0.0 + }, + { + "x": 392.3488376066322, + "y": -315.53403441164187, + "z": 0.0 + }, + { + "x": 392.3492271559503, + "y": -316.53627473589097, + "z": 0.0 + }, + { + "x": 392.34961670526843, + "y": -317.5385150601402, + "z": 0.0 + }, + { + "x": 392.3500062545866, + "y": -318.5407553843894, + "z": 0.0 + } + ] + }, + { + "id": 44, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 396.35000595244463, + "y": -318.5392006702981, + "z": 0.0 + }, + { + "x": 396.34961640312645, + "y": -317.536960346049, + "z": 0.0 + }, + { + "x": 396.3492268538083, + "y": -316.5347200217998, + "z": 0.0 + }, + { + "x": 396.3488373044902, + "y": -315.53247969755057, + "z": 0.0 + }, + { + "x": 396.348447755172, + "y": -314.53023937330147, + "z": 0.0 + }, + { + "x": 396.3480582058539, + "y": -313.52799904905214, + "z": 0.0 + }, + { + "x": 396.3476686565357, + "y": -312.52575872480304, + "z": 0.0 + }, + { + "x": 396.3472791072175, + "y": -311.52351840055394, + "z": 0.0 + }, + { + "x": 396.3468895578994, + "y": -310.5212780763047, + "z": 0.0 + }, + { + "x": 396.34650000858124, + "y": -309.5190377520555, + "z": 0.0 + }, + { + "x": 396.34611045926306, + "y": -308.5167974278063, + "z": 0.0 + }, + { + "x": 396.3457209099449, + "y": -307.5145571035572, + "z": 0.0 + }, + { + "x": 396.34533136062674, + "y": -306.51231677930787, + "z": 0.0 + }, + { + "x": 396.34494181130856, + "y": -305.5100764550589, + "z": 0.0 + }, + { + "x": 396.34455226199043, + "y": -304.50783613080966, + "z": 0.0 + }, + { + "x": 396.3441627126723, + "y": -303.50559580656034, + "z": 0.0 + }, + { + "x": 396.3437731633541, + "y": -302.50335548231124, + "z": 0.0 + }, + { + "x": 396.34338361403593, + "y": -301.50111515806213, + "z": 0.0 + }, + { + "x": 396.3429940647178, + "y": -300.4988748338128, + "z": 0.0 + }, + { + "x": 396.3426045153996, + "y": -299.4966345095638, + "z": 0.0 + }, + { + "x": 396.3422149660815, + "y": -298.4943941853146, + "z": 0.0 + }, + { + "x": 396.34182541676336, + "y": -297.4921538610653, + "z": 0.0 + }, + { + "x": 396.34143586744517, + "y": -296.4899135368162, + "z": 0.0 + }, + { + "x": 396.341046318127, + "y": -295.4876732125671, + "z": 0.0 + }, + { + "x": 396.34065676880886, + "y": -294.48543288831775, + "z": 0.0 + }, + { + "x": 396.34026721949067, + "y": -293.48319256406876, + "z": 0.0 + }, + { + "x": 396.33987767017254, + "y": -292.48095223981943, + "z": 0.0 + }, + { + "x": 396.33948812085436, + "y": -291.47871191557033, + "z": 0.0 + }, + { + "x": 396.3390985715362, + "y": -290.476471591321, + "z": 0.0 + }, + { + "x": 396.33870902221804, + "y": -289.474231267072, + "z": 0.0 + }, + { + "x": 396.3383194728999, + "y": -288.4719909428228, + "z": 0.0 + }, + { + "x": 396.3379299235818, + "y": -287.46975061857347, + "z": 0.0 + }, + { + "x": 396.3375403742636, + "y": -286.46751029432437, + "z": 0.0 + }, + { + "x": 396.3371508249454, + "y": -285.46526997007527, + "z": 0.0 + }, + { + "x": 396.3367612756273, + "y": -284.46302964582594, + "z": 0.0 + }, + { + "x": 396.3363717263091, + "y": -283.46078932157695, + "z": 0.0 + }, + { + "x": 396.33598217699097, + "y": -282.45854899732774, + "z": 0.0 + }, + { + "x": 396.33559262767284, + "y": -281.4563086730784, + "z": 0.0 + }, + { + "x": 396.33520307835465, + "y": -280.4540683488293, + "z": 0.0 + }, + { + "x": 396.33481352903647, + "y": -279.4518280245802, + "z": 0.0 + }, + { + "x": 396.33442397971834, + "y": -278.4495877003309, + "z": 0.0 + }, + { + "x": 396.33403443040015, + "y": -277.4473473760819, + "z": 0.0 + }, + { + "x": 396.333644881082, + "y": -276.44510705183257, + "z": 0.0 + }, + { + "x": 396.33325533176384, + "y": -275.44286672758346, + "z": 0.0 + }, + { + "x": 396.3328657824457, + "y": -274.44062640333425, + "z": 0.0 + }, + { + "x": 396.3324762331275, + "y": -273.43838607908503, + "z": 0.0 + }, + { + "x": 396.33208668380934, + "y": -272.43614575483593, + "z": 0.0 + }, + { + "x": 396.3316971344912, + "y": -271.43390543058683, + "z": 0.0 + }, + { + "x": 396.3313075851731, + "y": -270.4316651063375, + "z": 0.0 + }, + { + "x": 396.3309180358549, + "y": -269.4294247820884, + "z": 0.0 + }, + { + "x": 396.33052848653676, + "y": -268.4271844578392, + "z": 0.0 + }, + { + "x": 396.3301389372186, + "y": -267.4249441335901, + "z": 0.0 + }, + { + "x": 396.32974938790045, + "y": -266.4227038093409, + "z": 0.0 + }, + { + "x": 396.3293598385823, + "y": -265.42046348509166, + "z": 0.0 + }, + { + "x": 396.32897028926413, + "y": -264.41822316084244, + "z": 0.0 + }, + { + "x": 396.32858073994595, + "y": -263.41598283659334, + "z": 0.0 + }, + { + "x": 396.3281911906278, + "y": -262.41374251234413, + "z": 0.0 + }, + { + "x": 396.32780164130963, + "y": -261.4115021880949, + "z": 0.0 + }, + { + "x": 396.32741209199145, + "y": -260.4092618638458, + "z": 0.0 + }, + { + "x": 396.3270225426733, + "y": -259.4070215395967, + "z": 0.0 + }, + { + "x": 396.3266329933552, + "y": -258.4047812153474, + "z": 0.0 + }, + { + "x": 396.326243444037, + "y": -257.4025408910983, + "z": 0.0 + }, + { + "x": 396.3258538947188, + "y": -256.4003005668492, + "z": 0.0 + }, + { + "x": 396.3254643454007, + "y": -255.39806024259997, + "z": 0.0 + }, + { + "x": 396.32507479608256, + "y": -254.3958199183507, + "z": 0.0 + }, + { + "x": 396.3246852467644, + "y": -253.39357959410162, + "z": 0.0 + }, + { + "x": 396.32429569744625, + "y": -252.39133926985235, + "z": 0.0 + }, + { + "x": 396.32390614812806, + "y": -251.38909894560317, + "z": 0.0 + }, + { + "x": 396.3235165988099, + "y": -250.3868586213541, + "z": 0.0 + }, + { + "x": 396.32312704949175, + "y": -249.38461829710494, + "z": 0.0 + }, + { + "x": 396.3227375001736, + "y": -248.38237797285564, + "z": 0.0 + }, + { + "x": 396.32234795085543, + "y": -247.38013764860656, + "z": 0.0 + }, + { + "x": 396.3219584015373, + "y": -246.3778973243573, + "z": 0.0 + }, + { + "x": 396.3215688522191, + "y": -245.3756570001081, + "z": 0.0 + }, + { + "x": 396.32117930290093, + "y": -244.37341667585906, + "z": 0.0 + }, + { + "x": 396.3207897535828, + "y": -243.37117635160988, + "z": 0.0 + }, + { + "x": 396.3204002042647, + "y": -242.36893602736058, + "z": 0.0 + }, + { + "x": 396.3200107547, + "y": -241.3670199929265, + "z": 0.0 + }, + { + "x": 396.3197837203435, + "y": -240.36481062973377, + "z": 0.0 + }, + { + "x": 396.31957221900757, + "y": -239.36257025209625, + "z": 0.0 + }, + { + "x": 396.31936071767166, + "y": -238.36032987445878, + "z": 0.0 + }, + { + "x": 396.31914921633575, + "y": -237.35808949682126, + "z": 0.0 + }, + { + "x": 396.31893771499983, + "y": -236.3558491191838, + "z": 0.0 + }, + { + "x": 396.3187262136639, + "y": -235.35360874154628, + "z": 0.0 + }, + { + "x": 396.318514712328, + "y": -234.35136836390882, + "z": 0.0 + }, + { + "x": 396.3183032109921, + "y": -233.3491279862713, + "z": 0.0 + }, + { + "x": 396.3180917096562, + "y": -232.34688760863384, + "z": 0.0 + }, + { + "x": 396.3178802083203, + "y": -231.34464723099632, + "z": 0.0 + }, + { + "x": 396.31766870698436, + "y": -230.34240685335885, + "z": 0.0 + }, + { + "x": 396.31745720564845, + "y": -229.34016647572133, + "z": 0.0 + }, + { + "x": 396.31724570431254, + "y": -228.33792609808387, + "z": 0.0 + }, + { + "x": 396.31703420297663, + "y": -227.33568572044635, + "z": 0.0 + }, + { + "x": 396.3168227016407, + "y": -226.33344534280883, + "z": 0.0 + }, + { + "x": 396.3166112003048, + "y": -225.33120496517137, + "z": 0.0 + }, + { + "x": 396.3163996989689, + "y": -224.32896458753385, + "z": 0.0 + }, + { + "x": 396.316188197633, + "y": -223.32672420989638, + "z": 0.0 + }, + { + "x": 396.31597669629707, + "y": -222.32448383225886, + "z": 0.0 + }, + { + "x": 396.31576519496116, + "y": -221.3222434546214, + "z": 0.0 + }, + { + "x": 396.31555369362525, + "y": -220.32000307698388, + "z": 0.0 + }, + { + "x": 396.31534219228934, + "y": -219.31776269934636, + "z": 0.0 + }, + { + "x": 396.3151306909534, + "y": -218.3155223217089, + "z": 0.0 + }, + { + "x": 396.3149191896175, + "y": -217.31328194407138, + "z": 0.0 + }, + { + "x": 396.3147076882816, + "y": -216.31104156643391, + "z": 0.0 + }, + { + "x": 396.3144961869457, + "y": -215.3088011887964, + "z": 0.0 + }, + { + "x": 396.3142846856098, + "y": -214.30656081115893, + "z": 0.0 + }, + { + "x": 396.31407318427387, + "y": -213.3043204335214, + "z": 0.0 + }, + { + "x": 396.31386168293795, + "y": -212.30208005588406, + "z": 0.0 + }, + { + "x": 396.31365018160204, + "y": -211.29983967824631, + "z": 0.0 + }, + { + "x": 396.31343868026613, + "y": -210.2975993006089, + "z": 0.0 + }, + { + "x": 396.3132271789302, + "y": -209.29535892297145, + "z": 0.0 + }, + { + "x": 396.3130156775943, + "y": -208.29311854533393, + "z": 0.0 + }, + { + "x": 396.3128041762584, + "y": -207.29087816769646, + "z": 0.0 + }, + { + "x": 396.3125926749225, + "y": -206.28863779005894, + "z": 0.0 + }, + { + "x": 396.3123811735866, + "y": -205.28639741242148, + "z": 0.0 + }, + { + "x": 396.31216967225066, + "y": -204.28415703478396, + "z": 0.0 + }, + { + "x": 396.31195817091475, + "y": -203.28191665714655, + "z": 0.0 + }, + { + "x": 396.31174666957884, + "y": -202.27967627950886, + "z": 0.0 + }, + { + "x": 396.3115351682429, + "y": -201.27743590187146, + "z": 0.0 + }, + { + "x": 396.311323666907, + "y": -200.275195524234, + "z": 0.0 + }, + { + "x": 396.3111121655711, + "y": -199.2729551465966, + "z": 0.0 + }, + { + "x": 396.3109006642352, + "y": -198.2707147689589, + "z": 0.0 + }, + { + "x": 396.3106891628993, + "y": -197.2684743913215, + "z": 0.0 + }, + { + "x": 396.31047766156337, + "y": -196.26623401368403, + "z": 0.0 + }, + { + "x": 396.31026616022746, + "y": -195.2639936360465, + "z": 0.0 + }, + { + "x": 396.31005465889154, + "y": -194.2617532584091, + "z": 0.0 + }, + { + "x": 396.30984315755563, + "y": -193.2595128807714, + "z": 0.0 + }, + { + "x": 396.3096316562197, + "y": -192.257272503134, + "z": 0.0 + }, + { + "x": 396.3094201548838, + "y": -191.25503212549654, + "z": 0.0 + }, + { + "x": 396.3092086535479, + "y": -190.25279174785913, + "z": 0.0 + }, + { + "x": 396.308997152212, + "y": -189.2505513702215, + "z": 0.0 + }, + { + "x": 396.3087856508761, + "y": -188.24831099258404, + "z": 0.0 + }, + { + "x": 396.30857414954016, + "y": -187.2460706149464, + "z": 0.0 + }, + { + "x": 396.30836264820425, + "y": -186.243830237309, + "z": 0.0 + }, + { + "x": 396.30815114686834, + "y": -185.2415898596716, + "z": 0.0 + }, + { + "x": 396.30793964553243, + "y": -184.23934948203396, + "z": 0.0 + }, + { + "x": 396.3077281441965, + "y": -183.23710910439632, + "z": 0.0 + }, + { + "x": 396.3075166428606, + "y": -182.23486872675898, + "z": 0.0 + }, + { + "x": 396.3073051415247, + "y": -181.23262834912157, + "z": 0.0 + }, + { + "x": 396.3070936401888, + "y": -180.23038797148394, + "z": 0.0 + }, + { + "x": 396.30688213885287, + "y": -179.22814759384647, + "z": 0.0 + }, + { + "x": 396.30667063751696, + "y": -178.22590721620878, + "z": 0.0 + }, + { + "x": 396.30645913618105, + "y": -177.22366683857155, + "z": 0.0 + }, + { + "x": 396.30624763484514, + "y": -176.2214264609339, + "z": 0.0 + }, + { + "x": 396.3060361335092, + "y": -175.2191860832964, + "z": 0.0 + }, + { + "x": 396.3058246321733, + "y": -174.21694570565887, + "z": 0.0 + }, + { + "x": 396.3056131308374, + "y": -173.2147053280213, + "z": 0.0 + }, + { + "x": 396.3054016295015, + "y": -172.212464950384, + "z": 0.0 + }, + { + "x": 396.3051901281656, + "y": -171.21022457274637, + "z": 0.0 + }, + { + "x": 396.30497862682967, + "y": -170.20798419510885, + "z": 0.0 + }, + { + "x": 396.30476712549375, + "y": -169.20574381747122, + "z": 0.0 + }, + { + "x": 396.30455562415784, + "y": -168.20350343983392, + "z": 0.0 + }, + { + "x": 396.30434412282193, + "y": -167.20126306219635, + "z": 0.0 + }, + { + "x": 396.304132621486, + "y": -166.19902268455883, + "z": 0.0 + }, + { + "x": 396.3039211201501, + "y": -165.1967823069213, + "z": 0.0 + }, + { + "x": 396.3037096188142, + "y": -164.19454192928367, + "z": 0.0 + }, + { + "x": 396.3034981174783, + "y": -163.19230155164644, + "z": 0.0 + }, + { + "x": 396.3032866161424, + "y": -162.19006117400875, + "z": 0.0 + }, + { + "x": 396.30307511480646, + "y": -161.18782079637128, + "z": 0.0 + }, + { + "x": 396.30286361347055, + "y": -160.18558041873365, + "z": 0.0 + }, + { + "x": 396.30265211213464, + "y": -159.18334004109636, + "z": 0.0 + }, + { + "x": 396.3024406107987, + "y": -158.18109966345872, + "z": 0.0 + }, + { + "x": 396.3022291094628, + "y": -157.17885928582126, + "z": 0.0 + }, + { + "x": 396.3020176081269, + "y": -156.17661890818374, + "z": 0.0 + }, + { + "x": 396.301806106791, + "y": -155.1743785305461, + "z": 0.0 + }, + { + "x": 396.3015946054551, + "y": -154.17213815290881, + "z": 0.0 + }, + { + "x": 396.30138310411917, + "y": -153.16989777527118, + "z": 0.0 + }, + { + "x": 396.30117160278326, + "y": -152.16765739763366, + "z": 0.0 + }, + { + "x": 396.30096010144734, + "y": -151.1654170199962, + "z": 0.0 + }, + { + "x": 396.30074860011143, + "y": -150.16317664235868, + "z": 0.0 + }, + { + "x": 396.3005370987755, + "y": -149.16093626472116, + "z": 0.0 + }, + { + "x": 396.3003255974396, + "y": -148.1586958870837, + "z": 0.0 + }, + { + "x": 396.3001140961037, + "y": -147.15645550944618, + "z": 0.0 + }, + { + "x": 396.2999025947678, + "y": -146.15421513180866, + "z": 0.0 + }, + { + "x": 396.2996910934319, + "y": -145.15197475417114, + "z": 0.0 + }, + { + "x": 396.29947959209596, + "y": -144.14973437653362, + "z": 0.0 + }, + { + "x": 396.29926809076005, + "y": -143.1474939988961, + "z": 0.0 + }, + { + "x": 396.29905658942414, + "y": -142.14525362125863, + "z": 0.0 + }, + { + "x": 396.2988450880882, + "y": -141.1430132436211, + "z": 0.0 + }, + { + "x": 396.2986335867523, + "y": -140.1407728659836, + "z": 0.0 + }, + { + "x": 396.2984220854164, + "y": -139.13853248834607, + "z": 0.0 + }, + { + "x": 396.2982105840805, + "y": -138.1362921107086, + "z": 0.0 + }, + { + "x": 396.2979990827446, + "y": -137.13405173307115, + "z": 0.0 + }, + { + "x": 396.2977875814088, + "y": -136.13181135543346, + "z": 0.0 + }, + { + "x": 396.29757608007276, + "y": -135.12957097779605, + "z": 0.0 + }, + { + "x": 396.29736457873685, + "y": -134.12733060015853, + "z": 0.0 + }, + { + "x": 396.29715307740094, + "y": -133.125090222521, + "z": 0.0 + }, + { + "x": 396.296941576065, + "y": -132.12284984488355, + "z": 0.0 + }, + { + "x": 396.2967300747291, + "y": -131.12060946724603, + "z": 0.0 + }, + { + "x": 396.2965185733932, + "y": -130.1183690896085, + "z": 0.0 + }, + { + "x": 396.2963070720573, + "y": -129.116128711971, + "z": 0.0 + }, + { + "x": 396.2960955707214, + "y": -128.11388833433358, + "z": 0.0 + }, + { + "x": 396.2958840693856, + "y": -127.11164795669586, + "z": 0.0 + }, + { + "x": 396.29567256804955, + "y": -126.10940757905848, + "z": 0.0 + }, + { + "x": 396.29546106671364, + "y": -125.10716720142099, + "z": 0.0 + }, + { + "x": 396.29524956537773, + "y": -124.10492682378359, + "z": 0.0 + }, + { + "x": 396.29503806404193, + "y": -123.10268644614587, + "z": 0.0 + }, + { + "x": 396.2948265627059, + "y": -122.10044606850849, + "z": 0.0 + }, + { + "x": 396.29461506137, + "y": -121.09820569087097, + "z": 0.0 + }, + { + "x": 396.2944035600341, + "y": -120.09596531323345, + "z": 0.0 + }, + { + "x": 396.2941920586982, + "y": -119.09372493559607, + "z": 0.0 + }, + { + "x": 396.2939805573624, + "y": -118.09148455795835, + "z": 0.0 + }, + { + "x": 396.29376905602635, + "y": -117.08924418032097, + "z": 0.0 + }, + { + "x": 396.29355755469044, + "y": -116.08700380268348, + "z": 0.0 + }, + { + "x": 396.2933460533545, + "y": -115.0847634250461, + "z": 0.0 + }, + { + "x": 396.2931345520187, + "y": -114.08252304740847, + "z": 0.0 + }, + { + "x": 396.2929230506828, + "y": -113.08028266977087, + "z": 0.0 + }, + { + "x": 396.2927115493468, + "y": -112.07804229213346, + "z": 0.0 + }, + { + "x": 396.2925000480109, + "y": -111.07580191449597, + "z": 0.0 + }, + { + "x": 396.29228854667497, + "y": -110.07356153685856, + "z": 0.0 + }, + { + "x": 396.29207704533917, + "y": -109.07132115922084, + "z": 0.0 + }, + { + "x": 396.29186554400314, + "y": -108.06908078158344, + "z": 0.0 + }, + { + "x": 396.29165404266723, + "y": -107.06684040394595, + "z": 0.0 + }, + { + "x": 396.2914425413313, + "y": -106.06460002630854, + "z": 0.0 + }, + { + "x": 396.2912310399955, + "y": -105.0623596486709, + "z": 0.0 + }, + { + "x": 396.2910195386596, + "y": -104.06011927103339, + "z": 0.0 + }, + { + "x": 396.2908080373237, + "y": -103.05787889339578, + "z": 0.0 + }, + { + "x": 396.2905965359877, + "y": -102.05563851575852, + "z": 0.0 + }, + { + "x": 396.2903850346519, + "y": -101.05339813812088, + "z": 0.0 + }, + { + "x": 396.29017353331596, + "y": -100.05115776048339, + "z": 0.0 + }, + { + "x": 396.28996203198005, + "y": -99.04891738284587, + "z": 0.0 + }, + { + "x": 396.28975053064414, + "y": -98.04667700520824, + "z": 0.0 + }, + { + "x": 396.2895390293081, + "y": -97.04443662757095, + "z": 0.0 + }, + { + "x": 396.2893275279723, + "y": -96.04219624993334, + "z": 0.0 + }, + { + "x": 396.2891160266364, + "y": -95.03995587229582, + "z": 0.0 + }, + { + "x": 396.2889045253005, + "y": -94.03771549465822, + "z": 0.0 + }, + { + "x": 396.28869302396447, + "y": -93.03547511702092, + "z": 0.0 + }, + { + "x": 396.2884815226287, + "y": -92.03323473938332, + "z": 0.0 + }, + { + "x": 396.28827002129276, + "y": -91.0309943617458, + "z": 0.0 + }, + { + "x": 396.28805851995685, + "y": -90.0287539841083, + "z": 0.0 + }, + { + "x": 396.28784701862094, + "y": -89.02651360647064, + "z": 0.0 + }, + { + "x": 396.28763556119316, + "y": -88.02474527850603, + "z": 0.0 + }, + { + "x": 396.28765973167003, + "y": -87.02433370405193, + "z": 0.0 + }, + { + "x": 396.2886006598079, + "y": -86.02261500169513, + "z": 0.0 + }, + { + "x": 396.28980332800506, + "y": -85.02037532333011, + "z": 0.0 + }, + { + "x": 396.2910059962021, + "y": -84.01813564496533, + "z": 0.0 + }, + { + "x": 396.29220866439925, + "y": -83.01589596660044, + "z": 0.0 + }, + { + "x": 396.2934113325964, + "y": -82.0136562882354, + "z": 0.0 + }, + { + "x": 396.29461400079356, + "y": -81.01141660987061, + "z": 0.0 + }, + { + "x": 396.2958166689907, + "y": -80.0091769315057, + "z": 0.0 + }, + { + "x": 396.29701933718786, + "y": -79.00693725314069, + "z": 0.0 + }, + { + "x": 396.2982220053849, + "y": -78.0046975747759, + "z": 0.0 + }, + { + "x": 396.29942467358205, + "y": -77.00245789641102, + "z": 0.0 + }, + { + "x": 396.3006273417792, + "y": -76.00021821804611, + "z": 0.0 + }, + { + "x": 396.30183000997636, + "y": -74.99797853968121, + "z": 0.0 + }, + { + "x": 396.3030326781735, + "y": -73.9957388613162, + "z": 0.0 + }, + { + "x": 396.30423534637066, + "y": -72.99349918295138, + "z": 0.0 + }, + { + "x": 396.3054380145678, + "y": -71.9912595045865, + "z": 0.0 + }, + { + "x": 396.30664068276496, + "y": -70.98901982622147, + "z": 0.0 + }, + { + "x": 396.307843350962, + "y": -69.98678014785669, + "z": 0.0 + }, + { + "x": 396.30904601915915, + "y": -68.98454046949179, + "z": 0.0 + }, + { + "x": 396.3102486873563, + "y": -67.98230079112678, + "z": 0.0 + }, + { + "x": 396.31145135555346, + "y": -66.980061112762, + "z": 0.0 + }, + { + "x": 396.3126540237506, + "y": -65.97782143439707, + "z": 0.0 + }, + { + "x": 396.31385669194776, + "y": -64.97558175603217, + "z": 0.0 + }, + { + "x": 396.3150593601449, + "y": -63.973342077667155, + "z": 0.0 + }, + { + "x": 396.31626202834195, + "y": -62.97110239930238, + "z": 0.0 + }, + { + "x": 396.3174646965391, + "y": -61.96886272093751, + "z": 0.0 + }, + { + "x": 396.31866736473626, + "y": -60.96662304257252, + "z": 0.0 + }, + { + "x": 396.3198700329334, + "y": -59.96438336420772, + "z": 0.0 + }, + { + "x": 396.32107270113056, + "y": -58.96214368584283, + "z": 0.0 + }, + { + "x": 396.3222753693277, + "y": -57.9599040074778, + "z": 0.0 + }, + { + "x": 396.32347803752475, + "y": -56.95766432911315, + "z": 0.0 + }, + { + "x": 396.324680705722, + "y": -55.95542465074806, + "z": 0.0 + }, + { + "x": 396.32588337391905, + "y": -54.95318497238314, + "z": 0.0 + }, + { + "x": 396.3270860421162, + "y": -53.95094529401848, + "z": 0.0 + }, + { + "x": 396.32828871031336, + "y": -52.94870561565328, + "z": 0.0 + }, + { + "x": 396.3294913785105, + "y": -51.94646593728851, + "z": 0.0 + }, + { + "x": 396.33069404670766, + "y": -50.94422625892359, + "z": 0.0 + }, + { + "x": 396.3318967149048, + "y": -49.941986580558606, + "z": 0.0 + }, + { + "x": 396.33309938310185, + "y": -48.93974690219384, + "z": 0.0 + }, + { + "x": 396.334302051299, + "y": -47.93750722382893, + "z": 0.0 + }, + { + "x": 396.33550471949616, + "y": -46.93526754546404, + "z": 0.0 + }, + { + "x": 396.3367073876933, + "y": -45.93302786709903, + "z": 0.0 + }, + { + "x": 396.33791005589046, + "y": -44.93078818873424, + "z": 0.0 + }, + { + "x": 396.3391127240876, + "y": -43.92854851036934, + "z": 0.0 + }, + { + "x": 396.34031539228477, + "y": -42.92630883200434, + "z": 0.0 + }, + { + "x": 396.3415180604818, + "y": -41.92406915363958, + "z": 0.0 + }, + { + "x": 396.34272072867896, + "y": -40.921829475274706, + "z": 0.0 + }, + { + "x": 396.3439233968761, + "y": -39.91958979690972, + "z": 0.0 + }, + { + "x": 396.34512606507326, + "y": -38.91735011854496, + "z": 0.0 + }, + { + "x": 396.3463287332704, + "y": -37.91511044018003, + "z": 0.0 + }, + { + "x": 396.34753140146756, + "y": -36.912870761815014, + "z": 0.0 + }, + { + "x": 396.3487340696646, + "y": -35.91063108345024, + "z": 0.0 + }, + { + "x": 396.34993673786175, + "y": -34.90839140508534, + "z": 0.0 + }, + { + "x": 396.3511394060589, + "y": -33.90615172672044, + "z": 0.0 + }, + { + "x": 396.35234207425606, + "y": -32.903912048355565, + "z": 0.0 + }, + { + "x": 396.3535447424532, + "y": -31.901672369990585, + "z": 0.0 + }, + { + "x": 396.35474741065036, + "y": -30.899432691625826, + "z": 0.0 + }, + { + "x": 396.3559500788475, + "y": -29.897193013260953, + "z": 0.0 + }, + { + "x": 396.35715274704467, + "y": -28.894953334895966, + "z": 0.0 + }, + { + "x": 396.3583554152417, + "y": -27.892713656531193, + "z": 0.0 + }, + { + "x": 396.35955808343886, + "y": -26.890473978166284, + "z": 0.0 + }, + { + "x": 396.360760751636, + "y": -25.888234299801304, + "z": 0.0 + }, + { + "x": 396.36196341983316, + "y": -24.885994621436545, + "z": 0.0 + }, + { + "x": 396.3631660880303, + "y": -23.883754943071658, + "z": 0.0 + }, + { + "x": 396.36436875622746, + "y": -22.881515264706636, + "z": 0.0 + }, + { + "x": 396.3655714244245, + "y": -21.879275586341848, + "z": 0.0 + }, + { + "x": 396.36677409262165, + "y": -20.877035907976875, + "z": 0.0 + }, + { + "x": 396.3679767608188, + "y": -19.874796229611952, + "z": 0.0 + }, + { + "x": 396.36917942901596, + "y": -18.87255655124693, + "z": 0.0 + }, + { + "x": 396.3703820972131, + "y": -17.870316872882164, + "z": 0.0 + }, + { + "x": 396.37158476541026, + "y": -16.868077194517276, + "z": 0.0 + }, + { + "x": 396.3727874336074, + "y": -15.865837516152242, + "z": 0.0 + }, + { + "x": 396.37399010180445, + "y": -14.863597837787554, + "z": 0.0 + }, + { + "x": 396.3751927700017, + "y": -13.861358159422444, + "z": 0.0 + }, + { + "x": 396.37639543819876, + "y": -12.859118481057523, + "z": 0.0 + }, + { + "x": 396.3775981063959, + "y": -11.856878802692831, + "z": 0.0 + }, + { + "x": 396.37880077459306, + "y": -10.854639124327711, + "z": 0.0 + }, + { + "x": 396.3800034427902, + "y": -9.85239944596279, + "z": 0.0 + } + ] + }, + { + "id": 45, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 144.9895082163707, + "y": -53.49334930469749, + "z": 0.0 + }, + { + "x": 143.97555473552626, + "y": -53.49347285775378, + "z": 0.0 + }, + { + "x": 142.96160125468174, + "y": -53.493596410810085, + "z": 0.0 + }, + { + "x": 141.94764777383736, + "y": -53.493719963866376, + "z": 0.0 + }, + { + "x": 140.93369429299287, + "y": -53.493843516922674, + "z": 0.0 + }, + { + "x": 139.9197408121484, + "y": -53.49396706997897, + "z": 0.0 + }, + { + "x": 138.90578733130397, + "y": -53.49409062303527, + "z": 0.0 + }, + { + "x": 137.89183385045953, + "y": -53.49421417609156, + "z": 0.0 + }, + { + "x": 136.87788036961507, + "y": -53.49433772914786, + "z": 0.0 + }, + { + "x": 135.8639268887706, + "y": -53.494461282204156, + "z": 0.0 + }, + { + "x": 134.8499734079262, + "y": -53.49458483526045, + "z": 0.0 + }, + { + "x": 133.83601992708168, + "y": -53.49470838831675, + "z": 0.0 + }, + { + "x": 132.8220664462373, + "y": -53.49483194137304, + "z": 0.0 + }, + { + "x": 131.8081129653928, + "y": -53.49495549442934, + "z": 0.0 + }, + { + "x": 130.79415948454835, + "y": -53.49507904748564, + "z": 0.0 + }, + { + "x": 129.7802060037039, + "y": -53.49520260054194, + "z": 0.0 + }, + { + "x": 128.76625252285947, + "y": -53.49532615359823, + "z": 0.0 + }, + { + "x": 127.752299042015, + "y": -53.495449706654526, + "z": 0.0 + }, + { + "x": 126.73834556117055, + "y": -53.495573259710824, + "z": 0.0 + }, + { + "x": 125.72439208032611, + "y": -53.495696812767115, + "z": 0.0 + }, + { + "x": 124.71043859948163, + "y": -53.49582036582341, + "z": 0.0 + }, + { + "x": 123.69648511863718, + "y": -53.49594391887971, + "z": 0.0 + }, + { + "x": 122.68253163779274, + "y": -53.49606747193601, + "z": 0.0 + }, + { + "x": 121.66857815694829, + "y": -53.49619102499231, + "z": 0.0 + }, + { + "x": 120.65462467610384, + "y": -53.496314578048604, + "z": 0.0 + }, + { + "x": 119.64067119525942, + "y": -53.496438131104895, + "z": 0.0 + }, + { + "x": 118.62671771441494, + "y": -53.49656168416119, + "z": 0.0 + }, + { + "x": 117.61276423357049, + "y": -53.49668523721749, + "z": 0.0 + }, + { + "x": 116.59881075272605, + "y": -53.49680879027378, + "z": 0.0 + }, + { + "x": 115.58485727188157, + "y": -53.49693234333008, + "z": 0.0 + }, + { + "x": 114.57090379103713, + "y": -53.49705589638638, + "z": 0.0 + }, + { + "x": 113.55695031019268, + "y": -53.497179449442676, + "z": 0.0 + }, + { + "x": 112.54299682934824, + "y": -53.49730300249897, + "z": 0.0 + }, + { + "x": 111.52904334850375, + "y": -53.49742655555527, + "z": 0.0 + }, + { + "x": 110.51508986765934, + "y": -53.49755010861156, + "z": 0.0 + }, + { + "x": 109.50113638681486, + "y": -53.49767366166786, + "z": 0.0 + }, + { + "x": 108.48718290597041, + "y": -53.49779721472416, + "z": 0.0 + }, + { + "x": 107.47322942512598, + "y": -53.49792076778045, + "z": 0.0 + }, + { + "x": 106.4592759442815, + "y": -53.49804432083675, + "z": 0.0 + }, + { + "x": 105.44532246343705, + "y": -53.498167873893046, + "z": 0.0 + }, + { + "x": 104.4313689825926, + "y": -53.49829142694934, + "z": 0.0 + }, + { + "x": 103.41741550174817, + "y": -53.498414980005634, + "z": 0.0 + }, + { + "x": 102.40346202090367, + "y": -53.49853853306194, + "z": 0.0 + }, + { + "x": 101.38950854005927, + "y": -53.49866208611823, + "z": 0.0 + } + ] + }, + { + "id": 46, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 101.39048336233827, + "y": -61.498662026725825, + "z": 0.0 + }, + { + "x": 102.40443684318276, + "y": -61.498538473669534, + "z": 0.0 + }, + { + "x": 103.41839032402717, + "y": -61.49841492061323, + "z": 0.0 + }, + { + "x": 104.43234380487166, + "y": -61.49829136755694, + "z": 0.0 + }, + { + "x": 105.44629728571611, + "y": -61.49816781450064, + "z": 0.0 + }, + { + "x": 106.46025076656056, + "y": -61.49804426144434, + "z": 0.0 + }, + { + "x": 107.47420424740498, + "y": -61.497920708388044, + "z": 0.0 + }, + { + "x": 108.48815772824948, + "y": -61.49779715533175, + "z": 0.0 + }, + { + "x": 109.50211120909393, + "y": -61.497673602275455, + "z": 0.0 + }, + { + "x": 110.51606468993835, + "y": -61.49755004921916, + "z": 0.0 + }, + { + "x": 111.53001817078284, + "y": -61.497426496162866, + "z": 0.0 + }, + { + "x": 112.54397165162725, + "y": -61.49730294310656, + "z": 0.0 + }, + { + "x": 113.55792513247174, + "y": -61.49717939005027, + "z": 0.0 + }, + { + "x": 114.57187861331619, + "y": -61.49705583699397, + "z": 0.0 + }, + { + "x": 115.58583209416064, + "y": -61.496932283937674, + "z": 0.0 + }, + { + "x": 116.59978557500506, + "y": -61.49680873088138, + "z": 0.0 + }, + { + "x": 117.61373905584955, + "y": -61.496685177825086, + "z": 0.0 + }, + { + "x": 118.627692536694, + "y": -61.49656162476879, + "z": 0.0 + }, + { + "x": 119.64164601753842, + "y": -61.49643807171249, + "z": 0.0 + }, + { + "x": 120.6555994983829, + "y": -61.4963145186562, + "z": 0.0 + }, + { + "x": 121.66955297922735, + "y": -61.4961909655999, + "z": 0.0 + }, + { + "x": 122.6835064600718, + "y": -61.4960674125436, + "z": 0.0 + }, + { + "x": 123.69745994091625, + "y": -61.495943859487305, + "z": 0.0 + }, + { + "x": 124.7114134217607, + "y": -61.49582030643101, + "z": 0.0 + }, + { + "x": 125.72536690260512, + "y": -61.49569675337471, + "z": 0.0 + }, + { + "x": 126.73932038344961, + "y": -61.49557320031842, + "z": 0.0 + }, + { + "x": 127.75327386429406, + "y": -61.49544964726212, + "z": 0.0 + }, + { + "x": 128.76722734513845, + "y": -61.49532609420582, + "z": 0.0 + }, + { + "x": 129.78118082598294, + "y": -61.49520254114953, + "z": 0.0 + }, + { + "x": 130.79513430682738, + "y": -61.49507898809323, + "z": 0.0 + }, + { + "x": 131.80908778767184, + "y": -61.494955435036935, + "z": 0.0 + }, + { + "x": 132.82304126851628, + "y": -61.49483188198064, + "z": 0.0 + }, + { + "x": 133.83699474936077, + "y": -61.49470832892435, + "z": 0.0 + }, + { + "x": 134.85094823020518, + "y": -61.49458477586804, + "z": 0.0 + }, + { + "x": 135.86490171104964, + "y": -61.49446122281175, + "z": 0.0 + }, + { + "x": 136.8788551918941, + "y": -61.49433766975545, + "z": 0.0 + }, + { + "x": 137.8928086727385, + "y": -61.494214116699155, + "z": 0.0 + }, + { + "x": 138.906762153583, + "y": -61.494090563642864, + "z": 0.0 + }, + { + "x": 139.92071563442744, + "y": -61.493967010586566, + "z": 0.0 + }, + { + "x": 140.9346691152719, + "y": -61.49384345753027, + "z": 0.0 + }, + { + "x": 141.94862259611634, + "y": -61.49371990447397, + "z": 0.0 + }, + { + "x": 142.96257607696083, + "y": -61.49359635141768, + "z": 0.0 + }, + { + "x": 143.97652955780524, + "y": -61.493472798361374, + "z": 0.0 + }, + { + "x": 144.99048303864967, + "y": -61.49334924530508, + "z": 0.0 + } + ] + }, + { + "id": 47, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 101.38999595119877, + "y": -57.49866205642203, + "z": 0.0 + }, + { + "x": 102.40394943204322, + "y": -57.49853850336574, + "z": 0.0 + }, + { + "x": 103.41790291288767, + "y": -57.49841495030943, + "z": 0.0 + }, + { + "x": 104.43185639373213, + "y": -57.49829139725314, + "z": 0.0 + }, + { + "x": 105.44580987457658, + "y": -57.49816784419684, + "z": 0.0 + }, + { + "x": 106.45976335542103, + "y": -57.498044291140545, + "z": 0.0 + }, + { + "x": 107.47371683626548, + "y": -57.49792073808425, + "z": 0.0 + }, + { + "x": 108.48767031710995, + "y": -57.497797185027956, + "z": 0.0 + }, + { + "x": 109.5016237979544, + "y": -57.49767363197166, + "z": 0.0 + }, + { + "x": 110.51557727879884, + "y": -57.49755007891536, + "z": 0.0 + }, + { + "x": 111.5295307596433, + "y": -57.49742652585907, + "z": 0.0 + }, + { + "x": 112.54348424048774, + "y": -57.497302972802764, + "z": 0.0 + }, + { + "x": 113.5574377213322, + "y": -57.49717941974647, + "z": 0.0 + }, + { + "x": 114.57139120217666, + "y": -57.497055866690175, + "z": 0.0 + }, + { + "x": 115.5853446830211, + "y": -57.49693231363388, + "z": 0.0 + }, + { + "x": 116.59929816386556, + "y": -57.49680876057758, + "z": 0.0 + }, + { + "x": 117.61325164471002, + "y": -57.49668520752129, + "z": 0.0 + }, + { + "x": 118.62720512555447, + "y": -57.49656165446499, + "z": 0.0 + }, + { + "x": 119.64115860639892, + "y": -57.49643810140869, + "z": 0.0 + }, + { + "x": 120.65511208724337, + "y": -57.4963145483524, + "z": 0.0 + }, + { + "x": 121.66906556808782, + "y": -57.496190995296104, + "z": 0.0 + }, + { + "x": 122.68301904893227, + "y": -57.496067442239806, + "z": 0.0 + }, + { + "x": 123.69697252977672, + "y": -57.49594388918351, + "z": 0.0 + }, + { + "x": 124.71092601062117, + "y": -57.49582033612721, + "z": 0.0 + }, + { + "x": 125.72487949146561, + "y": -57.49569678307091, + "z": 0.0 + }, + { + "x": 126.73883297231008, + "y": -57.49557323001462, + "z": 0.0 + }, + { + "x": 127.75278645315453, + "y": -57.49544967695832, + "z": 0.0 + }, + { + "x": 128.76673993399896, + "y": -57.495326123902025, + "z": 0.0 + }, + { + "x": 129.78069341484343, + "y": -57.495202570845734, + "z": 0.0 + }, + { + "x": 130.79464689568786, + "y": -57.495079017789436, + "z": 0.0 + }, + { + "x": 131.80860037653233, + "y": -57.49495546473314, + "z": 0.0 + }, + { + "x": 132.8225538573768, + "y": -57.49483191167684, + "z": 0.0 + }, + { + "x": 133.83650733822122, + "y": -57.49470835862055, + "z": 0.0 + }, + { + "x": 134.8504608190657, + "y": -57.494584805564244, + "z": 0.0 + }, + { + "x": 135.86441429991012, + "y": -57.49446125250795, + "z": 0.0 + }, + { + "x": 136.8783677807546, + "y": -57.494337699451656, + "z": 0.0 + }, + { + "x": 137.89232126159902, + "y": -57.49421414639536, + "z": 0.0 + }, + { + "x": 138.9062747424435, + "y": -57.49409059333907, + "z": 0.0 + }, + { + "x": 139.92022822328792, + "y": -57.49396704028277, + "z": 0.0 + }, + { + "x": 140.93418170413238, + "y": -57.49384348722647, + "z": 0.0 + }, + { + "x": 141.94813518497685, + "y": -57.49371993417017, + "z": 0.0 + }, + { + "x": 142.96208866582128, + "y": -57.49359638111388, + "z": 0.0 + }, + { + "x": 143.97604214666575, + "y": -57.49347282805758, + "z": 0.0 + }, + { + "x": 144.98999562751018, + "y": -57.493349275001286, + "z": 0.0 + } + ] + }, + { + "id": 48, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 144.98975192194044, + "y": -55.49334928984939, + "z": 0.0 + }, + { + "x": 143.975798441096, + "y": -55.493472842905675, + "z": 0.0 + }, + { + "x": 142.9618449602515, + "y": -55.49359639596199, + "z": 0.0 + }, + { + "x": 141.9478914794071, + "y": -55.49371994901827, + "z": 0.0 + }, + { + "x": 140.9339379985626, + "y": -55.49384350207457, + "z": 0.0 + }, + { + "x": 139.91998451771815, + "y": -55.49396705513087, + "z": 0.0 + }, + { + "x": 138.90603103687374, + "y": -55.494090608187165, + "z": 0.0 + }, + { + "x": 137.89207755602928, + "y": -55.49421416124346, + "z": 0.0 + }, + { + "x": 136.87812407518481, + "y": -55.49433771429976, + "z": 0.0 + }, + { + "x": 135.86417059434035, + "y": -55.49446126735606, + "z": 0.0 + }, + { + "x": 134.85021711349594, + "y": -55.49458482041234, + "z": 0.0 + }, + { + "x": 133.83626363265145, + "y": -55.494708373468654, + "z": 0.0 + }, + { + "x": 132.82231015180705, + "y": -55.49483192652494, + "z": 0.0 + }, + { + "x": 131.80835667096255, + "y": -55.494955479581236, + "z": 0.0 + }, + { + "x": 130.7944031901181, + "y": -55.495079032637534, + "z": 0.0 + }, + { + "x": 129.78044970927368, + "y": -55.49520258569383, + "z": 0.0 + }, + { + "x": 128.76649622842922, + "y": -55.49532613875013, + "z": 0.0 + }, + { + "x": 127.75254274758476, + "y": -55.49544969180643, + "z": 0.0 + }, + { + "x": 126.73858926674032, + "y": -55.495573244862726, + "z": 0.0 + }, + { + "x": 125.72463578589586, + "y": -55.49569679791901, + "z": 0.0 + }, + { + "x": 124.71068230505139, + "y": -55.49582035097531, + "z": 0.0 + }, + { + "x": 123.69672882420696, + "y": -55.495943904031606, + "z": 0.0 + }, + { + "x": 122.6827753433625, + "y": -55.496067457087904, + "z": 0.0 + }, + { + "x": 121.66882186251806, + "y": -55.4961910101442, + "z": 0.0 + }, + { + "x": 120.6548683816736, + "y": -55.4963145632005, + "z": 0.0 + }, + { + "x": 119.64091490082916, + "y": -55.4964381162568, + "z": 0.0 + }, + { + "x": 118.6269614199847, + "y": -55.496561669313095, + "z": 0.0 + }, + { + "x": 117.61300793914026, + "y": -55.49668522236939, + "z": 0.0 + }, + { + "x": 116.5990544582958, + "y": -55.49680877542568, + "z": 0.0 + }, + { + "x": 115.58510097745133, + "y": -55.496932328481975, + "z": 0.0 + }, + { + "x": 114.5711474966069, + "y": -55.49705588153827, + "z": 0.0 + }, + { + "x": 113.55719401576243, + "y": -55.49717943459457, + "z": 0.0 + }, + { + "x": 112.543240534918, + "y": -55.49730298765087, + "z": 0.0 + }, + { + "x": 111.52928705407352, + "y": -55.49742654070717, + "z": 0.0 + }, + { + "x": 110.5153335732291, + "y": -55.497550093763465, + "z": 0.0 + }, + { + "x": 109.50138009238464, + "y": -55.49767364681976, + "z": 0.0 + }, + { + "x": 108.48742661154017, + "y": -55.49779719987606, + "z": 0.0 + }, + { + "x": 107.47347313069574, + "y": -55.497920752932345, + "z": 0.0 + }, + { + "x": 106.45951964985127, + "y": -55.49804430598864, + "z": 0.0 + }, + { + "x": 105.44556616900681, + "y": -55.49816785904494, + "z": 0.0 + }, + { + "x": 104.43161268816237, + "y": -55.49829141210124, + "z": 0.0 + }, + { + "x": 103.41765920731791, + "y": -55.49841496515754, + "z": 0.0 + }, + { + "x": 102.40370572647345, + "y": -55.498538518213834, + "z": 0.0 + }, + { + "x": 101.38975224562901, + "y": -55.49866207127013, + "z": 0.0 + } + ] + }, + { + "id": 49, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 101.39023965676853, + "y": -59.49866204157392, + "z": 0.0 + }, + { + "x": 102.40419313761299, + "y": -59.49853848851764, + "z": 0.0 + }, + { + "x": 103.41814661845743, + "y": -59.49841493546133, + "z": 0.0 + }, + { + "x": 104.43210009930189, + "y": -59.49829138240504, + "z": 0.0 + }, + { + "x": 105.44605358014635, + "y": -59.498167829348745, + "z": 0.0 + }, + { + "x": 106.46000706099079, + "y": -59.49804427629245, + "z": 0.0 + }, + { + "x": 107.47396054183523, + "y": -59.49792072323615, + "z": 0.0 + }, + { + "x": 108.48791402267972, + "y": -59.49779717017985, + "z": 0.0 + }, + { + "x": 109.50186750352415, + "y": -59.49767361712355, + "z": 0.0 + }, + { + "x": 110.51582098436859, + "y": -59.497550064067255, + "z": 0.0 + }, + { + "x": 111.52977446521307, + "y": -59.49742651101097, + "z": 0.0 + }, + { + "x": 112.54372794605749, + "y": -59.49730295795466, + "z": 0.0 + }, + { + "x": 113.55768142690198, + "y": -59.497179404898375, + "z": 0.0 + }, + { + "x": 114.57163490774641, + "y": -59.49705585184208, + "z": 0.0 + }, + { + "x": 115.58558838859088, + "y": -59.49693229878578, + "z": 0.0 + }, + { + "x": 116.59954186943531, + "y": -59.49680874572948, + "z": 0.0 + }, + { + "x": 117.61349535027978, + "y": -59.49668519267318, + "z": 0.0 + }, + { + "x": 118.62744883112424, + "y": -59.496561639616885, + "z": 0.0 + }, + { + "x": 119.64140231196868, + "y": -59.49643808656059, + "z": 0.0 + }, + { + "x": 120.65535579281314, + "y": -59.496314533504304, + "z": 0.0 + }, + { + "x": 121.66930927365757, + "y": -59.496190980448006, + "z": 0.0 + }, + { + "x": 122.68326275450204, + "y": -59.49606742739171, + "z": 0.0 + }, + { + "x": 123.69721623534647, + "y": -59.49594387433541, + "z": 0.0 + }, + { + "x": 124.71116971619094, + "y": -59.49582032127911, + "z": 0.0 + }, + { + "x": 125.72512319703537, + "y": -59.495696768222814, + "z": 0.0 + }, + { + "x": 126.73907667787984, + "y": -59.495573215166516, + "z": 0.0 + }, + { + "x": 127.7530301587243, + "y": -59.49544966211022, + "z": 0.0 + }, + { + "x": 128.7669836395687, + "y": -59.49532610905392, + "z": 0.0 + }, + { + "x": 129.78093712041317, + "y": -59.495202555997636, + "z": 0.0 + }, + { + "x": 130.79489060125763, + "y": -59.49507900294134, + "z": 0.0 + }, + { + "x": 131.8088440821021, + "y": -59.49495544988504, + "z": 0.0 + }, + { + "x": 132.82279756294653, + "y": -59.49483189682874, + "z": 0.0 + }, + { + "x": 133.836751043791, + "y": -59.494708343772444, + "z": 0.0 + }, + { + "x": 134.85070452463543, + "y": -59.49458479071615, + "z": 0.0 + }, + { + "x": 135.8646580054799, + "y": -59.49446123765985, + "z": 0.0 + }, + { + "x": 136.87861148632436, + "y": -59.49433768460355, + "z": 0.0 + }, + { + "x": 137.89256496716877, + "y": -59.49421413154725, + "z": 0.0 + }, + { + "x": 138.90651844801323, + "y": -59.49409057849097, + "z": 0.0 + }, + { + "x": 139.9204719288577, + "y": -59.49396702543467, + "z": 0.0 + }, + { + "x": 140.93442540970216, + "y": -59.49384347237837, + "z": 0.0 + }, + { + "x": 141.9483788905466, + "y": -59.493719919322075, + "z": 0.0 + }, + { + "x": 142.96233237139106, + "y": -59.49359636626578, + "z": 0.0 + }, + { + "x": 143.9762858522355, + "y": -59.49347281320948, + "z": 0.0 + }, + { + "x": 144.99023933307993, + "y": -59.49334926015318, + "z": 0.0 + } + ] + }, + { + "id": 50, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 325.15950687877944, + "y": -53.47139508844576, + "z": 0.0 + }, + { + "x": 324.15320115376625, + "y": -53.471517709601706, + "z": 0.0 + }, + { + "x": 323.1468954287531, + "y": -53.471640330757644, + "z": 0.0 + }, + { + "x": 322.14058970373986, + "y": -53.47176295191359, + "z": 0.0 + }, + { + "x": 321.13428397872667, + "y": -53.471885573069535, + "z": 0.0 + }, + { + "x": 320.1279782537135, + "y": -53.472008194225474, + "z": 0.0 + }, + { + "x": 319.12167252870023, + "y": -53.47213081538142, + "z": 0.0 + }, + { + "x": 318.11536680368704, + "y": -53.472253436537365, + "z": 0.0 + }, + { + "x": 317.10906107867385, + "y": -53.47237605769331, + "z": 0.0 + }, + { + "x": 316.10275535366065, + "y": -53.472498678849256, + "z": 0.0 + }, + { + "x": 315.09644962864746, + "y": -53.472621300005194, + "z": 0.0 + }, + { + "x": 314.0901439036342, + "y": -53.47274392116114, + "z": 0.0 + }, + { + "x": 313.083838178621, + "y": -53.472866542317085, + "z": 0.0 + }, + { + "x": 312.0775324536079, + "y": -53.472989163473024, + "z": 0.0 + }, + { + "x": 311.07122672859464, + "y": -53.47311178462897, + "z": 0.0 + }, + { + "x": 310.0649210035814, + "y": -53.473234405784915, + "z": 0.0 + }, + { + "x": 309.05861527856825, + "y": -53.47335702694085, + "z": 0.0 + }, + { + "x": 308.052309553555, + "y": -53.4734796480968, + "z": 0.0 + }, + { + "x": 307.0460038285418, + "y": -53.473602269252744, + "z": 0.0 + }, + { + "x": 306.0396981035287, + "y": -53.47372489040868, + "z": 0.0 + }, + { + "x": 305.03339237851543, + "y": -53.47384751156463, + "z": 0.0 + }, + { + "x": 304.0270866535022, + "y": -53.473970132720574, + "z": 0.0 + }, + { + "x": 303.02078092848905, + "y": -53.47409275387651, + "z": 0.0 + }, + { + "x": 302.0144752034758, + "y": -53.47421537503246, + "z": 0.0 + }, + { + "x": 301.0081694784626, + "y": -53.4743379961884, + "z": 0.0 + }, + { + "x": 300.00186375344947, + "y": -53.47446061734434, + "z": 0.0 + }, + { + "x": 298.99555802843616, + "y": -53.47458323850029, + "z": 0.0 + }, + { + "x": 297.989252303423, + "y": -53.47470585965623, + "z": 0.0 + }, + { + "x": 296.98294657840984, + "y": -53.47482848081217, + "z": 0.0 + }, + { + "x": 295.9766408533966, + "y": -53.47495110196812, + "z": 0.0 + }, + { + "x": 294.9703351283834, + "y": -53.475073723124055, + "z": 0.0 + }, + { + "x": 293.96402940337015, + "y": -53.47519634428, + "z": 0.0 + }, + { + "x": 292.95772367835696, + "y": -53.475318965435946, + "z": 0.0 + }, + { + "x": 291.95141795334376, + "y": -53.475441586591884, + "z": 0.0 + }, + { + "x": 290.9451122283305, + "y": -53.47556420774783, + "z": 0.0 + }, + { + "x": 289.93880650331727, + "y": -53.47568682890378, + "z": 0.0 + }, + { + "x": 288.93250077830413, + "y": -53.47580945005972, + "z": 0.0 + }, + { + "x": 287.9261950532908, + "y": -53.47593207121567, + "z": 0.0 + }, + { + "x": 286.91988932827763, + "y": -53.47605469237161, + "z": 0.0 + }, + { + "x": 285.91358360326444, + "y": -53.47617731352755, + "z": 0.0 + }, + { + "x": 284.9072778782512, + "y": -53.476299934683496, + "z": 0.0 + }, + { + "x": 283.900972153238, + "y": -53.47642255583944, + "z": 0.0 + }, + { + "x": 282.8946664282248, + "y": -53.47654517699538, + "z": 0.0 + }, + { + "x": 281.88836070321156, + "y": -53.476667798151325, + "z": 0.0 + }, + { + "x": 280.8820549781983, + "y": -53.47679041930727, + "z": 0.0 + }, + { + "x": 279.8757492531852, + "y": -53.47691304046321, + "z": 0.0 + }, + { + "x": 278.86944352817187, + "y": -53.477035661619155, + "z": 0.0 + }, + { + "x": 277.8631378031587, + "y": -53.4771582827751, + "z": 0.0 + }, + { + "x": 276.8568320781455, + "y": -53.47728090393104, + "z": 0.0 + }, + { + "x": 275.85052635313224, + "y": -53.477403525086984, + "z": 0.0 + }, + { + "x": 274.8442206281191, + "y": -53.47752614624292, + "z": 0.0 + }, + { + "x": 273.8379149031058, + "y": -53.47764876739887, + "z": 0.0 + }, + { + "x": 272.8316091780926, + "y": -53.477771388554814, + "z": 0.0 + }, + { + "x": 271.8253034530794, + "y": -53.47789400971075, + "z": 0.0 + }, + { + "x": 270.81899772806617, + "y": -53.4780166308667, + "z": 0.0 + }, + { + "x": 269.8126920030529, + "y": -53.47813925202264, + "z": 0.0 + }, + { + "x": 268.8063862780398, + "y": -53.47826187317858, + "z": 0.0 + }, + { + "x": 267.8000805530265, + "y": -53.47838449433453, + "z": 0.0 + }, + { + "x": 266.7937748280133, + "y": -53.47850711549047, + "z": 0.0 + }, + { + "x": 265.78746910300015, + "y": -53.47862973664641, + "z": 0.0 + }, + { + "x": 264.78116337798684, + "y": -53.47875235780236, + "z": 0.0 + }, + { + "x": 263.77485765297365, + "y": -53.4788749789583, + "z": 0.0 + }, + { + "x": 262.7685519279604, + "y": -53.47899760011425, + "z": 0.0 + }, + { + "x": 261.7622462029472, + "y": -53.47912022127019, + "z": 0.0 + }, + { + "x": 260.755940477934, + "y": -53.47924284242614, + "z": 0.0 + }, + { + "x": 259.7496347529208, + "y": -53.47936546358208, + "z": 0.0 + }, + { + "x": 258.7433290279076, + "y": -53.47948808473802, + "z": 0.0 + }, + { + "x": 257.73702330289433, + "y": -53.47961070589397, + "z": 0.0 + }, + { + "x": 256.7307175778812, + "y": -53.47973332704991, + "z": 0.0 + }, + { + "x": 255.72441185286795, + "y": -53.47985594820585, + "z": 0.0 + }, + { + "x": 254.71810612785475, + "y": -53.47997856936179, + "z": 0.0 + }, + { + "x": 253.7118004028415, + "y": -53.480101190517736, + "z": 0.0 + }, + { + "x": 252.70549467782828, + "y": -53.48022381167368, + "z": 0.0 + }, + { + "x": 251.6991889528151, + "y": -53.48034643282962, + "z": 0.0 + }, + { + "x": 250.69288322780184, + "y": -53.480469053985566, + "z": 0.0 + }, + { + "x": 249.68657750278862, + "y": -53.48059167514151, + "z": 0.0 + }, + { + "x": 248.68027177777543, + "y": -53.48071429629745, + "z": 0.0 + }, + { + "x": 247.67396605276218, + "y": -53.480836917453395, + "z": 0.0 + }, + { + "x": 246.667660327749, + "y": -53.48095953860934, + "z": 0.0 + }, + { + "x": 245.6613546027358, + "y": -53.48108215976528, + "z": 0.0 + }, + { + "x": 244.65504887772255, + "y": -53.481204780921225, + "z": 0.0 + }, + { + "x": 243.64874315270933, + "y": -53.48132740207717, + "z": 0.0 + }, + { + "x": 242.64243742769614, + "y": -53.48145002323311, + "z": 0.0 + }, + { + "x": 241.6361317026829, + "y": -53.481572644389054, + "z": 0.0 + }, + { + "x": 240.62982597766967, + "y": -53.481695265545, + "z": 0.0 + }, + { + "x": 239.62352025265648, + "y": -53.48181788670094, + "z": 0.0 + }, + { + "x": 238.61721452764323, + "y": -53.48194050785688, + "z": 0.0 + }, + { + "x": 237.61090880263004, + "y": -53.48206312901283, + "z": 0.0 + }, + { + "x": 236.60460307761684, + "y": -53.48218575016877, + "z": 0.0 + }, + { + "x": 235.5982973526036, + "y": -53.48230837132471, + "z": 0.0 + }, + { + "x": 234.59199162759037, + "y": -53.48243099248066, + "z": 0.0 + }, + { + "x": 233.58568590257715, + "y": -53.482553613636604, + "z": 0.0 + }, + { + "x": 232.57938017756393, + "y": -53.48267623479255, + "z": 0.0 + }, + { + "x": 231.57307445255074, + "y": -53.48279885594849, + "z": 0.0 + }, + { + "x": 230.56676872753752, + "y": -53.48292147710443, + "z": 0.0 + }, + { + "x": 229.5604630025243, + "y": -53.48304409826038, + "z": 0.0 + }, + { + "x": 228.5541572775111, + "y": -53.48316671941632, + "z": 0.0 + }, + { + "x": 227.5478515524979, + "y": -53.48328934057226, + "z": 0.0 + }, + { + "x": 226.54154582748467, + "y": -53.48341196172821, + "z": 0.0 + }, + { + "x": 225.5352401024715, + "y": -53.48353458288415, + "z": 0.0 + }, + { + "x": 224.52893437745826, + "y": -53.48365720404009, + "z": 0.0 + }, + { + "x": 223.52262865244504, + "y": -53.48377982519604, + "z": 0.0 + }, + { + "x": 222.51632292743187, + "y": -53.483902446351976, + "z": 0.0 + }, + { + "x": 221.51001720241862, + "y": -53.48402506750792, + "z": 0.0 + }, + { + "x": 220.5037114774054, + "y": -53.48414768866387, + "z": 0.0 + }, + { + "x": 219.49740575239224, + "y": -53.484270309819806, + "z": 0.0 + }, + { + "x": 218.491100027379, + "y": -53.48439293097575, + "z": 0.0 + }, + { + "x": 217.4847943023658, + "y": -53.4845155521317, + "z": 0.0 + }, + { + "x": 216.4784885773526, + "y": -53.484638173287635, + "z": 0.0 + }, + { + "x": 215.47218285233936, + "y": -53.48476079444358, + "z": 0.0 + }, + { + "x": 214.4658771273262, + "y": -53.48488341559952, + "z": 0.0 + }, + { + "x": 213.45957140231295, + "y": -53.485006036755465, + "z": 0.0 + }, + { + "x": 212.45326567729973, + "y": -53.48512865791141, + "z": 0.0 + }, + { + "x": 211.44695995228656, + "y": -53.48525127906735, + "z": 0.0 + }, + { + "x": 210.4406542272733, + "y": -53.485373900223294, + "z": 0.0 + }, + { + "x": 209.43434850226012, + "y": -53.48549652137924, + "z": 0.0 + }, + { + "x": 208.4280427772469, + "y": -53.485619142535185, + "z": 0.0 + }, + { + "x": 207.42173705223368, + "y": -53.48574176369113, + "z": 0.0 + }, + { + "x": 206.4154313272205, + "y": -53.485864384847076, + "z": 0.0 + }, + { + "x": 205.4091256022073, + "y": -53.485987006003015, + "z": 0.0 + }, + { + "x": 204.40281987719405, + "y": -53.48610962715896, + "z": 0.0 + }, + { + "x": 203.39651415218086, + "y": -53.486232248314906, + "z": 0.0 + }, + { + "x": 202.39020842716766, + "y": -53.486354869470844, + "z": 0.0 + }, + { + "x": 201.38390270215444, + "y": -53.48647749062679, + "z": 0.0 + }, + { + "x": 200.37759697714122, + "y": -53.486600111782735, + "z": 0.0 + }, + { + "x": 199.37129125212803, + "y": -53.486722732938674, + "z": 0.0 + }, + { + "x": 198.3649855271148, + "y": -53.48684535409462, + "z": 0.0 + }, + { + "x": 197.3586798021016, + "y": -53.486967975250565, + "z": 0.0 + }, + { + "x": 196.3523740770884, + "y": -53.4870905964065, + "z": 0.0 + }, + { + "x": 195.34606835207515, + "y": -53.48721321756245, + "z": 0.0 + }, + { + "x": 194.33976262706196, + "y": -53.48733583871839, + "z": 0.0 + }, + { + "x": 193.33345690204874, + "y": -53.48745845987433, + "z": 0.0 + }, + { + "x": 192.32715117703552, + "y": -53.48758108103028, + "z": 0.0 + }, + { + "x": 191.32084545202233, + "y": -53.48770370218622, + "z": 0.0 + }, + { + "x": 190.3145397270091, + "y": -53.48782632334216, + "z": 0.0 + }, + { + "x": 189.30823400199588, + "y": -53.48794894449811, + "z": 0.0 + }, + { + "x": 188.3019282769827, + "y": -53.488071565654046, + "z": 0.0 + }, + { + "x": 187.29562255196944, + "y": -53.48819418680999, + "z": 0.0 + }, + { + "x": 186.28931682695622, + "y": -53.48831680796594, + "z": 0.0 + }, + { + "x": 185.28301110194306, + "y": -53.488439429121875, + "z": 0.0 + }, + { + "x": 184.2767053769298, + "y": -53.48856205027782, + "z": 0.0 + }, + { + "x": 183.2703996519166, + "y": -53.48868467143377, + "z": 0.0 + }, + { + "x": 182.26409392690343, + "y": -53.488807292589705, + "z": 0.0 + }, + { + "x": 181.25778820189018, + "y": -53.48892991374565, + "z": 0.0 + }, + { + "x": 180.25148247687693, + "y": -53.4890525349016, + "z": 0.0 + }, + { + "x": 179.24517675186377, + "y": -53.48917515605754, + "z": 0.0 + }, + { + "x": 178.23887102685055, + "y": -53.48929777721349, + "z": 0.0 + }, + { + "x": 177.23256530183733, + "y": -53.48942039836943, + "z": 0.0 + }, + { + "x": 176.22625957682413, + "y": -53.48954301952537, + "z": 0.0 + }, + { + "x": 175.2199538518109, + "y": -53.48966564068132, + "z": 0.0 + }, + { + "x": 174.21364812679772, + "y": -53.489788261837255, + "z": 0.0 + }, + { + "x": 173.20734240178447, + "y": -53.4899108829932, + "z": 0.0 + }, + { + "x": 172.20103667677128, + "y": -53.490033504149146, + "z": 0.0 + }, + { + "x": 171.1947309517581, + "y": -53.490156125305084, + "z": 0.0 + }, + { + "x": 170.18842522674484, + "y": -53.49027874646103, + "z": 0.0 + }, + { + "x": 169.18211950173162, + "y": -53.490401367616975, + "z": 0.0 + }, + { + "x": 168.17581377671846, + "y": -53.490523988772914, + "z": 0.0 + }, + { + "x": 167.1695080517052, + "y": -53.49064660992886, + "z": 0.0 + } + ] + }, + { + "id": 51, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 167.17048287398424, + "y": -61.490646550536454, + "z": 0.0 + }, + { + "x": 168.17678859899743, + "y": -61.49052392938051, + "z": 0.0 + }, + { + "x": 169.18309432401065, + "y": -61.49040130822457, + "z": 0.0 + }, + { + "x": 170.18940004902387, + "y": -61.490278687068624, + "z": 0.0 + }, + { + "x": 171.19570577403707, + "y": -61.49015606591268, + "z": 0.0 + }, + { + "x": 172.20201149905031, + "y": -61.49003344475674, + "z": 0.0 + }, + { + "x": 173.2083172240635, + "y": -61.489910823600795, + "z": 0.0 + }, + { + "x": 174.2146229490767, + "y": -61.48978820244485, + "z": 0.0 + }, + { + "x": 175.22092867408995, + "y": -61.48966558128891, + "z": 0.0 + }, + { + "x": 176.2272343991031, + "y": -61.489542960132965, + "z": 0.0 + }, + { + "x": 177.23354012411636, + "y": -61.48942033897703, + "z": 0.0 + }, + { + "x": 178.23984584912958, + "y": -61.48929771782108, + "z": 0.0 + }, + { + "x": 179.24615157414274, + "y": -61.489175096665136, + "z": 0.0 + }, + { + "x": 180.25245729915602, + "y": -61.4890524755092, + "z": 0.0 + }, + { + "x": 181.2587630241692, + "y": -61.488929854353245, + "z": 0.0 + }, + { + "x": 182.2650687491824, + "y": -61.4888072331973, + "z": 0.0 + }, + { + "x": 183.27137447419562, + "y": -61.48868461204136, + "z": 0.0 + }, + { + "x": 184.27768019920885, + "y": -61.488561990885415, + "z": 0.0 + }, + { + "x": 185.28398592422204, + "y": -61.48843936972947, + "z": 0.0 + }, + { + "x": 186.29029164923526, + "y": -61.48831674857353, + "z": 0.0 + }, + { + "x": 187.29659737424848, + "y": -61.488194127417586, + "z": 0.0 + }, + { + "x": 188.30290309926167, + "y": -61.48807150626164, + "z": 0.0 + }, + { + "x": 189.30920882427492, + "y": -61.4879488851057, + "z": 0.0 + }, + { + "x": 190.31551454928814, + "y": -61.487826263949756, + "z": 0.0 + }, + { + "x": 191.3218202743013, + "y": -61.48770364279381, + "z": 0.0 + }, + { + "x": 192.32812599931455, + "y": -61.48758102163787, + "z": 0.0 + }, + { + "x": 193.33443172432777, + "y": -61.48745840048193, + "z": 0.0 + }, + { + "x": 194.34073744934093, + "y": -61.48733577932598, + "z": 0.0 + }, + { + "x": 195.34704317435418, + "y": -61.48721315817004, + "z": 0.0 + }, + { + "x": 196.35334889936738, + "y": -61.4870905370141, + "z": 0.0 + }, + { + "x": 197.35965462438062, + "y": -61.48696791585816, + "z": 0.0 + }, + { + "x": 198.36596034939384, + "y": -61.48684529470221, + "z": 0.0 + }, + { + "x": 199.372266074407, + "y": -61.48672267354627, + "z": 0.0 + }, + { + "x": 200.37857179942026, + "y": -61.48660005239033, + "z": 0.0 + }, + { + "x": 201.38487752443348, + "y": -61.486477431234384, + "z": 0.0 + }, + { + "x": 202.39118324944664, + "y": -61.48635481007844, + "z": 0.0 + }, + { + "x": 203.3974889744599, + "y": -61.4862321889225, + "z": 0.0 + }, + { + "x": 204.40379469947308, + "y": -61.486109567766555, + "z": 0.0 + }, + { + "x": 205.41010042448627, + "y": -61.48598694661061, + "z": 0.0 + }, + { + "x": 206.41640614949952, + "y": -61.48586432545467, + "z": 0.0 + }, + { + "x": 207.42271187451271, + "y": -61.485741704298725, + "z": 0.0 + }, + { + "x": 208.42901759952593, + "y": -61.48561908314278, + "z": 0.0 + }, + { + "x": 209.43532332453916, + "y": -61.485496461986834, + "z": 0.0 + }, + { + "x": 210.44162904955235, + "y": -61.48537384083089, + "z": 0.0 + }, + { + "x": 211.44793477456554, + "y": -61.48525121967494, + "z": 0.0 + }, + { + "x": 212.45424049957876, + "y": -61.485128598519005, + "z": 0.0 + }, + { + "x": 213.46054622459198, + "y": -61.48500597736306, + "z": 0.0 + }, + { + "x": 214.46685194960517, + "y": -61.48488335620711, + "z": 0.0 + }, + { + "x": 215.4731576746184, + "y": -61.484760735051175, + "z": 0.0 + }, + { + "x": 216.47946339963158, + "y": -61.48463811389523, + "z": 0.0 + }, + { + "x": 217.48576912464483, + "y": -61.48451549273929, + "z": 0.0 + }, + { + "x": 218.49207484965802, + "y": -61.484392871583346, + "z": 0.0 + }, + { + "x": 219.49838057467122, + "y": -61.4842702504274, + "z": 0.0 + }, + { + "x": 220.50468629968444, + "y": -61.48414762927146, + "z": 0.0 + }, + { + "x": 221.51099202469766, + "y": -61.484025008115516, + "z": 0.0 + }, + { + "x": 222.51729774971085, + "y": -61.48390238695957, + "z": 0.0 + }, + { + "x": 223.52360347472407, + "y": -61.48377976580363, + "z": 0.0 + }, + { + "x": 224.5299091997373, + "y": -61.48365714464769, + "z": 0.0 + }, + { + "x": 225.53621492475048, + "y": -61.48353452349174, + "z": 0.0 + }, + { + "x": 226.5425206497637, + "y": -61.4834119023358, + "z": 0.0 + }, + { + "x": 227.54882637477692, + "y": -61.48328928117986, + "z": 0.0 + }, + { + "x": 228.5551320997901, + "y": -61.48316666002391, + "z": 0.0 + }, + { + "x": 229.56143782480333, + "y": -61.48304403886797, + "z": 0.0 + }, + { + "x": 230.56774354981656, + "y": -61.48292141771203, + "z": 0.0 + }, + { + "x": 231.57404927482972, + "y": -61.48279879655608, + "z": 0.0 + }, + { + "x": 232.58035499984297, + "y": -61.482676175400144, + "z": 0.0 + }, + { + "x": 233.5866607248562, + "y": -61.4825535542442, + "z": 0.0 + }, + { + "x": 234.5929664498694, + "y": -61.48243093308825, + "z": 0.0 + }, + { + "x": 235.59927217488263, + "y": -61.48230831193231, + "z": 0.0 + }, + { + "x": 236.60557789989582, + "y": -61.48218569077636, + "z": 0.0 + }, + { + "x": 237.61188362490907, + "y": -61.48206306962042, + "z": 0.0 + }, + { + "x": 238.61818934992226, + "y": -61.48194044846448, + "z": 0.0 + }, + { + "x": 239.62449507493545, + "y": -61.48181782730853, + "z": 0.0 + }, + { + "x": 240.6308007999487, + "y": -61.481695206152594, + "z": 0.0 + }, + { + "x": 241.63710652496192, + "y": -61.48157258499665, + "z": 0.0 + }, + { + "x": 242.6434122499751, + "y": -61.4814499638407, + "z": 0.0 + }, + { + "x": 243.64971797498836, + "y": -61.481327342684764, + "z": 0.0 + }, + { + "x": 244.65602370000158, + "y": -61.48120472152882, + "z": 0.0 + }, + { + "x": 245.66232942501478, + "y": -61.48108210037287, + "z": 0.0 + }, + { + "x": 246.66863515002802, + "y": -61.480959479216935, + "z": 0.0 + }, + { + "x": 247.67494087504122, + "y": -61.48083685806099, + "z": 0.0 + }, + { + "x": 248.6812466000544, + "y": -61.480714236905044, + "z": 0.0 + }, + { + "x": 249.68755232506766, + "y": -61.480591615749105, + "z": 0.0 + }, + { + "x": 250.69385805008088, + "y": -61.48046899459316, + "z": 0.0 + }, + { + "x": 251.70016377509407, + "y": -61.480346373437214, + "z": 0.0 + }, + { + "x": 252.70646950010732, + "y": -61.480223752281276, + "z": 0.0 + }, + { + "x": 253.71277522512054, + "y": -61.48010113112533, + "z": 0.0 + }, + { + "x": 254.71908095013373, + "y": -61.479978509969385, + "z": 0.0 + }, + { + "x": 255.72538667514698, + "y": -61.47985588881345, + "z": 0.0 + }, + { + "x": 256.73169240016017, + "y": -61.4797332676575, + "z": 0.0 + }, + { + "x": 257.7379981251734, + "y": -61.47961064650156, + "z": 0.0 + }, + { + "x": 258.74430385018667, + "y": -61.47948802534562, + "z": 0.0 + }, + { + "x": 259.7506095751998, + "y": -61.47936540418967, + "z": 0.0 + }, + { + "x": 260.7569153002131, + "y": -61.47924278303373, + "z": 0.0 + }, + { + "x": 261.7632210252263, + "y": -61.47912016187779, + "z": 0.0 + }, + { + "x": 262.7695267502395, + "y": -61.47899754072184, + "z": 0.0 + }, + { + "x": 263.77583247525274, + "y": -61.4788749195659, + "z": 0.0 + }, + { + "x": 264.78213820026593, + "y": -61.47875229840995, + "z": 0.0 + }, + { + "x": 265.7884439252791, + "y": -61.478629677254006, + "z": 0.0 + }, + { + "x": 266.7947496502924, + "y": -61.47850705609807, + "z": 0.0 + }, + { + "x": 267.80105537530557, + "y": -61.47838443494212, + "z": 0.0 + }, + { + "x": 268.80736110031876, + "y": -61.478261813786176, + "z": 0.0 + }, + { + "x": 269.813666825332, + "y": -61.47813919263024, + "z": 0.0 + }, + { + "x": 270.81997255034526, + "y": -61.47801657147429, + "z": 0.0 + }, + { + "x": 271.8262782753584, + "y": -61.47789395031835, + "z": 0.0 + }, + { + "x": 272.8325840003717, + "y": -61.47777132916241, + "z": 0.0 + }, + { + "x": 273.8388897253849, + "y": -61.47764870800646, + "z": 0.0 + }, + { + "x": 274.8451954503981, + "y": -61.47752608685052, + "z": 0.0 + }, + { + "x": 275.85150117541133, + "y": -61.47740346569458, + "z": 0.0 + }, + { + "x": 276.85780690042446, + "y": -61.47728084453863, + "z": 0.0 + }, + { + "x": 277.86411262543777, + "y": -61.477158223382695, + "z": 0.0 + }, + { + "x": 278.87041835045096, + "y": -61.47703560222675, + "z": 0.0 + }, + { + "x": 279.87672407546415, + "y": -61.476912981070804, + "z": 0.0 + }, + { + "x": 280.8830298004774, + "y": -61.476790359914865, + "z": 0.0 + }, + { + "x": 281.88933552549065, + "y": -61.47666773875892, + "z": 0.0 + }, + { + "x": 282.8956412505038, + "y": -61.476545117602974, + "z": 0.0 + }, + { + "x": 283.9019469755171, + "y": -61.476422496447036, + "z": 0.0 + }, + { + "x": 284.9082527005303, + "y": -61.47629987529109, + "z": 0.0 + }, + { + "x": 285.9145584255434, + "y": -61.476177254135145, + "z": 0.0 + }, + { + "x": 286.9208641505567, + "y": -61.476054632979206, + "z": 0.0 + }, + { + "x": 287.9271698755699, + "y": -61.47593201182326, + "z": 0.0 + }, + { + "x": 288.9334756005831, + "y": -61.475809390667315, + "z": 0.0 + }, + { + "x": 289.93978132559636, + "y": -61.47568676951138, + "z": 0.0 + }, + { + "x": 290.9460870506096, + "y": -61.475564148355424, + "z": 0.0 + }, + { + "x": 291.95239277562274, + "y": -61.47544152719948, + "z": 0.0 + }, + { + "x": 292.95869850063605, + "y": -61.47531890604354, + "z": 0.0 + }, + { + "x": 293.96500422564924, + "y": -61.475196284887595, + "z": 0.0 + }, + { + "x": 294.9713099506624, + "y": -61.47507366373165, + "z": 0.0 + }, + { + "x": 295.9776156756757, + "y": -61.47495104257571, + "z": 0.0 + }, + { + "x": 296.9839214006888, + "y": -61.474828421419765, + "z": 0.0 + }, + { + "x": 297.99022712570206, + "y": -61.47470580026383, + "z": 0.0 + }, + { + "x": 298.99653285071525, + "y": -61.47458317910788, + "z": 0.0 + }, + { + "x": 300.00283857572845, + "y": -61.474460557951936, + "z": 0.0 + }, + { + "x": 301.0091443007417, + "y": -61.474337936796, + "z": 0.0 + }, + { + "x": 302.0154500257549, + "y": -61.47421531564005, + "z": 0.0 + }, + { + "x": 303.021755750768, + "y": -61.474092694484106, + "z": 0.0 + }, + { + "x": 304.02806147578127, + "y": -61.47397007332817, + "z": 0.0 + }, + { + "x": 305.0343672007945, + "y": -61.47384745217222, + "z": 0.0 + }, + { + "x": 306.04067292580766, + "y": -61.47372483101628, + "z": 0.0 + }, + { + "x": 307.0469786508209, + "y": -61.47360220986034, + "z": 0.0 + }, + { + "x": 308.0532843758341, + "y": -61.47347958870439, + "z": 0.0 + }, + { + "x": 309.05959010084723, + "y": -61.47335696754845, + "z": 0.0 + }, + { + "x": 310.0658958258605, + "y": -61.47323434639251, + "z": 0.0 + }, + { + "x": 311.07220155087373, + "y": -61.47311172523656, + "z": 0.0 + }, + { + "x": 312.07850727588686, + "y": -61.47298910408062, + "z": 0.0 + }, + { + "x": 313.0848130009001, + "y": -61.47286648292468, + "z": 0.0 + }, + { + "x": 314.0911187259133, + "y": -61.472743861768734, + "z": 0.0 + }, + { + "x": 315.09742445092644, + "y": -61.47262124061279, + "z": 0.0 + }, + { + "x": 316.10373017593975, + "y": -61.47249861945685, + "z": 0.0 + }, + { + "x": 317.11003590095294, + "y": -61.472375998300905, + "z": 0.0 + }, + { + "x": 318.11634162596613, + "y": -61.47225337714496, + "z": 0.0 + }, + { + "x": 319.1226473509793, + "y": -61.47213075598901, + "z": 0.0 + }, + { + "x": 320.12895307599246, + "y": -61.47200813483307, + "z": 0.0 + }, + { + "x": 321.13525880100576, + "y": -61.47188551367713, + "z": 0.0 + }, + { + "x": 322.14156452601895, + "y": -61.471762892521184, + "z": 0.0 + }, + { + "x": 323.1478702510321, + "y": -61.47164027136524, + "z": 0.0 + }, + { + "x": 324.15417597604534, + "y": -61.4715176502093, + "z": 0.0 + }, + { + "x": 325.16048170105853, + "y": -61.471395029053355, + "z": 0.0 + } + ] + }, + { + "id": 52, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 167.16999546284472, + "y": -57.49064658023266, + "z": 0.0 + }, + { + "x": 168.17630118785794, + "y": -57.49052395907671, + "z": 0.0 + }, + { + "x": 169.18260691287114, + "y": -57.49040133792077, + "z": 0.0 + }, + { + "x": 170.18891263788436, + "y": -57.49027871676483, + "z": 0.0 + }, + { + "x": 171.19521836289758, + "y": -57.49015609560888, + "z": 0.0 + }, + { + "x": 172.2015240879108, + "y": -57.49003347445294, + "z": 0.0 + }, + { + "x": 173.207829812924, + "y": -57.489910853297, + "z": 0.0 + }, + { + "x": 174.2141355379372, + "y": -57.48978823214105, + "z": 0.0 + }, + { + "x": 175.22044126295043, + "y": -57.489665610985114, + "z": 0.0 + }, + { + "x": 176.22674698796362, + "y": -57.48954298982917, + "z": 0.0 + }, + { + "x": 177.23305271297684, + "y": -57.48942036867323, + "z": 0.0 + }, + { + "x": 178.23935843799006, + "y": -57.489297747517284, + "z": 0.0 + }, + { + "x": 179.24566416300325, + "y": -57.48917512636134, + "z": 0.0 + }, + { + "x": 180.25196988801648, + "y": -57.4890525052054, + "z": 0.0 + }, + { + "x": 181.2582756130297, + "y": -57.48892988404945, + "z": 0.0 + }, + { + "x": 182.26458133804292, + "y": -57.4888072628935, + "z": 0.0 + }, + { + "x": 183.2708870630561, + "y": -57.488684641737564, + "z": 0.0 + }, + { + "x": 184.27719278806933, + "y": -57.48856202058162, + "z": 0.0 + }, + { + "x": 185.28349851308255, + "y": -57.48843939942567, + "z": 0.0 + }, + { + "x": 186.28980423809574, + "y": -57.488316778269734, + "z": 0.0 + }, + { + "x": 187.29610996310896, + "y": -57.48819415711379, + "z": 0.0 + }, + { + "x": 188.30241568812218, + "y": -57.48807153595784, + "z": 0.0 + }, + { + "x": 189.3087214131354, + "y": -57.487948914801905, + "z": 0.0 + }, + { + "x": 190.31502713814862, + "y": -57.48782629364596, + "z": 0.0 + }, + { + "x": 191.3213328631618, + "y": -57.487703672490014, + "z": 0.0 + }, + { + "x": 192.32763858817503, + "y": -57.487581051334075, + "z": 0.0 + }, + { + "x": 193.33394431318825, + "y": -57.48745843017813, + "z": 0.0 + }, + { + "x": 194.34025003820145, + "y": -57.487335809022184, + "z": 0.0 + }, + { + "x": 195.34655576321467, + "y": -57.487213187866246, + "z": 0.0 + }, + { + "x": 196.3528614882279, + "y": -57.4870905667103, + "z": 0.0 + }, + { + "x": 197.3591672132411, + "y": -57.48696794555436, + "z": 0.0 + }, + { + "x": 198.36547293825433, + "y": -57.486845324398416, + "z": 0.0 + }, + { + "x": 199.37177866326752, + "y": -57.48672270324247, + "z": 0.0 + }, + { + "x": 200.37808438828074, + "y": -57.48660008208653, + "z": 0.0 + }, + { + "x": 201.38439011329396, + "y": -57.48647746093059, + "z": 0.0 + }, + { + "x": 202.39069583830715, + "y": -57.48635483977464, + "z": 0.0 + }, + { + "x": 203.39700156332037, + "y": -57.4862322186187, + "z": 0.0 + }, + { + "x": 204.40330728833356, + "y": -57.48610959746276, + "z": 0.0 + }, + { + "x": 205.40961301334679, + "y": -57.48598697630681, + "z": 0.0 + }, + { + "x": 206.41591873836, + "y": -57.48586435515087, + "z": 0.0 + }, + { + "x": 207.4222244633732, + "y": -57.48574173399493, + "z": 0.0 + }, + { + "x": 208.42853018838642, + "y": -57.48561911283898, + "z": 0.0 + }, + { + "x": 209.43483591339964, + "y": -57.48549649168304, + "z": 0.0 + }, + { + "x": 210.44114163841283, + "y": -57.48537387052709, + "z": 0.0 + }, + { + "x": 211.44744736342605, + "y": -57.485251249371146, + "z": 0.0 + }, + { + "x": 212.45375308843924, + "y": -57.48512862821521, + "z": 0.0 + }, + { + "x": 213.46005881345246, + "y": -57.48500600705926, + "z": 0.0 + }, + { + "x": 214.46636453846568, + "y": -57.484883385903316, + "z": 0.0 + }, + { + "x": 215.47267026347888, + "y": -57.48476076474738, + "z": 0.0 + }, + { + "x": 216.4789759884921, + "y": -57.48463814359143, + "z": 0.0 + }, + { + "x": 217.48528171350532, + "y": -57.484515522435494, + "z": 0.0 + }, + { + "x": 218.4915874385185, + "y": -57.48439290127955, + "z": 0.0 + }, + { + "x": 219.49789316353173, + "y": -57.4842702801236, + "z": 0.0 + }, + { + "x": 220.50419888854492, + "y": -57.484147658967665, + "z": 0.0 + }, + { + "x": 221.51050461355814, + "y": -57.48402503781172, + "z": 0.0 + }, + { + "x": 222.51681033857136, + "y": -57.48390241665577, + "z": 0.0 + }, + { + "x": 223.52311606358455, + "y": -57.483779795499835, + "z": 0.0 + }, + { + "x": 224.52942178859777, + "y": -57.48365717434389, + "z": 0.0 + }, + { + "x": 225.535727513611, + "y": -57.483534553187944, + "z": 0.0 + }, + { + "x": 226.54203323862419, + "y": -57.483411932032006, + "z": 0.0 + }, + { + "x": 227.5483389636374, + "y": -57.48328931087606, + "z": 0.0 + }, + { + "x": 228.5546446886506, + "y": -57.483166689720115, + "z": 0.0 + }, + { + "x": 229.56095041366382, + "y": -57.483044068564176, + "z": 0.0 + }, + { + "x": 230.56725613867704, + "y": -57.48292144740823, + "z": 0.0 + }, + { + "x": 231.57356186369023, + "y": -57.482798826252285, + "z": 0.0 + }, + { + "x": 232.57986758870345, + "y": -57.48267620509635, + "z": 0.0 + }, + { + "x": 233.58617331371667, + "y": -57.4825535839404, + "z": 0.0 + }, + { + "x": 234.5924790387299, + "y": -57.482430962784456, + "z": 0.0 + }, + { + "x": 235.5987847637431, + "y": -57.48230834162851, + "z": 0.0 + }, + { + "x": 236.60509048875633, + "y": -57.482185720472565, + "z": 0.0 + }, + { + "x": 237.61139621376955, + "y": -57.482063099316626, + "z": 0.0 + }, + { + "x": 238.61770193878274, + "y": -57.48194047816068, + "z": 0.0 + }, + { + "x": 239.62400766379596, + "y": -57.481817857004735, + "z": 0.0 + }, + { + "x": 240.63031338880918, + "y": -57.4816952358488, + "z": 0.0 + }, + { + "x": 241.6366191138224, + "y": -57.48157261469285, + "z": 0.0 + }, + { + "x": 242.64292483883563, + "y": -57.481449993536906, + "z": 0.0 + }, + { + "x": 243.64923056384885, + "y": -57.48132737238097, + "z": 0.0 + }, + { + "x": 244.65553628886207, + "y": -57.48120475122502, + "z": 0.0 + }, + { + "x": 245.6618420138753, + "y": -57.481082130069076, + "z": 0.0 + }, + { + "x": 246.6681477388885, + "y": -57.48095950891314, + "z": 0.0 + }, + { + "x": 247.6744534639017, + "y": -57.48083688775719, + "z": 0.0 + }, + { + "x": 248.68075918891492, + "y": -57.48071426660125, + "z": 0.0 + }, + { + "x": 249.68706491392814, + "y": -57.48059164544531, + "z": 0.0 + }, + { + "x": 250.69337063894136, + "y": -57.48046902428936, + "z": 0.0 + }, + { + "x": 251.69967636395458, + "y": -57.48034640313342, + "z": 0.0 + }, + { + "x": 252.7059820889678, + "y": -57.48022378197748, + "z": 0.0 + }, + { + "x": 253.71228781398102, + "y": -57.48010116082153, + "z": 0.0 + }, + { + "x": 254.71859353899424, + "y": -57.47997853966559, + "z": 0.0 + }, + { + "x": 255.72489926400746, + "y": -57.47985591850965, + "z": 0.0 + }, + { + "x": 256.7312049890207, + "y": -57.479733297353704, + "z": 0.0 + }, + { + "x": 257.7375107140339, + "y": -57.479610676197765, + "z": 0.0 + }, + { + "x": 258.7438164390471, + "y": -57.47948805504182, + "z": 0.0 + }, + { + "x": 259.7501221640603, + "y": -57.479365433885874, + "z": 0.0 + }, + { + "x": 260.75642788907356, + "y": -57.479242812729936, + "z": 0.0 + }, + { + "x": 261.76273361408676, + "y": -57.47912019157399, + "z": 0.0 + }, + { + "x": 262.76903933909995, + "y": -57.478997570418045, + "z": 0.0 + }, + { + "x": 263.7753450641132, + "y": -57.4788749492621, + "z": 0.0 + }, + { + "x": 264.7816507891264, + "y": -57.478752328106154, + "z": 0.0 + }, + { + "x": 265.78795651413964, + "y": -57.47862970695021, + "z": 0.0 + }, + { + "x": 266.79426223915283, + "y": -57.47850708579427, + "z": 0.0 + }, + { + "x": 267.800567964166, + "y": -57.478384464638324, + "z": 0.0 + }, + { + "x": 268.80687368917927, + "y": -57.47826184348238, + "z": 0.0 + }, + { + "x": 269.81317941419246, + "y": -57.47813922232644, + "z": 0.0 + }, + { + "x": 270.8194851392057, + "y": -57.478016601170495, + "z": 0.0 + }, + { + "x": 271.8257908642189, + "y": -57.47789398001455, + "z": 0.0 + }, + { + "x": 272.83209658923215, + "y": -57.47777135885861, + "z": 0.0 + }, + { + "x": 273.83840231424534, + "y": -57.477648737702665, + "z": 0.0 + }, + { + "x": 274.8447080392586, + "y": -57.47752611654672, + "z": 0.0 + }, + { + "x": 275.8510137642718, + "y": -57.47740349539078, + "z": 0.0 + }, + { + "x": 276.857319489285, + "y": -57.477280874234836, + "z": 0.0 + }, + { + "x": 277.8636252142982, + "y": -57.4771582530789, + "z": 0.0 + }, + { + "x": 278.8699309393114, + "y": -57.47703563192295, + "z": 0.0 + }, + { + "x": 279.87623666432467, + "y": -57.47691301076701, + "z": 0.0 + }, + { + "x": 280.88254238933786, + "y": -57.47679038961107, + "z": 0.0 + }, + { + "x": 281.8888481143511, + "y": -57.47666776845512, + "z": 0.0 + }, + { + "x": 282.8951538393643, + "y": -57.47654514729918, + "z": 0.0 + }, + { + "x": 283.90145956437755, + "y": -57.47642252614324, + "z": 0.0 + }, + { + "x": 284.90776528939074, + "y": -57.47629990498729, + "z": 0.0 + }, + { + "x": 285.91407101440393, + "y": -57.47617728383135, + "z": 0.0 + }, + { + "x": 286.9203767394172, + "y": -57.47605466267541, + "z": 0.0 + }, + { + "x": 287.92668246443037, + "y": -57.475932041519464, + "z": 0.0 + }, + { + "x": 288.9329881894436, + "y": -57.47580942036352, + "z": 0.0 + }, + { + "x": 289.9392939144568, + "y": -57.47568679920758, + "z": 0.0 + }, + { + "x": 290.94559963947006, + "y": -57.47556417805163, + "z": 0.0 + }, + { + "x": 291.95190536448325, + "y": -57.47544155689568, + "z": 0.0 + }, + { + "x": 292.9582110894965, + "y": -57.47531893573974, + "z": 0.0 + }, + { + "x": 293.9645168145097, + "y": -57.4751963145838, + "z": 0.0 + }, + { + "x": 294.9708225395229, + "y": -57.47507369342785, + "z": 0.0 + }, + { + "x": 295.97712826453613, + "y": -57.474951072271914, + "z": 0.0 + }, + { + "x": 296.9834339895493, + "y": -57.47482845111597, + "z": 0.0 + }, + { + "x": 297.9897397145625, + "y": -57.47470582996003, + "z": 0.0 + }, + { + "x": 298.9960454395757, + "y": -57.474583208804084, + "z": 0.0 + }, + { + "x": 300.00235116458896, + "y": -57.47446058764814, + "z": 0.0 + }, + { + "x": 301.00865688960215, + "y": -57.4743379664922, + "z": 0.0 + }, + { + "x": 302.01496261461534, + "y": -57.474215345336255, + "z": 0.0 + }, + { + "x": 303.02126833962853, + "y": -57.47409272418031, + "z": 0.0 + }, + { + "x": 304.0275740646417, + "y": -57.47397010302437, + "z": 0.0 + }, + { + "x": 305.033879789655, + "y": -57.473847481868425, + "z": 0.0 + }, + { + "x": 306.04018551466817, + "y": -57.47372486071248, + "z": 0.0 + }, + { + "x": 307.04649123968136, + "y": -57.47360223955654, + "z": 0.0 + }, + { + "x": 308.05279696469455, + "y": -57.473479618400596, + "z": 0.0 + }, + { + "x": 309.05910268970774, + "y": -57.47335699724465, + "z": 0.0 + }, + { + "x": 310.06540841472093, + "y": -57.47323437608871, + "z": 0.0 + }, + { + "x": 311.0717141397342, + "y": -57.473111754932766, + "z": 0.0 + }, + { + "x": 312.0780198647474, + "y": -57.47298913377682, + "z": 0.0 + }, + { + "x": 313.08432558976057, + "y": -57.47286651262088, + "z": 0.0 + }, + { + "x": 314.09063131477376, + "y": -57.47274389146494, + "z": 0.0 + }, + { + "x": 315.09693703978695, + "y": -57.47262127030899, + "z": 0.0 + }, + { + "x": 316.1032427648002, + "y": -57.47249864915305, + "z": 0.0 + }, + { + "x": 317.1095484898134, + "y": -57.47237602799711, + "z": 0.0 + }, + { + "x": 318.1158542148266, + "y": -57.47225340684116, + "z": 0.0 + }, + { + "x": 319.1221599398398, + "y": -57.472130785685216, + "z": 0.0 + }, + { + "x": 320.12846566485297, + "y": -57.47200816452927, + "z": 0.0 + }, + { + "x": 321.1347713898662, + "y": -57.47188554337333, + "z": 0.0 + }, + { + "x": 322.1410771148794, + "y": -57.47176292221739, + "z": 0.0 + }, + { + "x": 323.1473828398926, + "y": -57.47164030106144, + "z": 0.0 + }, + { + "x": 324.1536885649058, + "y": -57.4715176799055, + "z": 0.0 + }, + { + "x": 325.159994289919, + "y": -57.47139505874956, + "z": 0.0 + } + ] + }, + { + "id": 53, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.15975058434924, + "y": -55.47139507359766, + "z": 0.0 + }, + { + "x": 324.153444859336, + "y": -55.4715176947536, + "z": 0.0 + }, + { + "x": 323.14713913432286, + "y": -55.47164031590954, + "z": 0.0 + }, + { + "x": 322.1408334093096, + "y": -55.47176293706549, + "z": 0.0 + }, + { + "x": 321.1345276842965, + "y": -55.47188555822143, + "z": 0.0 + }, + { + "x": 320.1282219592832, + "y": -55.47200817937737, + "z": 0.0 + }, + { + "x": 319.12191623427, + "y": -55.47213080053332, + "z": 0.0 + }, + { + "x": 318.11561050925684, + "y": -55.47225342168926, + "z": 0.0 + }, + { + "x": 317.1093047842436, + "y": -55.47237604284521, + "z": 0.0 + }, + { + "x": 316.10299905923046, + "y": -55.47249866400115, + "z": 0.0 + }, + { + "x": 315.0966933342172, + "y": -55.47262128515709, + "z": 0.0 + }, + { + "x": 314.09038760920396, + "y": -55.47274390631304, + "z": 0.0 + }, + { + "x": 313.0840818841908, + "y": -55.47286652746898, + "z": 0.0 + }, + { + "x": 312.07777615917763, + "y": -55.47298914862492, + "z": 0.0 + }, + { + "x": 311.07147043416444, + "y": -55.47311176978087, + "z": 0.0 + }, + { + "x": 310.0651647091512, + "y": -55.47323439093681, + "z": 0.0 + }, + { + "x": 309.058858984138, + "y": -55.47335701209275, + "z": 0.0 + }, + { + "x": 308.0525532591248, + "y": -55.4734796332487, + "z": 0.0 + }, + { + "x": 307.04624753411156, + "y": -55.47360225440464, + "z": 0.0 + }, + { + "x": 306.0399418090984, + "y": -55.47372487556058, + "z": 0.0 + }, + { + "x": 305.0336360840852, + "y": -55.47384749671653, + "z": 0.0 + }, + { + "x": 304.0273303590719, + "y": -55.47397011787247, + "z": 0.0 + }, + { + "x": 303.0210246340588, + "y": -55.47409273902841, + "z": 0.0 + }, + { + "x": 302.01471890904554, + "y": -55.47421536018436, + "z": 0.0 + }, + { + "x": 301.0084131840324, + "y": -55.4743379813403, + "z": 0.0 + }, + { + "x": 300.0021074590192, + "y": -55.47446060249624, + "z": 0.0 + }, + { + "x": 298.9958017340059, + "y": -55.47458322365219, + "z": 0.0 + }, + { + "x": 297.9894960089928, + "y": -55.47470584480813, + "z": 0.0 + }, + { + "x": 296.9831902839796, + "y": -55.474828465964066, + "z": 0.0 + }, + { + "x": 295.9768845589664, + "y": -55.47495108712002, + "z": 0.0 + }, + { + "x": 294.97057883395314, + "y": -55.47507370827596, + "z": 0.0 + }, + { + "x": 293.9642731089399, + "y": -55.475196329431895, + "z": 0.0 + }, + { + "x": 292.95796738392676, + "y": -55.47531895058785, + "z": 0.0 + }, + { + "x": 291.9516616589135, + "y": -55.47544157174379, + "z": 0.0 + }, + { + "x": 290.94535593390026, + "y": -55.475564192899725, + "z": 0.0 + }, + { + "x": 289.939050208887, + "y": -55.47568681405568, + "z": 0.0 + }, + { + "x": 288.9327444838739, + "y": -55.475809435211616, + "z": 0.0 + }, + { + "x": 287.9264387588606, + "y": -55.47593205636757, + "z": 0.0 + }, + { + "x": 286.9201330338474, + "y": -55.47605467752351, + "z": 0.0 + }, + { + "x": 285.9138273088342, + "y": -55.476177298679445, + "z": 0.0 + }, + { + "x": 284.907521583821, + "y": -55.4762999198354, + "z": 0.0 + }, + { + "x": 283.90121585880775, + "y": -55.47642254099134, + "z": 0.0 + }, + { + "x": 282.89491013379455, + "y": -55.476545162147275, + "z": 0.0 + }, + { + "x": 281.88860440878136, + "y": -55.47666778330323, + "z": 0.0 + }, + { + "x": 280.8822986837681, + "y": -55.476790404459166, + "z": 0.0 + }, + { + "x": 279.8759929587549, + "y": -55.476913025615104, + "z": 0.0 + }, + { + "x": 278.8696872337416, + "y": -55.47703564677106, + "z": 0.0 + }, + { + "x": 277.8633815087285, + "y": -55.477158267926995, + "z": 0.0 + }, + { + "x": 276.85707578371523, + "y": -55.477280889082934, + "z": 0.0 + }, + { + "x": 275.850770058702, + "y": -55.47740351023889, + "z": 0.0 + }, + { + "x": 274.84446433368885, + "y": -55.477526131394825, + "z": 0.0 + }, + { + "x": 273.8381586086756, + "y": -55.47764875255076, + "z": 0.0 + }, + { + "x": 272.83185288366235, + "y": -55.477771373706716, + "z": 0.0 + }, + { + "x": 271.82554715864916, + "y": -55.477893994862654, + "z": 0.0 + }, + { + "x": 270.81924143363597, + "y": -55.47801661601859, + "z": 0.0 + }, + { + "x": 269.8129357086227, + "y": -55.478139237174545, + "z": 0.0 + }, + { + "x": 268.8066299836095, + "y": -55.478261858330484, + "z": 0.0 + }, + { + "x": 267.8003242585962, + "y": -55.47838447948642, + "z": 0.0 + }, + { + "x": 266.7940185335831, + "y": -55.478507100642375, + "z": 0.0 + }, + { + "x": 265.7877128085699, + "y": -55.47862972179831, + "z": 0.0 + }, + { + "x": 264.7814070835566, + "y": -55.47875234295425, + "z": 0.0 + }, + { + "x": 263.77510135854345, + "y": -55.478874964110204, + "z": 0.0 + }, + { + "x": 262.7687956335302, + "y": -55.47899758526614, + "z": 0.0 + }, + { + "x": 261.76248990851695, + "y": -55.479120206422095, + "z": 0.0 + }, + { + "x": 260.7561841835038, + "y": -55.479242827578034, + "z": 0.0 + }, + { + "x": 259.74987845849057, + "y": -55.47936544873397, + "z": 0.0 + }, + { + "x": 258.7435727334773, + "y": -55.479488069889925, + "z": 0.0 + }, + { + "x": 257.7372670084641, + "y": -55.47961069104586, + "z": 0.0 + }, + { + "x": 256.73096128345094, + "y": -55.4797333122018, + "z": 0.0 + }, + { + "x": 255.7246555584377, + "y": -55.479855933357754, + "z": 0.0 + }, + { + "x": 254.7183498334245, + "y": -55.47997855451369, + "z": 0.0 + }, + { + "x": 253.71204410841125, + "y": -55.48010117566963, + "z": 0.0 + }, + { + "x": 252.70573838339806, + "y": -55.480223796825584, + "z": 0.0 + }, + { + "x": 251.69943265838484, + "y": -55.48034641798152, + "z": 0.0 + }, + { + "x": 250.69312693337162, + "y": -55.48046903913746, + "z": 0.0 + }, + { + "x": 249.68682120835837, + "y": -55.48059166029341, + "z": 0.0 + }, + { + "x": 248.68051548334518, + "y": -55.48071428144935, + "z": 0.0 + }, + { + "x": 247.67420975833193, + "y": -55.48083690260529, + "z": 0.0 + }, + { + "x": 246.66790403331873, + "y": -55.48095952376124, + "z": 0.0 + }, + { + "x": 245.66159830830554, + "y": -55.48108214491718, + "z": 0.0 + }, + { + "x": 244.6552925832923, + "y": -55.48120476607312, + "z": 0.0 + }, + { + "x": 243.6489868582791, + "y": -55.48132738722907, + "z": 0.0 + }, + { + "x": 242.64268113326588, + "y": -55.48145000838501, + "z": 0.0 + }, + { + "x": 241.63637540825266, + "y": -55.48157262954095, + "z": 0.0 + }, + { + "x": 240.6300696832394, + "y": -55.4816952506969, + "z": 0.0 + }, + { + "x": 239.62376395822622, + "y": -55.48181787185284, + "z": 0.0 + }, + { + "x": 238.61745823321297, + "y": -55.48194049300878, + "z": 0.0 + }, + { + "x": 237.61115250819978, + "y": -55.48206311416473, + "z": 0.0 + }, + { + "x": 236.6048467831866, + "y": -55.48218573532067, + "z": 0.0 + }, + { + "x": 235.59854105817334, + "y": -55.48230835647661, + "z": 0.0 + }, + { + "x": 234.59223533316015, + "y": -55.48243097763256, + "z": 0.0 + }, + { + "x": 233.5859296081469, + "y": -55.4825535987885, + "z": 0.0 + }, + { + "x": 232.5796238831337, + "y": -55.48267621994445, + "z": 0.0 + }, + { + "x": 231.5733181581205, + "y": -55.48279884110039, + "z": 0.0 + }, + { + "x": 230.56701243310727, + "y": -55.48292146225633, + "z": 0.0 + }, + { + "x": 229.56070670809407, + "y": -55.48304408341228, + "z": 0.0 + }, + { + "x": 228.55440098308085, + "y": -55.48316670456822, + "z": 0.0 + }, + { + "x": 227.54809525806763, + "y": -55.48328932572416, + "z": 0.0 + }, + { + "x": 226.54178953305444, + "y": -55.48341194688011, + "z": 0.0 + }, + { + "x": 225.53548380804125, + "y": -55.48353456803605, + "z": 0.0 + }, + { + "x": 224.529178083028, + "y": -55.48365718919199, + "z": 0.0 + }, + { + "x": 223.5228723580148, + "y": -55.48377981034794, + "z": 0.0 + }, + { + "x": 222.51656663300162, + "y": -55.48390243150388, + "z": 0.0 + }, + { + "x": 221.51026090798837, + "y": -55.48402505265982, + "z": 0.0 + }, + { + "x": 220.50395518297518, + "y": -55.48414767381577, + "z": 0.0 + }, + { + "x": 219.49764945796198, + "y": -55.48427029497171, + "z": 0.0 + }, + { + "x": 218.49134373294874, + "y": -55.484392916127646, + "z": 0.0 + }, + { + "x": 217.48503800793554, + "y": -55.4845155372836, + "z": 0.0 + }, + { + "x": 216.47873228292235, + "y": -55.48463815843954, + "z": 0.0 + }, + { + "x": 215.4724265579091, + "y": -55.484760779595476, + "z": 0.0 + }, + { + "x": 214.46612083289594, + "y": -55.484883400751414, + "z": 0.0 + }, + { + "x": 213.45981510788272, + "y": -55.48500602190737, + "z": 0.0 + }, + { + "x": 212.45350938286947, + "y": -55.485128643063305, + "z": 0.0 + }, + { + "x": 211.4472036578563, + "y": -55.485251264219244, + "z": 0.0 + }, + { + "x": 210.4408979328431, + "y": -55.485373885375196, + "z": 0.0 + }, + { + "x": 209.4345922078299, + "y": -55.485496506531135, + "z": 0.0 + }, + { + "x": 208.42828648281665, + "y": -55.48561912768709, + "z": 0.0 + }, + { + "x": 207.42198075780345, + "y": -55.485741748843026, + "z": 0.0 + }, + { + "x": 206.41567503279026, + "y": -55.48586436999898, + "z": 0.0 + }, + { + "x": 205.40936930777704, + "y": -55.48598699115492, + "z": 0.0 + }, + { + "x": 204.40306358276382, + "y": -55.486109612310855, + "z": 0.0 + }, + { + "x": 203.39675785775063, + "y": -55.48623223346681, + "z": 0.0 + }, + { + "x": 202.3904521327374, + "y": -55.486354854622746, + "z": 0.0 + }, + { + "x": 201.3841464077242, + "y": -55.486477475778685, + "z": 0.0 + }, + { + "x": 200.377840682711, + "y": -55.48660009693464, + "z": 0.0 + }, + { + "x": 199.37153495769778, + "y": -55.486722718090576, + "z": 0.0 + }, + { + "x": 198.36522923268456, + "y": -55.486845339246514, + "z": 0.0 + }, + { + "x": 197.35892350767136, + "y": -55.48696796040247, + "z": 0.0 + }, + { + "x": 196.35261778265814, + "y": -55.487090581558405, + "z": 0.0 + }, + { + "x": 195.34631205764492, + "y": -55.487213202714344, + "z": 0.0 + }, + { + "x": 194.3400063326317, + "y": -55.48733582387028, + "z": 0.0 + }, + { + "x": 193.33370060761848, + "y": -55.487458445026235, + "z": 0.0 + }, + { + "x": 192.3273948826053, + "y": -55.48758106618217, + "z": 0.0 + }, + { + "x": 191.32108915759207, + "y": -55.48770368733811, + "z": 0.0 + }, + { + "x": 190.31478343257885, + "y": -55.487826308494064, + "z": 0.0 + }, + { + "x": 189.30847770756566, + "y": -55.48794892965, + "z": 0.0 + }, + { + "x": 188.30217198255244, + "y": -55.48807155080594, + "z": 0.0 + }, + { + "x": 187.29586625753922, + "y": -55.488194171961894, + "z": 0.0 + }, + { + "x": 186.28956053252597, + "y": -55.48831679311783, + "z": 0.0 + }, + { + "x": 185.2832548075128, + "y": -55.48843941427377, + "z": 0.0 + }, + { + "x": 184.27694908249958, + "y": -55.48856203542972, + "z": 0.0 + }, + { + "x": 183.27064335748634, + "y": -55.48868465658566, + "z": 0.0 + }, + { + "x": 182.26433763247317, + "y": -55.4888072777416, + "z": 0.0 + }, + { + "x": 181.25803190745995, + "y": -55.48892989889755, + "z": 0.0 + }, + { + "x": 180.2517261824467, + "y": -55.489052520053505, + "z": 0.0 + }, + { + "x": 179.2454204574335, + "y": -55.489175141209444, + "z": 0.0 + }, + { + "x": 178.23911473242032, + "y": -55.48929776236538, + "z": 0.0 + }, + { + "x": 177.23280900740707, + "y": -55.489420383521335, + "z": 0.0 + }, + { + "x": 176.22650328239388, + "y": -55.48954300467727, + "z": 0.0 + }, + { + "x": 175.2201975573807, + "y": -55.48966562583321, + "z": 0.0 + }, + { + "x": 174.21389183236747, + "y": -55.48978824698915, + "z": 0.0 + }, + { + "x": 173.20758610735425, + "y": -55.4899108681451, + "z": 0.0 + }, + { + "x": 172.20128038234105, + "y": -55.49003348930104, + "z": 0.0 + }, + { + "x": 171.19497465732783, + "y": -55.49015611045698, + "z": 0.0 + }, + { + "x": 170.1886689323146, + "y": -55.49027873161293, + "z": 0.0 + }, + { + "x": 169.18236320730136, + "y": -55.49040135276887, + "z": 0.0 + }, + { + "x": 168.1760574822882, + "y": -55.49052397392481, + "z": 0.0 + }, + { + "x": 167.16975175727498, + "y": -55.49064659508076, + "z": 0.0 + } + ] + }, + { + "id": 54, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 167.17023916841447, + "y": -59.49064656538455, + "z": 0.0 + }, + { + "x": 168.1765448934277, + "y": -59.49052394422861, + "z": 0.0 + }, + { + "x": 169.1828506184409, + "y": -59.490401323072675, + "z": 0.0 + }, + { + "x": 170.1891563434541, + "y": -59.49027870191672, + "z": 0.0 + }, + { + "x": 171.19546206846732, + "y": -59.490156080760784, + "z": 0.0 + }, + { + "x": 172.20176779348054, + "y": -59.490033459604845, + "z": 0.0 + }, + { + "x": 173.20807351849373, + "y": -59.48991083844889, + "z": 0.0 + }, + { + "x": 174.21437924350695, + "y": -59.489788217292954, + "z": 0.0 + }, + { + "x": 175.22068496852017, + "y": -59.489665596137016, + "z": 0.0 + }, + { + "x": 176.22699069353337, + "y": -59.48954297498106, + "z": 0.0 + }, + { + "x": 177.23329641854662, + "y": -59.489420353825125, + "z": 0.0 + }, + { + "x": 178.2396021435598, + "y": -59.489297732669186, + "z": 0.0 + }, + { + "x": 179.245907868573, + "y": -59.489175111513234, + "z": 0.0 + }, + { + "x": 180.25221359358625, + "y": -59.489052490357295, + "z": 0.0 + }, + { + "x": 181.25851931859944, + "y": -59.48892986920134, + "z": 0.0 + }, + { + "x": 182.26482504361266, + "y": -59.488807248045404, + "z": 0.0 + }, + { + "x": 183.27113076862588, + "y": -59.488684626889466, + "z": 0.0 + }, + { + "x": 184.27743649363907, + "y": -59.48856200573351, + "z": 0.0 + }, + { + "x": 185.2837422186523, + "y": -59.488439384577575, + "z": 0.0 + }, + { + "x": 186.2900479436655, + "y": -59.488316763421636, + "z": 0.0 + }, + { + "x": 187.2963536686787, + "y": -59.488194142265684, + "z": 0.0 + }, + { + "x": 188.30265939369193, + "y": -59.488071521109745, + "z": 0.0 + }, + { + "x": 189.30896511870515, + "y": -59.48794889995381, + "z": 0.0 + }, + { + "x": 190.3152708437184, + "y": -59.487826278797854, + "z": 0.0 + }, + { + "x": 191.32157656873156, + "y": -59.487703657641916, + "z": 0.0 + }, + { + "x": 192.32788229374478, + "y": -59.48758103648598, + "z": 0.0 + }, + { + "x": 193.33418801875803, + "y": -59.487458415330025, + "z": 0.0 + }, + { + "x": 194.3404937437712, + "y": -59.487335794174086, + "z": 0.0 + }, + { + "x": 195.3467994687844, + "y": -59.48721317301815, + "z": 0.0 + }, + { + "x": 196.35310519379763, + "y": -59.487090551862195, + "z": 0.0 + }, + { + "x": 197.35941091881085, + "y": -59.48696793070626, + "z": 0.0 + }, + { + "x": 198.3657166438241, + "y": -59.48684530955032, + "z": 0.0 + }, + { + "x": 199.37202236883726, + "y": -59.486722688394366, + "z": 0.0 + }, + { + "x": 200.37832809385048, + "y": -59.48660006723843, + "z": 0.0 + }, + { + "x": 201.38463381886373, + "y": -59.48647744608249, + "z": 0.0 + }, + { + "x": 202.3909395438769, + "y": -59.486354824926536, + "z": 0.0 + }, + { + "x": 203.39724526889012, + "y": -59.4862322037706, + "z": 0.0 + }, + { + "x": 204.4035509939033, + "y": -59.48610958261466, + "z": 0.0 + }, + { + "x": 205.40985671891653, + "y": -59.48598696145871, + "z": 0.0 + }, + { + "x": 206.41616244392975, + "y": -59.48586434030277, + "z": 0.0 + }, + { + "x": 207.42246816894294, + "y": -59.48574171914683, + "z": 0.0 + }, + { + "x": 208.4287738939562, + "y": -59.48561909799088, + "z": 0.0 + }, + { + "x": 209.43507961896938, + "y": -59.48549647683494, + "z": 0.0 + }, + { + "x": 210.44138534398257, + "y": -59.485373855678986, + "z": 0.0 + }, + { + "x": 211.4476910689958, + "y": -59.48525123452305, + "z": 0.0 + }, + { + "x": 212.45399679400902, + "y": -59.48512861336711, + "z": 0.0 + }, + { + "x": 213.4603025190222, + "y": -59.48500599221116, + "z": 0.0 + }, + { + "x": 214.46660824403543, + "y": -59.48488337105522, + "z": 0.0 + }, + { + "x": 215.47291396904865, + "y": -59.48476074989928, + "z": 0.0 + }, + { + "x": 216.47921969406184, + "y": -59.48463812874333, + "z": 0.0 + }, + { + "x": 217.4855254190751, + "y": -59.48451550758739, + "z": 0.0 + }, + { + "x": 218.49183114408828, + "y": -59.48439288643145, + "z": 0.0 + }, + { + "x": 219.49813686910147, + "y": -59.4842702652755, + "z": 0.0 + }, + { + "x": 220.50444259411466, + "y": -59.48414764411956, + "z": 0.0 + }, + { + "x": 221.5107483191279, + "y": -59.48402502296362, + "z": 0.0 + }, + { + "x": 222.5170540441411, + "y": -59.48390240180767, + "z": 0.0 + }, + { + "x": 223.5233597691543, + "y": -59.48377978065173, + "z": 0.0 + }, + { + "x": 224.52966549416755, + "y": -59.48365715949579, + "z": 0.0 + }, + { + "x": 225.53597121918074, + "y": -59.48353453833984, + "z": 0.0 + }, + { + "x": 226.54227694419393, + "y": -59.4834119171839, + "z": 0.0 + }, + { + "x": 227.54858266920718, + "y": -59.48328929602796, + "z": 0.0 + }, + { + "x": 228.55488839422034, + "y": -59.48316667487201, + "z": 0.0 + }, + { + "x": 229.56119411923356, + "y": -59.48304405371607, + "z": 0.0 + }, + { + "x": 230.5674998442468, + "y": -59.48292143256013, + "z": 0.0 + }, + { + "x": 231.57380556925997, + "y": -59.48279881140418, + "z": 0.0 + }, + { + "x": 232.5801112942732, + "y": -59.48267619024824, + "z": 0.0 + }, + { + "x": 233.58641701928644, + "y": -59.4825535690923, + "z": 0.0 + }, + { + "x": 234.59272274429964, + "y": -59.48243094793635, + "z": 0.0 + }, + { + "x": 235.59902846931288, + "y": -59.48230832678041, + "z": 0.0 + }, + { + "x": 236.60533419432608, + "y": -59.48218570562446, + "z": 0.0 + }, + { + "x": 237.61163991933932, + "y": -59.48206308446852, + "z": 0.0 + }, + { + "x": 238.61794564435252, + "y": -59.48194046331258, + "z": 0.0 + }, + { + "x": 239.6242513693657, + "y": -59.48181784215663, + "z": 0.0 + }, + { + "x": 240.63055709437896, + "y": -59.48169522100069, + "z": 0.0 + }, + { + "x": 241.63686281939215, + "y": -59.48157259984475, + "z": 0.0 + }, + { + "x": 242.64316854440537, + "y": -59.4814499786888, + "z": 0.0 + }, + { + "x": 243.6494742694186, + "y": -59.48132735753286, + "z": 0.0 + }, + { + "x": 244.65577999443184, + "y": -59.481204736376924, + "z": 0.0 + }, + { + "x": 245.66208571944503, + "y": -59.48108211522097, + "z": 0.0 + }, + { + "x": 246.66839144445828, + "y": -59.48095949406503, + "z": 0.0 + }, + { + "x": 247.67469716947147, + "y": -59.480836872909094, + "z": 0.0 + }, + { + "x": 248.68100289448466, + "y": -59.48071425175314, + "z": 0.0 + }, + { + "x": 249.6873086194979, + "y": -59.4805916305972, + "z": 0.0 + }, + { + "x": 250.6936143445111, + "y": -59.480469009441265, + "z": 0.0 + }, + { + "x": 251.69992006952432, + "y": -59.48034638828531, + "z": 0.0 + }, + { + "x": 252.70622579453754, + "y": -59.480223767129374, + "z": 0.0 + }, + { + "x": 253.7125315195508, + "y": -59.480101145973435, + "z": 0.0 + }, + { + "x": 254.71883724456399, + "y": -59.47997852481748, + "z": 0.0 + }, + { + "x": 255.72514296957723, + "y": -59.479855903661544, + "z": 0.0 + }, + { + "x": 256.7314486945904, + "y": -59.479733282505606, + "z": 0.0 + }, + { + "x": 257.7377544196037, + "y": -59.47961066134967, + "z": 0.0 + }, + { + "x": 258.7440601446169, + "y": -59.479488040193715, + "z": 0.0 + }, + { + "x": 259.75036586963006, + "y": -59.47936541903778, + "z": 0.0 + }, + { + "x": 260.7566715946433, + "y": -59.47924279788184, + "z": 0.0 + }, + { + "x": 261.76297731965656, + "y": -59.479120176725885, + "z": 0.0 + }, + { + "x": 262.7692830446697, + "y": -59.47899755556995, + "z": 0.0 + }, + { + "x": 263.77558876968294, + "y": -59.478874934413994, + "z": 0.0 + }, + { + "x": 264.7818944946962, + "y": -59.478752313258056, + "z": 0.0 + }, + { + "x": 265.7882002197094, + "y": -59.4786296921021, + "z": 0.0 + }, + { + "x": 266.7945059447226, + "y": -59.478507070946165, + "z": 0.0 + }, + { + "x": 267.8008116697358, + "y": -59.47838444979023, + "z": 0.0 + }, + { + "x": 268.807117394749, + "y": -59.478261828634274, + "z": 0.0 + }, + { + "x": 269.8134231197622, + "y": -59.478139207478335, + "z": 0.0 + }, + { + "x": 270.81972884477545, + "y": -59.4780165863224, + "z": 0.0 + }, + { + "x": 271.82603456978865, + "y": -59.477893965166444, + "z": 0.0 + }, + { + "x": 272.83234029480195, + "y": -59.477771344010506, + "z": 0.0 + }, + { + "x": 273.8386460198151, + "y": -59.47764872285457, + "z": 0.0 + }, + { + "x": 274.84495174482834, + "y": -59.477526101698615, + "z": 0.0 + }, + { + "x": 275.8512574698416, + "y": -59.47740348054268, + "z": 0.0 + }, + { + "x": 276.8575631948547, + "y": -59.47728085938674, + "z": 0.0 + }, + { + "x": 277.86386891986797, + "y": -59.4771582382308, + "z": 0.0 + }, + { + "x": 278.8701746448812, + "y": -59.47703561707485, + "z": 0.0 + }, + { + "x": 279.8764803698944, + "y": -59.47691299591891, + "z": 0.0 + }, + { + "x": 280.8827860949076, + "y": -59.47679037476297, + "z": 0.0 + }, + { + "x": 281.88909181992085, + "y": -59.47666775360702, + "z": 0.0 + }, + { + "x": 282.89539754493404, + "y": -59.47654513245108, + "z": 0.0 + }, + { + "x": 283.90170326994735, + "y": -59.47642251129514, + "z": 0.0 + }, + { + "x": 284.9080089949605, + "y": -59.47629989013919, + "z": 0.0 + }, + { + "x": 285.9143147199737, + "y": -59.47617726898325, + "z": 0.0 + }, + { + "x": 286.920620444987, + "y": -59.47605464782731, + "z": 0.0 + }, + { + "x": 287.9269261700001, + "y": -59.47593202667136, + "z": 0.0 + }, + { + "x": 288.93323189501336, + "y": -59.47580940551542, + "z": 0.0 + }, + { + "x": 289.9395376200266, + "y": -59.47568678435948, + "z": 0.0 + }, + { + "x": 290.94584334503986, + "y": -59.47556416320353, + "z": 0.0 + }, + { + "x": 291.952149070053, + "y": -59.47544154204758, + "z": 0.0 + }, + { + "x": 292.95845479506625, + "y": -59.47531892089164, + "z": 0.0 + }, + { + "x": 293.9647605200795, + "y": -59.4751962997357, + "z": 0.0 + }, + { + "x": 294.97106624509263, + "y": -59.47507367857975, + "z": 0.0 + }, + { + "x": 295.9773719701059, + "y": -59.47495105742381, + "z": 0.0 + }, + { + "x": 296.98367769511907, + "y": -59.47482843626787, + "z": 0.0 + }, + { + "x": 297.98998342013226, + "y": -59.47470581511193, + "z": 0.0 + }, + { + "x": 298.9962891451455, + "y": -59.47458319395598, + "z": 0.0 + }, + { + "x": 300.0025948701587, + "y": -59.47446057280004, + "z": 0.0 + }, + { + "x": 301.0089005951719, + "y": -59.4743379516441, + "z": 0.0 + }, + { + "x": 302.01520632018514, + "y": -59.47421533048815, + "z": 0.0 + }, + { + "x": 303.0215120451983, + "y": -59.47409270933221, + "z": 0.0 + }, + { + "x": 304.0278177702115, + "y": -59.47397008817627, + "z": 0.0 + }, + { + "x": 305.0341234952248, + "y": -59.47384746702032, + "z": 0.0 + }, + { + "x": 306.0404292202379, + "y": -59.47372484586438, + "z": 0.0 + }, + { + "x": 307.04673494525116, + "y": -59.47360222470844, + "z": 0.0 + }, + { + "x": 308.0530406702643, + "y": -59.47347960355249, + "z": 0.0 + }, + { + "x": 309.0593463952775, + "y": -59.47335698239655, + "z": 0.0 + }, + { + "x": 310.0656521202907, + "y": -59.473234361240614, + "z": 0.0 + }, + { + "x": 311.0719578453039, + "y": -59.47311174008466, + "z": 0.0 + }, + { + "x": 312.0782635703171, + "y": -59.47298911892872, + "z": 0.0 + }, + { + "x": 313.0845692953303, + "y": -59.472866497772785, + "z": 0.0 + }, + { + "x": 314.09087502034356, + "y": -59.47274387661683, + "z": 0.0 + }, + { + "x": 315.0971807453567, + "y": -59.47262125546089, + "z": 0.0 + }, + { + "x": 316.10348647036994, + "y": -59.472498634304955, + "z": 0.0 + }, + { + "x": 317.1097921953832, + "y": -59.472376013149, + "z": 0.0 + }, + { + "x": 318.1160979203963, + "y": -59.472253391993064, + "z": 0.0 + }, + { + "x": 319.1224036454096, + "y": -59.47213077083711, + "z": 0.0 + }, + { + "x": 320.1287093704227, + "y": -59.47200814968117, + "z": 0.0 + }, + { + "x": 321.13501509543596, + "y": -59.471885528525235, + "z": 0.0 + }, + { + "x": 322.1413208204492, + "y": -59.47176290736928, + "z": 0.0 + }, + { + "x": 323.14762654546234, + "y": -59.47164028621334, + "z": 0.0 + }, + { + "x": 324.1539322704756, + "y": -59.471517665057405, + "z": 0.0 + }, + { + "x": 325.1602379954887, + "y": -59.47139504390145, + "z": 0.0 + } + ] + }, + { + "id": 55, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 398.37974812672553, + "y": -9.804292031687147, + "z": 0.0 + }, + { + "x": 398.36780240926834, + "y": -8.75089642316067, + "z": 0.0 + }, + { + "x": 398.2768958325799, + "y": -7.442858360963409, + "z": 0.0 + }, + { + "x": 397.9900120694231, + "y": -5.900146342483256, + "z": 0.0 + }, + { + "x": 397.5637979654414, + "y": -4.495994891100093, + "z": 0.0 + }, + { + "x": 396.99328823353665, + "y": -3.1428683346251147, + "z": 0.0 + }, + { + "x": 396.2283922371167, + "y": -1.799105281797945, + "z": 0.0 + }, + { + "x": 395.2664453280994, + "y": -0.5316745673262111, + "z": 0.0 + }, + { + "x": 394.24725845204534, + "y": 0.534257017414824, + "z": 0.0 + }, + { + "x": 393.11216551907125, + "y": 1.4903391899191767, + "z": 0.0 + }, + { + "x": 391.8245853286279, + "y": 2.3367176074276426, + "z": 0.0 + }, + { + "x": 390.3361931478448, + "y": 3.0382856252769592, + "z": 0.0 + }, + { + "x": 388.92224985890766, + "y": 3.5068677477098023, + "z": 0.0 + }, + { + "x": 387.4654183079017, + "y": 3.817648145243075, + "z": 0.0 + }, + { + "x": 385.96655987486594, + "y": 3.964678690223338, + "z": 0.0 + }, + { + "x": 384.598648710693, + "y": 3.9799906424916998, + "z": 0.0 + } + ] + }, + { + "id": 56, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 384.58134396508825, + "y": -4.01999064159763, + "z": 0.0 + }, + { + "x": 385.3210700215233, + "y": -4.009237715736265, + "z": 0.0 + }, + { + "x": 385.92311669882133, + "y": -4.032275787294617, + "z": 0.0 + }, + { + "x": 386.5289887266621, + "y": -4.1267618708191725, + "z": 0.0 + }, + { + "x": 387.12013661858225, + "y": -4.286806892950213, + "z": 0.0 + }, + { + "x": 387.55998559978843, + "y": -4.4318264865989745, + "z": 0.0 + }, + { + "x": 388.0557284532175, + "y": -4.709051441349425, + "z": 0.0 + }, + { + "x": 388.5501652261215, + "y": -5.082069965154249, + "z": 0.0 + }, + { + "x": 389.0062153063385, + "y": -5.5125901533047585, + "z": 0.0 + }, + { + "x": 389.3549299813356, + "y": -5.892455574449731, + "z": 0.0 + }, + { + "x": 389.66851789550583, + "y": -6.359658581921938, + "z": 0.0 + }, + { + "x": 389.9439489261116, + "y": -6.932775680958885, + "z": 0.0 + }, + { + "x": 390.1578642512467, + "y": -7.530318282566346, + "z": 0.0 + }, + { + "x": 390.2998091030685, + "y": -8.047909854519496, + "z": 0.0 + }, + { + "x": 390.36831676025355, + "y": -8.841612194702273, + "z": 0.0 + }, + { + "x": 390.38026247771074, + "y": -9.89500780322875, + "z": 0.0 + } + ] + }, + { + "id": 57, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 384.5899963378906, + "y": -0.019999999552965164, + "z": 0.0 + }, + { + "x": 385.64381494819463, + "y": -0.022279512756463074, + "z": 0.0 + }, + { + "x": 386.6942675033615, + "y": -0.10731382102577092, + "z": 0.0 + }, + { + "x": 387.72561929278487, + "y": -0.3099470615546849, + "z": 0.0 + }, + { + "x": 388.72816488321354, + "y": -0.624260633836627, + "z": 0.0 + }, + { + "x": 389.69228546420817, + "y": -1.0475544395856662, + "z": 0.0 + }, + { + "x": 390.5839469861444, + "y": -1.6093561257151243, + "z": 0.0 + }, + { + "x": 391.39871183908343, + "y": -2.2739064738697126, + "z": 0.0 + }, + { + "x": 392.13633031721895, + "y": -3.022132360315485, + "z": 0.0 + }, + { + "x": 392.79166110922614, + "y": -3.845780428123838, + "z": 0.0 + }, + { + "x": 393.33090306452124, + "y": -4.7512634582735265, + "z": 0.0 + }, + { + "x": 393.7538734457765, + "y": -5.714385286029489, + "z": 0.0 + }, + { + "x": 394.0739381603349, + "y": -6.715232312524801, + "z": 0.0 + }, + { + "x": 394.2883524678242, + "y": -7.745384107741452, + "z": 0.0 + }, + { + "x": 394.36805958476094, + "y": -8.796254308931472, + "z": 0.0 + }, + { + "x": 394.38000530221814, + "y": -9.849649917457949, + "z": 0.0 + } + ] + }, + { + "id": 58, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 396.37987671447183, + "y": -9.826970974572548, + "z": 0.0 + }, + { + "x": 396.36793099701464, + "y": -8.773575366046071, + "z": 0.0 + }, + { + "x": 396.2826241502021, + "y": -7.59412123435243, + "z": 0.0 + }, + { + "x": 396.03197511487895, + "y": -6.307689327504029, + "z": 0.0 + }, + { + "x": 395.6588357056089, + "y": -5.105190088564791, + "z": 0.0 + }, + { + "x": 395.16209564902897, + "y": -3.9470658964493204, + "z": 0.0 + }, + { + "x": 394.5100266731714, + "y": -2.8224428549608915, + "z": 0.0 + }, + { + "x": 393.70138782265917, + "y": -1.776903463820848, + "z": 0.0 + }, + { + "x": 392.8229851455644, + "y": -0.8698247282274443, + "z": 0.0 + }, + { + "x": 391.8480562526078, + "y": -0.059508467897973816, + "z": 0.0 + }, + { + "x": 390.758435396418, + "y": 0.6445815839209882, + "z": 0.0 + }, + { + "x": 389.5321790155292, + "y": 1.207012495720166, + "z": 0.0 + }, + { + "x": 388.32393457584624, + "y": 1.5984603430775586, + "z": 0.0 + }, + { + "x": 387.0798429056316, + "y": 1.855167162108652, + "z": 0.0 + }, + { + "x": 385.80518741153026, + "y": 1.9711995887334375, + "z": 0.0 + }, + { + "x": 384.5943225242918, + "y": 1.9799953214693673, + "z": 0.0 + } + ] + }, + { + "id": 59, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 384.58567015148947, + "y": -2.0199953205752976, + "z": 0.0 + }, + { + "x": 385.482442484859, + "y": -2.015758614246364, + "z": 0.0 + }, + { + "x": 386.3086921010914, + "y": -2.0697948041601943, + "z": 0.0 + }, + { + "x": 387.1273040097235, + "y": -2.2183544661869288, + "z": 0.0 + }, + { + "x": 387.92415075089787, + "y": -2.45553376339342, + "z": 0.0 + }, + { + "x": 388.62613553199833, + "y": -2.7396904630923204, + "z": 0.0 + }, + { + "x": 389.31983771968095, + "y": -3.159203783532275, + "z": 0.0 + }, + { + "x": 389.97443853260245, + "y": -3.6779882195119806, + "z": 0.0 + }, + { + "x": 390.5712728117787, + "y": -4.267361256810122, + "z": 0.0 + }, + { + "x": 391.07329554528087, + "y": -4.869118001286784, + "z": 0.0 + }, + { + "x": 391.4997104800135, + "y": -5.555461020097733, + "z": 0.0 + }, + { + "x": 391.8489111859441, + "y": -6.323580483494187, + "z": 0.0 + }, + { + "x": 392.1159012057908, + "y": -7.122775297545573, + "z": 0.0 + }, + { + "x": 392.29408078544634, + "y": -7.896646981130473, + "z": 0.0 + }, + { + "x": 392.36818817250725, + "y": -8.818933251816873, + "z": 0.0 + }, + { + "x": 392.38013388996444, + "y": -9.87232886034335, + "z": 0.0 + } + ] + }, + { + "id": 60, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 325.6703254820158, + "y": -193.1591116276879, + "z": 0.0 + }, + { + "x": 324.66472010416993, + "y": -193.15902991273836, + "z": 0.0 + }, + { + "x": 323.6591147263242, + "y": -193.1589481977888, + "z": 0.0 + }, + { + "x": 322.65350934847834, + "y": -193.15886648283922, + "z": 0.0 + }, + { + "x": 321.64790397063246, + "y": -193.15878476788964, + "z": 0.0 + }, + { + "x": 320.6422985927866, + "y": -193.15870305294007, + "z": 0.0 + }, + { + "x": 319.6366932149407, + "y": -193.1586213379905, + "z": 0.0 + }, + { + "x": 318.63108783709475, + "y": -193.15853962304095, + "z": 0.0 + }, + { + "x": 317.62548245924904, + "y": -193.15845790809138, + "z": 0.0 + }, + { + "x": 316.61987708140316, + "y": -193.1583761931418, + "z": 0.0 + }, + { + "x": 315.6142717035573, + "y": -193.15829447819223, + "z": 0.0 + }, + { + "x": 314.6086663257114, + "y": -193.15821276324266, + "z": 0.0 + }, + { + "x": 313.6030609478655, + "y": -193.1581310482931, + "z": 0.0 + }, + { + "x": 312.5974555700196, + "y": -193.15804933334354, + "z": 0.0 + }, + { + "x": 311.5918501921738, + "y": -193.15796761839397, + "z": 0.0 + }, + { + "x": 310.586244814328, + "y": -193.1578859034444, + "z": 0.0 + }, + { + "x": 309.5806394364821, + "y": -193.15780418849482, + "z": 0.0 + }, + { + "x": 308.5750340586362, + "y": -193.15772247354525, + "z": 0.0 + }, + { + "x": 307.5694286807902, + "y": -193.1576407585957, + "z": 0.0 + }, + { + "x": 306.5638233029445, + "y": -193.15755904364613, + "z": 0.0 + }, + { + "x": 305.55821792509863, + "y": -193.15747732869656, + "z": 0.0 + }, + { + "x": 304.5526125472528, + "y": -193.15739561374698, + "z": 0.0 + }, + { + "x": 303.5470071694069, + "y": -193.1573138987974, + "z": 0.0 + }, + { + "x": 302.54140179156104, + "y": -193.15723218384784, + "z": 0.0 + }, + { + "x": 301.53579641371505, + "y": -193.1571504688983, + "z": 0.0 + }, + { + "x": 300.53019103586934, + "y": -193.15706875394872, + "z": 0.0 + }, + { + "x": 299.52458565802345, + "y": -193.15698703899915, + "z": 0.0 + }, + { + "x": 298.51898028017763, + "y": -193.15690532404957, + "z": 0.0 + }, + { + "x": 297.51337490233175, + "y": -193.1568236091, + "z": 0.0 + }, + { + "x": 296.50776952448575, + "y": -193.15674189415046, + "z": 0.0 + }, + { + "x": 295.50216414664, + "y": -193.15666017920088, + "z": 0.0 + }, + { + "x": 294.49655876879416, + "y": -193.1565784642513, + "z": 0.0 + }, + { + "x": 293.4909533909483, + "y": -193.15649674930174, + "z": 0.0 + }, + { + "x": 292.48534801310245, + "y": -193.15641503435216, + "z": 0.0 + }, + { + "x": 291.47974263525657, + "y": -193.1563333194026, + "z": 0.0 + }, + { + "x": 290.4741372574106, + "y": -193.15625160445305, + "z": 0.0 + }, + { + "x": 289.4685318795648, + "y": -193.15616988950347, + "z": 0.0 + }, + { + "x": 288.4629265017189, + "y": -193.1560881745539, + "z": 0.0 + }, + { + "x": 287.4573211238731, + "y": -193.15600645960433, + "z": 0.0 + }, + { + "x": 286.4517157460273, + "y": -193.15592474465475, + "z": 0.0 + }, + { + "x": 285.4461103681814, + "y": -193.15584302970518, + "z": 0.0 + }, + { + "x": 284.4405049903354, + "y": -193.15576131475564, + "z": 0.0 + }, + { + "x": 283.43489961248963, + "y": -193.15567959980606, + "z": 0.0 + }, + { + "x": 282.42929423464375, + "y": -193.1555978848565, + "z": 0.0 + }, + { + "x": 281.4236888567979, + "y": -193.15551616990692, + "z": 0.0 + }, + { + "x": 280.4180834789521, + "y": -193.15543445495734, + "z": 0.0 + }, + { + "x": 279.4124781011061, + "y": -193.1553527400078, + "z": 0.0 + }, + { + "x": 278.40687272326034, + "y": -193.15527102505823, + "z": 0.0 + }, + { + "x": 277.40126734541445, + "y": -193.15518931010865, + "z": 0.0 + }, + { + "x": 276.39566196756857, + "y": -193.15510759515908, + "z": 0.0 + }, + { + "x": 275.39005658972275, + "y": -193.1550258802095, + "z": 0.0 + }, + { + "x": 274.38445121187686, + "y": -193.15494416525993, + "z": 0.0 + }, + { + "x": 273.3788458340309, + "y": -193.1548624503104, + "z": 0.0 + }, + { + "x": 272.37324045618516, + "y": -193.15478073536082, + "z": 0.0 + }, + { + "x": 271.3676350783393, + "y": -193.15469902041124, + "z": 0.0 + }, + { + "x": 270.3620297004934, + "y": -193.15461730546167, + "z": 0.0 + }, + { + "x": 269.35642432264757, + "y": -193.1545355905121, + "z": 0.0 + }, + { + "x": 268.3508189448017, + "y": -193.15445387556252, + "z": 0.0 + }, + { + "x": 267.34521356695575, + "y": -193.15437216061298, + "z": 0.0 + }, + { + "x": 266.33960818911, + "y": -193.1542904456634, + "z": 0.0 + }, + { + "x": 265.3340028112641, + "y": -193.15420873071383, + "z": 0.0 + }, + { + "x": 264.3283974334182, + "y": -193.15412701576426, + "z": 0.0 + }, + { + "x": 263.3227920555724, + "y": -193.1540453008147, + "z": 0.0 + }, + { + "x": 262.3171866777264, + "y": -193.15396358586514, + "z": 0.0 + }, + { + "x": 261.3115812998807, + "y": -193.15388187091557, + "z": 0.0 + }, + { + "x": 260.3059759220348, + "y": -193.153800155966, + "z": 0.0 + }, + { + "x": 259.3003705441889, + "y": -193.15371844101642, + "z": 0.0 + }, + { + "x": 258.29476516634304, + "y": -193.15363672606685, + "z": 0.0 + }, + { + "x": 257.28915978849716, + "y": -193.15355501111728, + "z": 0.0 + }, + { + "x": 256.2835544106512, + "y": -193.15347329616773, + "z": 0.0 + }, + { + "x": 255.27794903280545, + "y": -193.15339158121816, + "z": 0.0 + }, + { + "x": 254.27234365495957, + "y": -193.1533098662686, + "z": 0.0 + }, + { + "x": 253.26673827711372, + "y": -193.153228151319, + "z": 0.0 + }, + { + "x": 252.26113289926786, + "y": -193.15314643636944, + "z": 0.0 + }, + { + "x": 251.25552752142187, + "y": -193.1530647214199, + "z": 0.0 + }, + { + "x": 250.24992214357613, + "y": -193.15298300647032, + "z": 0.0 + }, + { + "x": 249.24431676573028, + "y": -193.15290129152075, + "z": 0.0 + }, + { + "x": 248.2387113878844, + "y": -193.15281957657118, + "z": 0.0 + }, + { + "x": 247.23310601003854, + "y": -193.1527378616216, + "z": 0.0 + }, + { + "x": 246.2275006321927, + "y": -193.15265614667203, + "z": 0.0 + }, + { + "x": 245.2218952543467, + "y": -193.15257443172248, + "z": 0.0 + }, + { + "x": 244.21628987650095, + "y": -193.1524927167729, + "z": 0.0 + }, + { + "x": 243.2106844986551, + "y": -193.15241100182334, + "z": 0.0 + }, + { + "x": 242.20507912080922, + "y": -193.15232928687377, + "z": 0.0 + }, + { + "x": 241.19947374296336, + "y": -193.1522475719242, + "z": 0.0 + }, + { + "x": 240.1938683651175, + "y": -193.15216585697462, + "z": 0.0 + }, + { + "x": 239.18826298727151, + "y": -193.15208414202507, + "z": 0.0 + }, + { + "x": 238.18265760942577, + "y": -193.1520024270755, + "z": 0.0 + }, + { + "x": 237.1770522315799, + "y": -193.15192071212593, + "z": 0.0 + }, + { + "x": 236.17144685373404, + "y": -193.15183899717636, + "z": 0.0 + }, + { + "x": 235.1658414758882, + "y": -193.15175728222678, + "z": 0.0 + }, + { + "x": 234.1602360980422, + "y": -193.15167556727724, + "z": 0.0 + }, + { + "x": 233.15463072019645, + "y": -193.15159385232766, + "z": 0.0 + }, + { + "x": 232.1490253423506, + "y": -193.1515121373781, + "z": 0.0 + }, + { + "x": 231.14341996450472, + "y": -193.15143042242852, + "z": 0.0 + }, + { + "x": 230.13781458665886, + "y": -193.15134870747895, + "z": 0.0 + }, + { + "x": 229.132209208813, + "y": -193.15126699252937, + "z": 0.0 + }, + { + "x": 228.126603830967, + "y": -193.15118527757983, + "z": 0.0 + }, + { + "x": 227.12099845312127, + "y": -193.15110356263025, + "z": 0.0 + }, + { + "x": 226.11539307527542, + "y": -193.15102184768068, + "z": 0.0 + }, + { + "x": 225.10978769742954, + "y": -193.1509401327311, + "z": 0.0 + }, + { + "x": 224.10418231958369, + "y": -193.15085841778154, + "z": 0.0 + }, + { + "x": 223.09857694173783, + "y": -193.15077670283196, + "z": 0.0 + }, + { + "x": 222.09297156389184, + "y": -193.15069498788242, + "z": 0.0 + }, + { + "x": 221.0873661860461, + "y": -193.15061327293284, + "z": 0.0 + }, + { + "x": 220.08176080820024, + "y": -193.15053155798327, + "z": 0.0 + }, + { + "x": 219.07615543035436, + "y": -193.1504498430337, + "z": 0.0 + }, + { + "x": 218.0705500525085, + "y": -193.15036812808412, + "z": 0.0 + }, + { + "x": 217.06494467466254, + "y": -193.15028641313458, + "z": 0.0 + }, + { + "x": 216.05933929681677, + "y": -193.150204698185, + "z": 0.0 + }, + { + "x": 215.0537339189709, + "y": -193.15012298323543, + "z": 0.0 + }, + { + "x": 214.04812854112507, + "y": -193.15004126828586, + "z": 0.0 + }, + { + "x": 213.04252316327918, + "y": -193.1499595533363, + "z": 0.0 + }, + { + "x": 212.0369177854333, + "y": -193.14987783838671, + "z": 0.0 + }, + { + "x": 211.03131240758736, + "y": -193.14979612343717, + "z": 0.0 + }, + { + "x": 210.0257070297416, + "y": -193.1497144084876, + "z": 0.0 + }, + { + "x": 209.02010165189571, + "y": -193.14963269353802, + "z": 0.0 + }, + { + "x": 208.0144962740499, + "y": -193.14955097858845, + "z": 0.0 + }, + { + "x": 207.008890896204, + "y": -193.14946926363888, + "z": 0.0 + }, + { + "x": 206.003285518358, + "y": -193.14938754868933, + "z": 0.0 + }, + { + "x": 204.99768014051227, + "y": -193.14930583373976, + "z": 0.0 + }, + { + "x": 203.99207476266642, + "y": -193.1492241187902, + "z": 0.0 + }, + { + "x": 202.98646938482054, + "y": -193.1491424038406, + "z": 0.0 + }, + { + "x": 201.98086400697468, + "y": -193.14906068889104, + "z": 0.0 + }, + { + "x": 200.97525862912883, + "y": -193.14897897394147, + "z": 0.0 + }, + { + "x": 199.96965325128284, + "y": -193.14889725899192, + "z": 0.0 + }, + { + "x": 198.9640478734371, + "y": -193.14881554404235, + "z": 0.0 + }, + { + "x": 197.95844249559124, + "y": -193.14873382909278, + "z": 0.0 + }, + { + "x": 196.95283711774536, + "y": -193.1486521141432, + "z": 0.0 + }, + { + "x": 195.9472317398995, + "y": -193.14857039919363, + "z": 0.0 + }, + { + "x": 194.94162636205365, + "y": -193.14848868424406, + "z": 0.0 + }, + { + "x": 193.93602098420766, + "y": -193.1484069692945, + "z": 0.0 + }, + { + "x": 192.93041560636192, + "y": -193.14832525434494, + "z": 0.0 + }, + { + "x": 191.92481022851607, + "y": -193.14824353939537, + "z": 0.0 + }, + { + "x": 190.91920485067018, + "y": -193.1481618244458, + "z": 0.0 + }, + { + "x": 189.91359947282433, + "y": -193.14808010949622, + "z": 0.0 + }, + { + "x": 188.90799409497836, + "y": -193.14799839454668, + "z": 0.0 + }, + { + "x": 187.9023887171326, + "y": -193.1479166795971, + "z": 0.0 + }, + { + "x": 186.89678333928674, + "y": -193.14783496464753, + "z": 0.0 + }, + { + "x": 185.8911779614409, + "y": -193.14775324969796, + "z": 0.0 + }, + { + "x": 184.885572583595, + "y": -193.14767153474838, + "z": 0.0 + }, + { + "x": 183.87996720574915, + "y": -193.1475898197988, + "z": 0.0 + }, + { + "x": 182.8743618279032, + "y": -193.14750810484927, + "z": 0.0 + }, + { + "x": 181.86875645005742, + "y": -193.1474263898997, + "z": 0.0 + }, + { + "x": 180.86315107221156, + "y": -193.14734467495012, + "z": 0.0 + }, + { + "x": 179.8575456943657, + "y": -193.14726296000055, + "z": 0.0 + }, + { + "x": 178.85194031651983, + "y": -193.14718124505097, + "z": 0.0 + }, + { + "x": 177.84633493867395, + "y": -193.1470995301014, + "z": 0.0 + }, + { + "x": 176.840729560828, + "y": -193.14701781515186, + "z": 0.0 + }, + { + "x": 175.83512418298224, + "y": -193.14693610020228, + "z": 0.0 + }, + { + "x": 174.82951880513636, + "y": -193.1468543852527, + "z": 0.0 + }, + { + "x": 173.82391342729053, + "y": -193.14677267030314, + "z": 0.0 + }, + { + "x": 172.81830804944465, + "y": -193.14669095535356, + "z": 0.0 + }, + { + "x": 171.81270267159866, + "y": -193.14660924040402, + "z": 0.0 + }, + { + "x": 170.80709729375295, + "y": -193.14652752545445, + "z": 0.0 + }, + { + "x": 169.80149191590706, + "y": -193.14644581050487, + "z": 0.0 + }, + { + "x": 168.79588653806118, + "y": -193.1463640955553, + "z": 0.0 + }, + { + "x": 167.79028116021533, + "y": -193.14628238060573, + "z": 0.0 + }, + { + "x": 166.78467578236948, + "y": -193.14620066565615, + "z": 0.0 + }, + { + "x": 165.77907040452348, + "y": -193.1461189507066, + "z": 0.0 + }, + { + "x": 164.77346502667777, + "y": -193.14603723575703, + "z": 0.0 + }, + { + "x": 163.7678596488319, + "y": -193.14595552080746, + "z": 0.0 + }, + { + "x": 162.76225427098603, + "y": -193.1458738058579, + "z": 0.0 + }, + { + "x": 161.75664889314015, + "y": -193.14579209090832, + "z": 0.0 + }, + { + "x": 160.75104351529419, + "y": -193.14571037595877, + "z": 0.0 + }, + { + "x": 159.74543813744845, + "y": -193.1456286610092, + "z": 0.0 + }, + { + "x": 158.73983275960256, + "y": -193.14554694605962, + "z": 0.0 + }, + { + "x": 157.7342273817567, + "y": -193.14546523111005, + "z": 0.0 + }, + { + "x": 156.72862200391083, + "y": -193.14538351616048, + "z": 0.0 + }, + { + "x": 155.72301662606498, + "y": -193.1453018012109, + "z": 0.0 + }, + { + "x": 154.717411248219, + "y": -193.14522008626136, + "z": 0.0 + }, + { + "x": 153.71180587037324, + "y": -193.1451383713118, + "z": 0.0 + }, + { + "x": 152.7062004925274, + "y": -193.14505665636221, + "z": 0.0 + }, + { + "x": 151.70059511468153, + "y": -193.14497494141264, + "z": 0.0 + }, + { + "x": 150.69498973683565, + "y": -193.14489322646307, + "z": 0.0 + }, + { + "x": 149.6893843589898, + "y": -193.1448115115135, + "z": 0.0 + }, + { + "x": 148.68377898114383, + "y": -193.14472979656395, + "z": 0.0 + }, + { + "x": 147.67817360329806, + "y": -193.14464808161438, + "z": 0.0 + }, + { + "x": 146.6725682254522, + "y": -193.1445663666648, + "z": 0.0 + }, + { + "x": 145.66696284760636, + "y": -193.14448465171523, + "z": 0.0 + }, + { + "x": 144.66135746976047, + "y": -193.14440293676566, + "z": 0.0 + }, + { + "x": 143.6557520919145, + "y": -193.1443212218161, + "z": 0.0 + }, + { + "x": 142.65014671406877, + "y": -193.14423950686654, + "z": 0.0 + }, + { + "x": 141.6445413362229, + "y": -193.14415779191697, + "z": 0.0 + }, + { + "x": 140.63893595837703, + "y": -193.1440760769674, + "z": 0.0 + }, + { + "x": 139.63333058053118, + "y": -193.14399436201782, + "z": 0.0 + }, + { + "x": 138.6277252026853, + "y": -193.14391264706825, + "z": 0.0 + }, + { + "x": 137.62211982483933, + "y": -193.1438309321187, + "z": 0.0 + }, + { + "x": 136.6165144469936, + "y": -193.14374921716913, + "z": 0.0 + }, + { + "x": 135.6109090691477, + "y": -193.14366750221956, + "z": 0.0 + }, + { + "x": 134.60530369130186, + "y": -193.14358578726998, + "z": 0.0 + }, + { + "x": 133.599698313456, + "y": -193.1435040723204, + "z": 0.0 + }, + { + "x": 132.59409293561012, + "y": -193.14342235737084, + "z": 0.0 + }, + { + "x": 131.58848755776415, + "y": -193.1433406424213, + "z": 0.0 + }, + { + "x": 130.5828821799184, + "y": -193.14325892747172, + "z": 0.0 + }, + { + "x": 129.57727680207256, + "y": -193.14317721252215, + "z": 0.0 + }, + { + "x": 128.57167142422668, + "y": -193.14309549757257, + "z": 0.0 + }, + { + "x": 127.56606604638083, + "y": -193.143013782623, + "z": 0.0 + }, + { + "x": 126.56046066853487, + "y": -193.14293206767346, + "z": 0.0 + }, + { + "x": 125.55485529068912, + "y": -193.14285035272388, + "z": 0.0 + }, + { + "x": 124.54924991284325, + "y": -193.1427686377743, + "z": 0.0 + }, + { + "x": 123.54364453499738, + "y": -193.14268692282474, + "z": 0.0 + }, + { + "x": 122.53803915715153, + "y": -193.14260520787516, + "z": 0.0 + }, + { + "x": 121.53243377930568, + "y": -193.1425234929256, + "z": 0.0 + }, + { + "x": 120.52682840145971, + "y": -193.14244177797605, + "z": 0.0 + }, + { + "x": 119.52122302361396, + "y": -193.14236006302647, + "z": 0.0 + }, + { + "x": 118.51561764576809, + "y": -193.1422783480769, + "z": 0.0 + }, + { + "x": 117.51001226792224, + "y": -193.14219663312733, + "z": 0.0 + }, + { + "x": 116.50440689007637, + "y": -193.14211491817775, + "z": 0.0 + }, + { + "x": 115.49880151223041, + "y": -193.1420332032282, + "z": 0.0 + }, + { + "x": 114.49319613438465, + "y": -193.14195148827864, + "z": 0.0 + }, + { + "x": 113.4875907565388, + "y": -193.14186977332906, + "z": 0.0 + }, + { + "x": 112.48198537869294, + "y": -193.1417880583795, + "z": 0.0 + }, + { + "x": 111.47638000084707, + "y": -193.14170634342992, + "z": 0.0 + }, + { + "x": 110.47077462300122, + "y": -193.14162462848034, + "z": 0.0 + }, + { + "x": 109.46516924515525, + "y": -193.1415429135308, + "z": 0.0 + }, + { + "x": 108.4595638673095, + "y": -193.14146119858123, + "z": 0.0 + }, + { + "x": 107.45395848946363, + "y": -193.14137948363165, + "z": 0.0 + }, + { + "x": 106.44835311161778, + "y": -193.14129776868208, + "z": 0.0 + }, + { + "x": 105.44274773377191, + "y": -193.1412160537325, + "z": 0.0 + }, + { + "x": 104.43714235592606, + "y": -193.14113433878293, + "z": 0.0 + }, + { + "x": 103.43153697808009, + "y": -193.1410526238334, + "z": 0.0 + }, + { + "x": 102.42593160023434, + "y": -193.14097090888382, + "z": 0.0 + }, + { + "x": 101.42032622238847, + "y": -193.14088919393424, + "z": 0.0 + } + ] + }, + { + "id": 61, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 101.41967614671384, + "y": -201.14088916752183, + "z": 0.0 + }, + { + "x": 102.42528152455971, + "y": -201.1409708824714, + "z": 0.0 + }, + { + "x": 103.43088690240566, + "y": -201.14105259742098, + "z": 0.0 + }, + { + "x": 104.43649228025143, + "y": -201.14113431237053, + "z": 0.0 + }, + { + "x": 105.44209765809728, + "y": -201.1412160273201, + "z": 0.0 + }, + { + "x": 106.44770303594315, + "y": -201.14129774226967, + "z": 0.0 + }, + { + "x": 107.453308413789, + "y": -201.14137945721924, + "z": 0.0 + }, + { + "x": 108.45891379163487, + "y": -201.14146117216882, + "z": 0.0 + }, + { + "x": 109.46451916948082, + "y": -201.1415428871184, + "z": 0.0 + }, + { + "x": 110.47012454732659, + "y": -201.14162460206794, + "z": 0.0 + }, + { + "x": 111.47572992517244, + "y": -201.1417063170175, + "z": 0.0 + }, + { + "x": 112.48133530301831, + "y": -201.14178803196708, + "z": 0.0 + }, + { + "x": 113.48694068086417, + "y": -201.14186974691665, + "z": 0.0 + }, + { + "x": 114.49254605871002, + "y": -201.14195146186623, + "z": 0.0 + }, + { + "x": 115.49815143655599, + "y": -201.1420331768158, + "z": 0.0 + }, + { + "x": 116.50375681440174, + "y": -201.14211489176535, + "z": 0.0 + }, + { + "x": 117.50936219224761, + "y": -201.14219660671492, + "z": 0.0 + }, + { + "x": 118.51496757009346, + "y": -201.1422783216645, + "z": 0.0 + }, + { + "x": 119.52057294793933, + "y": -201.14236003661406, + "z": 0.0 + }, + { + "x": 120.52617832578528, + "y": -201.14244175156364, + "z": 0.0 + }, + { + "x": 121.53178370363105, + "y": -201.14252346651318, + "z": 0.0 + }, + { + "x": 122.5373890814769, + "y": -201.14260518146276, + "z": 0.0 + }, + { + "x": 123.54299445932276, + "y": -201.14268689641233, + "z": 0.0 + }, + { + "x": 124.54859983716862, + "y": -201.1427686113619, + "z": 0.0 + }, + { + "x": 125.55420521501449, + "y": -201.14285032631147, + "z": 0.0 + }, + { + "x": 126.55981059286044, + "y": -201.14293204126105, + "z": 0.0 + }, + { + "x": 127.5654159707062, + "y": -201.1430137562106, + "z": 0.0 + }, + { + "x": 128.57102134855205, + "y": -201.14309547116017, + "z": 0.0 + }, + { + "x": 129.57662672639793, + "y": -201.14317718610974, + "z": 0.0 + }, + { + "x": 130.5822321042438, + "y": -201.1432589010593, + "z": 0.0 + }, + { + "x": 131.58783748208975, + "y": -201.14334061600889, + "z": 0.0 + }, + { + "x": 132.5934428599355, + "y": -201.14342233095843, + "z": 0.0 + }, + { + "x": 133.59904823778137, + "y": -201.143504045908, + "z": 0.0 + }, + { + "x": 134.60465361562723, + "y": -201.14358576085758, + "z": 0.0 + }, + { + "x": 135.61025899347308, + "y": -201.14366747580715, + "z": 0.0 + }, + { + "x": 136.61586437131896, + "y": -201.14374919075672, + "z": 0.0 + }, + { + "x": 137.62146974916493, + "y": -201.1438309057063, + "z": 0.0 + }, + { + "x": 138.62707512701067, + "y": -201.14391262065584, + "z": 0.0 + }, + { + "x": 139.63268050485655, + "y": -201.1439943356054, + "z": 0.0 + }, + { + "x": 140.6382858827024, + "y": -201.144076050555, + "z": 0.0 + }, + { + "x": 141.64389126054826, + "y": -201.14415776550456, + "z": 0.0 + }, + { + "x": 142.64949663839414, + "y": -201.14423948045413, + "z": 0.0 + }, + { + "x": 143.6551020162401, + "y": -201.1443211954037, + "z": 0.0 + }, + { + "x": 144.66070739408585, + "y": -201.14440291035325, + "z": 0.0 + }, + { + "x": 145.66631277193173, + "y": -201.14448462530282, + "z": 0.0 + }, + { + "x": 146.67191814977758, + "y": -201.1445663402524, + "z": 0.0 + }, + { + "x": 147.67752352762344, + "y": -201.14464805520197, + "z": 0.0 + }, + { + "x": 148.68312890546943, + "y": -201.14472977015154, + "z": 0.0 + }, + { + "x": 149.68873428331517, + "y": -201.1448114851011, + "z": 0.0 + }, + { + "x": 150.69433966116102, + "y": -201.14489320005066, + "z": 0.0 + }, + { + "x": 151.6999450390069, + "y": -201.14497491500023, + "z": 0.0 + }, + { + "x": 152.70555041685276, + "y": -201.1450566299498, + "z": 0.0 + }, + { + "x": 153.7111557946986, + "y": -201.14513834489938, + "z": 0.0 + }, + { + "x": 154.7167611725446, + "y": -201.14522005984895, + "z": 0.0 + }, + { + "x": 155.72236655039035, + "y": -201.1453017747985, + "z": 0.0 + }, + { + "x": 156.7279719282362, + "y": -201.14538348974807, + "z": 0.0 + }, + { + "x": 157.73357730608208, + "y": -201.14546520469764, + "z": 0.0 + }, + { + "x": 158.73918268392794, + "y": -201.14554691964722, + "z": 0.0 + }, + { + "x": 159.74478806177382, + "y": -201.1456286345968, + "z": 0.0 + }, + { + "x": 160.75039343961978, + "y": -201.14571034954636, + "z": 0.0 + }, + { + "x": 161.75599881746552, + "y": -201.1457920644959, + "z": 0.0 + }, + { + "x": 162.7616041953114, + "y": -201.14587377944548, + "z": 0.0 + }, + { + "x": 163.76720957315726, + "y": -201.14595549439505, + "z": 0.0 + }, + { + "x": 164.77281495100314, + "y": -201.14603720934463, + "z": 0.0 + }, + { + "x": 165.77842032884908, + "y": -201.1461189242942, + "z": 0.0 + }, + { + "x": 166.78402570669485, + "y": -201.14620063924374, + "z": 0.0 + }, + { + "x": 167.7896310845407, + "y": -201.14628235419332, + "z": 0.0 + }, + { + "x": 168.79523646238655, + "y": -201.1463640691429, + "z": 0.0 + }, + { + "x": 169.80084184023244, + "y": -201.14644578409246, + "z": 0.0 + }, + { + "x": 170.80644721807832, + "y": -201.14652749904204, + "z": 0.0 + }, + { + "x": 171.81205259592426, + "y": -201.1466092139916, + "z": 0.0 + }, + { + "x": 172.81765797377003, + "y": -201.14669092894115, + "z": 0.0 + }, + { + "x": 173.8232633516159, + "y": -201.14677264389073, + "z": 0.0 + }, + { + "x": 174.82886872946173, + "y": -201.1468543588403, + "z": 0.0 + }, + { + "x": 175.8344741073076, + "y": -201.14693607378987, + "z": 0.0 + }, + { + "x": 176.8400794851536, + "y": -201.14701778873945, + "z": 0.0 + }, + { + "x": 177.84568486299932, + "y": -201.147099503689, + "z": 0.0 + }, + { + "x": 178.8512902408452, + "y": -201.14718121863856, + "z": 0.0 + }, + { + "x": 179.85689561869108, + "y": -201.14726293358814, + "z": 0.0 + }, + { + "x": 180.86250099653694, + "y": -201.1473446485377, + "z": 0.0 + }, + { + "x": 181.8681063743828, + "y": -201.14742636348728, + "z": 0.0 + }, + { + "x": 182.8737117522288, + "y": -201.14750807843686, + "z": 0.0 + }, + { + "x": 183.87931713007453, + "y": -201.1475897933864, + "z": 0.0 + }, + { + "x": 184.88492250792038, + "y": -201.14767150833597, + "z": 0.0 + }, + { + "x": 185.89052788576626, + "y": -201.14775322328555, + "z": 0.0 + }, + { + "x": 186.8961332636121, + "y": -201.14783493823512, + "z": 0.0 + }, + { + "x": 187.90173864145797, + "y": -201.1479166531847, + "z": 0.0 + }, + { + "x": 188.90734401930396, + "y": -201.14799836813427, + "z": 0.0 + }, + { + "x": 189.9129493971497, + "y": -201.1480800830838, + "z": 0.0 + }, + { + "x": 190.91855477499556, + "y": -201.14816179803339, + "z": 0.0 + }, + { + "x": 191.92416015284144, + "y": -201.14824351298296, + "z": 0.0 + }, + { + "x": 192.9297655306873, + "y": -201.14832522793253, + "z": 0.0 + }, + { + "x": 193.93537090853326, + "y": -201.1484069428821, + "z": 0.0 + }, + { + "x": 194.94097628637903, + "y": -201.14848865783165, + "z": 0.0 + }, + { + "x": 195.94658166422488, + "y": -201.14857037278122, + "z": 0.0 + }, + { + "x": 196.95218704207073, + "y": -201.1486520877308, + "z": 0.0 + }, + { + "x": 197.95779241991661, + "y": -201.14873380268037, + "z": 0.0 + }, + { + "x": 198.96339779776247, + "y": -201.14881551762994, + "z": 0.0 + }, + { + "x": 199.96900317560844, + "y": -201.14889723257951, + "z": 0.0 + }, + { + "x": 200.9746085534542, + "y": -201.14897894752906, + "z": 0.0 + }, + { + "x": 201.98021393130006, + "y": -201.14906066247863, + "z": 0.0 + }, + { + "x": 202.9858193091459, + "y": -201.1491423774282, + "z": 0.0 + }, + { + "x": 203.9914246869918, + "y": -201.14922409237778, + "z": 0.0 + }, + { + "x": 204.99703006483765, + "y": -201.14930580732735, + "z": 0.0 + }, + { + "x": 206.0026354426836, + "y": -201.14938752227692, + "z": 0.0 + }, + { + "x": 207.00824082052938, + "y": -201.14946923722647, + "z": 0.0 + }, + { + "x": 208.01384619837526, + "y": -201.14955095217604, + "z": 0.0 + }, + { + "x": 209.0194515762211, + "y": -201.14963266712562, + "z": 0.0 + }, + { + "x": 210.02505695406697, + "y": -201.1497143820752, + "z": 0.0 + }, + { + "x": 211.03066233191296, + "y": -201.14979609702476, + "z": 0.0 + }, + { + "x": 212.03626770975868, + "y": -201.1498778119743, + "z": 0.0 + }, + { + "x": 213.04187308760456, + "y": -201.14995952692388, + "z": 0.0 + }, + { + "x": 214.04747846545044, + "y": -201.15004124187345, + "z": 0.0 + }, + { + "x": 215.05308384329626, + "y": -201.15012295682303, + "z": 0.0 + }, + { + "x": 216.05868922114215, + "y": -201.1502046717726, + "z": 0.0 + }, + { + "x": 217.06429459898814, + "y": -201.15028638672217, + "z": 0.0 + }, + { + "x": 218.06989997683388, + "y": -201.15036810167172, + "z": 0.0 + }, + { + "x": 219.07550535467973, + "y": -201.1504498166213, + "z": 0.0 + }, + { + "x": 220.08111073252562, + "y": -201.15053153157086, + "z": 0.0 + }, + { + "x": 221.08671611037147, + "y": -201.15061324652044, + "z": 0.0 + }, + { + "x": 222.09232148821744, + "y": -201.15069496147, + "z": 0.0 + }, + { + "x": 223.0979268660632, + "y": -201.15077667641955, + "z": 0.0 + }, + { + "x": 224.10353224390906, + "y": -201.15085839136913, + "z": 0.0 + }, + { + "x": 225.1091376217549, + "y": -201.1509401063187, + "z": 0.0 + }, + { + "x": 226.1147429996008, + "y": -201.15102182126827, + "z": 0.0 + }, + { + "x": 227.12034837744665, + "y": -201.15110353621785, + "z": 0.0 + }, + { + "x": 228.1259537552926, + "y": -201.15118525116742, + "z": 0.0 + }, + { + "x": 229.13155913313838, + "y": -201.15126696611696, + "z": 0.0 + }, + { + "x": 230.13716451098423, + "y": -201.15134868106654, + "z": 0.0 + }, + { + "x": 231.1427698888301, + "y": -201.1514303960161, + "z": 0.0 + }, + { + "x": 232.14837526667597, + "y": -201.15151211096568, + "z": 0.0 + }, + { + "x": 233.15398064452182, + "y": -201.15159382591526, + "z": 0.0 + }, + { + "x": 234.1595860223678, + "y": -201.15167554086483, + "z": 0.0 + }, + { + "x": 235.16519140021356, + "y": -201.15175725581437, + "z": 0.0 + }, + { + "x": 236.1707967780594, + "y": -201.15183897076395, + "z": 0.0 + }, + { + "x": 237.17640215590527, + "y": -201.15192068571352, + "z": 0.0 + }, + { + "x": 238.18200753375115, + "y": -201.1520024006631, + "z": 0.0 + }, + { + "x": 239.1876129115971, + "y": -201.15208411561267, + "z": 0.0 + }, + { + "x": 240.19321828944288, + "y": -201.1521658305622, + "z": 0.0 + }, + { + "x": 241.19882366728874, + "y": -201.15224754551178, + "z": 0.0 + }, + { + "x": 242.2044290451346, + "y": -201.15232926046136, + "z": 0.0 + }, + { + "x": 243.21003442298047, + "y": -201.15241097541093, + "z": 0.0 + }, + { + "x": 244.21563980082632, + "y": -201.1524926903605, + "z": 0.0 + }, + { + "x": 245.2212451786723, + "y": -201.15257440531008, + "z": 0.0 + }, + { + "x": 246.22685055651806, + "y": -201.15265612025962, + "z": 0.0 + }, + { + "x": 247.2324559343639, + "y": -201.1527378352092, + "z": 0.0 + }, + { + "x": 248.23806131220977, + "y": -201.15281955015877, + "z": 0.0 + }, + { + "x": 249.24366669005565, + "y": -201.15290126510834, + "z": 0.0 + }, + { + "x": 250.2492720679015, + "y": -201.1529829800579, + "z": 0.0 + }, + { + "x": 251.25487744574747, + "y": -201.1530646950075, + "z": 0.0 + }, + { + "x": 252.26048282359324, + "y": -201.15314640995703, + "z": 0.0 + }, + { + "x": 253.2660882014391, + "y": -201.1532281249066, + "z": 0.0 + }, + { + "x": 254.27169357928494, + "y": -201.15330983985618, + "z": 0.0 + }, + { + "x": 255.27729895713082, + "y": -201.15339155480575, + "z": 0.0 + }, + { + "x": 256.28290433497676, + "y": -201.15347326975532, + "z": 0.0 + }, + { + "x": 257.2885097128225, + "y": -201.15355498470487, + "z": 0.0 + }, + { + "x": 258.29411509066836, + "y": -201.15363669965444, + "z": 0.0 + }, + { + "x": 259.29972046851424, + "y": -201.15371841460401, + "z": 0.0 + }, + { + "x": 260.3053258463601, + "y": -201.1538001295536, + "z": 0.0 + }, + { + "x": 261.310931224206, + "y": -201.15388184450316, + "z": 0.0 + }, + { + "x": 262.31653660205194, + "y": -201.15396355945273, + "z": 0.0 + }, + { + "x": 263.3221419798977, + "y": -201.15404527440228, + "z": 0.0 + }, + { + "x": 264.32774735774353, + "y": -201.15412698935185, + "z": 0.0 + }, + { + "x": 265.3333527355894, + "y": -201.15420870430142, + "z": 0.0 + }, + { + "x": 266.3389581134353, + "y": -201.154290419251, + "z": 0.0 + }, + { + "x": 267.3445634912813, + "y": -201.15437213420057, + "z": 0.0 + }, + { + "x": 268.350168869127, + "y": -201.15445384915012, + "z": 0.0 + }, + { + "x": 269.3557742469729, + "y": -201.1545355640997, + "z": 0.0 + }, + { + "x": 270.3613796248187, + "y": -201.15461727904926, + "z": 0.0 + }, + { + "x": 271.3669850026646, + "y": -201.15469899399884, + "z": 0.0 + }, + { + "x": 272.3725903805105, + "y": -201.1547807089484, + "z": 0.0 + }, + { + "x": 273.37819575835647, + "y": -201.15486242389798, + "z": 0.0 + }, + { + "x": 274.3838011362022, + "y": -201.15494413884753, + "z": 0.0 + }, + { + "x": 275.38940651404806, + "y": -201.1550258537971, + "z": 0.0 + }, + { + "x": 276.3950118918939, + "y": -201.15510756874667, + "z": 0.0 + }, + { + "x": 277.40061726973977, + "y": -201.15518928369625, + "z": 0.0 + }, + { + "x": 278.40622264758565, + "y": -201.15527099864582, + "z": 0.0 + }, + { + "x": 279.41182802543165, + "y": -201.1553527135954, + "z": 0.0 + }, + { + "x": 280.4174334032774, + "y": -201.15543442854494, + "z": 0.0 + }, + { + "x": 281.42303878112324, + "y": -201.1555161434945, + "z": 0.0 + }, + { + "x": 282.42864415896906, + "y": -201.15559785844408, + "z": 0.0 + }, + { + "x": 283.43424953681495, + "y": -201.15567957339366, + "z": 0.0 + }, + { + "x": 284.43985491466094, + "y": -201.15576128834323, + "z": 0.0 + }, + { + "x": 285.4454602925067, + "y": -201.15584300329277, + "z": 0.0 + }, + { + "x": 286.4510656703526, + "y": -201.15592471824235, + "z": 0.0 + }, + { + "x": 287.4566710481984, + "y": -201.15600643319192, + "z": 0.0 + }, + { + "x": 288.46227642604424, + "y": -201.1560881481415, + "z": 0.0 + }, + { + "x": 289.4678818038901, + "y": -201.15616986309107, + "z": 0.0 + }, + { + "x": 290.4734871817361, + "y": -201.15625157804064, + "z": 0.0 + }, + { + "x": 291.4790925595819, + "y": -201.15633329299018, + "z": 0.0 + }, + { + "x": 292.48469793742777, + "y": -201.15641500793976, + "z": 0.0 + }, + { + "x": 293.4903033152736, + "y": -201.15649672288933, + "z": 0.0 + }, + { + "x": 294.4959086931195, + "y": -201.1565784378389, + "z": 0.0 + }, + { + "x": 295.5015140709653, + "y": -201.15666015278848, + "z": 0.0 + }, + { + "x": 296.5071194488113, + "y": -201.15674186773805, + "z": 0.0 + }, + { + "x": 297.51272482665706, + "y": -201.1568235826876, + "z": 0.0 + }, + { + "x": 298.51833020450294, + "y": -201.15690529763717, + "z": 0.0 + }, + { + "x": 299.52393558234877, + "y": -201.15698701258674, + "z": 0.0 + }, + { + "x": 300.52954096019465, + "y": -201.1570687275363, + "z": 0.0 + }, + { + "x": 301.5351463380406, + "y": -201.1571504424859, + "z": 0.0 + }, + { + "x": 302.54075171588636, + "y": -201.15723215743543, + "z": 0.0 + }, + { + "x": 303.54635709373224, + "y": -201.157313872385, + "z": 0.0 + }, + { + "x": 304.5519624715781, + "y": -201.15739558733458, + "z": 0.0 + }, + { + "x": 305.55756784942395, + "y": -201.15747730228415, + "z": 0.0 + }, + { + "x": 306.56317322726983, + "y": -201.15755901723372, + "z": 0.0 + }, + { + "x": 307.56877860511577, + "y": -201.1576407321833, + "z": 0.0 + }, + { + "x": 308.57438398296154, + "y": -201.15772244713284, + "z": 0.0 + }, + { + "x": 309.5799893608074, + "y": -201.1578041620824, + "z": 0.0 + }, + { + "x": 310.5855947386533, + "y": -201.157885877032, + "z": 0.0 + }, + { + "x": 311.5912001164991, + "y": -201.15796759198156, + "z": 0.0 + }, + { + "x": 312.5968054943451, + "y": -201.15804930693113, + "z": 0.0 + }, + { + "x": 313.60241087219083, + "y": -201.15813102188068, + "z": 0.0 + }, + { + "x": 314.6080162500367, + "y": -201.15821273683025, + "z": 0.0 + }, + { + "x": 315.6136216278826, + "y": -201.15829445177982, + "z": 0.0 + }, + { + "x": 316.6192270057285, + "y": -201.1583761667294, + "z": 0.0 + }, + { + "x": 317.62483238357436, + "y": -201.15845788167897, + "z": 0.0 + }, + { + "x": 318.6304377614203, + "y": -201.15853959662854, + "z": 0.0 + }, + { + "x": 319.636043139266, + "y": -201.1586213115781, + "z": 0.0 + }, + { + "x": 320.6416485171119, + "y": -201.15870302652766, + "z": 0.0 + }, + { + "x": 321.64725389495777, + "y": -201.15878474147723, + "z": 0.0 + }, + { + "x": 322.65285927280365, + "y": -201.1588664564268, + "z": 0.0 + }, + { + "x": 323.65846465064953, + "y": -201.15894817137638, + "z": 0.0 + }, + { + "x": 324.6640700284955, + "y": -201.15902988632595, + "z": 0.0 + }, + { + "x": 325.66967540634136, + "y": -201.1591116012755, + "z": 0.0 + } + ] + }, + { + "id": 62, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 101.42000118455115, + "y": -197.14088918072804, + "z": 0.0 + }, + { + "x": 102.42560656239702, + "y": -197.1409708956776, + "z": 0.0 + }, + { + "x": 103.43121194024287, + "y": -197.14105261062718, + "z": 0.0 + }, + { + "x": 104.43681731808874, + "y": -197.14113432557673, + "z": 0.0 + }, + { + "x": 105.4424226959346, + "y": -197.1412160405263, + "z": 0.0 + }, + { + "x": 106.44802807378046, + "y": -197.14129775547588, + "z": 0.0 + }, + { + "x": 107.45363345162632, + "y": -197.14137947042545, + "z": 0.0 + }, + { + "x": 108.45923882947218, + "y": -197.14146118537502, + "z": 0.0 + }, + { + "x": 109.46484420731804, + "y": -197.1415429003246, + "z": 0.0 + }, + { + "x": 110.4704495851639, + "y": -197.14162461527414, + "z": 0.0 + }, + { + "x": 111.47605496300976, + "y": -197.1417063302237, + "z": 0.0 + }, + { + "x": 112.48166034085563, + "y": -197.14178804517329, + "z": 0.0 + }, + { + "x": 113.48726571870148, + "y": -197.14186976012286, + "z": 0.0 + }, + { + "x": 114.49287109654733, + "y": -197.14195147507243, + "z": 0.0 + }, + { + "x": 115.4984764743932, + "y": -197.142033190022, + "z": 0.0 + }, + { + "x": 116.50408185223905, + "y": -197.14211490497155, + "z": 0.0 + }, + { + "x": 117.50968723008492, + "y": -197.14219661992112, + "z": 0.0 + }, + { + "x": 118.51529260793077, + "y": -197.1422783348707, + "z": 0.0 + }, + { + "x": 119.52089798577664, + "y": -197.14236004982027, + "z": 0.0 + }, + { + "x": 120.5265033636225, + "y": -197.14244176476984, + "z": 0.0 + }, + { + "x": 121.53210874146836, + "y": -197.1425234797194, + "z": 0.0 + }, + { + "x": 122.53771411931422, + "y": -197.14260519466896, + "z": 0.0 + }, + { + "x": 123.54331949716007, + "y": -197.14268690961853, + "z": 0.0 + }, + { + "x": 124.54892487500594, + "y": -197.1427686245681, + "z": 0.0 + }, + { + "x": 125.5545302528518, + "y": -197.14285033951768, + "z": 0.0 + }, + { + "x": 126.56013563069766, + "y": -197.14293205446725, + "z": 0.0 + }, + { + "x": 127.56574100854351, + "y": -197.1430137694168, + "z": 0.0 + }, + { + "x": 128.57134638638937, + "y": -197.14309548436637, + "z": 0.0 + }, + { + "x": 129.57695176423525, + "y": -197.14317719931594, + "z": 0.0 + }, + { + "x": 130.5825571420811, + "y": -197.14325891426552, + "z": 0.0 + }, + { + "x": 131.58816251992695, + "y": -197.1433406292151, + "z": 0.0 + }, + { + "x": 132.5937678977728, + "y": -197.14342234416463, + "z": 0.0 + }, + { + "x": 133.5993732756187, + "y": -197.1435040591142, + "z": 0.0 + }, + { + "x": 134.60497865346454, + "y": -197.14358577406378, + "z": 0.0 + }, + { + "x": 135.6105840313104, + "y": -197.14366748901335, + "z": 0.0 + }, + { + "x": 136.61618940915628, + "y": -197.14374920396293, + "z": 0.0 + }, + { + "x": 137.62179478700213, + "y": -197.1438309189125, + "z": 0.0 + }, + { + "x": 138.62740016484798, + "y": -197.14391263386204, + "z": 0.0 + }, + { + "x": 139.63300554269387, + "y": -197.14399434881162, + "z": 0.0 + }, + { + "x": 140.63861092053972, + "y": -197.1440760637612, + "z": 0.0 + }, + { + "x": 141.64421629838557, + "y": -197.14415777871076, + "z": 0.0 + }, + { + "x": 142.64982167623145, + "y": -197.14423949366034, + "z": 0.0 + }, + { + "x": 143.6554270540773, + "y": -197.1443212086099, + "z": 0.0 + }, + { + "x": 144.66103243192316, + "y": -197.14440292355945, + "z": 0.0 + }, + { + "x": 145.66663780976904, + "y": -197.14448463850903, + "z": 0.0 + }, + { + "x": 146.6722431876149, + "y": -197.1445663534586, + "z": 0.0 + }, + { + "x": 147.67784856546075, + "y": -197.14464806840817, + "z": 0.0 + }, + { + "x": 148.68345394330663, + "y": -197.14472978335775, + "z": 0.0 + }, + { + "x": 149.68905932115248, + "y": -197.1448114983073, + "z": 0.0 + }, + { + "x": 150.69466469899834, + "y": -197.14489321325686, + "z": 0.0 + }, + { + "x": 151.70027007684422, + "y": -197.14497492820644, + "z": 0.0 + }, + { + "x": 152.70587545469007, + "y": -197.145056643156, + "z": 0.0 + }, + { + "x": 153.71148083253593, + "y": -197.14513835810558, + "z": 0.0 + }, + { + "x": 154.7170862103818, + "y": -197.14522007305516, + "z": 0.0 + }, + { + "x": 155.72269158822766, + "y": -197.1453017880047, + "z": 0.0 + }, + { + "x": 156.72829696607351, + "y": -197.14538350295427, + "z": 0.0 + }, + { + "x": 157.7339023439194, + "y": -197.14546521790385, + "z": 0.0 + }, + { + "x": 158.73950772176525, + "y": -197.14554693285342, + "z": 0.0 + }, + { + "x": 159.74511309961113, + "y": -197.145628647803, + "z": 0.0 + }, + { + "x": 160.75071847745699, + "y": -197.14571036275257, + "z": 0.0 + }, + { + "x": 161.75632385530284, + "y": -197.1457920777021, + "z": 0.0 + }, + { + "x": 162.76192923314872, + "y": -197.14587379265168, + "z": 0.0 + }, + { + "x": 163.76753461099457, + "y": -197.14595550760126, + "z": 0.0 + }, + { + "x": 164.77313998884046, + "y": -197.14603722255083, + "z": 0.0 + }, + { + "x": 165.77874536668628, + "y": -197.1461189375004, + "z": 0.0 + }, + { + "x": 166.78435074453216, + "y": -197.14620065244995, + "z": 0.0 + }, + { + "x": 167.78995612237802, + "y": -197.14628236739952, + "z": 0.0 + }, + { + "x": 168.79556150022387, + "y": -197.1463640823491, + "z": 0.0 + }, + { + "x": 169.80116687806975, + "y": -197.14644579729867, + "z": 0.0 + }, + { + "x": 170.80677225591563, + "y": -197.14652751224824, + "z": 0.0 + }, + { + "x": 171.81237763376146, + "y": -197.1466092271978, + "z": 0.0 + }, + { + "x": 172.81798301160734, + "y": -197.14669094214736, + "z": 0.0 + }, + { + "x": 173.82358838945322, + "y": -197.14677265709693, + "z": 0.0 + }, + { + "x": 174.82919376729905, + "y": -197.1468543720465, + "z": 0.0 + }, + { + "x": 175.83479914514493, + "y": -197.14693608699608, + "z": 0.0 + }, + { + "x": 176.8404045229908, + "y": -197.14701780194565, + "z": 0.0 + }, + { + "x": 177.84600990083663, + "y": -197.1470995168952, + "z": 0.0 + }, + { + "x": 178.85161527868252, + "y": -197.14718123184477, + "z": 0.0 + }, + { + "x": 179.8572206565284, + "y": -197.14726294679434, + "z": 0.0 + }, + { + "x": 180.86282603437425, + "y": -197.14734466174392, + "z": 0.0 + }, + { + "x": 181.8684314122201, + "y": -197.1474263766935, + "z": 0.0 + }, + { + "x": 182.874036790066, + "y": -197.14750809164306, + "z": 0.0 + }, + { + "x": 183.87964216791184, + "y": -197.1475898065926, + "z": 0.0 + }, + { + "x": 184.8852475457577, + "y": -197.14767152154218, + "z": 0.0 + }, + { + "x": 185.89085292360357, + "y": -197.14775323649175, + "z": 0.0 + }, + { + "x": 186.89645830144943, + "y": -197.14783495144133, + "z": 0.0 + }, + { + "x": 187.90206367929528, + "y": -197.1479166663909, + "z": 0.0 + }, + { + "x": 188.90766905714116, + "y": -197.14799838134047, + "z": 0.0 + }, + { + "x": 189.91327443498702, + "y": -197.14808009629002, + "z": 0.0 + }, + { + "x": 190.91887981283287, + "y": -197.1481618112396, + "z": 0.0 + }, + { + "x": 191.92448519067875, + "y": -197.14824352618916, + "z": 0.0 + }, + { + "x": 192.9300905685246, + "y": -197.14832524113874, + "z": 0.0 + }, + { + "x": 193.93569594637046, + "y": -197.1484069560883, + "z": 0.0 + }, + { + "x": 194.94130132421634, + "y": -197.14848867103785, + "z": 0.0 + }, + { + "x": 195.9469067020622, + "y": -197.14857038598743, + "z": 0.0 + }, + { + "x": 196.95251207990805, + "y": -197.148652100937, + "z": 0.0 + }, + { + "x": 197.95811745775393, + "y": -197.14873381588657, + "z": 0.0 + }, + { + "x": 198.96372283559978, + "y": -197.14881553083615, + "z": 0.0 + }, + { + "x": 199.96932821344564, + "y": -197.14889724578572, + "z": 0.0 + }, + { + "x": 200.97493359129152, + "y": -197.14897896073526, + "z": 0.0 + }, + { + "x": 201.98053896913737, + "y": -197.14906067568484, + "z": 0.0 + }, + { + "x": 202.98614434698322, + "y": -197.1491423906344, + "z": 0.0 + }, + { + "x": 203.9917497248291, + "y": -197.14922410558398, + "z": 0.0 + }, + { + "x": 204.99735510267496, + "y": -197.14930582053356, + "z": 0.0 + }, + { + "x": 206.0029604805208, + "y": -197.14938753548313, + "z": 0.0 + }, + { + "x": 207.0085658583667, + "y": -197.14946925043267, + "z": 0.0 + }, + { + "x": 208.01417123621258, + "y": -197.14955096538225, + "z": 0.0 + }, + { + "x": 209.0197766140584, + "y": -197.14963268033182, + "z": 0.0 + }, + { + "x": 210.02538199190428, + "y": -197.1497143952814, + "z": 0.0 + }, + { + "x": 211.03098736975016, + "y": -197.14979611023097, + "z": 0.0 + }, + { + "x": 212.036592747596, + "y": -197.1498778251805, + "z": 0.0 + }, + { + "x": 213.04219812544187, + "y": -197.14995954013008, + "z": 0.0 + }, + { + "x": 214.04780350328775, + "y": -197.15004125507966, + "z": 0.0 + }, + { + "x": 215.05340888113358, + "y": -197.15012297002923, + "z": 0.0 + }, + { + "x": 216.05901425897946, + "y": -197.1502046849788, + "z": 0.0 + }, + { + "x": 217.06461963682534, + "y": -197.15028639992838, + "z": 0.0 + }, + { + "x": 218.0702250146712, + "y": -197.15036811487792, + "z": 0.0 + }, + { + "x": 219.07583039251705, + "y": -197.1504498298275, + "z": 0.0 + }, + { + "x": 220.08143577036293, + "y": -197.15053154477707, + "z": 0.0 + }, + { + "x": 221.08704114820878, + "y": -197.15061325972664, + "z": 0.0 + }, + { + "x": 222.09264652605464, + "y": -197.1506949746762, + "z": 0.0 + }, + { + "x": 223.09825190390052, + "y": -197.15077668962576, + "z": 0.0 + }, + { + "x": 224.10385728174637, + "y": -197.15085840457533, + "z": 0.0 + }, + { + "x": 225.10946265959223, + "y": -197.1509401195249, + "z": 0.0 + }, + { + "x": 226.1150680374381, + "y": -197.15102183447448, + "z": 0.0 + }, + { + "x": 227.12067341528396, + "y": -197.15110354942405, + "z": 0.0 + }, + { + "x": 228.1262787931298, + "y": -197.15118526437362, + "z": 0.0 + }, + { + "x": 229.1318841709757, + "y": -197.15126697932317, + "z": 0.0 + }, + { + "x": 230.13748954882155, + "y": -197.15134869427274, + "z": 0.0 + }, + { + "x": 231.1430949266674, + "y": -197.1514304092223, + "z": 0.0 + }, + { + "x": 232.14870030451328, + "y": -197.1515121241719, + "z": 0.0 + }, + { + "x": 233.15430568235914, + "y": -197.15159383912146, + "z": 0.0 + }, + { + "x": 234.159911060205, + "y": -197.15167555407103, + "z": 0.0 + }, + { + "x": 235.16551643805087, + "y": -197.15175726902058, + "z": 0.0 + }, + { + "x": 236.17112181589673, + "y": -197.15183898397015, + "z": 0.0 + }, + { + "x": 237.17672719374258, + "y": -197.15192069891972, + "z": 0.0 + }, + { + "x": 238.18233257158846, + "y": -197.1520024138693, + "z": 0.0 + }, + { + "x": 239.1879379494343, + "y": -197.15208412881887, + "z": 0.0 + }, + { + "x": 240.1935433272802, + "y": -197.15216584376842, + "z": 0.0 + }, + { + "x": 241.19914870512605, + "y": -197.152247558718, + "z": 0.0 + }, + { + "x": 242.2047540829719, + "y": -197.15232927366756, + "z": 0.0 + }, + { + "x": 243.21035946081778, + "y": -197.15241098861713, + "z": 0.0 + }, + { + "x": 244.21596483866364, + "y": -197.1524927035667, + "z": 0.0 + }, + { + "x": 245.2215702165095, + "y": -197.15257441851628, + "z": 0.0 + }, + { + "x": 246.22717559435537, + "y": -197.15265613346583, + "z": 0.0 + }, + { + "x": 247.23278097220123, + "y": -197.1527378484154, + "z": 0.0 + }, + { + "x": 248.23838635004708, + "y": -197.15281956336497, + "z": 0.0 + }, + { + "x": 249.24399172789296, + "y": -197.15290127831454, + "z": 0.0 + }, + { + "x": 250.24959710573881, + "y": -197.15298299326412, + "z": 0.0 + }, + { + "x": 251.25520248358467, + "y": -197.1530647082137, + "z": 0.0 + }, + { + "x": 252.26080786143055, + "y": -197.15314642316324, + "z": 0.0 + }, + { + "x": 253.2664132392764, + "y": -197.1532281381128, + "z": 0.0 + }, + { + "x": 254.27201861712226, + "y": -197.15330985306238, + "z": 0.0 + }, + { + "x": 255.27762399496814, + "y": -197.15339156801195, + "z": 0.0 + }, + { + "x": 256.283229372814, + "y": -197.15347328296153, + "z": 0.0 + }, + { + "x": 257.2888347506598, + "y": -197.15355499791107, + "z": 0.0 + }, + { + "x": 258.2944401285057, + "y": -197.15363671286065, + "z": 0.0 + }, + { + "x": 259.3000455063516, + "y": -197.15371842781022, + "z": 0.0 + }, + { + "x": 260.30565088419746, + "y": -197.1538001427598, + "z": 0.0 + }, + { + "x": 261.31125626204334, + "y": -197.15388185770937, + "z": 0.0 + }, + { + "x": 262.31686163988917, + "y": -197.15396357265894, + "z": 0.0 + }, + { + "x": 263.32246701773505, + "y": -197.15404528760848, + "z": 0.0 + }, + { + "x": 264.3280723955809, + "y": -197.15412700255806, + "z": 0.0 + }, + { + "x": 265.33367777342676, + "y": -197.15420871750763, + "z": 0.0 + }, + { + "x": 266.33928315127264, + "y": -197.1542904324572, + "z": 0.0 + }, + { + "x": 267.3448885291185, + "y": -197.15437214740678, + "z": 0.0 + }, + { + "x": 268.35049390696435, + "y": -197.15445386235632, + "z": 0.0 + }, + { + "x": 269.3560992848102, + "y": -197.1545355773059, + "z": 0.0 + }, + { + "x": 270.36170466265605, + "y": -197.15461729225547, + "z": 0.0 + }, + { + "x": 271.36731004050193, + "y": -197.15469900720504, + "z": 0.0 + }, + { + "x": 272.3729154183478, + "y": -197.1547807221546, + "z": 0.0 + }, + { + "x": 273.3785207961937, + "y": -197.15486243710419, + "z": 0.0 + }, + { + "x": 274.3841261740395, + "y": -197.15494415205373, + "z": 0.0 + }, + { + "x": 275.3897315518854, + "y": -197.1550258670033, + "z": 0.0 + }, + { + "x": 276.39533692973123, + "y": -197.15510758195288, + "z": 0.0 + }, + { + "x": 277.4009423075771, + "y": -197.15518929690245, + "z": 0.0 + }, + { + "x": 278.406547685423, + "y": -197.15527101185202, + "z": 0.0 + }, + { + "x": 279.4121530632689, + "y": -197.1553527268016, + "z": 0.0 + }, + { + "x": 280.41775844111476, + "y": -197.15543444175114, + "z": 0.0 + }, + { + "x": 281.4233638189606, + "y": -197.1555161567007, + "z": 0.0 + }, + { + "x": 282.4289691968064, + "y": -197.1555978716503, + "z": 0.0 + }, + { + "x": 283.4345745746523, + "y": -197.15567958659986, + "z": 0.0 + }, + { + "x": 284.44017995249817, + "y": -197.15576130154943, + "z": 0.0 + }, + { + "x": 285.44578533034405, + "y": -197.15584301649898, + "z": 0.0 + }, + { + "x": 286.45139070818993, + "y": -197.15592473144855, + "z": 0.0 + }, + { + "x": 287.45699608603576, + "y": -197.15600644639812, + "z": 0.0 + }, + { + "x": 288.4626014638816, + "y": -197.1560881613477, + "z": 0.0 + }, + { + "x": 289.46820684172746, + "y": -197.15616987629727, + "z": 0.0 + }, + { + "x": 290.47381221957335, + "y": -197.15625159124684, + "z": 0.0 + }, + { + "x": 291.47941759741923, + "y": -197.1563333061964, + "z": 0.0 + }, + { + "x": 292.4850229752651, + "y": -197.15641502114596, + "z": 0.0 + }, + { + "x": 293.49062835311094, + "y": -197.15649673609553, + "z": 0.0 + }, + { + "x": 294.4962337309568, + "y": -197.1565784510451, + "z": 0.0 + }, + { + "x": 295.50183910880264, + "y": -197.15666016599468, + "z": 0.0 + }, + { + "x": 296.5074444866485, + "y": -197.15674188094425, + "z": 0.0 + }, + { + "x": 297.5130498644944, + "y": -197.1568235958938, + "z": 0.0 + }, + { + "x": 298.5186552423403, + "y": -197.15690531084337, + "z": 0.0 + }, + { + "x": 299.5242606201861, + "y": -197.15698702579294, + "z": 0.0 + }, + { + "x": 300.529865998032, + "y": -197.15706874074252, + "z": 0.0 + }, + { + "x": 301.5354713758778, + "y": -197.1571504556921, + "z": 0.0 + }, + { + "x": 302.5410767537237, + "y": -197.15723217064163, + "z": 0.0 + }, + { + "x": 303.5466821315696, + "y": -197.1573138855912, + "z": 0.0 + }, + { + "x": 304.55228750941546, + "y": -197.15739560054078, + "z": 0.0 + }, + { + "x": 305.5578928872613, + "y": -197.15747731549035, + "z": 0.0 + }, + { + "x": 306.56349826510717, + "y": -197.15755903043993, + "z": 0.0 + }, + { + "x": 307.569103642953, + "y": -197.1576407453895, + "z": 0.0 + }, + { + "x": 308.5747090207989, + "y": -197.15772246033904, + "z": 0.0 + }, + { + "x": 309.58031439864476, + "y": -197.15780417528862, + "z": 0.0 + }, + { + "x": 310.58591977649064, + "y": -197.1578858902382, + "z": 0.0 + }, + { + "x": 311.59152515433647, + "y": -197.15796760518776, + "z": 0.0 + }, + { + "x": 312.59713053218235, + "y": -197.15804932013734, + "z": 0.0 + }, + { + "x": 313.6027359100282, + "y": -197.15813103508688, + "z": 0.0 + }, + { + "x": 314.60834128787405, + "y": -197.15821275003645, + "z": 0.0 + }, + { + "x": 315.61394666571994, + "y": -197.15829446498603, + "z": 0.0 + }, + { + "x": 316.6195520435658, + "y": -197.1583761799356, + "z": 0.0 + }, + { + "x": 317.6251574214117, + "y": -197.15845789488517, + "z": 0.0 + }, + { + "x": 318.6307627992575, + "y": -197.15853960983475, + "z": 0.0 + }, + { + "x": 319.63636817710335, + "y": -197.1586213247843, + "z": 0.0 + }, + { + "x": 320.64197355494923, + "y": -197.15870303973387, + "z": 0.0 + }, + { + "x": 321.6475789327951, + "y": -197.15878475468344, + "z": 0.0 + }, + { + "x": 322.653184310641, + "y": -197.158866469633, + "z": 0.0 + }, + { + "x": 323.6587896884869, + "y": -197.15894818458258, + "z": 0.0 + }, + { + "x": 324.6643950663327, + "y": -197.15902989953216, + "z": 0.0 + }, + { + "x": 325.6700004441786, + "y": -197.1591116144817, + "z": 0.0 + } + ] + }, + { + "id": 63, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.6701629630972, + "y": -195.1591116210848, + "z": 0.0 + }, + { + "x": 324.6645575852513, + "y": -195.15902990613526, + "z": 0.0 + }, + { + "x": 323.65895220740555, + "y": -195.1589481911857, + "z": 0.0 + }, + { + "x": 322.65334682955967, + "y": -195.1588664762361, + "z": 0.0 + }, + { + "x": 321.6477414517138, + "y": -195.15878476128654, + "z": 0.0 + }, + { + "x": 320.6421360738679, + "y": -195.15870304633697, + "z": 0.0 + }, + { + "x": 319.636530696022, + "y": -195.1586213313874, + "z": 0.0 + }, + { + "x": 318.63092531817614, + "y": -195.15853961643785, + "z": 0.0 + }, + { + "x": 317.62531994033037, + "y": -195.15845790148828, + "z": 0.0 + }, + { + "x": 316.6197145624845, + "y": -195.1583761865387, + "z": 0.0 + }, + { + "x": 315.6141091846386, + "y": -195.15829447158913, + "z": 0.0 + }, + { + "x": 314.6085038067927, + "y": -195.15821275663956, + "z": 0.0 + }, + { + "x": 313.60289842894684, + "y": -195.15813104168998, + "z": 0.0 + }, + { + "x": 312.59729305110096, + "y": -195.15804932674044, + "z": 0.0 + }, + { + "x": 311.59168767325514, + "y": -195.15796761179087, + "z": 0.0 + }, + { + "x": 310.5860822954093, + "y": -195.1578858968413, + "z": 0.0 + }, + { + "x": 309.58047691756343, + "y": -195.15780418189172, + "z": 0.0 + }, + { + "x": 308.57487153971755, + "y": -195.15772246694215, + "z": 0.0 + }, + { + "x": 307.5692661618716, + "y": -195.1576407519926, + "z": 0.0 + }, + { + "x": 306.56366078402584, + "y": -195.15755903704303, + "z": 0.0 + }, + { + "x": 305.55805540617996, + "y": -195.15747732209346, + "z": 0.0 + }, + { + "x": 304.55245002833414, + "y": -195.15739560714388, + "z": 0.0 + }, + { + "x": 303.54684465048825, + "y": -195.1573138921943, + "z": 0.0 + }, + { + "x": 302.5412392726424, + "y": -195.15723217724474, + "z": 0.0 + }, + { + "x": 301.53563389479643, + "y": -195.1571504622952, + "z": 0.0 + }, + { + "x": 300.53002851695067, + "y": -195.15706874734562, + "z": 0.0 + }, + { + "x": 299.5244231391048, + "y": -195.15698703239605, + "z": 0.0 + }, + { + "x": 298.51881776125896, + "y": -195.15690531744647, + "z": 0.0 + }, + { + "x": 297.5132123834131, + "y": -195.1568236024969, + "z": 0.0 + }, + { + "x": 296.50760700556714, + "y": -195.15674188754735, + "z": 0.0 + }, + { + "x": 295.5020016277213, + "y": -195.15666017259778, + "z": 0.0 + }, + { + "x": 294.4963962498755, + "y": -195.1565784576482, + "z": 0.0 + }, + { + "x": 293.4907908720296, + "y": -195.15649674269864, + "z": 0.0 + }, + { + "x": 292.4851854941838, + "y": -195.15641502774906, + "z": 0.0 + }, + { + "x": 291.4795801163379, + "y": -195.1563333127995, + "z": 0.0 + }, + { + "x": 290.47397473849196, + "y": -195.15625159784994, + "z": 0.0 + }, + { + "x": 289.46836936064614, + "y": -195.15616988290037, + "z": 0.0 + }, + { + "x": 288.46276398280025, + "y": -195.1560881679508, + "z": 0.0 + }, + { + "x": 287.45715860495443, + "y": -195.15600645300123, + "z": 0.0 + }, + { + "x": 286.4515532271086, + "y": -195.15592473805165, + "z": 0.0 + }, + { + "x": 285.4459478492627, + "y": -195.15584302310208, + "z": 0.0 + }, + { + "x": 284.4403424714168, + "y": -195.15576130815253, + "z": 0.0 + }, + { + "x": 283.43473709357096, + "y": -195.15567959320296, + "z": 0.0 + }, + { + "x": 282.4291317157251, + "y": -195.1555978782534, + "z": 0.0 + }, + { + "x": 281.42352633787925, + "y": -195.15551616330382, + "z": 0.0 + }, + { + "x": 280.4179209600334, + "y": -195.15543444835424, + "z": 0.0 + }, + { + "x": 279.4123155821875, + "y": -195.1553527334047, + "z": 0.0 + }, + { + "x": 278.40671020434166, + "y": -195.15527101845512, + "z": 0.0 + }, + { + "x": 277.4011048264958, + "y": -195.15518930350555, + "z": 0.0 + }, + { + "x": 276.3954994486499, + "y": -195.15510758855598, + "z": 0.0 + }, + { + "x": 275.3898940708041, + "y": -195.1550258736064, + "z": 0.0 + }, + { + "x": 274.3842886929582, + "y": -195.15494415865683, + "z": 0.0 + }, + { + "x": 273.3786833151123, + "y": -195.1548624437073, + "z": 0.0 + }, + { + "x": 272.3730779372665, + "y": -195.15478072875771, + "z": 0.0 + }, + { + "x": 271.3674725594206, + "y": -195.15469901380814, + "z": 0.0 + }, + { + "x": 270.3618671815747, + "y": -195.15461729885857, + "z": 0.0 + }, + { + "x": 269.3562618037289, + "y": -195.154535583909, + "z": 0.0 + }, + { + "x": 268.350656425883, + "y": -195.15445386895942, + "z": 0.0 + }, + { + "x": 267.34505104803713, + "y": -195.15437215400988, + "z": 0.0 + }, + { + "x": 266.3394456701913, + "y": -195.1542904390603, + "z": 0.0 + }, + { + "x": 265.3338402923454, + "y": -195.15420872411073, + "z": 0.0 + }, + { + "x": 264.32823491449955, + "y": -195.15412700916116, + "z": 0.0 + }, + { + "x": 263.3226295366537, + "y": -195.15404529421158, + "z": 0.0 + }, + { + "x": 262.3170241588078, + "y": -195.15396357926204, + "z": 0.0 + }, + { + "x": 261.311418780962, + "y": -195.15388186431247, + "z": 0.0 + }, + { + "x": 260.30581340311613, + "y": -195.1538001493629, + "z": 0.0 + }, + { + "x": 259.30020802527025, + "y": -195.15371843441332, + "z": 0.0 + }, + { + "x": 258.29460264742437, + "y": -195.15363671946375, + "z": 0.0 + }, + { + "x": 257.2889972695785, + "y": -195.15355500451417, + "z": 0.0 + }, + { + "x": 256.2833918917326, + "y": -195.15347328956463, + "z": 0.0 + }, + { + "x": 255.27778651388678, + "y": -195.15339157461506, + "z": 0.0 + }, + { + "x": 254.2721811360409, + "y": -195.15330985966548, + "z": 0.0 + }, + { + "x": 253.26657575819507, + "y": -195.1532281447159, + "z": 0.0 + }, + { + "x": 252.2609703803492, + "y": -195.15314642976634, + "z": 0.0 + }, + { + "x": 251.25536500250325, + "y": -195.1530647148168, + "z": 0.0 + }, + { + "x": 250.2497596246575, + "y": -195.15298299986722, + "z": 0.0 + }, + { + "x": 249.2441542468116, + "y": -195.15290128491765, + "z": 0.0 + }, + { + "x": 248.23854886896572, + "y": -195.15281956996807, + "z": 0.0 + }, + { + "x": 247.2329434911199, + "y": -195.1527378550185, + "z": 0.0 + }, + { + "x": 246.22733811327402, + "y": -195.15265614006893, + "z": 0.0 + }, + { + "x": 245.22173273542808, + "y": -195.15257442511938, + "z": 0.0 + }, + { + "x": 244.2161273575823, + "y": -195.1524927101698, + "z": 0.0 + }, + { + "x": 243.21052197973643, + "y": -195.15241099522024, + "z": 0.0 + }, + { + "x": 242.20491660189055, + "y": -195.15232928027066, + "z": 0.0 + }, + { + "x": 241.19931122404472, + "y": -195.1522475653211, + "z": 0.0 + }, + { + "x": 240.19370584619884, + "y": -195.15216585037152, + "z": 0.0 + }, + { + "x": 239.1881004683529, + "y": -195.15208413542197, + "z": 0.0 + }, + { + "x": 238.18249509050713, + "y": -195.1520024204724, + "z": 0.0 + }, + { + "x": 237.17688971266125, + "y": -195.15192070552283, + "z": 0.0 + }, + { + "x": 236.17128433481537, + "y": -195.15183899057325, + "z": 0.0 + }, + { + "x": 235.16567895696954, + "y": -195.15175727562368, + "z": 0.0 + }, + { + "x": 234.1600735791236, + "y": -195.15167556067414, + "z": 0.0 + }, + { + "x": 233.15446820127778, + "y": -195.15159384572456, + "z": 0.0 + }, + { + "x": 232.14886282343195, + "y": -195.151512130775, + "z": 0.0 + }, + { + "x": 231.14325744558607, + "y": -195.15143041582542, + "z": 0.0 + }, + { + "x": 230.1376520677402, + "y": -195.15134870087584, + "z": 0.0 + }, + { + "x": 229.13204668989437, + "y": -195.15126698592627, + "z": 0.0 + }, + { + "x": 228.12644131204843, + "y": -195.15118527097673, + "z": 0.0 + }, + { + "x": 227.1208359342026, + "y": -195.15110355602715, + "z": 0.0 + }, + { + "x": 226.11523055635678, + "y": -195.15102184107758, + "z": 0.0 + }, + { + "x": 225.1096251785109, + "y": -195.150940126128, + "z": 0.0 + }, + { + "x": 224.10401980066501, + "y": -195.15085841117843, + "z": 0.0 + }, + { + "x": 223.0984144228192, + "y": -195.15077669622886, + "z": 0.0 + }, + { + "x": 222.09280904497325, + "y": -195.15069498127932, + "z": 0.0 + }, + { + "x": 221.08720366712743, + "y": -195.15061326632974, + "z": 0.0 + }, + { + "x": 220.0815982892816, + "y": -195.15053155138017, + "z": 0.0 + }, + { + "x": 219.07599291143572, + "y": -195.1504498364306, + "z": 0.0 + }, + { + "x": 218.07038753358984, + "y": -195.15036812148102, + "z": 0.0 + }, + { + "x": 217.06478215574396, + "y": -195.15028640653148, + "z": 0.0 + }, + { + "x": 216.05917677789813, + "y": -195.1502046915819, + "z": 0.0 + }, + { + "x": 215.05357140005225, + "y": -195.15012297663233, + "z": 0.0 + }, + { + "x": 214.04796602220642, + "y": -195.15004126168276, + "z": 0.0 + }, + { + "x": 213.04236064436054, + "y": -195.14995954673319, + "z": 0.0 + }, + { + "x": 212.03675526651466, + "y": -195.1498778317836, + "z": 0.0 + }, + { + "x": 211.03114988866878, + "y": -195.14979611683407, + "z": 0.0 + }, + { + "x": 210.02554451082295, + "y": -195.1497144018845, + "z": 0.0 + }, + { + "x": 209.01993913297707, + "y": -195.14963268693492, + "z": 0.0 + }, + { + "x": 208.01433375513125, + "y": -195.14955097198535, + "z": 0.0 + }, + { + "x": 207.00872837728537, + "y": -195.14946925703578, + "z": 0.0 + }, + { + "x": 206.00312299943943, + "y": -195.14938754208623, + "z": 0.0 + }, + { + "x": 204.9975176215936, + "y": -195.14930582713666, + "z": 0.0 + }, + { + "x": 203.99191224374778, + "y": -195.14922411218708, + "z": 0.0 + }, + { + "x": 202.9863068659019, + "y": -195.1491423972375, + "z": 0.0 + }, + { + "x": 201.980701488056, + "y": -195.14906068228794, + "z": 0.0 + }, + { + "x": 200.9750961102102, + "y": -195.14897896733837, + "z": 0.0 + }, + { + "x": 199.96949073236425, + "y": -195.14889725238882, + "z": 0.0 + }, + { + "x": 198.96388535451842, + "y": -195.14881553743925, + "z": 0.0 + }, + { + "x": 197.9582799766726, + "y": -195.14873382248967, + "z": 0.0 + }, + { + "x": 196.95267459882672, + "y": -195.1486521075401, + "z": 0.0 + }, + { + "x": 195.94706922098084, + "y": -195.14857039259053, + "z": 0.0 + }, + { + "x": 194.941463843135, + "y": -195.14848867764096, + "z": 0.0 + }, + { + "x": 193.93585846528907, + "y": -195.1484069626914, + "z": 0.0 + }, + { + "x": 192.93025308744325, + "y": -195.14832524774184, + "z": 0.0 + }, + { + "x": 191.92464770959742, + "y": -195.14824353279226, + "z": 0.0 + }, + { + "x": 190.91904233175154, + "y": -195.1481618178427, + "z": 0.0 + }, + { + "x": 189.91343695390566, + "y": -195.14808010289312, + "z": 0.0 + }, + { + "x": 188.90783157605978, + "y": -195.14799838794357, + "z": 0.0 + }, + { + "x": 187.90222619821395, + "y": -195.147916672994, + "z": 0.0 + }, + { + "x": 186.89662082036807, + "y": -195.14783495804443, + "z": 0.0 + }, + { + "x": 185.89101544252225, + "y": -195.14775324309485, + "z": 0.0 + }, + { + "x": 184.88541006467636, + "y": -195.14767152814528, + "z": 0.0 + }, + { + "x": 183.87980468683048, + "y": -195.1475898131957, + "z": 0.0 + }, + { + "x": 182.8741993089846, + "y": -195.14750809824616, + "z": 0.0 + }, + { + "x": 181.86859393113878, + "y": -195.1474263832966, + "z": 0.0 + }, + { + "x": 180.8629885532929, + "y": -195.14734466834702, + "z": 0.0 + }, + { + "x": 179.85738317544707, + "y": -195.14726295339744, + "z": 0.0 + }, + { + "x": 178.8517777976012, + "y": -195.14718123844787, + "z": 0.0 + }, + { + "x": 177.8461724197553, + "y": -195.1470995234983, + "z": 0.0 + }, + { + "x": 176.84056704190942, + "y": -195.14701780854875, + "z": 0.0 + }, + { + "x": 175.8349616640636, + "y": -195.14693609359918, + "z": 0.0 + }, + { + "x": 174.82935628621772, + "y": -195.1468543786496, + "z": 0.0 + }, + { + "x": 173.8237509083719, + "y": -195.14677266370003, + "z": 0.0 + }, + { + "x": 172.818145530526, + "y": -195.14669094875046, + "z": 0.0 + }, + { + "x": 171.81254015268007, + "y": -195.14660923380092, + "z": 0.0 + }, + { + "x": 170.8069347748343, + "y": -195.14652751885134, + "z": 0.0 + }, + { + "x": 169.80132939698842, + "y": -195.14644580390177, + "z": 0.0 + }, + { + "x": 168.79572401914254, + "y": -195.1463640889522, + "z": 0.0 + }, + { + "x": 167.79011864129666, + "y": -195.14628237400262, + "z": 0.0 + }, + { + "x": 166.78451326345083, + "y": -195.14620065905305, + "z": 0.0 + }, + { + "x": 165.7789078856049, + "y": -195.1461189441035, + "z": 0.0 + }, + { + "x": 164.77330250775913, + "y": -195.14603722915393, + "z": 0.0 + }, + { + "x": 163.76769712991324, + "y": -195.14595551420436, + "z": 0.0 + }, + { + "x": 162.76209175206736, + "y": -195.1458737992548, + "z": 0.0 + }, + { + "x": 161.75648637422148, + "y": -195.1457920843052, + "z": 0.0 + }, + { + "x": 160.7508809963756, + "y": -195.14571036935567, + "z": 0.0 + }, + { + "x": 159.74527561852977, + "y": -195.1456286544061, + "z": 0.0 + }, + { + "x": 158.7396702406839, + "y": -195.14554693945652, + "z": 0.0 + }, + { + "x": 157.73406486283807, + "y": -195.14546522450695, + "z": 0.0 + }, + { + "x": 156.7284594849922, + "y": -195.14538350955738, + "z": 0.0 + }, + { + "x": 155.7228541071463, + "y": -195.1453017946078, + "z": 0.0 + }, + { + "x": 154.71724872930042, + "y": -195.14522007965826, + "z": 0.0 + }, + { + "x": 153.7116433514546, + "y": -195.14513836470869, + "z": 0.0 + }, + { + "x": 152.70603797360872, + "y": -195.1450566497591, + "z": 0.0 + }, + { + "x": 151.7004325957629, + "y": -195.14497493480954, + "z": 0.0 + }, + { + "x": 150.694827217917, + "y": -195.14489321985997, + "z": 0.0 + }, + { + "x": 149.68922184007113, + "y": -195.1448115049104, + "z": 0.0 + }, + { + "x": 148.68361646222525, + "y": -195.14472978996085, + "z": 0.0 + }, + { + "x": 147.67801108437942, + "y": -195.14464807501128, + "z": 0.0 + }, + { + "x": 146.67240570653354, + "y": -195.1445663600617, + "z": 0.0 + }, + { + "x": 145.6668003286877, + "y": -195.14448464511213, + "z": 0.0 + }, + { + "x": 144.66119495084183, + "y": -195.14440293016256, + "z": 0.0 + }, + { + "x": 143.6555895729959, + "y": -195.144321215213, + "z": 0.0 + }, + { + "x": 142.64998419515013, + "y": -195.14423950026344, + "z": 0.0 + }, + { + "x": 141.64437881730424, + "y": -195.14415778531387, + "z": 0.0 + }, + { + "x": 140.63877343945836, + "y": -195.1440760703643, + "z": 0.0 + }, + { + "x": 139.63316806161254, + "y": -195.14399435541472, + "z": 0.0 + }, + { + "x": 138.62756268376666, + "y": -195.14391264046515, + "z": 0.0 + }, + { + "x": 137.62195730592072, + "y": -195.1438309255156, + "z": 0.0 + }, + { + "x": 136.61635192807495, + "y": -195.14374921056603, + "z": 0.0 + }, + { + "x": 135.61074655022907, + "y": -195.14366749561646, + "z": 0.0 + }, + { + "x": 134.60514117238318, + "y": -195.14358578066688, + "z": 0.0 + }, + { + "x": 133.59953579453736, + "y": -195.1435040657173, + "z": 0.0 + }, + { + "x": 132.59393041669148, + "y": -195.14342235076774, + "z": 0.0 + }, + { + "x": 131.58832503884554, + "y": -195.1433406358182, + "z": 0.0 + }, + { + "x": 130.58271966099977, + "y": -195.14325892086862, + "z": 0.0 + }, + { + "x": 129.5771142831539, + "y": -195.14317720591905, + "z": 0.0 + }, + { + "x": 128.571508905308, + "y": -195.14309549096947, + "z": 0.0 + }, + { + "x": 127.56590352746217, + "y": -195.1430137760199, + "z": 0.0 + }, + { + "x": 126.56029814961627, + "y": -195.14293206107035, + "z": 0.0 + }, + { + "x": 125.55469277177046, + "y": -195.14285034612078, + "z": 0.0 + }, + { + "x": 124.5490873939246, + "y": -195.1427686311712, + "z": 0.0 + }, + { + "x": 123.54348201607873, + "y": -195.14268691622163, + "z": 0.0 + }, + { + "x": 122.53787663823287, + "y": -195.14260520127206, + "z": 0.0 + }, + { + "x": 121.53227126038702, + "y": -195.1425234863225, + "z": 0.0 + }, + { + "x": 120.5266658825411, + "y": -195.14244177137294, + "z": 0.0 + }, + { + "x": 119.5210605046953, + "y": -195.14236005642337, + "z": 0.0 + }, + { + "x": 118.51545512684943, + "y": -195.1422783414738, + "z": 0.0 + }, + { + "x": 117.50984974900358, + "y": -195.14219662652422, + "z": 0.0 + }, + { + "x": 116.50424437115771, + "y": -195.14211491157465, + "z": 0.0 + }, + { + "x": 115.4986389933118, + "y": -195.1420331966251, + "z": 0.0 + }, + { + "x": 114.49303361546599, + "y": -195.14195148167553, + "z": 0.0 + }, + { + "x": 113.48742823762014, + "y": -195.14186976672596, + "z": 0.0 + }, + { + "x": 112.48182285977428, + "y": -195.1417880517764, + "z": 0.0 + }, + { + "x": 111.47621748192842, + "y": -195.14170633682681, + "z": 0.0 + }, + { + "x": 110.47061210408256, + "y": -195.14162462187724, + "z": 0.0 + }, + { + "x": 109.46500672623665, + "y": -195.1415429069277, + "z": 0.0 + }, + { + "x": 108.45940134839084, + "y": -195.14146119197812, + "z": 0.0 + }, + { + "x": 107.45379597054497, + "y": -195.14137947702855, + "z": 0.0 + }, + { + "x": 106.44819059269912, + "y": -195.14129776207898, + "z": 0.0 + }, + { + "x": 105.44258521485325, + "y": -195.1412160471294, + "z": 0.0 + }, + { + "x": 104.4369798370074, + "y": -195.14113433217983, + "z": 0.0 + }, + { + "x": 103.43137445916147, + "y": -195.1410526172303, + "z": 0.0 + }, + { + "x": 102.42576908131568, + "y": -195.1409709022807, + "z": 0.0 + }, + { + "x": 101.42016370346981, + "y": -195.14088918733114, + "z": 0.0 + } + ] + }, + { + "id": 64, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 101.4198386656325, + "y": -199.14088917412494, + "z": 0.0 + }, + { + "x": 102.42544404347836, + "y": -199.1409708890745, + "z": 0.0 + }, + { + "x": 103.43104942132427, + "y": -199.14105260402408, + "z": 0.0 + }, + { + "x": 104.43665479917009, + "y": -199.14113431897363, + "z": 0.0 + }, + { + "x": 105.44226017701594, + "y": -199.1412160339232, + "z": 0.0 + }, + { + "x": 106.4478655548618, + "y": -199.14129774887277, + "z": 0.0 + }, + { + "x": 107.45347093270766, + "y": -199.14137946382235, + "z": 0.0 + }, + { + "x": 108.45907631055353, + "y": -199.14146117877192, + "z": 0.0 + }, + { + "x": 109.46468168839942, + "y": -199.1415428937215, + "z": 0.0 + }, + { + "x": 110.47028706624525, + "y": -199.14162460867104, + "z": 0.0 + }, + { + "x": 111.4758924440911, + "y": -199.1417063236206, + "z": 0.0 + }, + { + "x": 112.48149782193697, + "y": -199.14178803857018, + "z": 0.0 + }, + { + "x": 113.48710319978282, + "y": -199.14186975351976, + "z": 0.0 + }, + { + "x": 114.49270857762868, + "y": -199.14195146846933, + "z": 0.0 + }, + { + "x": 115.4983139554746, + "y": -199.1420331834189, + "z": 0.0 + }, + { + "x": 116.5039193333204, + "y": -199.14211489836845, + "z": 0.0 + }, + { + "x": 117.50952471116626, + "y": -199.14219661331802, + "z": 0.0 + }, + { + "x": 118.51513008901212, + "y": -199.1422783282676, + "z": 0.0 + }, + { + "x": 119.52073546685799, + "y": -199.14236004321717, + "z": 0.0 + }, + { + "x": 120.5263408447039, + "y": -199.14244175816674, + "z": 0.0 + }, + { + "x": 121.5319462225497, + "y": -199.14252347311628, + "z": 0.0 + }, + { + "x": 122.53755160039556, + "y": -199.14260518806586, + "z": 0.0 + }, + { + "x": 123.54315697824141, + "y": -199.14268690301543, + "z": 0.0 + }, + { + "x": 124.54876235608728, + "y": -199.142768617965, + "z": 0.0 + }, + { + "x": 125.55436773393315, + "y": -199.14285033291458, + "z": 0.0 + }, + { + "x": 126.55997311177904, + "y": -199.14293204786415, + "z": 0.0 + }, + { + "x": 127.56557848962485, + "y": -199.1430137628137, + "z": 0.0 + }, + { + "x": 128.57118386747072, + "y": -199.14309547776327, + "z": 0.0 + }, + { + "x": 129.5767892453166, + "y": -199.14317719271284, + "z": 0.0 + }, + { + "x": 130.58239462316243, + "y": -199.1432589076624, + "z": 0.0 + }, + { + "x": 131.58800000100837, + "y": -199.143340622612, + "z": 0.0 + }, + { + "x": 132.59360537885414, + "y": -199.14342233756153, + "z": 0.0 + }, + { + "x": 133.59921075670002, + "y": -199.1435040525111, + "z": 0.0 + }, + { + "x": 134.6048161345459, + "y": -199.14358576746068, + "z": 0.0 + }, + { + "x": 135.61042151239172, + "y": -199.14366748241025, + "z": 0.0 + }, + { + "x": 136.6160268902376, + "y": -199.14374919735982, + "z": 0.0 + }, + { + "x": 137.62163226808354, + "y": -199.1438309123094, + "z": 0.0 + }, + { + "x": 138.6272376459293, + "y": -199.14391262725894, + "z": 0.0 + }, + { + "x": 139.6328430237752, + "y": -199.14399434220852, + "z": 0.0 + }, + { + "x": 140.63844840162108, + "y": -199.1440760571581, + "z": 0.0 + }, + { + "x": 141.6440537794669, + "y": -199.14415777210766, + "z": 0.0 + }, + { + "x": 142.64965915731278, + "y": -199.14423948705723, + "z": 0.0 + }, + { + "x": 143.65526453515872, + "y": -199.1443212020068, + "z": 0.0 + }, + { + "x": 144.6608699130045, + "y": -199.14440291695635, + "z": 0.0 + }, + { + "x": 145.66647529085037, + "y": -199.14448463190593, + "z": 0.0 + }, + { + "x": 146.67208066869625, + "y": -199.1445663468555, + "z": 0.0 + }, + { + "x": 147.67768604654208, + "y": -199.14464806180507, + "z": 0.0 + }, + { + "x": 148.68329142438802, + "y": -199.14472977675464, + "z": 0.0 + }, + { + "x": 149.68889680223384, + "y": -199.1448114917042, + "z": 0.0 + }, + { + "x": 150.69450218007967, + "y": -199.14489320665376, + "z": 0.0 + }, + { + "x": 151.70010755792555, + "y": -199.14497492160334, + "z": 0.0 + }, + { + "x": 152.70571293577143, + "y": -199.1450566365529, + "z": 0.0 + }, + { + "x": 153.71131831361726, + "y": -199.14513835150248, + "z": 0.0 + }, + { + "x": 154.7169236914632, + "y": -199.14522006645205, + "z": 0.0 + }, + { + "x": 155.72252906930902, + "y": -199.1453017814016, + "z": 0.0 + }, + { + "x": 156.72813444715484, + "y": -199.14538349635117, + "z": 0.0 + }, + { + "x": 157.73373982500073, + "y": -199.14546521130075, + "z": 0.0 + }, + { + "x": 158.7393452028466, + "y": -199.14554692625032, + "z": 0.0 + }, + { + "x": 159.7449505806925, + "y": -199.1456286411999, + "z": 0.0 + }, + { + "x": 160.75055595853837, + "y": -199.14571035614946, + "z": 0.0 + }, + { + "x": 161.7561613363842, + "y": -199.145792071099, + "z": 0.0 + }, + { + "x": 162.76176671423008, + "y": -199.14587378604858, + "z": 0.0 + }, + { + "x": 163.7673720920759, + "y": -199.14595550099816, + "z": 0.0 + }, + { + "x": 164.77297746992178, + "y": -199.14603721594773, + "z": 0.0 + }, + { + "x": 165.77858284776767, + "y": -199.1461189308973, + "z": 0.0 + }, + { + "x": 166.7841882256135, + "y": -199.14620064584685, + "z": 0.0 + }, + { + "x": 167.78979360345937, + "y": -199.14628236079642, + "z": 0.0 + }, + { + "x": 168.7953989813052, + "y": -199.146364075746, + "z": 0.0 + }, + { + "x": 169.80100435915108, + "y": -199.14644579069557, + "z": 0.0 + }, + { + "x": 170.80660973699696, + "y": -199.14652750564514, + "z": 0.0 + }, + { + "x": 171.81221511484284, + "y": -199.1466092205947, + "z": 0.0 + }, + { + "x": 172.81782049268867, + "y": -199.14669093554426, + "z": 0.0 + }, + { + "x": 173.82342587053455, + "y": -199.14677265049383, + "z": 0.0 + }, + { + "x": 174.82903124838037, + "y": -199.1468543654434, + "z": 0.0 + }, + { + "x": 175.83463662622626, + "y": -199.14693608039298, + "z": 0.0 + }, + { + "x": 176.8402420040722, + "y": -199.14701779534255, + "z": 0.0 + }, + { + "x": 177.84584738191796, + "y": -199.1470995102921, + "z": 0.0 + }, + { + "x": 178.85145275976384, + "y": -199.14718122524167, + "z": 0.0 + }, + { + "x": 179.85705813760973, + "y": -199.14726294019124, + "z": 0.0 + }, + { + "x": 180.8626635154556, + "y": -199.1473446551408, + "z": 0.0 + }, + { + "x": 181.86826889330143, + "y": -199.1474263700904, + "z": 0.0 + }, + { + "x": 182.87387427114737, + "y": -199.14750808503996, + "z": 0.0 + }, + { + "x": 183.8794796489932, + "y": -199.1475897999895, + "z": 0.0 + }, + { + "x": 184.88508502683902, + "y": -199.14767151493908, + "z": 0.0 + }, + { + "x": 185.8906904046849, + "y": -199.14775322988865, + "z": 0.0 + }, + { + "x": 186.89629578253079, + "y": -199.14783494483822, + "z": 0.0 + }, + { + "x": 187.9019011603766, + "y": -199.1479166597878, + "z": 0.0 + }, + { + "x": 188.90750653822255, + "y": -199.14799837473737, + "z": 0.0 + }, + { + "x": 189.91311191606837, + "y": -199.1480800896869, + "z": 0.0 + }, + { + "x": 190.9187172939142, + "y": -199.1481618046365, + "z": 0.0 + }, + { + "x": 191.92432267176008, + "y": -199.14824351958606, + "z": 0.0 + }, + { + "x": 192.92992804960596, + "y": -199.14832523453563, + "z": 0.0 + }, + { + "x": 193.93553342745184, + "y": -199.1484069494852, + "z": 0.0 + }, + { + "x": 194.94113880529767, + "y": -199.14848866443475, + "z": 0.0 + }, + { + "x": 195.94674418314355, + "y": -199.14857037938432, + "z": 0.0 + }, + { + "x": 196.95234956098938, + "y": -199.1486520943339, + "z": 0.0 + }, + { + "x": 197.95795493883526, + "y": -199.14873380928347, + "z": 0.0 + }, + { + "x": 198.96356031668114, + "y": -199.14881552423304, + "z": 0.0 + }, + { + "x": 199.96916569452702, + "y": -199.14889723918262, + "z": 0.0 + }, + { + "x": 200.97477107237285, + "y": -199.14897895413216, + "z": 0.0 + }, + { + "x": 201.98037645021873, + "y": -199.14906066908173, + "z": 0.0 + }, + { + "x": 202.98598182806455, + "y": -199.1491423840313, + "z": 0.0 + }, + { + "x": 203.99158720591043, + "y": -199.14922409898088, + "z": 0.0 + }, + { + "x": 204.99719258375632, + "y": -199.14930581393045, + "z": 0.0 + }, + { + "x": 206.0027979616022, + "y": -199.14938752888003, + "z": 0.0 + }, + { + "x": 207.00840333944802, + "y": -199.14946924382957, + "z": 0.0 + }, + { + "x": 208.0140087172939, + "y": -199.14955095877914, + "z": 0.0 + }, + { + "x": 209.01961409513973, + "y": -199.14963267372872, + "z": 0.0 + }, + { + "x": 210.0252194729856, + "y": -199.1497143886783, + "z": 0.0 + }, + { + "x": 211.03082485083155, + "y": -199.14979610362786, + "z": 0.0 + }, + { + "x": 212.03643022867732, + "y": -199.1498778185774, + "z": 0.0 + }, + { + "x": 213.0420356065232, + "y": -199.14995953352698, + "z": 0.0 + }, + { + "x": 214.04764098436908, + "y": -199.15004124847655, + "z": 0.0 + }, + { + "x": 215.0532463622149, + "y": -199.15012296342613, + "z": 0.0 + }, + { + "x": 216.0588517400608, + "y": -199.1502046783757, + "z": 0.0 + }, + { + "x": 217.06445711790673, + "y": -199.15028639332527, + "z": 0.0 + }, + { + "x": 218.07006249575255, + "y": -199.15036810827482, + "z": 0.0 + }, + { + "x": 219.07566787359838, + "y": -199.1504498232244, + "z": 0.0 + }, + { + "x": 220.08127325144426, + "y": -199.15053153817396, + "z": 0.0 + }, + { + "x": 221.08687862929014, + "y": -199.15061325312354, + "z": 0.0 + }, + { + "x": 222.09248400713602, + "y": -199.1506949680731, + "z": 0.0 + }, + { + "x": 223.09808938498185, + "y": -199.15077668302266, + "z": 0.0 + }, + { + "x": 224.10369476282773, + "y": -199.15085839797223, + "z": 0.0 + }, + { + "x": 225.10930014067355, + "y": -199.1509401129218, + "z": 0.0 + }, + { + "x": 226.11490551851944, + "y": -199.15102182787138, + "z": 0.0 + }, + { + "x": 227.12051089636532, + "y": -199.15110354282095, + "z": 0.0 + }, + { + "x": 228.1261162742112, + "y": -199.15118525777052, + "z": 0.0 + }, + { + "x": 229.13172165205702, + "y": -199.15126697272007, + "z": 0.0 + }, + { + "x": 230.1373270299029, + "y": -199.15134868766964, + "z": 0.0 + }, + { + "x": 231.14293240774873, + "y": -199.1514304026192, + "z": 0.0 + }, + { + "x": 232.1485377855946, + "y": -199.15151211756879, + "z": 0.0 + }, + { + "x": 233.1541431634405, + "y": -199.15159383251836, + "z": 0.0 + }, + { + "x": 234.15974854128638, + "y": -199.15167554746793, + "z": 0.0 + }, + { + "x": 235.1653539191322, + "y": -199.15175726241748, + "z": 0.0 + }, + { + "x": 236.17095929697808, + "y": -199.15183897736705, + "z": 0.0 + }, + { + "x": 237.1765646748239, + "y": -199.15192069231662, + "z": 0.0 + }, + { + "x": 238.1821700526698, + "y": -199.1520024072662, + "z": 0.0 + }, + { + "x": 239.18777543051573, + "y": -199.15208412221577, + "z": 0.0 + }, + { + "x": 240.19338080836155, + "y": -199.1521658371653, + "z": 0.0 + }, + { + "x": 241.19898618620738, + "y": -199.1522475521149, + "z": 0.0 + }, + { + "x": 242.20459156405326, + "y": -199.15232926706446, + "z": 0.0 + }, + { + "x": 243.21019694189914, + "y": -199.15241098201403, + "z": 0.0 + }, + { + "x": 244.21580231974497, + "y": -199.1524926969636, + "z": 0.0 + }, + { + "x": 245.2214076975909, + "y": -199.15257441191318, + "z": 0.0 + }, + { + "x": 246.22701307543673, + "y": -199.15265612686272, + "z": 0.0 + }, + { + "x": 247.23261845328256, + "y": -199.1527378418123, + "z": 0.0 + }, + { + "x": 248.23822383112844, + "y": -199.15281955676187, + "z": 0.0 + }, + { + "x": 249.24382920897432, + "y": -199.15290127171144, + "z": 0.0 + }, + { + "x": 250.24943458682014, + "y": -199.15298298666102, + "z": 0.0 + }, + { + "x": 251.25503996466608, + "y": -199.1530647016106, + "z": 0.0 + }, + { + "x": 252.2606453425119, + "y": -199.15314641656013, + "z": 0.0 + }, + { + "x": 253.26625072035773, + "y": -199.1532281315097, + "z": 0.0 + }, + { + "x": 254.2718560982036, + "y": -199.15330984645928, + "z": 0.0 + }, + { + "x": 255.2774614760495, + "y": -199.15339156140885, + "z": 0.0 + }, + { + "x": 256.2830668538954, + "y": -199.15347327635843, + "z": 0.0 + }, + { + "x": 257.28867223174115, + "y": -199.15355499130797, + "z": 0.0 + }, + { + "x": 258.294277609587, + "y": -199.15363670625754, + "z": 0.0 + }, + { + "x": 259.2998829874329, + "y": -199.15371842120712, + "z": 0.0 + }, + { + "x": 260.3054883652788, + "y": -199.1538001361567, + "z": 0.0 + }, + { + "x": 261.3110937431247, + "y": -199.15388185110626, + "z": 0.0 + }, + { + "x": 262.31669912097055, + "y": -199.15396356605584, + "z": 0.0 + }, + { + "x": 263.3223044988164, + "y": -199.15404528100538, + "z": 0.0 + }, + { + "x": 264.3279098766622, + "y": -199.15412699595495, + "z": 0.0 + }, + { + "x": 265.3335152545081, + "y": -199.15420871090453, + "z": 0.0 + }, + { + "x": 266.33912063235397, + "y": -199.1542904258541, + "z": 0.0 + }, + { + "x": 267.3447260101999, + "y": -199.15437214080367, + "z": 0.0 + }, + { + "x": 268.3503313880457, + "y": -199.15445385575322, + "z": 0.0 + }, + { + "x": 269.35593676589156, + "y": -199.1545355707028, + "z": 0.0 + }, + { + "x": 270.3615421437374, + "y": -199.15461728565236, + "z": 0.0 + }, + { + "x": 271.36714752158326, + "y": -199.15469900060194, + "z": 0.0 + }, + { + "x": 272.37275289942914, + "y": -199.1547807155515, + "z": 0.0 + }, + { + "x": 273.3783582772751, + "y": -199.15486243050108, + "z": 0.0 + }, + { + "x": 274.38396365512085, + "y": -199.15494414545063, + "z": 0.0 + }, + { + "x": 275.38956903296673, + "y": -199.1550258604002, + "z": 0.0 + }, + { + "x": 276.39517441081256, + "y": -199.15510757534977, + "z": 0.0 + }, + { + "x": 277.40077978865844, + "y": -199.15518929029935, + "z": 0.0 + }, + { + "x": 278.4063851665043, + "y": -199.15527100524892, + "z": 0.0 + }, + { + "x": 279.41199054435026, + "y": -199.1553527201985, + "z": 0.0 + }, + { + "x": 280.4175959221961, + "y": -199.15543443514804, + "z": 0.0 + }, + { + "x": 281.4232013000419, + "y": -199.1555161500976, + "z": 0.0 + }, + { + "x": 282.42880667788774, + "y": -199.15559786504718, + "z": 0.0 + }, + { + "x": 283.4344120557336, + "y": -199.15567957999676, + "z": 0.0 + }, + { + "x": 284.44001743357956, + "y": -199.15576129494633, + "z": 0.0 + }, + { + "x": 285.4456228114254, + "y": -199.15584300989588, + "z": 0.0 + }, + { + "x": 286.45122818927126, + "y": -199.15592472484545, + "z": 0.0 + }, + { + "x": 287.4568335671171, + "y": -199.15600643979502, + "z": 0.0 + }, + { + "x": 288.4624389449629, + "y": -199.1560881547446, + "z": 0.0 + }, + { + "x": 289.4680443228088, + "y": -199.15616986969417, + "z": 0.0 + }, + { + "x": 290.47364970065473, + "y": -199.15625158464374, + "z": 0.0 + }, + { + "x": 291.47925507850056, + "y": -199.15633329959329, + "z": 0.0 + }, + { + "x": 292.48486045634644, + "y": -199.15641501454286, + "z": 0.0 + }, + { + "x": 293.49046583419226, + "y": -199.15649672949243, + "z": 0.0 + }, + { + "x": 294.49607121203815, + "y": -199.156578444442, + "z": 0.0 + }, + { + "x": 295.50167658988397, + "y": -199.15666015939158, + "z": 0.0 + }, + { + "x": 296.5072819677299, + "y": -199.15674187434115, + "z": 0.0 + }, + { + "x": 297.51288734557573, + "y": -199.1568235892907, + "z": 0.0 + }, + { + "x": 298.5184927234216, + "y": -199.15690530424027, + "z": 0.0 + }, + { + "x": 299.52409810126744, + "y": -199.15698701918984, + "z": 0.0 + }, + { + "x": 300.5297034791133, + "y": -199.15706873413941, + "z": 0.0 + }, + { + "x": 301.5353088569592, + "y": -199.157150449089, + "z": 0.0 + }, + { + "x": 302.54091423480503, + "y": -199.15723216403853, + "z": 0.0 + }, + { + "x": 303.5465196126509, + "y": -199.1573138789881, + "z": 0.0 + }, + { + "x": 304.5521249904968, + "y": -199.15739559393768, + "z": 0.0 + }, + { + "x": 305.5577303683426, + "y": -199.15747730888725, + "z": 0.0 + }, + { + "x": 306.5633357461885, + "y": -199.15755902383682, + "z": 0.0 + }, + { + "x": 307.5689411240344, + "y": -199.1576407387864, + "z": 0.0 + }, + { + "x": 308.5745465018802, + "y": -199.15772245373594, + "z": 0.0 + }, + { + "x": 309.5801518797261, + "y": -199.15780416868552, + "z": 0.0 + }, + { + "x": 310.58575725757197, + "y": -199.1578858836351, + "z": 0.0 + }, + { + "x": 311.5913626354178, + "y": -199.15796759858466, + "z": 0.0 + }, + { + "x": 312.59696801326373, + "y": -199.15804931353424, + "z": 0.0 + }, + { + "x": 313.6025733911095, + "y": -199.15813102848378, + "z": 0.0 + }, + { + "x": 314.6081787689554, + "y": -199.15821274343335, + "z": 0.0 + }, + { + "x": 315.61378414680127, + "y": -199.15829445838293, + "z": 0.0 + }, + { + "x": 316.61938952464715, + "y": -199.1583761733325, + "z": 0.0 + }, + { + "x": 317.62499490249303, + "y": -199.15845788828207, + "z": 0.0 + }, + { + "x": 318.6306002803389, + "y": -199.15853960323165, + "z": 0.0 + }, + { + "x": 319.6362056581847, + "y": -199.1586213181812, + "z": 0.0 + }, + { + "x": 320.64181103603056, + "y": -199.15870303313076, + "z": 0.0 + }, + { + "x": 321.64741641387644, + "y": -199.15878474808034, + "z": 0.0 + }, + { + "x": 322.6530217917223, + "y": -199.1588664630299, + "z": 0.0 + }, + { + "x": 323.6586271695682, + "y": -199.15894817797948, + "z": 0.0 + }, + { + "x": 324.6642325474141, + "y": -199.15902989292906, + "z": 0.0 + }, + { + "x": 325.66983792525997, + "y": -199.1591116078786, + "z": 0.0 + } + ] + }, + { + "id": 65, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 11.028342463475031, + "y": 4.019999671866976, + "z": 0.0 + }, + { + "x": 9.953070070668474, + "y": 4.019649230031031, + "z": 0.0 + }, + { + "x": 8.800612790358642, + "y": 3.9976050577194115, + "z": 0.0 + }, + { + "x": 7.459285666338035, + "y": 3.8888366999628543, + "z": 0.0 + }, + { + "x": 5.97521383867693, + "y": 3.6174579798610065, + "z": 0.0 + }, + { + "x": 4.528719668379331, + "y": 3.186406110896411, + "z": 0.0 + }, + { + "x": 3.113186224320456, + "y": 2.5812645029885717, + "z": 0.0 + }, + { + "x": 1.7875954122404156, + "y": 1.8263279175440637, + "z": 0.0 + }, + { + "x": 0.5663901916985239, + "y": 0.9406644934610671, + "z": 0.0 + }, + { + "x": -0.590244979393741, + "y": -0.13645072900332167, + "z": 0.0 + }, + { + "x": -1.5775183083072448, + "y": -1.299702319737953, + "z": 0.0 + }, + { + "x": -2.4352046366311417, + "y": -2.593825751303942, + "z": 0.0 + }, + { + "x": -3.148498396979441, + "y": -4.074152675533871, + "z": 0.0 + }, + { + "x": -3.6444600059072725, + "y": -5.6604724247747775, + "z": 0.0 + }, + { + "x": -3.9150557372144608, + "y": -7.187614391929258, + "z": 0.0 + }, + { + "x": -4.022155975422126, + "y": -8.641040654230935, + "z": 0.0 + }, + { + "x": -4.02999970255904, + "y": -9.958459206173217, + "z": 0.0 + } + ] + }, + { + "id": 66, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 3.969999703900145, + "y": -9.961540870120729, + "z": 0.0 + }, + { + "x": 3.962984383848893, + "y": -9.128414681791984, + "z": 0.0 + }, + { + "x": 3.9868029716624225, + "y": -8.436865745719414, + "z": 0.0 + }, + { + "x": 4.050850939410168, + "y": -7.847294195033525, + "z": 0.0 + }, + { + "x": 4.141788106296348, + "y": -7.368347979421437, + "z": 0.0 + }, + { + "x": 4.314033709673633, + "y": -6.8889138464155195, + "z": 0.0 + }, + { + "x": 4.6087026679026915, + "y": -6.37224310651337, + "z": 0.0 + }, + { + "x": 4.980163347792317, + "y": -5.878449602950986, + "z": 0.0 + }, + { + "x": 5.364000502351587, + "y": -5.46112707664768, + "z": 0.0 + }, + { + "x": 5.8620495302655184, + "y": -5.058352441057074, + "z": 0.0 + }, + { + "x": 6.386402842845939, + "y": -4.718465147362091, + "z": 0.0 + }, + { + "x": 6.933168944995435, + "y": -4.443706842145653, + "z": 0.0 + }, + { + "x": 7.537298805651212, + "y": -4.228553144012891, + "z": 0.0 + }, + { + "x": 8.160644969253037, + "y": -4.0803599426238115, + "z": 0.0 + }, + { + "x": 8.958862123970693, + "y": -4.000829610914904, + "z": 0.0 + }, + { + "x": 9.955677349119426, + "y": -3.980350345100149, + "z": 0.0 + }, + { + "x": 11.030949741925983, + "y": -3.9799999032642037, + "z": 0.0 + } + ] + }, + { + "id": 67, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": -0.029999999329447746, + "y": -9.960000038146973, + "z": 0.0 + }, + { + "x": -0.029585795786616468, + "y": -8.88472766801146, + "z": 0.0 + }, + { + "x": 0.035873617223980664, + "y": -7.8122400688243365, + "z": 0.0 + }, + { + "x": 0.2031954667514479, + "y": -6.753883309904151, + "z": 0.0 + }, + { + "x": 0.4966448546584533, + "y": -5.721250327477654, + "z": 0.0 + }, + { + "x": 0.9394145365212455, + "y": -4.741369798859731, + "z": 0.0 + }, + { + "x": 1.5155921797977234, + "y": -3.8359727131256616, + "z": 0.0 + }, + { + "x": 2.1949591841992877, + "y": -3.0074501659771538, + "z": 0.0 + }, + { + "x": 2.9651953470250554, + "y": -2.2602312915933065, + "z": 0.0 + }, + { + "x": 3.824822471252967, + "y": -1.6160122617565051, + "z": 0.0 + }, + { + "x": 4.749794533583198, + "y": -1.0686003221867595, + "z": 0.0 + }, + { + "x": 5.730944306687383, + "y": -0.6286503656246212, + "z": 0.0 + }, + { + "x": 6.756256322164071, + "y": -0.3055475820759422, + "z": 0.0 + }, + { + "x": 7.809965317795536, + "y": -0.09576162133047841, + "z": 0.0 + }, + { + "x": 8.879737457164667, + "y": -0.0016122765977463205, + "z": 0.0 + }, + { + "x": 9.95437370989395, + "y": 0.01964944246544118, + "z": 0.0 + }, + { + "x": 11.029646102700507, + "y": 0.019999884301386054, + "z": 0.0 + } + ] + }, + { + "id": 68, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 11.02899428308777, + "y": 2.019999778084181, + "z": 0.0 + }, + { + "x": 9.953721890281212, + "y": 2.019649336248236, + "z": 0.0 + }, + { + "x": 8.840175123761654, + "y": 1.9979963905608327, + "z": 0.0 + }, + { + "x": 7.634625492066785, + "y": 1.8965375393161878, + "z": 0.0 + }, + { + "x": 6.3657350804205, + "y": 1.655955198892532, + "z": 0.0 + }, + { + "x": 5.129831987533358, + "y": 1.278877872635895, + "z": 0.0 + }, + { + "x": 3.931490378951827, + "y": 0.7563320904009061, + "z": 0.0 + }, + { + "x": 2.806208941746691, + "y": 0.10515782789377925, + "z": 0.0 + }, + { + "x": 1.7657927693617896, + "y": -0.6597833990661197, + "z": 0.0 + }, + { + "x": 0.8023571024027734, + "y": -1.5719504474902377, + "z": 0.0 + }, + { + "x": -0.030963064254760697, + "y": -2.5678375164318075, + "z": 0.0 + }, + { + "x": -0.7478950500549482, + "y": -3.6675977750818367, + "z": 0.0 + }, + { + "x": -1.3259267711604938, + "y": -4.897701501505763, + "z": 0.0 + }, + { + "x": -1.7206322695779124, + "y": -6.207177867339464, + "z": 0.0 + }, + { + "x": -1.93959105999524, + "y": -7.499927230376797, + "z": 0.0 + }, + { + "x": -2.025870885604371, + "y": -8.762884161121196, + "z": 0.0 + }, + { + "x": -2.029999850944244, + "y": -9.959229622160095, + "z": 0.0 + } + ] + }, + { + "id": 69, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 1.9699998522853486, + "y": -9.96077045413385, + "z": 0.0 + }, + { + "x": 1.9666992940311383, + "y": -9.006571174901723, + "z": 0.0 + }, + { + "x": 2.0113382944432017, + "y": -8.124552907271875, + "z": 0.0 + }, + { + "x": 2.127023203080808, + "y": -7.300588752468839, + "z": 0.0 + }, + { + "x": 2.3192164804774005, + "y": -6.544799153449546, + "z": 0.0 + }, + { + "x": 2.626724123097439, + "y": -5.815141822637625, + "z": 0.0 + }, + { + "x": 3.0621474238502073, + "y": -5.104107909819516, + "z": 0.0 + }, + { + "x": 3.5875612659958023, + "y": -4.44294988446407, + "z": 0.0 + }, + { + "x": 4.164597924688321, + "y": -3.8606791841204933, + "z": 0.0 + }, + { + "x": 4.843436000759243, + "y": -3.3371823514067893, + "z": 0.0 + }, + { + "x": 5.568098688214569, + "y": -2.893532734774425, + "z": 0.0 + }, + { + "x": 6.332056625841409, + "y": -2.536178603885137, + "z": 0.0 + }, + { + "x": 7.146777563907642, + "y": -2.2670503630444165, + "z": 0.0 + }, + { + "x": 7.985305143524286, + "y": -2.088060781977145, + "z": 0.0 + }, + { + "x": 8.919299790567681, + "y": -2.001220943756325, + "z": 0.0 + }, + { + "x": 9.955025529506688, + "y": -1.980350451317354, + "z": 0.0 + }, + { + "x": 11.030297922313245, + "y": -1.9800000094814088, + "z": 0.0 + } + ] + }, + { + "id": 70, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 384.1736658134914, + "y": -332.60889681208965, + "z": 0.0 + }, + { + "x": 385.2643279115696, + "y": -332.58344691864033, + "z": 0.0 + }, + { + "x": 386.62477890205395, + "y": -332.46711385713115, + "z": 0.0 + }, + { + "x": 388.11199738649975, + "y": -332.1915900435458, + "z": 0.0 + }, + { + "x": 389.56266099323636, + "y": -331.7604566938843, + "z": 0.0 + }, + { + "x": 390.99555684282876, + "y": -331.1497265885555, + "z": 0.0 + }, + { + "x": 392.32475767360006, + "y": -330.39944230918036, + "z": 0.0 + }, + { + "x": 393.55519954086054, + "y": -329.5203187020522, + "z": 0.0 + }, + { + "x": 394.7013785390999, + "y": -328.49147913981506, + "z": 0.0 + }, + { + "x": 395.7435380994426, + "y": -327.29875989133785, + "z": 0.0 + }, + { + "x": 396.6346132755301, + "y": -325.97213713418074, + "z": 0.0 + }, + { + "x": 397.34968153032514, + "y": -324.5427275788562, + "z": 0.0 + }, + { + "x": 397.8771365105912, + "y": -323.0335278027845, + "z": 0.0 + }, + { + "x": 398.2083233275286, + "y": -321.4688127703625, + "z": 0.0 + }, + { + "x": 398.34184677749806, + "y": -319.89331026646045, + "z": 0.0 + }, + { + "x": 398.35000580137364, + "y": -318.5384233132525, + "z": 0.0 + } + ] + }, + { + "id": 71, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 390.3500064056576, + "y": -318.541532741435, + "z": 0.0 + }, + { + "x": 390.35901385763646, + "y": -319.36949868433095, + "z": 0.0 + }, + { + "x": 390.3496352343571, + "y": -319.97180861063424, + "z": 0.0 + }, + { + "x": 390.27293211969754, + "y": -320.54835666551554, + "z": 0.0 + }, + { + "x": 390.123631148747, + "y": -321.1099159203329, + "z": 0.0 + }, + { + "x": 389.9042235497951, + "y": -321.64757309375756, + "z": 0.0 + }, + { + "x": 389.61826346121734, + "y": -322.15278956434275, + "z": 0.0 + }, + { + "x": 389.259771012167, + "y": -322.62727352244224, + "z": 0.0 + }, + { + "x": 388.8089051340767, + "y": -323.0803894008771, + "z": 0.0 + }, + { + "x": 388.2842881070022, + "y": -323.4947623251842, + "z": 0.0 + }, + { + "x": 387.7306371533386, + "y": -323.84628223529455, + "z": 0.0 + }, + { + "x": 387.1707397701482, + "y": -324.1264071222257, + "z": 0.0 + }, + { + "x": 386.53881093627876, + "y": -324.34779731344116, + "z": 0.0 + }, + { + "x": 385.8877456964572, + "y": -324.5011373285537, + "z": 0.0 + }, + { + "x": 385.0777038952716, + "y": -324.585623997586, + "z": 0.0 + }, + { + "x": 383.98704179719346, + "y": -324.61107389103535, + "z": 0.0 + } + ] + }, + { + "id": 72, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 394.3500061035156, + "y": -318.53997802734375, + "z": 0.0 + }, + { + "x": 394.35043031756726, + "y": -319.6314044753957, + "z": 0.0 + }, + { + "x": 394.27897928094285, + "y": -320.72031069049837, + "z": 0.0 + }, + { + "x": 394.07503431514436, + "y": -321.79094223415, + "z": 0.0 + }, + { + "x": 393.73665633953607, + "y": -322.82632174959457, + "z": 0.0 + }, + { + "x": 393.2694184126626, + "y": -323.80985511396915, + "z": 0.0 + }, + { + "x": 392.68090078033, + "y": -324.7257747278403, + "z": 0.0 + }, + { + "x": 391.98057477563344, + "y": -325.55937633112865, + "z": 0.0 + }, + { + "x": 391.18205233746863, + "y": -326.30035405146464, + "z": 0.0 + }, + { + "x": 390.30452289030114, + "y": -326.94710231718227, + "z": 0.0 + }, + { + "x": 389.3630969980837, + "y": -327.498004411925, + "z": 0.0 + }, + { + "x": 388.3667003816923, + "y": -327.943431908055, + "z": 0.0 + }, + { + "x": 387.32540416138926, + "y": -328.26969367849347, + "z": 0.0 + }, + { + "x": 386.2562622992556, + "y": -328.4841255928424, + "z": 0.0 + }, + { + "x": 385.1710159034206, + "y": -328.5845354581132, + "z": 0.0 + }, + { + "x": 384.08035380534244, + "y": -328.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 73, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 384.1270098094169, + "y": -330.60944108182605, + "z": 0.0 + }, + { + "x": 385.21767190749506, + "y": -330.5839911883768, + "z": 0.0 + }, + { + "x": 386.44052060065474, + "y": -330.4756197249868, + "z": 0.0 + }, + { + "x": 387.71870077394453, + "y": -330.23064186101965, + "z": 0.0 + }, + { + "x": 388.96468068746435, + "y": -329.85194430096965, + "z": 0.0 + }, + { + "x": 390.1793269204562, + "y": -329.32386550024023, + "z": 0.0 + }, + { + "x": 391.3146402819506, + "y": -328.6732723131813, + "z": 0.0 + }, + { + "x": 392.3686259391646, + "y": -327.91033637675844, + "z": 0.0 + }, + { + "x": 393.3409766573667, + "y": -327.02542773547185, + "z": 0.0 + }, + { + "x": 394.2122194398863, + "y": -326.0122673095891, + "z": 0.0 + }, + { + "x": 394.95201584409637, + "y": -324.89099612407495, + "z": 0.0 + }, + { + "x": 395.5431689349306, + "y": -323.68452466422536, + "z": 0.0 + }, + { + "x": 395.97608541286775, + "y": -322.41223501846724, + "z": 0.0 + }, + { + "x": 396.24365130423575, + "y": -321.0945617304304, + "z": 0.0 + }, + { + "x": 396.34613854753263, + "y": -319.76235737092804, + "z": 0.0 + }, + { + "x": 396.35000595244463, + "y": -318.5392006702981, + "z": 0.0 + } + ] + }, + { + "id": 74, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 392.3500062545866, + "y": -318.5407553843894, + "z": 0.0 + }, + { + "x": 392.3547220876019, + "y": -319.50045157986335, + "z": 0.0 + }, + { + "x": 392.31430725764994, + "y": -320.3460596505663, + "z": 0.0 + }, + { + "x": 392.173983217421, + "y": -321.1696494498328, + "z": 0.0 + }, + { + "x": 391.93014374414156, + "y": -321.9681188349638, + "z": 0.0 + }, + { + "x": 391.58682098122887, + "y": -322.72871410386335, + "z": 0.0 + }, + { + "x": 391.14958212077363, + "y": -323.4392821460915, + "z": 0.0 + }, + { + "x": 390.6201728939002, + "y": -324.09332492678544, + "z": 0.0 + }, + { + "x": 389.9954787357727, + "y": -324.69037172617084, + "z": 0.0 + }, + { + "x": 389.2944054986517, + "y": -325.2209323211832, + "z": 0.0 + }, + { + "x": 388.54686707571113, + "y": -325.6721433236098, + "z": 0.0 + }, + { + "x": 387.7687200759202, + "y": -326.03491951514036, + "z": 0.0 + }, + { + "x": 386.932107548834, + "y": -326.3087454959673, + "z": 0.0 + }, + { + "x": 386.0720039978564, + "y": -326.492631460698, + "z": 0.0 + }, + { + "x": 385.12435989934613, + "y": -326.5850797278496, + "z": 0.0 + }, + { + "x": 384.033697801268, + "y": -326.61052962129895, + "z": 0.0 + } + ] + }, + { + "id": 75, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 4.009999965684669, + "y": -317.6005283434444, + "z": 0.0 + }, + { + "x": 4.010130803211286, + "y": -316.59844355295434, + "z": 0.0 + }, + { + "x": 4.0102616407379035, + "y": -315.59635876246426, + "z": 0.0 + }, + { + "x": 4.010392478264521, + "y": -314.5942739719742, + "z": 0.0 + }, + { + "x": 4.010523315791139, + "y": -313.5921891814841, + "z": 0.0 + }, + { + "x": 4.010654153317756, + "y": -312.59010439099404, + "z": 0.0 + }, + { + "x": 4.010784990844374, + "y": -311.58801960050397, + "z": 0.0 + }, + { + "x": 4.010915828370991, + "y": -310.5859348100139, + "z": 0.0 + }, + { + "x": 4.0110466658976085, + "y": -309.5838500195239, + "z": 0.0 + }, + { + "x": 4.011177503424226, + "y": -308.5817652290338, + "z": 0.0 + }, + { + "x": 4.011308340950843, + "y": -307.57968043854373, + "z": 0.0 + }, + { + "x": 4.0114391784774615, + "y": -306.57759564805366, + "z": 0.0 + }, + { + "x": 4.011570016004079, + "y": -305.5755108575636, + "z": 0.0 + }, + { + "x": 4.011700853530696, + "y": -304.5734260670735, + "z": 0.0 + }, + { + "x": 4.0118316910573135, + "y": -303.57134127658344, + "z": 0.0 + }, + { + "x": 4.011962528583931, + "y": -302.5692564860934, + "z": 0.0 + }, + { + "x": 4.012093366110548, + "y": -301.56717169560335, + "z": 0.0 + }, + { + "x": 4.012224203637166, + "y": -300.5650869051133, + "z": 0.0 + }, + { + "x": 4.012355041163783, + "y": -299.5630021146232, + "z": 0.0 + }, + { + "x": 4.012485878690401, + "y": -298.56091732413313, + "z": 0.0 + }, + { + "x": 4.0126167162170185, + "y": -297.55883253364306, + "z": 0.0 + }, + { + "x": 4.012747553743636, + "y": -296.556747743153, + "z": 0.0 + }, + { + "x": 4.012878391270253, + "y": -295.5546629526629, + "z": 0.0 + }, + { + "x": 4.013009228796871, + "y": -294.55257816217284, + "z": 0.0 + }, + { + "x": 4.013140066323488, + "y": -293.5504933716828, + "z": 0.0 + }, + { + "x": 4.013270903850105, + "y": -292.54840858119275, + "z": 0.0 + }, + { + "x": 4.013401741376724, + "y": -291.5463237907027, + "z": 0.0 + }, + { + "x": 4.013532578903341, + "y": -290.5442390002126, + "z": 0.0 + }, + { + "x": 4.013663416429958, + "y": -289.5421542097225, + "z": 0.0 + }, + { + "x": 4.013794253956576, + "y": -288.54006941923245, + "z": 0.0 + }, + { + "x": 4.013925091483193, + "y": -287.5379846287424, + "z": 0.0 + }, + { + "x": 4.01405592900981, + "y": -286.5358998382523, + "z": 0.0 + }, + { + "x": 4.014186766536428, + "y": -285.53381504776223, + "z": 0.0 + }, + { + "x": 4.014317604063046, + "y": -284.53173025727216, + "z": 0.0 + }, + { + "x": 4.014448441589663, + "y": -283.5296454667821, + "z": 0.0 + }, + { + "x": 4.014579279116281, + "y": -282.527560676292, + "z": 0.0 + }, + { + "x": 4.014710116642898, + "y": -281.52547588580194, + "z": 0.0 + }, + { + "x": 4.014840954169515, + "y": -280.52339109531187, + "z": 0.0 + }, + { + "x": 4.014971791696133, + "y": -279.5213063048218, + "z": 0.0 + }, + { + "x": 4.01510262922275, + "y": -278.5192215143317, + "z": 0.0 + }, + { + "x": 4.015233466749367, + "y": -277.5171367238417, + "z": 0.0 + }, + { + "x": 4.015364304275986, + "y": -276.51505193335163, + "z": 0.0 + }, + { + "x": 4.015495141802603, + "y": -275.51296714286156, + "z": 0.0 + }, + { + "x": 4.01562597932922, + "y": -274.5108823523715, + "z": 0.0 + }, + { + "x": 4.015756816855838, + "y": -273.5087975618814, + "z": 0.0 + }, + { + "x": 4.015887654382455, + "y": -272.50671277139134, + "z": 0.0 + }, + { + "x": 4.0160184919090725, + "y": -271.50462798090126, + "z": 0.0 + }, + { + "x": 4.01614932943569, + "y": -270.50254319041125, + "z": 0.0 + }, + { + "x": 4.016280166962308, + "y": -269.5004583999212, + "z": 0.0 + }, + { + "x": 4.016411004488925, + "y": -268.4983736094311, + "z": 0.0 + }, + { + "x": 4.016541842015543, + "y": -267.496288818941, + "z": 0.0 + }, + { + "x": 4.01667267954216, + "y": -266.49420402845095, + "z": 0.0 + }, + { + "x": 4.0168035170687775, + "y": -265.4921192379609, + "z": 0.0 + }, + { + "x": 4.016934354595395, + "y": -264.49003444747086, + "z": 0.0 + }, + { + "x": 4.017065192122012, + "y": -263.48794965698085, + "z": 0.0 + }, + { + "x": 4.0171960296486295, + "y": -262.4858648664908, + "z": 0.0 + }, + { + "x": 4.017326867175248, + "y": -261.48378007600076, + "z": 0.0 + }, + { + "x": 4.017457704701865, + "y": -260.48169528551074, + "z": 0.0 + }, + { + "x": 4.0175885422284825, + "y": -259.47961049502067, + "z": 0.0 + }, + { + "x": 4.0177193797551, + "y": -258.47752570453065, + "z": 0.0 + }, + { + "x": 4.017850217281717, + "y": -257.4754409140406, + "z": 0.0 + }, + { + "x": 4.017981054808335, + "y": -256.4733561235505, + "z": 0.0 + }, + { + "x": 4.018111892334951, + "y": -255.4712713330605, + "z": 0.0 + }, + { + "x": 4.018242729861569, + "y": -254.46918654257047, + "z": 0.0 + }, + { + "x": 4.018373567388187, + "y": -253.46710175208042, + "z": 0.0 + }, + { + "x": 4.018504404914805, + "y": -252.4650169615904, + "z": 0.0 + }, + { + "x": 4.018635242441421, + "y": -251.46293217110036, + "z": 0.0 + }, + { + "x": 4.018766079968039, + "y": -250.46084738061032, + "z": 0.0 + }, + { + "x": 4.018896917494656, + "y": -249.45876259012027, + "z": 0.0 + }, + { + "x": 4.019027755021273, + "y": -248.45667779963023, + "z": 0.0 + }, + { + "x": 4.019158592547892, + "y": -247.4545930091402, + "z": 0.0 + }, + { + "x": 4.01928943007451, + "y": -246.45250821865014, + "z": 0.0 + }, + { + "x": 4.019420267601126, + "y": -245.4504234281601, + "z": 0.0 + }, + { + "x": 4.019551105127745, + "y": -244.44833863767008, + "z": 0.0 + }, + { + "x": 4.019681942654361, + "y": -243.44625384718003, + "z": 0.0 + }, + { + "x": 4.019812780180978, + "y": -242.44416905669, + "z": 0.0 + }, + { + "x": 4.019943617707596, + "y": -241.44208426619994, + "z": 0.0 + }, + { + "x": 4.0197019046914795, + "y": -240.4385127574555, + "z": 0.0 + }, + { + "x": 4.019178091099026, + "y": -239.43530342597631, + "z": 0.0 + }, + { + "x": 4.018654706806054, + "y": -238.43321876362546, + "z": 0.0 + }, + { + "x": 4.018131322513082, + "y": -237.4311341012746, + "z": 0.0 + }, + { + "x": 4.0176079382201095, + "y": -236.42904943892378, + "z": 0.0 + }, + { + "x": 4.017084553927138, + "y": -235.42696477657293, + "z": 0.0 + }, + { + "x": 4.016561169634166, + "y": -234.42488011422208, + "z": 0.0 + }, + { + "x": 4.016037785341194, + "y": -233.42279545187122, + "z": 0.0 + }, + { + "x": 4.015514401048222, + "y": -232.42071078952037, + "z": 0.0 + }, + { + "x": 4.01499101675525, + "y": -231.41862612716957, + "z": 0.0 + }, + { + "x": 4.014467632462277, + "y": -230.41654146481872, + "z": 0.0 + }, + { + "x": 4.013944248169305, + "y": -229.41445680246787, + "z": 0.0 + }, + { + "x": 4.013420863876333, + "y": -228.41237214011704, + "z": 0.0 + }, + { + "x": 4.012897479583361, + "y": -227.4102874777662, + "z": 0.0 + }, + { + "x": 4.012374095290389, + "y": -226.40820281541534, + "z": 0.0 + }, + { + "x": 4.011850710997417, + "y": -225.40611815306448, + "z": 0.0 + }, + { + "x": 4.0113273267044445, + "y": -224.40403349071363, + "z": 0.0 + }, + { + "x": 4.0108039424114725, + "y": -223.4019488283628, + "z": 0.0 + }, + { + "x": 4.010280558118501, + "y": -222.39986416601195, + "z": 0.0 + }, + { + "x": 4.009757173825529, + "y": -221.3977795036611, + "z": 0.0 + }, + { + "x": 4.009233789532557, + "y": -220.39569484131027, + "z": 0.0 + }, + { + "x": 4.008710405239585, + "y": -219.39361017895945, + "z": 0.0 + }, + { + "x": 4.008187020946612, + "y": -218.3915255166086, + "z": 0.0 + }, + { + "x": 4.00766363665364, + "y": -217.38944085425774, + "z": 0.0 + }, + { + "x": 4.007140252360668, + "y": -216.3873561919069, + "z": 0.0 + }, + { + "x": 4.006616868067696, + "y": -215.38527152955606, + "z": 0.0 + }, + { + "x": 4.006093483774724, + "y": -214.3831868672052, + "z": 0.0 + }, + { + "x": 4.005570099481752, + "y": -213.38110220485436, + "z": 0.0 + }, + { + "x": 4.005046715188779, + "y": -212.37901754250353, + "z": 0.0 + }, + { + "x": 4.0045233308958075, + "y": -211.37693288015268, + "z": 0.0 + }, + { + "x": 4.0039999466028355, + "y": -210.37484821780183, + "z": 0.0 + }, + { + "x": 4.003476562309864, + "y": -209.37276355545097, + "z": 0.0 + }, + { + "x": 4.002953178016892, + "y": -208.37067889310012, + "z": 0.0 + }, + { + "x": 4.002429793723919, + "y": -207.3685942307493, + "z": 0.0 + }, + { + "x": 4.001906409430947, + "y": -206.36650956839847, + "z": 0.0 + }, + { + "x": 4.001383025137975, + "y": -205.36442490604762, + "z": 0.0 + }, + { + "x": 4.000859640845003, + "y": -204.3623402436968, + "z": 0.0 + }, + { + "x": 4.000336256552031, + "y": -203.36025558134594, + "z": 0.0 + }, + { + "x": 3.9998128722590587, + "y": -202.35817091899509, + "z": 0.0 + }, + { + "x": 3.9992894879660867, + "y": -201.35608625664423, + "z": 0.0 + }, + { + "x": 3.998766103673115, + "y": -200.35400159429338, + "z": 0.0 + }, + { + "x": 3.9982427193801424, + "y": -199.35191693194255, + "z": 0.0 + }, + { + "x": 3.9977193350871705, + "y": -198.3498322695917, + "z": 0.0 + }, + { + "x": 3.9971959507941985, + "y": -197.34774760724085, + "z": 0.0 + }, + { + "x": 3.996672566501226, + "y": -196.34566294489002, + "z": 0.0 + }, + { + "x": 3.996149182208254, + "y": -195.34357828253917, + "z": 0.0 + }, + { + "x": 3.9956257979152823, + "y": -194.34149362018834, + "z": 0.0 + }, + { + "x": 3.99510241362231, + "y": -193.3394089578375, + "z": 0.0 + }, + { + "x": 3.994579029329338, + "y": -192.33732429548664, + "z": 0.0 + }, + { + "x": 3.994055645036366, + "y": -191.3352396331358, + "z": 0.0 + }, + { + "x": 3.9935322607433936, + "y": -190.33315497078496, + "z": 0.0 + }, + { + "x": 3.9930088764504217, + "y": -189.3310703084341, + "z": 0.0 + }, + { + "x": 3.9924854921574493, + "y": -188.32898564608328, + "z": 0.0 + }, + { + "x": 3.9919621078644774, + "y": -187.32690098373243, + "z": 0.0 + }, + { + "x": 3.9914387235715054, + "y": -186.32481632138158, + "z": 0.0 + }, + { + "x": 3.990915339278533, + "y": -185.32273165903072, + "z": 0.0 + }, + { + "x": 3.990391954985561, + "y": -184.32064699667987, + "z": 0.0 + }, + { + "x": 3.989868570692589, + "y": -183.31856233432904, + "z": 0.0 + }, + { + "x": 3.9893451863996168, + "y": -182.3164776719782, + "z": 0.0 + }, + { + "x": 3.988821802106645, + "y": -181.31439300962737, + "z": 0.0 + }, + { + "x": 3.988298417813673, + "y": -180.31230834727654, + "z": 0.0 + }, + { + "x": 3.9877750335207005, + "y": -179.3102236849257, + "z": 0.0 + }, + { + "x": 3.9872516492277286, + "y": -178.30813902257484, + "z": 0.0 + }, + { + "x": 3.9867282649347566, + "y": -177.30605436022398, + "z": 0.0 + }, + { + "x": 3.9862048806417842, + "y": -176.30396969787313, + "z": 0.0 + }, + { + "x": 3.9856814963488123, + "y": -175.3018850355223, + "z": 0.0 + }, + { + "x": 3.9851581120558404, + "y": -174.29980037317145, + "z": 0.0 + }, + { + "x": 3.984634727762868, + "y": -173.2977157108206, + "z": 0.0 + }, + { + "x": 3.984111343469896, + "y": -172.29563104846977, + "z": 0.0 + }, + { + "x": 3.983587959176924, + "y": -171.29354638611892, + "z": 0.0 + }, + { + "x": 3.9830645748839517, + "y": -170.29146172376807, + "z": 0.0 + }, + { + "x": 3.9825411905909798, + "y": -169.28937706141724, + "z": 0.0 + }, + { + "x": 3.982017806298008, + "y": -168.2872923990664, + "z": 0.0 + }, + { + "x": 3.9814944220050354, + "y": -167.28520773671556, + "z": 0.0 + }, + { + "x": 3.9809710377120635, + "y": -166.2831230743647, + "z": 0.0 + }, + { + "x": 3.9804476534190916, + "y": -165.28103841201386, + "z": 0.0 + }, + { + "x": 3.979924269126119, + "y": -164.27895374966303, + "z": 0.0 + }, + { + "x": 3.9794008848331472, + "y": -163.27686908731218, + "z": 0.0 + }, + { + "x": 3.9788775005401753, + "y": -162.27478442496133, + "z": 0.0 + }, + { + "x": 3.978354116247203, + "y": -161.27269976261047, + "z": 0.0 + }, + { + "x": 3.977830731954231, + "y": -160.27061510025962, + "z": 0.0 + }, + { + "x": 3.977307347661259, + "y": -159.2685304379088, + "z": 0.0 + }, + { + "x": 3.9767839633682867, + "y": -158.26644577555794, + "z": 0.0 + }, + { + "x": 3.9762605790753147, + "y": -157.2643611132071, + "z": 0.0 + }, + { + "x": 3.9757371947823428, + "y": -156.2622764508563, + "z": 0.0 + }, + { + "x": 3.9752138104893704, + "y": -155.26019178850544, + "z": 0.0 + }, + { + "x": 3.9746904261963985, + "y": -154.25810712615458, + "z": 0.0 + }, + { + "x": 3.9741670419034265, + "y": -153.25602246380373, + "z": 0.0 + }, + { + "x": 3.973643657610454, + "y": -152.25393780145288, + "z": 0.0 + }, + { + "x": 3.973120273317482, + "y": -151.25185313910205, + "z": 0.0 + }, + { + "x": 3.9725968890245102, + "y": -150.2497684767512, + "z": 0.0 + }, + { + "x": 3.972073504731538, + "y": -149.24768381440035, + "z": 0.0 + }, + { + "x": 3.971550120438566, + "y": -148.24559915204952, + "z": 0.0 + }, + { + "x": 3.9710267361455935, + "y": -147.24351448969867, + "z": 0.0 + }, + { + "x": 3.9705033518526216, + "y": -146.24142982734782, + "z": 0.0 + }, + { + "x": 3.9699799675596497, + "y": -145.23934516499696, + "z": 0.0 + }, + { + "x": 3.9694565832666773, + "y": -144.23726050264614, + "z": 0.0 + }, + { + "x": 3.9689331989737053, + "y": -143.2351758402953, + "z": 0.0 + }, + { + "x": 3.9684098146807334, + "y": -142.23309117794446, + "z": 0.0 + }, + { + "x": 3.967886430387761, + "y": -141.2310065155936, + "z": 0.0 + }, + { + "x": 3.967363046094789, + "y": -140.22892185324278, + "z": 0.0 + }, + { + "x": 3.966839661801817, + "y": -139.22683719089193, + "z": 0.0 + }, + { + "x": 3.9663162775088447, + "y": -138.22475252854107, + "z": 0.0 + }, + { + "x": 3.965792893215873, + "y": -137.22266786619022, + "z": 0.0 + }, + { + "x": 3.965269508922901, + "y": -136.22058320383937, + "z": 0.0 + }, + { + "x": 3.9647461246299285, + "y": -135.21849854148851, + "z": 0.0 + }, + { + "x": 3.9642227403369565, + "y": -134.21641387913766, + "z": 0.0 + }, + { + "x": 3.9636993560439846, + "y": -133.21432921678678, + "z": 0.0 + }, + { + "x": 3.963175971751012, + "y": -132.21224455443593, + "z": 0.0 + }, + { + "x": 3.9626525874580403, + "y": -131.21015989208507, + "z": 0.0 + }, + { + "x": 3.9621292031650683, + "y": -130.20807522973422, + "z": 0.0 + }, + { + "x": 3.961605818872096, + "y": -129.20599056738337, + "z": 0.0 + }, + { + "x": 3.961082434579124, + "y": -128.2039059050325, + "z": 0.0 + }, + { + "x": 3.9605590502861516, + "y": -127.20182124268165, + "z": 0.0 + }, + { + "x": 3.9600356659931797, + "y": -126.19973658033079, + "z": 0.0 + }, + { + "x": 3.9595122817002077, + "y": -125.19765191797993, + "z": 0.0 + }, + { + "x": 3.9589888974072354, + "y": -124.19556725562907, + "z": 0.0 + }, + { + "x": 3.9584655131142634, + "y": -123.19348259327822, + "z": 0.0 + }, + { + "x": 3.9579421288212915, + "y": -122.19139793092735, + "z": 0.0 + }, + { + "x": 3.957418744528319, + "y": -121.18931326857648, + "z": 0.0 + }, + { + "x": 3.956895360235347, + "y": -120.18722860622564, + "z": 0.0 + }, + { + "x": 3.956371975942375, + "y": -119.18514394387479, + "z": 0.0 + }, + { + "x": 3.955848591649403, + "y": -118.18305928152392, + "z": 0.0 + }, + { + "x": 3.955325207356431, + "y": -117.18097461917306, + "z": 0.0 + }, + { + "x": 3.954801823063459, + "y": -116.1788899568222, + "z": 0.0 + }, + { + "x": 3.9542784387704866, + "y": -115.17680529447135, + "z": 0.0 + }, + { + "x": 3.9537550544775146, + "y": -114.1747206321205, + "z": 0.0 + }, + { + "x": 3.9532316701845422, + "y": -113.17263596976963, + "z": 0.0 + }, + { + "x": 3.9527082858915703, + "y": -112.17055130741878, + "z": 0.0 + }, + { + "x": 3.9521849015985984, + "y": -111.16846664506792, + "z": 0.0 + }, + { + "x": 3.951661517305626, + "y": -110.16638198271706, + "z": 0.0 + }, + { + "x": 3.951138133012654, + "y": -109.16429732036619, + "z": 0.0 + }, + { + "x": 3.950614748719682, + "y": -108.16221265801535, + "z": 0.0 + }, + { + "x": 3.9500913644267097, + "y": -107.1601279956645, + "z": 0.0 + }, + { + "x": 3.9495679801337378, + "y": -106.15804333331363, + "z": 0.0 + }, + { + "x": 3.949044595840766, + "y": -105.15595867096276, + "z": 0.0 + }, + { + "x": 3.9485212115477935, + "y": -104.15387400861191, + "z": 0.0 + }, + { + "x": 3.9479978272548215, + "y": -103.15178934626105, + "z": 0.0 + }, + { + "x": 3.9474744429618496, + "y": -102.1497046839102, + "z": 0.0 + }, + { + "x": 3.946951058668877, + "y": -101.14762002155933, + "z": 0.0 + }, + { + "x": 3.9464276743759052, + "y": -100.14553535920848, + "z": 0.0 + }, + { + "x": 3.945904290082933, + "y": -99.14345069685763, + "z": 0.0 + }, + { + "x": 3.945380905789961, + "y": -98.14136603450676, + "z": 0.0 + }, + { + "x": 3.944857521496989, + "y": -97.13928137215589, + "z": 0.0 + }, + { + "x": 3.9443341372040166, + "y": -96.13719670980505, + "z": 0.0 + }, + { + "x": 3.9438107529110447, + "y": -95.1351120474542, + "z": 0.0 + }, + { + "x": 3.9432873686180727, + "y": -94.13302738510333, + "z": 0.0 + }, + { + "x": 3.9427639843251003, + "y": -93.13094272275247, + "z": 0.0 + }, + { + "x": 3.9422406000321284, + "y": -92.12885806040161, + "z": 0.0 + }, + { + "x": 3.9417172157391565, + "y": -91.12677339805077, + "z": 0.0 + }, + { + "x": 3.941193831446184, + "y": -90.1246887356999, + "z": 0.0 + }, + { + "x": 3.940670447153212, + "y": -89.12260407334904, + "z": 0.0 + }, + { + "x": 3.94014706286024, + "y": -88.12051941099818, + "z": 0.0 + }, + { + "x": 3.9402771144979183, + "y": -87.12104091873772, + "z": 0.0 + }, + { + "x": 3.9406628622236557, + "y": -86.11997994611951, + "z": 0.0 + }, + { + "x": 3.9410488732983464, + "y": -85.1178952214353, + "z": 0.0 + }, + { + "x": 3.941434884373037, + "y": -84.11581049675112, + "z": 0.0 + }, + { + "x": 3.941820895447728, + "y": -83.11372577206693, + "z": 0.0 + }, + { + "x": 3.9422069065224186, + "y": -82.11164104738273, + "z": 0.0 + }, + { + "x": 3.942592917597109, + "y": -81.10955632269852, + "z": 0.0 + }, + { + "x": 3.9429789286717996, + "y": -80.10747159801434, + "z": 0.0 + }, + { + "x": 3.9433649397464903, + "y": -79.10538687333015, + "z": 0.0 + }, + { + "x": 3.943750950821181, + "y": -78.10330214864595, + "z": 0.0 + }, + { + "x": 3.9441369618958717, + "y": -77.10121742396174, + "z": 0.0 + }, + { + "x": 3.9445229729705624, + "y": -76.09913269927756, + "z": 0.0 + }, + { + "x": 3.9449089840452527, + "y": -75.09704797459337, + "z": 0.0 + }, + { + "x": 3.9452949951199434, + "y": -74.09496324990917, + "z": 0.0 + }, + { + "x": 3.945681006194634, + "y": -73.09287852522498, + "z": 0.0 + }, + { + "x": 3.946067017269325, + "y": -72.09079380054078, + "z": 0.0 + }, + { + "x": 3.9464530283440156, + "y": -71.08870907585658, + "z": 0.0 + }, + { + "x": 3.9468390394187063, + "y": -70.08662435117239, + "z": 0.0 + }, + { + "x": 3.9472250504933966, + "y": -69.0845396264882, + "z": 0.0 + }, + { + "x": 3.9476110615680873, + "y": -68.082454901804, + "z": 0.0 + }, + { + "x": 3.947997072642778, + "y": -67.0803701771198, + "z": 0.0 + }, + { + "x": 3.9483830837174687, + "y": -66.07828545243561, + "z": 0.0 + }, + { + "x": 3.9487690947921594, + "y": -65.07620072775141, + "z": 0.0 + }, + { + "x": 3.94915510586685, + "y": -64.07411600306722, + "z": 0.0 + }, + { + "x": 3.949541116941541, + "y": -63.072031278383015, + "z": 0.0 + }, + { + "x": 3.949927128016231, + "y": -62.06994655369882, + "z": 0.0 + }, + { + "x": 3.950313139090922, + "y": -61.067861829014625, + "z": 0.0 + }, + { + "x": 3.9506991501656126, + "y": -60.06577710433043, + "z": 0.0 + }, + { + "x": 3.9510851612403033, + "y": -59.063692379646234, + "z": 0.0 + }, + { + "x": 3.951471172314994, + "y": -58.06160765496204, + "z": 0.0 + }, + { + "x": 3.9518571833896847, + "y": -57.05952293027784, + "z": 0.0 + }, + { + "x": 3.952243194464375, + "y": -56.05743820559365, + "z": 0.0 + }, + { + "x": 3.9526292055390657, + "y": -55.055353480909446, + "z": 0.0 + }, + { + "x": 3.9530152166137564, + "y": -54.05326875622525, + "z": 0.0 + }, + { + "x": 3.953401227688447, + "y": -53.051184031541055, + "z": 0.0 + }, + { + "x": 3.953787238763138, + "y": -52.04909930685686, + "z": 0.0 + }, + { + "x": 3.9541732498378286, + "y": -51.047014582172665, + "z": 0.0 + }, + { + "x": 3.954559260912519, + "y": -50.04492985748847, + "z": 0.0 + }, + { + "x": 3.9549452719872096, + "y": -49.042845132804274, + "z": 0.0 + }, + { + "x": 3.9553312830619003, + "y": -48.04076040812008, + "z": 0.0 + }, + { + "x": 3.955717294136591, + "y": -47.03867568343588, + "z": 0.0 + }, + { + "x": 3.9561033052112817, + "y": -46.03659095875169, + "z": 0.0 + }, + { + "x": 3.9564893162859724, + "y": -45.03450623406749, + "z": 0.0 + }, + { + "x": 3.956875327360663, + "y": -44.0324215093833, + "z": 0.0 + }, + { + "x": 3.9572613384353534, + "y": -43.0303367846991, + "z": 0.0 + }, + { + "x": 3.957647349510044, + "y": -42.02825206001491, + "z": 0.0 + }, + { + "x": 3.958033360584735, + "y": -41.02616733533071, + "z": 0.0 + }, + { + "x": 3.9584193716594256, + "y": -40.02408261064652, + "z": 0.0 + }, + { + "x": 3.9588053827341163, + "y": -39.02199788596233, + "z": 0.0 + }, + { + "x": 3.959191393808807, + "y": -38.01991316127813, + "z": 0.0 + }, + { + "x": 3.9595774048834973, + "y": -37.017828436593945, + "z": 0.0 + }, + { + "x": 3.959963415958188, + "y": -36.01574371190975, + "z": 0.0 + }, + { + "x": 3.9603494270328787, + "y": -35.01365898722556, + "z": 0.0 + }, + { + "x": 3.9607354381075695, + "y": -34.011574262541366, + "z": 0.0 + }, + { + "x": 3.96112144918226, + "y": -33.00948953785717, + "z": 0.0 + }, + { + "x": 3.961507460256951, + "y": -32.00740481317298, + "z": 0.0 + }, + { + "x": 3.961893471331641, + "y": -31.00532008848879, + "z": 0.0 + }, + { + "x": 3.962279482406332, + "y": -30.003235363804595, + "z": 0.0 + }, + { + "x": 3.9626654934810226, + "y": -29.001150639120404, + "z": 0.0 + }, + { + "x": 3.9630515045557133, + "y": -27.999065914436212, + "z": 0.0 + }, + { + "x": 3.963437515630404, + "y": -26.99698118975202, + "z": 0.0 + }, + { + "x": 3.9638235267050947, + "y": -25.99489646506783, + "z": 0.0 + }, + { + "x": 3.964209537779785, + "y": -24.992811740383633, + "z": 0.0 + }, + { + "x": 3.9645955488544757, + "y": -23.99072701569944, + "z": 0.0 + }, + { + "x": 3.9649815599291665, + "y": -22.988642291015246, + "z": 0.0 + }, + { + "x": 3.965367571003857, + "y": -21.98655756633105, + "z": 0.0 + }, + { + "x": 3.965753582078548, + "y": -20.98447284164686, + "z": 0.0 + }, + { + "x": 3.9661395931532386, + "y": -19.982388116962664, + "z": 0.0 + }, + { + "x": 3.966525604227929, + "y": -18.98030339227847, + "z": 0.0 + }, + { + "x": 3.9669116153026196, + "y": -17.978218667594277, + "z": 0.0 + }, + { + "x": 3.9672976263773103, + "y": -16.97613394291008, + "z": 0.0 + }, + { + "x": 3.967683637452001, + "y": -15.97404921822589, + "z": 0.0 + }, + { + "x": 3.9680696485266918, + "y": -14.971964493541696, + "z": 0.0 + }, + { + "x": 3.9684556596013825, + "y": -13.969879768857503, + "z": 0.0 + }, + { + "x": 3.9688416706760727, + "y": -12.96779504417331, + "z": 0.0 + }, + { + "x": 3.9692276817507635, + "y": -11.965710319489116, + "z": 0.0 + }, + { + "x": 3.969613692825454, + "y": -10.963625594804922, + "z": 0.0 + }, + { + "x": 3.969999703900145, + "y": -9.961540870120729, + "z": 0.0 + } + ] + }, + { + "id": 76, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": -4.02999970255904, + "y": -9.958459206173217, + "z": 0.0 + }, + { + "x": -4.030385713633731, + "y": -10.96054393085741, + "z": 0.0 + }, + { + "x": -4.030771724708422, + "y": -11.962628655541604, + "z": 0.0 + }, + { + "x": -4.031157735783112, + "y": -12.964713380225797, + "z": 0.0 + }, + { + "x": -4.031543746857803, + "y": -13.96679810490999, + "z": 0.0 + }, + { + "x": -4.0319297579324935, + "y": -14.968882829594184, + "z": 0.0 + }, + { + "x": -4.032315769007185, + "y": -15.970967554278378, + "z": 0.0 + }, + { + "x": -4.032701780081875, + "y": -16.97305227896257, + "z": 0.0 + }, + { + "x": -4.033087791156565, + "y": -17.975137003646765, + "z": 0.0 + }, + { + "x": -4.033473802231256, + "y": -18.977221728330957, + "z": 0.0 + }, + { + "x": -4.033859813305947, + "y": -19.979306453015152, + "z": 0.0 + }, + { + "x": -4.034245824380638, + "y": -20.981391177699347, + "z": 0.0 + }, + { + "x": -4.034631835455328, + "y": -21.98347590238354, + "z": 0.0 + }, + { + "x": -4.035017846530018, + "y": -22.985560627067734, + "z": 0.0 + }, + { + "x": -4.0354038576047095, + "y": -23.98764535175193, + "z": 0.0 + }, + { + "x": -4.0357898686794, + "y": -24.98973007643612, + "z": 0.0 + }, + { + "x": -4.036175879754091, + "y": -25.991814801120317, + "z": 0.0 + }, + { + "x": -4.036561890828781, + "y": -26.99389952580451, + "z": 0.0 + }, + { + "x": -4.036947901903472, + "y": -27.9959842504887, + "z": 0.0 + }, + { + "x": -4.037333912978163, + "y": -28.99806897517289, + "z": 0.0 + }, + { + "x": -4.037719924052853, + "y": -30.000153699857083, + "z": 0.0 + }, + { + "x": -4.038105935127544, + "y": -31.00223842454128, + "z": 0.0 + }, + { + "x": -4.038491946202234, + "y": -32.00432314922547, + "z": 0.0 + }, + { + "x": -4.038877957276926, + "y": -33.00640787390966, + "z": 0.0 + }, + { + "x": -4.039263968351616, + "y": -34.008492598593854, + "z": 0.0 + }, + { + "x": -4.039649979426306, + "y": -35.01057732327805, + "z": 0.0 + }, + { + "x": -4.040035990500997, + "y": -36.01266204796224, + "z": 0.0 + }, + { + "x": -4.0404220015756875, + "y": -37.01474677264643, + "z": 0.0 + }, + { + "x": -4.040808012650379, + "y": -38.01683149733062, + "z": 0.0 + }, + { + "x": -4.041194023725069, + "y": -39.018916222014816, + "z": 0.0 + }, + { + "x": -4.04158003479976, + "y": -40.02100094669901, + "z": 0.0 + }, + { + "x": -4.04196604587445, + "y": -41.0230856713832, + "z": 0.0 + }, + { + "x": -4.042352056949141, + "y": -42.025170396067395, + "z": 0.0 + }, + { + "x": -4.042738068023832, + "y": -43.02725512075159, + "z": 0.0 + }, + { + "x": -4.043124079098522, + "y": -44.029339845435786, + "z": 0.0 + }, + { + "x": -4.043510090173213, + "y": -45.03142457011998, + "z": 0.0 + }, + { + "x": -4.0438961012479036, + "y": -46.033509294804176, + "z": 0.0 + }, + { + "x": -4.044282112322595, + "y": -47.03559401948837, + "z": 0.0 + }, + { + "x": -4.044668123397285, + "y": -48.03767874417257, + "z": 0.0 + }, + { + "x": -4.045054134471975, + "y": -49.03976346885676, + "z": 0.0 + }, + { + "x": -4.045440145546666, + "y": -50.04184819354096, + "z": 0.0 + }, + { + "x": -4.045826156621357, + "y": -51.04393291822515, + "z": 0.0 + }, + { + "x": -4.046212167696048, + "y": -52.04601764290935, + "z": 0.0 + }, + { + "x": -4.046598178770738, + "y": -53.04810236759354, + "z": 0.0 + }, + { + "x": -4.046984189845428, + "y": -54.05018709227774, + "z": 0.0 + }, + { + "x": -4.04737020092012, + "y": -55.052271816961934, + "z": 0.0 + }, + { + "x": -4.04775621199481, + "y": -56.054356541646136, + "z": 0.0 + }, + { + "x": -4.048142223069501, + "y": -57.05644126633033, + "z": 0.0 + }, + { + "x": -4.048528234144191, + "y": -58.05852599101453, + "z": 0.0 + }, + { + "x": -4.048914245218882, + "y": -59.06061071569872, + "z": 0.0 + }, + { + "x": -4.049300256293573, + "y": -60.06269544038292, + "z": 0.0 + }, + { + "x": -4.049686267368263, + "y": -61.06478016506711, + "z": 0.0 + }, + { + "x": -4.050072278442954, + "y": -62.06686488975131, + "z": 0.0 + }, + { + "x": -4.050458289517644, + "y": -63.0689496144355, + "z": 0.0 + }, + { + "x": -4.050844300592336, + "y": -64.0710343391197, + "z": 0.0 + }, + { + "x": -4.051230311667026, + "y": -65.0731190638039, + "z": 0.0 + }, + { + "x": -4.051616322741716, + "y": -66.0752037884881, + "z": 0.0 + }, + { + "x": -4.052002333816407, + "y": -67.07728851317229, + "z": 0.0 + }, + { + "x": -4.052388344891098, + "y": -68.07937323785649, + "z": 0.0 + }, + { + "x": -4.052774355965789, + "y": -69.08145796254068, + "z": 0.0 + }, + { + "x": -4.053160367040479, + "y": -70.08354268722488, + "z": 0.0 + }, + { + "x": -4.05354637811517, + "y": -71.08562741190907, + "z": 0.0 + }, + { + "x": -4.05393238918986, + "y": -72.08771213659327, + "z": 0.0 + }, + { + "x": -4.054318400264551, + "y": -73.08979686127746, + "z": 0.0 + }, + { + "x": -4.054704411339242, + "y": -74.09188158596166, + "z": 0.0 + }, + { + "x": -4.055090422413932, + "y": -75.09396631064585, + "z": 0.0 + }, + { + "x": -4.055476433488623, + "y": -76.09605103533005, + "z": 0.0 + }, + { + "x": -4.055862444563314, + "y": -77.09813576001423, + "z": 0.0 + }, + { + "x": -4.056248455638005, + "y": -78.10022048469844, + "z": 0.0 + }, + { + "x": -4.056634466712695, + "y": -79.10230520938264, + "z": 0.0 + }, + { + "x": -4.057020477787385, + "y": -80.10438993406683, + "z": 0.0 + }, + { + "x": -4.057406488862076, + "y": -81.10647465875101, + "z": 0.0 + }, + { + "x": -4.057792499936767, + "y": -82.10855938343522, + "z": 0.0 + }, + { + "x": -4.058178511011458, + "y": -83.11064410811942, + "z": 0.0 + }, + { + "x": -4.058564522086148, + "y": -84.11272883280361, + "z": 0.0 + }, + { + "x": -4.058950533160838, + "y": -85.11481355748779, + "z": 0.0 + }, + { + "x": -4.05933654423553, + "y": -86.116898282172, + "z": 0.0 + }, + { + "x": -4.059722818659173, + "y": -87.12000675892219, + "z": 0.0 + }, + { + "x": -4.059851845969695, + "y": -88.12469777429422, + "z": 0.0 + }, + { + "x": -4.059328461676723, + "y": -89.12678243664507, + "z": 0.0 + }, + { + "x": -4.058805077383751, + "y": -90.12886709899594, + "z": 0.0 + }, + { + "x": -4.0582816930907795, + "y": -91.13095176134681, + "z": 0.0 + }, + { + "x": -4.0577583087978075, + "y": -92.13303642369765, + "z": 0.0 + }, + { + "x": -4.057234924504835, + "y": -93.1351210860485, + "z": 0.0 + }, + { + "x": -4.056711540211863, + "y": -94.13720574839937, + "z": 0.0 + }, + { + "x": -4.056188155918891, + "y": -95.13929041075023, + "z": 0.0 + }, + { + "x": -4.055664771625919, + "y": -96.14137507310109, + "z": 0.0 + }, + { + "x": -4.055141387332947, + "y": -97.14345973545193, + "z": 0.0 + }, + { + "x": -4.054618003039974, + "y": -98.1455443978028, + "z": 0.0 + }, + { + "x": -4.054094618747002, + "y": -99.14762906015366, + "z": 0.0 + }, + { + "x": -4.05357123445403, + "y": -100.14971372250452, + "z": 0.0 + }, + { + "x": -4.053047850161058, + "y": -101.15179838485537, + "z": 0.0 + }, + { + "x": -4.052524465868086, + "y": -102.15388304720624, + "z": 0.0 + }, + { + "x": -4.052001081575114, + "y": -103.15596770955709, + "z": 0.0 + }, + { + "x": -4.051477697282142, + "y": -104.15805237190794, + "z": 0.0 + }, + { + "x": -4.05095431298917, + "y": -105.1601370342588, + "z": 0.0 + }, + { + "x": -4.050430928696198, + "y": -106.16222169660966, + "z": 0.0 + }, + { + "x": -4.049907544403226, + "y": -107.16430635896053, + "z": 0.0 + }, + { + "x": -4.049384160110254, + "y": -108.16639102131138, + "z": 0.0 + }, + { + "x": -4.048860775817281, + "y": -109.16847568366222, + "z": 0.0 + }, + { + "x": -4.048337391524309, + "y": -110.17056034601309, + "z": 0.0 + }, + { + "x": -4.047814007231337, + "y": -111.17264500836396, + "z": 0.0 + }, + { + "x": -4.047290622938365, + "y": -112.17472967071481, + "z": 0.0 + }, + { + "x": -4.046767238645393, + "y": -113.17681433306566, + "z": 0.0 + }, + { + "x": -4.046243854352421, + "y": -114.17889899541653, + "z": 0.0 + }, + { + "x": -4.0457204700594485, + "y": -115.18098365776738, + "z": 0.0 + }, + { + "x": -4.0451970857664765, + "y": -116.18306832011824, + "z": 0.0 + }, + { + "x": -4.044673701473505, + "y": -117.18515298246909, + "z": 0.0 + }, + { + "x": -4.044150317180533, + "y": -118.18723764481996, + "z": 0.0 + }, + { + "x": -4.043626932887561, + "y": -119.18932230717083, + "z": 0.0 + }, + { + "x": -4.043103548594589, + "y": -120.19140696952168, + "z": 0.0 + }, + { + "x": -4.042580164301616, + "y": -121.19349163187252, + "z": 0.0 + }, + { + "x": -4.042056780008644, + "y": -122.19557629422339, + "z": 0.0 + }, + { + "x": -4.041533395715672, + "y": -123.19766095657425, + "z": 0.0 + }, + { + "x": -4.0410100114227, + "y": -124.1997456189251, + "z": 0.0 + }, + { + "x": -4.040486627129728, + "y": -125.20183028127596, + "z": 0.0 + }, + { + "x": -4.039963242836755, + "y": -126.20391494362683, + "z": 0.0 + }, + { + "x": -4.039439858543783, + "y": -127.20599960597768, + "z": 0.0 + }, + { + "x": -4.0389164742508115, + "y": -128.20808426832855, + "z": 0.0 + }, + { + "x": -4.0383930899578395, + "y": -129.2101689306794, + "z": 0.0 + }, + { + "x": -4.037869705664868, + "y": -130.21225359303025, + "z": 0.0 + }, + { + "x": -4.037346321371896, + "y": -131.2143382553811, + "z": 0.0 + }, + { + "x": -4.036822937078923, + "y": -132.21642291773196, + "z": 0.0 + }, + { + "x": -4.036299552785951, + "y": -133.21850758008281, + "z": 0.0 + }, + { + "x": -4.035776168492979, + "y": -134.2205922424337, + "z": 0.0 + }, + { + "x": -4.035252784200007, + "y": -135.22267690478455, + "z": 0.0 + }, + { + "x": -4.034729399907035, + "y": -136.2247615671354, + "z": 0.0 + }, + { + "x": -4.034206015614062, + "y": -137.22684622948626, + "z": 0.0 + }, + { + "x": -4.03368263132109, + "y": -138.2289308918371, + "z": 0.0 + }, + { + "x": -4.033159247028118, + "y": -139.23101555418796, + "z": 0.0 + }, + { + "x": -4.032635862735146, + "y": -140.23310021653882, + "z": 0.0 + }, + { + "x": -4.0321124784421745, + "y": -141.23518487888964, + "z": 0.0 + }, + { + "x": -4.0315890941492025, + "y": -142.2372695412405, + "z": 0.0 + }, + { + "x": -4.03106570985623, + "y": -143.23935420359135, + "z": 0.0 + }, + { + "x": -4.030542325563258, + "y": -144.24143886594217, + "z": 0.0 + }, + { + "x": -4.030018941270286, + "y": -145.243523528293, + "z": 0.0 + }, + { + "x": -4.029495556977314, + "y": -146.24560819064385, + "z": 0.0 + }, + { + "x": -4.028972172684342, + "y": -147.2476928529947, + "z": 0.0 + }, + { + "x": -4.02844878839137, + "y": -148.24977751534556, + "z": 0.0 + }, + { + "x": -4.027925404098397, + "y": -149.25186217769638, + "z": 0.0 + }, + { + "x": -4.027402019805425, + "y": -150.25394684004723, + "z": 0.0 + }, + { + "x": -4.026878635512453, + "y": -151.2560315023981, + "z": 0.0 + }, + { + "x": -4.026355251219481, + "y": -152.2581161647489, + "z": 0.0 + }, + { + "x": -4.025831866926509, + "y": -153.26020082709977, + "z": 0.0 + }, + { + "x": -4.0253084826335375, + "y": -154.26228548945062, + "z": 0.0 + }, + { + "x": -4.024785098340565, + "y": -155.26437015180147, + "z": 0.0 + }, + { + "x": -4.024261714047593, + "y": -156.26645481415233, + "z": 0.0 + }, + { + "x": -4.023738329754621, + "y": -157.26853947650312, + "z": 0.0 + }, + { + "x": -4.023214945461649, + "y": -158.27062413885398, + "z": 0.0 + }, + { + "x": -4.022691561168677, + "y": -159.27270880120483, + "z": 0.0 + }, + { + "x": -4.022168176875705, + "y": -160.27479346355565, + "z": 0.0 + }, + { + "x": -4.021644792582732, + "y": -161.2768781259065, + "z": 0.0 + }, + { + "x": -4.02112140828976, + "y": -162.27896278825736, + "z": 0.0 + }, + { + "x": -4.020598023996788, + "y": -163.2810474506082, + "z": 0.0 + }, + { + "x": -4.020074639703816, + "y": -164.28313211295907, + "z": 0.0 + }, + { + "x": -4.019551255410844, + "y": -165.2852167753099, + "z": 0.0 + }, + { + "x": -4.019027871117872, + "y": -166.28730143766074, + "z": 0.0 + }, + { + "x": -4.0185044868249, + "y": -167.2893861000116, + "z": 0.0 + }, + { + "x": -4.017981102531928, + "y": -168.29147076236242, + "z": 0.0 + }, + { + "x": -4.017457718238956, + "y": -169.29355542471328, + "z": 0.0 + }, + { + "x": -4.016934333945984, + "y": -170.2956400870641, + "z": 0.0 + }, + { + "x": -4.016410949653012, + "y": -171.29772474941495, + "z": 0.0 + }, + { + "x": -4.015887565360039, + "y": -172.2998094117658, + "z": 0.0 + }, + { + "x": -4.015364181067067, + "y": -173.30189407411663, + "z": 0.0 + }, + { + "x": -4.014840796774095, + "y": -174.30397873646749, + "z": 0.0 + }, + { + "x": -4.014317412481123, + "y": -175.30606339881834, + "z": 0.0 + }, + { + "x": -4.013794028188151, + "y": -176.30814806116916, + "z": 0.0 + }, + { + "x": -4.013270643895179, + "y": -177.31023272352002, + "z": 0.0 + }, + { + "x": -4.0127472596022065, + "y": -178.31231738587087, + "z": 0.0 + }, + { + "x": -4.0122238753092345, + "y": -179.31440204822172, + "z": 0.0 + }, + { + "x": -4.011700491016263, + "y": -180.31648671057258, + "z": 0.0 + }, + { + "x": -4.011177106723291, + "y": -181.3185713729234, + "z": 0.0 + }, + { + "x": -4.010653722430319, + "y": -182.32065603527423, + "z": 0.0 + }, + { + "x": -4.010130338137347, + "y": -183.32274069762508, + "z": 0.0 + }, + { + "x": -4.009606953844374, + "y": -184.3248253599759, + "z": 0.0 + }, + { + "x": -4.009083569551402, + "y": -185.32691002232676, + "z": 0.0 + }, + { + "x": -4.00856018525843, + "y": -186.3289946846776, + "z": 0.0 + }, + { + "x": -4.008036800965458, + "y": -187.33107934702846, + "z": 0.0 + }, + { + "x": -4.007513416672486, + "y": -188.33316400937932, + "z": 0.0 + }, + { + "x": -4.006990032379514, + "y": -189.33524867173014, + "z": 0.0 + }, + { + "x": -4.006466648086541, + "y": -190.337333334081, + "z": 0.0 + }, + { + "x": -4.0059432637935695, + "y": -191.33941799643185, + "z": 0.0 + }, + { + "x": -4.0054198795005975, + "y": -192.34150265878267, + "z": 0.0 + }, + { + "x": -4.004896495207626, + "y": -193.34358732113353, + "z": 0.0 + }, + { + "x": -4.004373110914654, + "y": -194.34567198348438, + "z": 0.0 + }, + { + "x": -4.003849726621682, + "y": -195.3477566458352, + "z": 0.0 + }, + { + "x": -4.003326342328709, + "y": -196.34984130818606, + "z": 0.0 + }, + { + "x": -4.002802958035737, + "y": -197.35192597053688, + "z": 0.0 + }, + { + "x": -4.002279573742765, + "y": -198.35401063288774, + "z": 0.0 + }, + { + "x": -4.001756189449793, + "y": -199.3560952952386, + "z": 0.0 + }, + { + "x": -4.001232805156821, + "y": -200.3581799575894, + "z": 0.0 + }, + { + "x": -4.000709420863849, + "y": -201.36026461994027, + "z": 0.0 + }, + { + "x": -4.000186036570876, + "y": -202.36234928229112, + "z": 0.0 + }, + { + "x": -3.9996626522779044, + "y": -203.36443394464197, + "z": 0.0 + }, + { + "x": -3.9991392679849325, + "y": -204.36651860699283, + "z": 0.0 + }, + { + "x": -3.9986158836919605, + "y": -205.36860326934365, + "z": 0.0 + }, + { + "x": -3.998092499398988, + "y": -206.3706879316945, + "z": 0.0 + }, + { + "x": -3.997569115106016, + "y": -207.37277259404533, + "z": 0.0 + }, + { + "x": -3.9970457308130443, + "y": -208.37485725639615, + "z": 0.0 + }, + { + "x": -3.996522346520072, + "y": -209.376941918747, + "z": 0.0 + }, + { + "x": -3.9959989622271, + "y": -210.37902658109786, + "z": 0.0 + }, + { + "x": -3.995475577934128, + "y": -211.38111124344871, + "z": 0.0 + }, + { + "x": -3.9949521936411556, + "y": -212.38319590579957, + "z": 0.0 + }, + { + "x": -3.9944288093481837, + "y": -213.3852805681504, + "z": 0.0 + }, + { + "x": -3.9939054250552117, + "y": -214.38736523050125, + "z": 0.0 + }, + { + "x": -3.9933820407622393, + "y": -215.3894498928521, + "z": 0.0 + }, + { + "x": -3.9928586564692674, + "y": -216.39153455520292, + "z": 0.0 + }, + { + "x": -3.9923352721762955, + "y": -217.39361921755378, + "z": 0.0 + }, + { + "x": -3.991811887883323, + "y": -218.39570387990463, + "z": 0.0 + }, + { + "x": -3.991288503590351, + "y": -219.39778854225548, + "z": 0.0 + }, + { + "x": -3.990765119297379, + "y": -220.3998732046063, + "z": 0.0 + }, + { + "x": -3.990241735004407, + "y": -221.40195786695713, + "z": 0.0 + }, + { + "x": -3.989718350711435, + "y": -222.404042529308, + "z": 0.0 + }, + { + "x": -3.989194966418463, + "y": -223.40612719165884, + "z": 0.0 + }, + { + "x": -3.9886715821254906, + "y": -224.40821185400966, + "z": 0.0 + }, + { + "x": -3.9881481978325186, + "y": -225.41029651636052, + "z": 0.0 + }, + { + "x": -3.9876248135395467, + "y": -226.41238117871137, + "z": 0.0 + }, + { + "x": -3.9871014292465743, + "y": -227.41446584106222, + "z": 0.0 + }, + { + "x": -3.9865780449536024, + "y": -228.41655050341308, + "z": 0.0 + }, + { + "x": -3.9860546606606304, + "y": -229.4186351657639, + "z": 0.0 + }, + { + "x": -3.985531276367658, + "y": -230.42071982811476, + "z": 0.0 + }, + { + "x": -3.985007892074686, + "y": -231.4228044904656, + "z": 0.0 + }, + { + "x": -3.984484507781714, + "y": -232.4248891528164, + "z": 0.0 + }, + { + "x": -3.9839611234887418, + "y": -233.42697381516726, + "z": 0.0 + }, + { + "x": -3.98343773919577, + "y": -234.4290584775181, + "z": 0.0 + }, + { + "x": -3.9829143549027974, + "y": -235.43114313986896, + "z": 0.0 + }, + { + "x": -3.9823909706098255, + "y": -236.43322780221982, + "z": 0.0 + }, + { + "x": -3.9818675863168536, + "y": -237.43531246457064, + "z": 0.0 + }, + { + "x": -3.981344202023881, + "y": -238.4373971269215, + "z": 0.0 + }, + { + "x": -3.9808208177309092, + "y": -239.43948178927235, + "z": 0.0 + }, + { + "x": -3.980297862737418, + "y": -240.44044178249482, + "z": 0.0 + }, + { + "x": -3.9800563141031873, + "y": -241.4410397436067, + "z": 0.0 + }, + { + "x": -3.9801871516298046, + "y": -242.44312453409674, + "z": 0.0 + }, + { + "x": -3.980317989156422, + "y": -243.44520932458678, + "z": 0.0 + }, + { + "x": -3.9804488266830402, + "y": -244.44729411507683, + "z": 0.0 + }, + { + "x": -3.980579664209657, + "y": -245.44937890556685, + "z": 0.0 + }, + { + "x": -3.9807105017362754, + "y": -246.4514636960569, + "z": 0.0 + }, + { + "x": -3.9808413392628927, + "y": -247.45354848654696, + "z": 0.0 + }, + { + "x": -3.980972176789509, + "y": -248.45563327703698, + "z": 0.0 + }, + { + "x": -3.981103014316127, + "y": -249.45771806752703, + "z": 0.0 + }, + { + "x": -3.9812338518427444, + "y": -250.45980285801707, + "z": 0.0 + }, + { + "x": -3.9813646893693617, + "y": -251.46188764850712, + "z": 0.0 + }, + { + "x": -3.98149552689598, + "y": -252.46397243899716, + "z": 0.0 + }, + { + "x": -3.981626364422597, + "y": -253.46605722948718, + "z": 0.0 + }, + { + "x": -3.9817572019492142, + "y": -254.46814201997722, + "z": 0.0 + }, + { + "x": -3.9818880394758316, + "y": -255.47022681046727, + "z": 0.0 + }, + { + "x": -3.98201887700245, + "y": -256.47231160095725, + "z": 0.0 + }, + { + "x": -3.9821497145290676, + "y": -257.4743963914473, + "z": 0.0 + }, + { + "x": -3.982280552055685, + "y": -258.4764811819374, + "z": 0.0 + }, + { + "x": -3.9824113895823023, + "y": -259.4785659724274, + "z": 0.0 + }, + { + "x": -3.98254222710892, + "y": -260.4806507629175, + "z": 0.0 + }, + { + "x": -3.9826730646355375, + "y": -261.4827355534075, + "z": 0.0 + }, + { + "x": -3.982803902162155, + "y": -262.4848203438975, + "z": 0.0 + }, + { + "x": -3.982934739688772, + "y": -263.4869051343876, + "z": 0.0 + }, + { + "x": -3.98306557721539, + "y": -264.4889899248776, + "z": 0.0 + }, + { + "x": -3.9831964147420074, + "y": -265.49107471536763, + "z": 0.0 + }, + { + "x": -3.9833272522686247, + "y": -266.4931595058577, + "z": 0.0 + }, + { + "x": -3.983458089795242, + "y": -267.4952442963478, + "z": 0.0 + }, + { + "x": -3.98358892732186, + "y": -268.49732908683785, + "z": 0.0 + }, + { + "x": -3.9837197648484772, + "y": -269.4994138773279, + "z": 0.0 + }, + { + "x": -3.9838506023750946, + "y": -270.501498667818, + "z": 0.0 + }, + { + "x": -3.983981439901712, + "y": -271.503583458308, + "z": 0.0 + }, + { + "x": -3.9841122774283297, + "y": -272.5056682487981, + "z": 0.0 + }, + { + "x": -3.984243114954947, + "y": -273.50775303928816, + "z": 0.0 + }, + { + "x": -3.9843739524815645, + "y": -274.50983782977823, + "z": 0.0 + }, + { + "x": -3.9845047900081823, + "y": -275.5119226202683, + "z": 0.0 + }, + { + "x": -3.9846356275347996, + "y": -276.5140074107584, + "z": 0.0 + }, + { + "x": -3.984766465061417, + "y": -277.51609220124845, + "z": 0.0 + }, + { + "x": -3.9848973025880343, + "y": -278.51817699173847, + "z": 0.0 + }, + { + "x": -3.985028140114652, + "y": -279.52026178222854, + "z": 0.0 + }, + { + "x": -3.9851589776412695, + "y": -280.5223465727186, + "z": 0.0 + }, + { + "x": -3.985289815167887, + "y": -281.5244313632087, + "z": 0.0 + }, + { + "x": -3.985420652694504, + "y": -282.52651615369876, + "z": 0.0 + }, + { + "x": -3.985551490221122, + "y": -283.52860094418884, + "z": 0.0 + }, + { + "x": -3.9856823277477393, + "y": -284.5306857346789, + "z": 0.0 + }, + { + "x": -3.9858131652743567, + "y": -285.532770525169, + "z": 0.0 + }, + { + "x": -3.9859440028009745, + "y": -286.53485531565906, + "z": 0.0 + }, + { + "x": -3.986074840327592, + "y": -287.53694010614913, + "z": 0.0 + }, + { + "x": -3.986205677854209, + "y": -288.5390248966392, + "z": 0.0 + }, + { + "x": -3.9863365153808266, + "y": -289.5411096871293, + "z": 0.0 + }, + { + "x": -3.9864673529074444, + "y": -290.54319447761935, + "z": 0.0 + }, + { + "x": -3.9865981904340617, + "y": -291.5452792681094, + "z": 0.0 + }, + { + "x": -3.986729027960679, + "y": -292.5473640585995, + "z": 0.0 + }, + { + "x": -3.9868598654872964, + "y": -293.5494488490896, + "z": 0.0 + }, + { + "x": -3.9869907030139142, + "y": -294.5515336395796, + "z": 0.0 + }, + { + "x": -3.9871215405405316, + "y": -295.55361843006966, + "z": 0.0 + }, + { + "x": -3.987252378067149, + "y": -296.55570322055974, + "z": 0.0 + }, + { + "x": -3.9873832155937663, + "y": -297.5577880110498, + "z": 0.0 + }, + { + "x": -3.987514053120384, + "y": -298.5598728015399, + "z": 0.0 + }, + { + "x": -3.9876448906470014, + "y": -299.56195759202996, + "z": 0.0 + }, + { + "x": -3.987775728173619, + "y": -300.56404238252003, + "z": 0.0 + }, + { + "x": -3.9879065657002366, + "y": -301.5661271730101, + "z": 0.0 + }, + { + "x": -3.988037403226854, + "y": -302.5682119635002, + "z": 0.0 + }, + { + "x": -3.9881682407534713, + "y": -303.5702967539902, + "z": 0.0 + }, + { + "x": -3.9882990782800887, + "y": -304.57238154448027, + "z": 0.0 + }, + { + "x": -3.9884299158067065, + "y": -305.57446633497034, + "z": 0.0 + }, + { + "x": -3.988560753333324, + "y": -306.5765511254604, + "z": 0.0 + }, + { + "x": -3.988691590859941, + "y": -307.5786359159505, + "z": 0.0 + }, + { + "x": -3.9888224283865585, + "y": -308.58072070644056, + "z": 0.0 + }, + { + "x": -3.9889532659131763, + "y": -309.58280549693063, + "z": 0.0 + }, + { + "x": -3.9890841034397937, + "y": -310.58489028742065, + "z": 0.0 + }, + { + "x": -3.989214940966411, + "y": -311.5869750779107, + "z": 0.0 + }, + { + "x": -3.989345778493029, + "y": -312.5890598684008, + "z": 0.0 + }, + { + "x": -3.989476616019646, + "y": -313.59114465889087, + "z": 0.0 + }, + { + "x": -3.9896074535462636, + "y": -314.59322944938094, + "z": 0.0 + }, + { + "x": -3.989738291072881, + "y": -315.595314239871, + "z": 0.0 + }, + { + "x": -3.9898691285994987, + "y": -316.5973990303611, + "z": 0.0 + }, + { + "x": -3.989999966126116, + "y": -317.59948382085116, + "z": 0.0 + } + ] + }, + { + "id": 77, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": -0.029999999329447746, + "y": -9.960000038146973, + "z": 0.0 + }, + { + "x": -0.030386010404138394, + "y": -10.962084762831166, + "z": 0.0 + }, + { + "x": -0.030772021478829036, + "y": -11.96416948751536, + "z": 0.0 + }, + { + "x": -0.031158032553519684, + "y": -12.966254212199553, + "z": 0.0 + }, + { + "x": -0.031544043628210325, + "y": -13.968338936883747, + "z": 0.0 + }, + { + "x": -0.03193005470290097, + "y": -14.97042366156794, + "z": 0.0 + }, + { + "x": -0.03231606577759162, + "y": -15.972508386252134, + "z": 0.0 + }, + { + "x": -0.03270207685228226, + "y": -16.974593110936326, + "z": 0.0 + }, + { + "x": -0.03308808792697291, + "y": -17.97667783562052, + "z": 0.0 + }, + { + "x": -0.03347409900166356, + "y": -18.978762560304713, + "z": 0.0 + }, + { + "x": -0.033860110076354206, + "y": -19.980847284988908, + "z": 0.0 + }, + { + "x": -0.03424612115104485, + "y": -20.982932009673103, + "z": 0.0 + }, + { + "x": -0.034632132225735496, + "y": -21.985016734357295, + "z": 0.0 + }, + { + "x": -0.035018143300426144, + "y": -22.98710145904149, + "z": 0.0 + }, + { + "x": -0.035404154375116785, + "y": -23.989186183725685, + "z": 0.0 + }, + { + "x": -0.03579016544980743, + "y": -24.991270908409877, + "z": 0.0 + }, + { + "x": -0.03617617652449808, + "y": -25.993355633094072, + "z": 0.0 + }, + { + "x": -0.03656218759918872, + "y": -26.995440357778264, + "z": 0.0 + }, + { + "x": -0.03694819867387937, + "y": -27.997525082462456, + "z": 0.0 + }, + { + "x": -0.03733420974857001, + "y": -28.999609807146648, + "z": 0.0 + }, + { + "x": -0.03772022082326066, + "y": -30.00169453183084, + "z": 0.0 + }, + { + "x": -0.0381062318979513, + "y": -31.003779256515035, + "z": 0.0 + }, + { + "x": -0.03849224297264195, + "y": -32.00586398119923, + "z": 0.0 + }, + { + "x": -0.03887825404733259, + "y": -33.007948705883415, + "z": 0.0 + }, + { + "x": -0.03926426512202324, + "y": -34.01003343056761, + "z": 0.0 + }, + { + "x": -0.039650276196713886, + "y": -35.012118155251805, + "z": 0.0 + }, + { + "x": -0.04003628727140453, + "y": -36.01420287993599, + "z": 0.0 + }, + { + "x": -0.040422298346095176, + "y": -37.01628760462019, + "z": 0.0 + }, + { + "x": -0.040808309420785824, + "y": -38.01837232930438, + "z": 0.0 + }, + { + "x": -0.041194320495476465, + "y": -39.02045705398857, + "z": 0.0 + }, + { + "x": -0.04158033157016711, + "y": -40.02254177867277, + "z": 0.0 + }, + { + "x": -0.041966342644857754, + "y": -41.024626503356956, + "z": 0.0 + }, + { + "x": -0.0423523537195484, + "y": -42.02671122804115, + "z": 0.0 + }, + { + "x": -0.04273836479423905, + "y": -43.028795952725346, + "z": 0.0 + }, + { + "x": -0.04312437586892969, + "y": -44.03088067740954, + "z": 0.0 + }, + { + "x": -0.04351038694362034, + "y": -45.03296540209374, + "z": 0.0 + }, + { + "x": -0.04389639801831098, + "y": -46.03505012677793, + "z": 0.0 + }, + { + "x": -0.04428240909300163, + "y": -47.03713485146213, + "z": 0.0 + }, + { + "x": -0.04466842016769228, + "y": -48.03921957614632, + "z": 0.0 + }, + { + "x": -0.045054431242382925, + "y": -49.04130430083052, + "z": 0.0 + }, + { + "x": -0.04544044231707357, + "y": -50.04338902551471, + "z": 0.0 + }, + { + "x": -0.04582645339176422, + "y": -51.04547375019891, + "z": 0.0 + }, + { + "x": -0.04621246446645486, + "y": -52.047558474883104, + "z": 0.0 + }, + { + "x": -0.04659847554114551, + "y": -53.0496431995673, + "z": 0.0 + }, + { + "x": -0.04698448661583616, + "y": -54.051727924251495, + "z": 0.0 + }, + { + "x": -0.0473704976905268, + "y": -55.05381264893569, + "z": 0.0 + }, + { + "x": -0.04775650876521745, + "y": -56.05589737361989, + "z": 0.0 + }, + { + "x": -0.0481425198399081, + "y": -57.05798209830409, + "z": 0.0 + }, + { + "x": -0.048528530914598744, + "y": -58.06006682298828, + "z": 0.0 + }, + { + "x": -0.04891454198928939, + "y": -59.06215154767248, + "z": 0.0 + }, + { + "x": -0.04930055306398004, + "y": -60.06423627235667, + "z": 0.0 + }, + { + "x": -0.04968656413867068, + "y": -61.06632099704087, + "z": 0.0 + }, + { + "x": -0.05007257521336133, + "y": -62.068405721725064, + "z": 0.0 + }, + { + "x": -0.05045858628805198, + "y": -63.07049044640926, + "z": 0.0 + }, + { + "x": -0.050844597362742626, + "y": -64.07257517109346, + "z": 0.0 + }, + { + "x": -0.051230608437433274, + "y": -65.07465989577766, + "z": 0.0 + }, + { + "x": -0.05161661951212392, + "y": -66.07674462046185, + "z": 0.0 + }, + { + "x": -0.05200263058681456, + "y": -67.07882934514605, + "z": 0.0 + }, + { + "x": -0.05238864166150521, + "y": -68.08091406983024, + "z": 0.0 + }, + { + "x": -0.05277465273619586, + "y": -69.08299879451444, + "z": 0.0 + }, + { + "x": -0.0531606638108865, + "y": -70.08508351919863, + "z": 0.0 + }, + { + "x": -0.05354667488557715, + "y": -71.08716824388283, + "z": 0.0 + }, + { + "x": -0.0539326859602678, + "y": -72.08925296856702, + "z": 0.0 + }, + { + "x": -0.05431869703495844, + "y": -73.09133769325122, + "z": 0.0 + }, + { + "x": -0.054704708109649086, + "y": -74.09342241793541, + "z": 0.0 + }, + { + "x": -0.055090719184339734, + "y": -75.09550714261961, + "z": 0.0 + }, + { + "x": -0.05547673025903038, + "y": -76.0975918673038, + "z": 0.0 + }, + { + "x": -0.05586274133372103, + "y": -77.09967659198799, + "z": 0.0 + }, + { + "x": -0.05624875240841167, + "y": -78.1017613166722, + "z": 0.0 + }, + { + "x": -0.05663476348310232, + "y": -79.10384604135639, + "z": 0.0 + }, + { + "x": -0.05702077455779297, + "y": -80.10593076604059, + "z": 0.0 + }, + { + "x": -0.05740678563248361, + "y": -81.10801549072477, + "z": 0.0 + }, + { + "x": -0.05779279670717426, + "y": -82.11010021540898, + "z": 0.0 + }, + { + "x": -0.05817880778186491, + "y": -83.11218494009317, + "z": 0.0 + }, + { + "x": -0.05856481885655555, + "y": -84.11426966477737, + "z": 0.0 + }, + { + "x": -0.058950829931246194, + "y": -85.11635438946155, + "z": 0.0 + }, + { + "x": -0.05933684100593684, + "y": -86.11843911414576, + "z": 0.0 + }, + { + "x": -0.05972285208062749, + "y": -87.12052383882995, + "z": 0.0 + }, + { + "x": -0.059852391554727755, + "y": -88.1226085926462, + "z": 0.0 + }, + { + "x": -0.05932900726175566, + "y": -89.12469325499706, + "z": 0.0 + }, + { + "x": -0.058805622968783555, + "y": -90.12677791734792, + "z": 0.0 + }, + { + "x": -0.058282238675811456, + "y": -91.12886257969879, + "z": 0.0 + }, + { + "x": -0.05775885438283937, + "y": -92.13094724204963, + "z": 0.0 + }, + { + "x": -0.05723547008986727, + "y": -93.13303190440048, + "z": 0.0 + }, + { + "x": -0.05671208579689516, + "y": -94.13511656675135, + "z": 0.0 + }, + { + "x": -0.05618870150392306, + "y": -95.13720122910222, + "z": 0.0 + }, + { + "x": -0.055665317210950964, + "y": -96.13928589145307, + "z": 0.0 + }, + { + "x": -0.05514193291797887, + "y": -97.14137055380391, + "z": 0.0 + }, + { + "x": -0.054618548625006764, + "y": -98.14345521615478, + "z": 0.0 + }, + { + "x": -0.05409516433203466, + "y": -99.14553987850564, + "z": 0.0 + }, + { + "x": -0.053571780039062565, + "y": -100.1476245408565, + "z": 0.0 + }, + { + "x": -0.05304839574609047, + "y": -101.14970920320735, + "z": 0.0 + }, + { + "x": -0.05252501145311837, + "y": -102.15179386555822, + "z": 0.0 + }, + { + "x": -0.05200162716014627, + "y": -103.15387852790907, + "z": 0.0 + }, + { + "x": -0.05147824286717417, + "y": -104.15596319025992, + "z": 0.0 + }, + { + "x": -0.05095485857420208, + "y": -105.15804785261078, + "z": 0.0 + }, + { + "x": -0.050431474281229974, + "y": -106.16013251496165, + "z": 0.0 + }, + { + "x": -0.04990808998825787, + "y": -107.16221717731251, + "z": 0.0 + }, + { + "x": -0.04938470569528578, + "y": -108.16430183966337, + "z": 0.0 + }, + { + "x": -0.04886132140231368, + "y": -109.1663865020142, + "z": 0.0 + }, + { + "x": -0.04833793710934158, + "y": -110.16847116436507, + "z": 0.0 + }, + { + "x": -0.04781455281636948, + "y": -111.17055582671594, + "z": 0.0 + }, + { + "x": -0.04729116852339738, + "y": -112.1726404890668, + "z": 0.0 + }, + { + "x": -0.04676778423042528, + "y": -113.17472515141765, + "z": 0.0 + }, + { + "x": -0.04624439993745318, + "y": -114.17680981376851, + "z": 0.0 + }, + { + "x": -0.04572101564448108, + "y": -115.17889447611937, + "z": 0.0 + }, + { + "x": -0.045197631351508984, + "y": -116.18097913847022, + "z": 0.0 + }, + { + "x": -0.04467424705853689, + "y": -117.18306380082107, + "z": 0.0 + }, + { + "x": -0.044150862765564784, + "y": -118.18514846317194, + "z": 0.0 + }, + { + "x": -0.043627478472592685, + "y": -119.18723312552281, + "z": 0.0 + }, + { + "x": -0.043104094179620585, + "y": -120.18931778787366, + "z": 0.0 + }, + { + "x": -0.0425807098866485, + "y": -121.1914024502245, + "z": 0.0 + }, + { + "x": -0.0420573255936764, + "y": -122.19348711257537, + "z": 0.0 + }, + { + "x": -0.041533941300704286, + "y": -123.19557177492624, + "z": 0.0 + }, + { + "x": -0.04101055700773219, + "y": -124.19765643727709, + "z": 0.0 + }, + { + "x": -0.0404871727147601, + "y": -125.19974109962794, + "z": 0.0 + }, + { + "x": -0.039963788421787994, + "y": -126.20182576197881, + "z": 0.0 + }, + { + "x": -0.039440404128815894, + "y": -127.20391042432966, + "z": 0.0 + }, + { + "x": -0.0389170198358438, + "y": -128.20599508668053, + "z": 0.0 + }, + { + "x": -0.0383936355428717, + "y": -129.20807974903138, + "z": 0.0 + }, + { + "x": -0.0378702512498996, + "y": -130.21016441138224, + "z": 0.0 + }, + { + "x": -0.0373468669569275, + "y": -131.2122490737331, + "z": 0.0 + }, + { + "x": -0.0368234826639554, + "y": -132.21433373608394, + "z": 0.0 + }, + { + "x": -0.03630009837098331, + "y": -133.2164183984348, + "z": 0.0 + }, + { + "x": -0.0357767140780112, + "y": -134.21850306078568, + "z": 0.0 + }, + { + "x": -0.0352533297850391, + "y": -135.22058772313653, + "z": 0.0 + }, + { + "x": -0.034729945492067, + "y": -136.22267238548739, + "z": 0.0 + }, + { + "x": -0.03420656119909491, + "y": -137.22475704783824, + "z": 0.0 + }, + { + "x": -0.03368317690612281, + "y": -138.2268417101891, + "z": 0.0 + }, + { + "x": -0.03315979261315071, + "y": -139.22892637253995, + "z": 0.0 + }, + { + "x": -0.032636408320178625, + "y": -140.2310110348908, + "z": 0.0 + }, + { + "x": -0.03211302402720654, + "y": -141.23309569724162, + "z": 0.0 + }, + { + "x": -0.03158963973423444, + "y": -142.23518035959248, + "z": 0.0 + }, + { + "x": -0.03106625544126235, + "y": -143.23726502194333, + "z": 0.0 + }, + { + "x": -0.03054287114829027, + "y": -144.23934968429415, + "z": 0.0 + }, + { + "x": -0.03001948685531817, + "y": -145.24143434664498, + "z": 0.0 + }, + { + "x": -0.029496102562346072, + "y": -146.24351900899583, + "z": 0.0 + }, + { + "x": -0.028972718269373976, + "y": -147.2456036713467, + "z": 0.0 + }, + { + "x": -0.028449333976401887, + "y": -148.24768833369754, + "z": 0.0 + }, + { + "x": -0.0279259496834298, + "y": -149.24977299604836, + "z": 0.0 + }, + { + "x": -0.027402565390457705, + "y": -150.25185765839922, + "z": 0.0 + }, + { + "x": -0.026879181097485615, + "y": -151.25394232075007, + "z": 0.0 + }, + { + "x": -0.026355796804513533, + "y": -152.2560269831009, + "z": 0.0 + }, + { + "x": -0.025832412511541437, + "y": -153.25811164545175, + "z": 0.0 + }, + { + "x": -0.02530902821856935, + "y": -154.2601963078026, + "z": 0.0 + }, + { + "x": -0.024785643925597255, + "y": -155.26228097015345, + "z": 0.0 + }, + { + "x": -0.024262259632625155, + "y": -156.2643656325043, + "z": 0.0 + }, + { + "x": -0.02373887533965308, + "y": -157.2664502948551, + "z": 0.0 + }, + { + "x": -0.023215491046680976, + "y": -158.26853495720596, + "z": 0.0 + }, + { + "x": -0.022692106753708877, + "y": -159.2706196195568, + "z": 0.0 + }, + { + "x": -0.022168722460736805, + "y": -160.27270428190764, + "z": 0.0 + }, + { + "x": -0.02164533816776471, + "y": -161.2747889442585, + "z": 0.0 + }, + { + "x": -0.02112195387479261, + "y": -162.27687360660934, + "z": 0.0 + }, + { + "x": -0.02059856958182052, + "y": -163.2789582689602, + "z": 0.0 + }, + { + "x": -0.020075185288848416, + "y": -164.28104293131105, + "z": 0.0 + }, + { + "x": -0.019551800995876334, + "y": -165.28312759366187, + "z": 0.0 + }, + { + "x": -0.019028416702904248, + "y": -166.28521225601273, + "z": 0.0 + }, + { + "x": -0.018505032409932155, + "y": -167.28729691836358, + "z": 0.0 + }, + { + "x": -0.01798164811696007, + "y": -168.2893815807144, + "z": 0.0 + }, + { + "x": -0.01745826382398798, + "y": -169.29146624306526, + "z": 0.0 + }, + { + "x": -0.016934879531015877, + "y": -170.29355090541608, + "z": 0.0 + }, + { + "x": -0.01641149523804378, + "y": -171.29563556776694, + "z": 0.0 + }, + { + "x": -0.01588811094507169, + "y": -172.2977202301178, + "z": 0.0 + }, + { + "x": -0.015364726652099606, + "y": -173.29980489246861, + "z": 0.0 + }, + { + "x": -0.014841342359127515, + "y": -174.30188955481947, + "z": 0.0 + }, + { + "x": -0.014317958066155425, + "y": -175.30397421717032, + "z": 0.0 + }, + { + "x": -0.013794573773183338, + "y": -176.30605887952115, + "z": 0.0 + }, + { + "x": -0.01327118948021124, + "y": -177.308143541872, + "z": 0.0 + }, + { + "x": -0.01274780518723915, + "y": -178.31022820422285, + "z": 0.0 + }, + { + "x": -0.012224420894267046, + "y": -179.3123128665737, + "z": 0.0 + }, + { + "x": -0.011701036601294953, + "y": -180.31439752892456, + "z": 0.0 + }, + { + "x": -0.011177652308322879, + "y": -181.31648219127538, + "z": 0.0 + }, + { + "x": -0.010654268015350778, + "y": -182.3185668536262, + "z": 0.0 + }, + { + "x": -0.010130883722378678, + "y": -183.32065151597706, + "z": 0.0 + }, + { + "x": -0.009607499429406606, + "y": -184.3227361783279, + "z": 0.0 + }, + { + "x": -0.009084115136434505, + "y": -185.32482084067874, + "z": 0.0 + }, + { + "x": -0.008560730843462412, + "y": -186.3269055030296, + "z": 0.0 + }, + { + "x": -0.008037346550490324, + "y": -187.32899016538045, + "z": 0.0 + }, + { + "x": -0.007513962257518224, + "y": -188.3310748277313, + "z": 0.0 + }, + { + "x": -0.006990577964546139, + "y": -189.33315949008212, + "z": 0.0 + }, + { + "x": -0.00646719367157405, + "y": -190.33524415243298, + "z": 0.0 + }, + { + "x": -0.005943809378601944, + "y": -191.33732881478383, + "z": 0.0 + }, + { + "x": -0.005420425085629872, + "y": -192.33941347713466, + "z": 0.0 + }, + { + "x": -0.004897040792657784, + "y": -193.3414981394855, + "z": 0.0 + }, + { + "x": -0.00437365649968567, + "y": -194.34358280183636, + "z": 0.0 + }, + { + "x": -0.003850272206713584, + "y": -195.3456674641872, + "z": 0.0 + }, + { + "x": -0.003326887913741497, + "y": -196.34775212653804, + "z": 0.0 + }, + { + "x": -0.0028035036207694035, + "y": -197.34983678888887, + "z": 0.0 + }, + { + "x": -0.0022801193277973172, + "y": -198.35192145123972, + "z": 0.0 + }, + { + "x": -0.001756735034825231, + "y": -199.35400611359057, + "z": 0.0 + }, + { + "x": -0.0012333507418531237, + "y": -200.3560907759414, + "z": 0.0 + }, + { + "x": -0.0007099664488810368, + "y": -201.35817543829225, + "z": 0.0 + }, + { + "x": -0.0001865821559089505, + "y": -202.3602601006431, + "z": 0.0 + }, + { + "x": 0.00033680213706315724, + "y": -203.36234476299396, + "z": 0.0 + }, + { + "x": 0.0008601864300352446, + "y": -204.3644294253448, + "z": 0.0 + }, + { + "x": 0.00138357072300733, + "y": -205.36651408769563, + "z": 0.0 + }, + { + "x": 0.0019069550159794308, + "y": -206.3685987500465, + "z": 0.0 + }, + { + "x": 0.002430339308951518, + "y": -207.3706834123973, + "z": 0.0 + }, + { + "x": 0.002953723601923583, + "y": -208.37276807474814, + "z": 0.0 + }, + { + "x": 0.003477107894895689, + "y": -209.374852737099, + "z": 0.0 + }, + { + "x": 0.004000492187867783, + "y": -210.37693739944984, + "z": 0.0 + }, + { + "x": 0.00452387648083989, + "y": -211.3790220618007, + "z": 0.0 + }, + { + "x": 0.0050472607738119854, + "y": -212.38110672415155, + "z": 0.0 + }, + { + "x": 0.005570645066784064, + "y": -213.38319138650238, + "z": 0.0 + }, + { + "x": 0.006094029359756146, + "y": -214.38527604885323, + "z": 0.0 + }, + { + "x": 0.00661741365272825, + "y": -215.38736071120408, + "z": 0.0 + }, + { + "x": 0.0071407979457003305, + "y": -216.3894453735549, + "z": 0.0 + }, + { + "x": 0.007664182238672424, + "y": -217.39153003590576, + "z": 0.0 + }, + { + "x": 0.008187566531644517, + "y": -218.3936146982566, + "z": 0.0 + }, + { + "x": 0.008710950824616611, + "y": -219.39569936060747, + "z": 0.0 + }, + { + "x": 0.009234335117588716, + "y": -220.3977840229583, + "z": 0.0 + }, + { + "x": 0.009757719410560787, + "y": -221.39986868530912, + "z": 0.0 + }, + { + "x": 0.010281103703532888, + "y": -222.40195334765997, + "z": 0.0 + }, + { + "x": 0.010804487996504976, + "y": -223.40403801001082, + "z": 0.0 + }, + { + "x": 0.011327872289477061, + "y": -224.40612267236165, + "z": 0.0 + }, + { + "x": 0.01185125658244916, + "y": -225.4082073347125, + "z": 0.0 + }, + { + "x": 0.012374640875421252, + "y": -226.41029199706335, + "z": 0.0 + }, + { + "x": 0.012898025168393347, + "y": -227.4123766594142, + "z": 0.0 + }, + { + "x": 0.01342140946136544, + "y": -228.41446132176506, + "z": 0.0 + }, + { + "x": 0.013944793754337529, + "y": -229.41654598411588, + "z": 0.0 + }, + { + "x": 0.014468178047309627, + "y": -230.41863064646674, + "z": 0.0 + }, + { + "x": 0.01499156234028172, + "y": -231.4207153088176, + "z": 0.0 + }, + { + "x": 0.015514946633253798, + "y": -232.4227999711684, + "z": 0.0 + }, + { + "x": 0.01603833092622589, + "y": -233.42488463351924, + "z": 0.0 + }, + { + "x": 0.016561715219197987, + "y": -234.4269692958701, + "z": 0.0 + }, + { + "x": 0.01708509951217009, + "y": -235.42905395822095, + "z": 0.0 + }, + { + "x": 0.01760848380514218, + "y": -236.4311386205718, + "z": 0.0 + }, + { + "x": 0.018131868098114262, + "y": -237.43322328292263, + "z": 0.0 + }, + { + "x": 0.01865525239108635, + "y": -238.43530794527348, + "z": 0.0 + }, + { + "x": 0.019178636684058448, + "y": -239.43739260762433, + "z": 0.0 + }, + { + "x": 0.019702020977030534, + "y": -240.43947726997516, + "z": 0.0 + }, + { + "x": 0.01994365180220445, + "y": -241.44156200490332, + "z": 0.0 + }, + { + "x": 0.019812814275586975, + "y": -242.44364679539336, + "z": 0.0 + }, + { + "x": 0.0196819767489695, + "y": -243.4457315858834, + "z": 0.0 + }, + { + "x": 0.01955113922235203, + "y": -244.44781637637345, + "z": 0.0 + }, + { + "x": 0.01942030169573456, + "y": -245.44990116686347, + "z": 0.0 + }, + { + "x": 0.019289464169117088, + "y": -246.45198595735351, + "z": 0.0 + }, + { + "x": 0.019158626642499614, + "y": -247.4540707478436, + "z": 0.0 + }, + { + "x": 0.019027789115882147, + "y": -248.4561555383336, + "z": 0.0 + }, + { + "x": 0.018896951589264674, + "y": -249.45824032882365, + "z": 0.0 + }, + { + "x": 0.0187661140626472, + "y": -250.4603251193137, + "z": 0.0 + }, + { + "x": 0.018635276536029727, + "y": -251.46240990980374, + "z": 0.0 + }, + { + "x": 0.018504439009412253, + "y": -252.46449470029378, + "z": 0.0 + }, + { + "x": 0.01837360148279479, + "y": -253.4665794907838, + "z": 0.0 + }, + { + "x": 0.018242763956177317, + "y": -254.46866428127385, + "z": 0.0 + }, + { + "x": 0.018111926429559843, + "y": -255.4707490717639, + "z": 0.0 + }, + { + "x": 0.017981088902942376, + "y": -256.4728338622539, + "z": 0.0 + }, + { + "x": 0.0178502513763249, + "y": -257.47491865274395, + "z": 0.0 + }, + { + "x": 0.017719413849707426, + "y": -258.477003443234, + "z": 0.0 + }, + { + "x": 0.017588576323089952, + "y": -259.47908823372404, + "z": 0.0 + }, + { + "x": 0.017457738796472482, + "y": -260.4811730242141, + "z": 0.0 + }, + { + "x": 0.017326901269855012, + "y": -261.48325781470413, + "z": 0.0 + }, + { + "x": 0.01719606374323754, + "y": -262.48534260519415, + "z": 0.0 + }, + { + "x": 0.017065226216620065, + "y": -263.4874273956842, + "z": 0.0 + }, + { + "x": 0.016934388690002602, + "y": -264.48951218617424, + "z": 0.0 + }, + { + "x": 0.016803551163385128, + "y": -265.49159697666425, + "z": 0.0 + }, + { + "x": 0.01667271363676765, + "y": -266.4936817671543, + "z": 0.0 + }, + { + "x": 0.016541876110150174, + "y": -267.4957665576444, + "z": 0.0 + }, + { + "x": 0.016411038583532694, + "y": -268.4978513481345, + "z": 0.0 + }, + { + "x": 0.01628020105691522, + "y": -269.49993613862455, + "z": 0.0 + }, + { + "x": 0.016149363530297743, + "y": -270.5020209291146, + "z": 0.0 + }, + { + "x": 0.016018526003680273, + "y": -271.50410571960464, + "z": 0.0 + }, + { + "x": 0.015887688477062796, + "y": -272.5061905100947, + "z": 0.0 + }, + { + "x": 0.015756850950445322, + "y": -273.5082753005848, + "z": 0.0 + }, + { + "x": 0.01562601342382785, + "y": -274.51036009107486, + "z": 0.0 + }, + { + "x": 0.01549517589721037, + "y": -275.51244488156493, + "z": 0.0 + }, + { + "x": 0.015364338370592895, + "y": -276.514529672055, + "z": 0.0 + }, + { + "x": 0.015233500843975418, + "y": -277.5166144625451, + "z": 0.0 + }, + { + "x": 0.015102663317357948, + "y": -278.5186992530351, + "z": 0.0 + }, + { + "x": 0.01497182579074047, + "y": -279.52078404352517, + "z": 0.0 + }, + { + "x": 0.014840988264122999, + "y": -280.52286883401524, + "z": 0.0 + }, + { + "x": 0.014710150737505518, + "y": -281.5249536245053, + "z": 0.0 + }, + { + "x": 0.014579313210888043, + "y": -282.5270384149954, + "z": 0.0 + }, + { + "x": 0.01444847568427057, + "y": -283.52912320548546, + "z": 0.0 + }, + { + "x": 0.01431763815765309, + "y": -284.53120799597554, + "z": 0.0 + }, + { + "x": 0.014186800631035616, + "y": -285.5332927864656, + "z": 0.0 + }, + { + "x": 0.014055963104418139, + "y": -286.5353775769557, + "z": 0.0 + }, + { + "x": 0.013925125577800668, + "y": -287.53746236744576, + "z": 0.0 + }, + { + "x": 0.013794288051183191, + "y": -288.53954715793583, + "z": 0.0 + }, + { + "x": 0.013663450524565718, + "y": -289.5416319484259, + "z": 0.0 + }, + { + "x": 0.01353261299794824, + "y": -290.543716738916, + "z": 0.0 + }, + { + "x": 0.013401775471330764, + "y": -291.54580152940605, + "z": 0.0 + }, + { + "x": 0.01327093794471329, + "y": -292.5478863198961, + "z": 0.0 + }, + { + "x": 0.013140100418095813, + "y": -293.5499711103862, + "z": 0.0 + }, + { + "x": 0.013009262891478343, + "y": -294.5520559008762, + "z": 0.0 + }, + { + "x": 0.012878425364860866, + "y": -295.5541406913663, + "z": 0.0 + }, + { + "x": 0.012747587838243389, + "y": -296.55622548185636, + "z": 0.0 + }, + { + "x": 0.01261675031162591, + "y": -297.55831027234643, + "z": 0.0 + }, + { + "x": 0.012485912785008433, + "y": -298.5603950628365, + "z": 0.0 + }, + { + "x": 0.01235507525839096, + "y": -299.5624798533266, + "z": 0.0 + }, + { + "x": 0.012224237731773488, + "y": -300.56456464381665, + "z": 0.0 + }, + { + "x": 0.012093400205156011, + "y": -301.5666494343067, + "z": 0.0 + }, + { + "x": 0.011962562678538534, + "y": -302.5687342247968, + "z": 0.0 + }, + { + "x": 0.011831725151921064, + "y": -303.5708190152868, + "z": 0.0 + }, + { + "x": 0.011700887625303587, + "y": -304.5729038057769, + "z": 0.0 + }, + { + "x": 0.01157005009868611, + "y": -305.57498859626696, + "z": 0.0 + }, + { + "x": 0.011439212572068633, + "y": -306.57707338675704, + "z": 0.0 + }, + { + "x": 0.011308375045451156, + "y": -307.5791581772471, + "z": 0.0 + }, + { + "x": 0.011177537518833684, + "y": -308.5812429677372, + "z": 0.0 + }, + { + "x": 0.011046699992216202, + "y": -309.58332775822726, + "z": 0.0 + }, + { + "x": 0.010915862465598737, + "y": -310.5854125487173, + "z": 0.0 + }, + { + "x": 0.010785024938981261, + "y": -311.58749733920735, + "z": 0.0 + }, + { + "x": 0.010654187412363784, + "y": -312.5895821296974, + "z": 0.0 + }, + { + "x": 0.010523349885746306, + "y": -313.5916669201875, + "z": 0.0 + }, + { + "x": 0.010392512359128829, + "y": -314.59375171067757, + "z": 0.0 + }, + { + "x": 0.010261674832511353, + "y": -315.59583650116764, + "z": 0.0 + }, + { + "x": 0.010130837305893875, + "y": -316.5979212916577, + "z": 0.0 + }, + { + "x": 0.0099999997792764, + "y": -317.6000060821478, + "z": 0.0 + } + ] + }, + { + "id": 78, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 2.009999982731973, + "y": -317.6002672127961, + "z": 0.0 + }, + { + "x": 2.01013082025859, + "y": -316.598182422306, + "z": 0.0 + }, + { + "x": 2.0102616577852075, + "y": -315.59609763181595, + "z": 0.0 + }, + { + "x": 2.010392495311825, + "y": -314.5940128413259, + "z": 0.0 + }, + { + "x": 2.0105233328384426, + "y": -313.5919280508358, + "z": 0.0 + }, + { + "x": 2.01065417036506, + "y": -312.58984326034573, + "z": 0.0 + }, + { + "x": 2.0107850078916774, + "y": -311.58775846985566, + "z": 0.0 + }, + { + "x": 2.010915845418295, + "y": -310.5856736793656, + "z": 0.0 + }, + { + "x": 2.0110466829449125, + "y": -309.58358888887557, + "z": 0.0 + }, + { + "x": 2.01117752047153, + "y": -308.5815040983855, + "z": 0.0 + }, + { + "x": 2.0113083579981472, + "y": -307.5794193078954, + "z": 0.0 + }, + { + "x": 2.011439195524765, + "y": -306.57733451740535, + "z": 0.0 + }, + { + "x": 2.0115700330513824, + "y": -305.5752497269153, + "z": 0.0 + }, + { + "x": 2.0117008705779997, + "y": -304.5731649364252, + "z": 0.0 + }, + { + "x": 2.011831708104617, + "y": -303.5710801459351, + "z": 0.0 + }, + { + "x": 2.011962545631235, + "y": -302.5689953554451, + "z": 0.0 + }, + { + "x": 2.0120933831578522, + "y": -301.56691056495504, + "z": 0.0 + }, + { + "x": 2.0122242206844696, + "y": -300.56482577446496, + "z": 0.0 + }, + { + "x": 2.012355058211087, + "y": -299.5627409839749, + "z": 0.0 + }, + { + "x": 2.0124858957377048, + "y": -298.5606561934848, + "z": 0.0 + }, + { + "x": 2.012616733264322, + "y": -297.55857140299474, + "z": 0.0 + }, + { + "x": 2.0127475707909395, + "y": -296.55648661250467, + "z": 0.0 + }, + { + "x": 2.0128784083175573, + "y": -295.5544018220146, + "z": 0.0 + }, + { + "x": 2.0130092458441746, + "y": -294.5523170315245, + "z": 0.0 + }, + { + "x": 2.013140083370792, + "y": -293.5502322410345, + "z": 0.0 + }, + { + "x": 2.0132709208974093, + "y": -292.54814745054443, + "z": 0.0 + }, + { + "x": 2.013401758424027, + "y": -291.54606266005436, + "z": 0.0 + }, + { + "x": 2.0135325959506445, + "y": -290.5439778695643, + "z": 0.0 + }, + { + "x": 2.013663433477262, + "y": -289.5418930790742, + "z": 0.0 + }, + { + "x": 2.013794271003879, + "y": -288.53980828858414, + "z": 0.0 + }, + { + "x": 2.013925108530497, + "y": -287.53772349809407, + "z": 0.0 + }, + { + "x": 2.0140559460571144, + "y": -286.535638707604, + "z": 0.0 + }, + { + "x": 2.0141867835837317, + "y": -285.5335539171139, + "z": 0.0 + }, + { + "x": 2.0143176211103495, + "y": -284.53146912662385, + "z": 0.0 + }, + { + "x": 2.014448458636967, + "y": -283.5293843361338, + "z": 0.0 + }, + { + "x": 2.014579296163584, + "y": -282.5272995456437, + "z": 0.0 + }, + { + "x": 2.0147101336902016, + "y": -281.5252147551536, + "z": 0.0 + }, + { + "x": 2.0148409712168194, + "y": -280.52312996466355, + "z": 0.0 + }, + { + "x": 2.0149718087434367, + "y": -279.5210451741735, + "z": 0.0 + }, + { + "x": 2.015102646270054, + "y": -278.5189603836834, + "z": 0.0 + }, + { + "x": 2.0152334837966714, + "y": -277.5168755931934, + "z": 0.0 + }, + { + "x": 2.0153643213232892, + "y": -276.5147908027033, + "z": 0.0 + }, + { + "x": 2.0154951588499066, + "y": -275.51270601221324, + "z": 0.0 + }, + { + "x": 2.015625996376524, + "y": -274.51062122172317, + "z": 0.0 + }, + { + "x": 2.0157568339031418, + "y": -273.5085364312331, + "z": 0.0 + }, + { + "x": 2.015887671429759, + "y": -272.506451640743, + "z": 0.0 + }, + { + "x": 2.0160185089563765, + "y": -271.50436685025295, + "z": 0.0 + }, + { + "x": 2.016149346482994, + "y": -270.50228205976293, + "z": 0.0 + }, + { + "x": 2.0162801840096116, + "y": -269.50019726927286, + "z": 0.0 + }, + { + "x": 2.016411021536229, + "y": -268.4981124787828, + "z": 0.0 + }, + { + "x": 2.0165418590628463, + "y": -267.4960276882927, + "z": 0.0 + }, + { + "x": 2.0166726965894637, + "y": -266.49394289780264, + "z": 0.0 + }, + { + "x": 2.0168035341160815, + "y": -265.49185810731257, + "z": 0.0 + }, + { + "x": 2.016934371642699, + "y": -264.48977331682255, + "z": 0.0 + }, + { + "x": 2.017065209169316, + "y": -263.48768852633253, + "z": 0.0 + }, + { + "x": 2.0171960466959336, + "y": -262.48560373584246, + "z": 0.0 + }, + { + "x": 2.0173268842225514, + "y": -261.48351894535244, + "z": 0.0 + }, + { + "x": 2.0174577217491687, + "y": -260.4814341548624, + "z": 0.0 + }, + { + "x": 2.017588559275786, + "y": -259.47934936437235, + "z": 0.0 + }, + { + "x": 2.0177193968024034, + "y": -258.47726457388234, + "z": 0.0 + }, + { + "x": 2.017850234329021, + "y": -257.47517978339226, + "z": 0.0 + }, + { + "x": 2.0179810718556386, + "y": -256.4730949929022, + "z": 0.0 + }, + { + "x": 2.0181119093822555, + "y": -255.4710102024122, + "z": 0.0 + }, + { + "x": 2.0182427469088733, + "y": -254.46892541192216, + "z": 0.0 + }, + { + "x": 2.0183735844354906, + "y": -253.4668406214321, + "z": 0.0 + }, + { + "x": 2.0185044219621084, + "y": -252.4647558309421, + "z": 0.0 + }, + { + "x": 2.0186352594887254, + "y": -251.46267104045205, + "z": 0.0 + }, + { + "x": 2.018766097015343, + "y": -250.460586249962, + "z": 0.0 + }, + { + "x": 2.0188969345419605, + "y": -249.45850145947196, + "z": 0.0 + }, + { + "x": 2.019027772068578, + "y": -248.45641666898192, + "z": 0.0 + }, + { + "x": 2.0191586095951957, + "y": -247.4543318784919, + "z": 0.0 + }, + { + "x": 2.0192894471218135, + "y": -246.45224708800183, + "z": 0.0 + }, + { + "x": 2.0194202846484304, + "y": -245.45016229751178, + "z": 0.0 + }, + { + "x": 2.019551122175048, + "y": -244.44807750702176, + "z": 0.0 + }, + { + "x": 2.019681959701665, + "y": -243.44599271653172, + "z": 0.0 + }, + { + "x": 2.019812797228283, + "y": -242.44390792604167, + "z": 0.0 + }, + { + "x": 2.0199436347549002, + "y": -241.44182313555163, + "z": 0.0 + }, + { + "x": 2.019701962834255, + "y": -240.43899501371533, + "z": 0.0 + }, + { + "x": 2.0191783638915424, + "y": -239.4363480168003, + "z": 0.0 + }, + { + "x": 2.0186549795985704, + "y": -238.43426335444946, + "z": 0.0 + }, + { + "x": 2.0181315953055985, + "y": -237.4321786920986, + "z": 0.0 + }, + { + "x": 2.0176082110126257, + "y": -236.4300940297478, + "z": 0.0 + }, + { + "x": 2.0170848267196537, + "y": -235.42800936739695, + "z": 0.0 + }, + { + "x": 2.016561442426682, + "y": -234.4259247050461, + "z": 0.0 + }, + { + "x": 2.01603805813371, + "y": -233.42384004269525, + "z": 0.0 + }, + { + "x": 2.015514673840738, + "y": -232.4217553803444, + "z": 0.0 + }, + { + "x": 2.014991289547766, + "y": -231.4196707179936, + "z": 0.0 + }, + { + "x": 2.014467905254793, + "y": -230.41758605564274, + "z": 0.0 + }, + { + "x": 2.013944520961821, + "y": -229.4155013932919, + "z": 0.0 + }, + { + "x": 2.0134211366688493, + "y": -228.41341673094104, + "z": 0.0 + }, + { + "x": 2.0128977523758773, + "y": -227.41133206859018, + "z": 0.0 + }, + { + "x": 2.0123743680829054, + "y": -226.40924740623933, + "z": 0.0 + }, + { + "x": 2.0118509837899334, + "y": -225.40716274388848, + "z": 0.0 + }, + { + "x": 2.0113275994969606, + "y": -224.40507808153762, + "z": 0.0 + }, + { + "x": 2.0108042152039887, + "y": -223.40299341918683, + "z": 0.0 + }, + { + "x": 2.0102808309110167, + "y": -222.40090875683597, + "z": 0.0 + }, + { + "x": 2.009757446618045, + "y": -221.39882409448512, + "z": 0.0 + }, + { + "x": 2.009234062325073, + "y": -220.39673943213427, + "z": 0.0 + }, + { + "x": 2.008710678032101, + "y": -219.39465476978347, + "z": 0.0 + }, + { + "x": 2.008187293739128, + "y": -218.39257010743262, + "z": 0.0 + }, + { + "x": 2.007663909446156, + "y": -217.39048544508177, + "z": 0.0 + }, + { + "x": 2.007140525153184, + "y": -216.3884007827309, + "z": 0.0 + }, + { + "x": 2.0066171408602123, + "y": -215.38631612038006, + "z": 0.0 + }, + { + "x": 2.0060937565672403, + "y": -214.3842314580292, + "z": 0.0 + }, + { + "x": 2.0055703722742684, + "y": -213.38214679567835, + "z": 0.0 + }, + { + "x": 2.0050469879812955, + "y": -212.38006213332756, + "z": 0.0 + }, + { + "x": 2.0045236036883236, + "y": -211.3779774709767, + "z": 0.0 + }, + { + "x": 2.0040002193953517, + "y": -210.37589280862585, + "z": 0.0 + }, + { + "x": 2.0034768351023797, + "y": -209.373808146275, + "z": 0.0 + }, + { + "x": 2.002953450809408, + "y": -208.37172348392414, + "z": 0.0 + }, + { + "x": 2.002430066516435, + "y": -207.3696388215733, + "z": 0.0 + }, + { + "x": 2.001906682223463, + "y": -206.3675541592225, + "z": 0.0 + }, + { + "x": 2.001383297930491, + "y": -205.36546949687164, + "z": 0.0 + }, + { + "x": 2.000859913637519, + "y": -204.3633848345208, + "z": 0.0 + }, + { + "x": 2.000336529344547, + "y": -203.36130017216993, + "z": 0.0 + }, + { + "x": 1.9998131450515748, + "y": -202.35921550981908, + "z": 0.0 + }, + { + "x": 1.9992897607586029, + "y": -201.35713084746823, + "z": 0.0 + }, + { + "x": 1.998766376465631, + "y": -200.35504618511737, + "z": 0.0 + }, + { + "x": 1.9982429921726585, + "y": -199.35296152276658, + "z": 0.0 + }, + { + "x": 1.9977196078796866, + "y": -198.35087686041572, + "z": 0.0 + }, + { + "x": 1.9971962235867147, + "y": -197.34879219806487, + "z": 0.0 + }, + { + "x": 1.9966728392937423, + "y": -196.34670753571402, + "z": 0.0 + }, + { + "x": 1.9961494550007703, + "y": -195.34462287336316, + "z": 0.0 + }, + { + "x": 1.9956260707077984, + "y": -194.34253821101237, + "z": 0.0 + }, + { + "x": 1.995102686414826, + "y": -193.34045354866151, + "z": 0.0 + }, + { + "x": 1.994579302121854, + "y": -192.33836888631066, + "z": 0.0 + }, + { + "x": 1.9940559178288821, + "y": -191.3362842239598, + "z": 0.0 + }, + { + "x": 1.9935325335359098, + "y": -190.33419956160895, + "z": 0.0 + }, + { + "x": 1.9930091492429378, + "y": -189.3321148992581, + "z": 0.0 + }, + { + "x": 1.9924857649499654, + "y": -188.3300302369073, + "z": 0.0 + }, + { + "x": 1.9919623806569935, + "y": -187.32794557455645, + "z": 0.0 + }, + { + "x": 1.9914389963640216, + "y": -186.3258609122056, + "z": 0.0 + }, + { + "x": 1.9909156120710492, + "y": -185.32377624985475, + "z": 0.0 + }, + { + "x": 1.9903922277780772, + "y": -184.3216915875039, + "z": 0.0 + }, + { + "x": 1.9898688434851053, + "y": -183.31960692515304, + "z": 0.0 + }, + { + "x": 1.989345459192133, + "y": -182.31752226280219, + "z": 0.0 + }, + { + "x": 1.988822074899161, + "y": -181.3154376004514, + "z": 0.0 + }, + { + "x": 1.988298690606189, + "y": -180.31335293810054, + "z": 0.0 + }, + { + "x": 1.9877753063132166, + "y": -179.31126827574968, + "z": 0.0 + }, + { + "x": 1.9872519220202447, + "y": -178.30918361339883, + "z": 0.0 + }, + { + "x": 1.9867285377272728, + "y": -177.30709895104798, + "z": 0.0 + }, + { + "x": 1.9862051534343004, + "y": -176.30501428869712, + "z": 0.0 + }, + { + "x": 1.9856817691413284, + "y": -175.30292962634633, + "z": 0.0 + }, + { + "x": 1.9851583848483565, + "y": -174.30084496399547, + "z": 0.0 + }, + { + "x": 1.984635000555384, + "y": -173.29876030164462, + "z": 0.0 + }, + { + "x": 1.9841116162624122, + "y": -172.29667563929377, + "z": 0.0 + }, + { + "x": 1.9835882319694402, + "y": -171.2945909769429, + "z": 0.0 + }, + { + "x": 1.9830648476764678, + "y": -170.29250631459206, + "z": 0.0 + }, + { + "x": 1.982541463383496, + "y": -169.29042165224126, + "z": 0.0 + }, + { + "x": 1.982018079090524, + "y": -168.2883369898904, + "z": 0.0 + }, + { + "x": 1.9814946947975516, + "y": -167.28625232753956, + "z": 0.0 + }, + { + "x": 1.9809713105045796, + "y": -166.2841676651887, + "z": 0.0 + }, + { + "x": 1.9804479262116077, + "y": -165.28208300283785, + "z": 0.0 + }, + { + "x": 1.9799245419186353, + "y": -164.27999834048705, + "z": 0.0 + }, + { + "x": 1.9794011576256634, + "y": -163.2779136781362, + "z": 0.0 + }, + { + "x": 1.9788777733326914, + "y": -162.27582901578535, + "z": 0.0 + }, + { + "x": 1.978354389039719, + "y": -161.2737443534345, + "z": 0.0 + }, + { + "x": 1.9778310047467471, + "y": -160.27165969108364, + "z": 0.0 + }, + { + "x": 1.9773076204537752, + "y": -159.2695750287328, + "z": 0.0 + }, + { + "x": 1.9767842361608028, + "y": -158.26749036638194, + "z": 0.0 + }, + { + "x": 1.9762608518678308, + "y": -157.26540570403108, + "z": 0.0 + }, + { + "x": 1.975737467574859, + "y": -156.26332104168029, + "z": 0.0 + }, + { + "x": 1.9752140832818865, + "y": -155.26123637932943, + "z": 0.0 + }, + { + "x": 1.9746906989889146, + "y": -154.25915171697858, + "z": 0.0 + }, + { + "x": 1.9741673146959426, + "y": -153.25706705462773, + "z": 0.0 + }, + { + "x": 1.9736439304029703, + "y": -152.25498239227687, + "z": 0.0 + }, + { + "x": 1.9731205461099983, + "y": -151.25289772992608, + "z": 0.0 + }, + { + "x": 1.9725971618170264, + "y": -150.25081306757522, + "z": 0.0 + }, + { + "x": 1.972073777524054, + "y": -149.24872840522437, + "z": 0.0 + }, + { + "x": 1.971550393231082, + "y": -148.24664374287352, + "z": 0.0 + }, + { + "x": 1.9710270089381097, + "y": -147.24455908052266, + "z": 0.0 + }, + { + "x": 1.9705036246451377, + "y": -146.2424744181718, + "z": 0.0 + }, + { + "x": 1.9699802403521658, + "y": -145.24038975582096, + "z": 0.0 + }, + { + "x": 1.9694568560591934, + "y": -144.23830509347016, + "z": 0.0 + }, + { + "x": 1.9689334717662215, + "y": -143.2362204311193, + "z": 0.0 + }, + { + "x": 1.9684100874732495, + "y": -142.23413576876845, + "z": 0.0 + }, + { + "x": 1.9678867031802771, + "y": -141.2320511064176, + "z": 0.0 + }, + { + "x": 1.9673633188873052, + "y": -140.2299664440668, + "z": 0.0 + }, + { + "x": 1.9668399345943333, + "y": -139.22788178171595, + "z": 0.0 + }, + { + "x": 1.9663165503013609, + "y": -138.2257971193651, + "z": 0.0 + }, + { + "x": 1.965793166008389, + "y": -137.22371245701424, + "z": 0.0 + }, + { + "x": 1.965269781715417, + "y": -136.2216277946634, + "z": 0.0 + }, + { + "x": 1.9647463974224446, + "y": -135.21954313231254, + "z": 0.0 + }, + { + "x": 1.9642230131294727, + "y": -134.21745846996168, + "z": 0.0 + }, + { + "x": 1.9636996288365007, + "y": -133.21537380761077, + "z": 0.0 + }, + { + "x": 1.9631762445435283, + "y": -132.21328914525992, + "z": 0.0 + }, + { + "x": 1.9626528602505564, + "y": -131.21120448290907, + "z": 0.0 + }, + { + "x": 1.9621294759575845, + "y": -130.20911982055821, + "z": 0.0 + }, + { + "x": 1.961606091664612, + "y": -129.20703515820736, + "z": 0.0 + }, + { + "x": 1.9610827073716401, + "y": -128.2049504958565, + "z": 0.0 + }, + { + "x": 1.9605593230786678, + "y": -127.20286583350565, + "z": 0.0 + }, + { + "x": 1.9600359387856958, + "y": -126.2007811711548, + "z": 0.0 + }, + { + "x": 1.9595125544927239, + "y": -125.19869650880393, + "z": 0.0 + }, + { + "x": 1.9589891701997515, + "y": -124.19661184645308, + "z": 0.0 + }, + { + "x": 1.9584657859067796, + "y": -123.19452718410223, + "z": 0.0 + }, + { + "x": 1.9579424016138076, + "y": -122.19244252175136, + "z": 0.0 + }, + { + "x": 1.9574190173208352, + "y": -121.19035785940049, + "z": 0.0 + }, + { + "x": 1.9568956330278633, + "y": -120.18827319704965, + "z": 0.0 + }, + { + "x": 1.9563722487348914, + "y": -119.1861885346988, + "z": 0.0 + }, + { + "x": 1.955848864441919, + "y": -118.18410387234793, + "z": 0.0 + }, + { + "x": 1.955325480148947, + "y": -117.18201920999707, + "z": 0.0 + }, + { + "x": 1.954802095855975, + "y": -116.17993454764621, + "z": 0.0 + }, + { + "x": 1.9542787115630027, + "y": -115.17784988529536, + "z": 0.0 + }, + { + "x": 1.9537553272700308, + "y": -114.1757652229445, + "z": 0.0 + }, + { + "x": 1.9532319429770584, + "y": -113.17368056059364, + "z": 0.0 + }, + { + "x": 1.9527085586840864, + "y": -112.17159589824278, + "z": 0.0 + }, + { + "x": 1.9521851743911145, + "y": -111.16951123589193, + "z": 0.0 + }, + { + "x": 1.9516617900981421, + "y": -110.16742657354106, + "z": 0.0 + }, + { + "x": 1.9511384058051702, + "y": -109.1653419111902, + "z": 0.0 + }, + { + "x": 1.9506150215121982, + "y": -108.16325724883936, + "z": 0.0 + }, + { + "x": 1.9500916372192258, + "y": -107.1611725864885, + "z": 0.0 + }, + { + "x": 1.949568252926254, + "y": -106.15908792413764, + "z": 0.0 + }, + { + "x": 1.949044868633282, + "y": -105.15700326178677, + "z": 0.0 + }, + { + "x": 1.9485214843403096, + "y": -104.15491859943592, + "z": 0.0 + }, + { + "x": 1.9479981000473376, + "y": -103.15283393708506, + "z": 0.0 + }, + { + "x": 1.9474747157543657, + "y": -102.15074927473421, + "z": 0.0 + }, + { + "x": 1.9469513314613933, + "y": -101.14866461238334, + "z": 0.0 + }, + { + "x": 1.9464279471684214, + "y": -100.14657995003249, + "z": 0.0 + }, + { + "x": 1.945904562875449, + "y": -99.14449528768164, + "z": 0.0 + }, + { + "x": 1.945381178582477, + "y": -98.14241062533077, + "z": 0.0 + }, + { + "x": 1.9448577942895051, + "y": -97.1403259629799, + "z": 0.0 + }, + { + "x": 1.9443344099965327, + "y": -96.13824130062906, + "z": 0.0 + }, + { + "x": 1.9438110257035608, + "y": -95.13615663827821, + "z": 0.0 + }, + { + "x": 1.9432876414105889, + "y": -94.13407197592734, + "z": 0.0 + }, + { + "x": 1.9427642571176165, + "y": -93.13198731357647, + "z": 0.0 + }, + { + "x": 1.9422408728246445, + "y": -92.12990265122562, + "z": 0.0 + }, + { + "x": 1.9417174885316726, + "y": -91.12781798887478, + "z": 0.0 + }, + { + "x": 1.9411941042387002, + "y": -90.12573332652391, + "z": 0.0 + }, + { + "x": 1.9406707199457283, + "y": -89.12364866417305, + "z": 0.0 + }, + { + "x": 1.9401473356527563, + "y": -88.1215640018222, + "z": 0.0 + }, + { + "x": 1.9402771312086453, + "y": -87.12078237878384, + "z": 0.0 + }, + { + "x": 1.9406630106088594, + "y": -86.11920953013264, + "z": 0.0 + }, + { + "x": 1.94104902168355, + "y": -85.11712480544843, + "z": 0.0 + }, + { + "x": 1.9414350327582408, + "y": -84.11504008076425, + "z": 0.0 + }, + { + "x": 1.9418210438329315, + "y": -83.11295535608005, + "z": 0.0 + }, + { + "x": 1.9422070549076222, + "y": -82.11087063139585, + "z": 0.0 + }, + { + "x": 1.9425930659823125, + "y": -81.10878590671165, + "z": 0.0 + }, + { + "x": 1.9429790770570032, + "y": -80.10670118202746, + "z": 0.0 + }, + { + "x": 1.943365088131694, + "y": -79.10461645734327, + "z": 0.0 + }, + { + "x": 1.9437510992063847, + "y": -78.10253173265907, + "z": 0.0 + }, + { + "x": 1.9441371102810754, + "y": -77.10044700797486, + "z": 0.0 + }, + { + "x": 1.944523121355766, + "y": -76.09836228329068, + "z": 0.0 + }, + { + "x": 1.9449091324304564, + "y": -75.09627755860649, + "z": 0.0 + }, + { + "x": 1.945295143505147, + "y": -74.09419283392229, + "z": 0.0 + }, + { + "x": 1.9456811545798378, + "y": -73.0921081092381, + "z": 0.0 + }, + { + "x": 1.9460671656545285, + "y": -72.0900233845539, + "z": 0.0 + }, + { + "x": 1.9464531767292192, + "y": -71.0879386598697, + "z": 0.0 + }, + { + "x": 1.94683918780391, + "y": -70.08585393518551, + "z": 0.0 + }, + { + "x": 1.9472251988786002, + "y": -69.08376921050132, + "z": 0.0 + }, + { + "x": 1.947611209953291, + "y": -68.08168448581712, + "z": 0.0 + }, + { + "x": 1.9479972210279817, + "y": -67.07959976113293, + "z": 0.0 + }, + { + "x": 1.9483832321026724, + "y": -66.07751503644873, + "z": 0.0 + }, + { + "x": 1.948769243177363, + "y": -65.07543031176453, + "z": 0.0 + }, + { + "x": 1.9491552542520538, + "y": -64.07334558708034, + "z": 0.0 + }, + { + "x": 1.9495412653267445, + "y": -63.07126086239614, + "z": 0.0 + }, + { + "x": 1.9499272764014348, + "y": -62.06917613771194, + "z": 0.0 + }, + { + "x": 1.9503132874761255, + "y": -61.06709141302775, + "z": 0.0 + }, + { + "x": 1.9506992985508163, + "y": -60.06500668834355, + "z": 0.0 + }, + { + "x": 1.951085309625507, + "y": -59.062921963659356, + "z": 0.0 + }, + { + "x": 1.9514713207001977, + "y": -58.06083723897516, + "z": 0.0 + }, + { + "x": 1.9518573317748884, + "y": -57.058752514290966, + "z": 0.0 + }, + { + "x": 1.9522433428495787, + "y": -56.05666778960677, + "z": 0.0 + }, + { + "x": 1.9526293539242694, + "y": -55.05458306492257, + "z": 0.0 + }, + { + "x": 1.9530153649989601, + "y": -54.05249834023837, + "z": 0.0 + }, + { + "x": 1.9534013760736508, + "y": -53.05041361555418, + "z": 0.0 + }, + { + "x": 1.9537873871483415, + "y": -52.04832889086998, + "z": 0.0 + }, + { + "x": 1.9541733982230323, + "y": -51.04624416618579, + "z": 0.0 + }, + { + "x": 1.9545594092977225, + "y": -50.04415944150159, + "z": 0.0 + }, + { + "x": 1.9549454203724133, + "y": -49.042074716817396, + "z": 0.0 + }, + { + "x": 1.955331431447104, + "y": -48.0399899921332, + "z": 0.0 + }, + { + "x": 1.9557174425217947, + "y": -47.037905267449005, + "z": 0.0 + }, + { + "x": 1.9561034535964854, + "y": -46.03582054276481, + "z": 0.0 + }, + { + "x": 1.9564894646711761, + "y": -45.033735818080615, + "z": 0.0 + }, + { + "x": 1.9568754757458668, + "y": -44.03165109339642, + "z": 0.0 + }, + { + "x": 1.9572614868205571, + "y": -43.029566368712224, + "z": 0.0 + }, + { + "x": 1.9576474978952478, + "y": -42.02748164402803, + "z": 0.0 + }, + { + "x": 1.9580335089699386, + "y": -41.025396919343834, + "z": 0.0 + }, + { + "x": 1.9584195200446293, + "y": -40.023312194659646, + "z": 0.0 + }, + { + "x": 1.95880553111932, + "y": -39.02122746997545, + "z": 0.0 + }, + { + "x": 1.9591915421940107, + "y": -38.019142745291255, + "z": 0.0 + }, + { + "x": 1.959577553268701, + "y": -37.01705802060707, + "z": 0.0 + }, + { + "x": 1.9599635643433917, + "y": -36.01497329592287, + "z": 0.0 + }, + { + "x": 1.9603495754180824, + "y": -35.01288857123868, + "z": 0.0 + }, + { + "x": 1.9607355864927731, + "y": -34.01080384655449, + "z": 0.0 + }, + { + "x": 1.9611215975674638, + "y": -33.00871912187029, + "z": 0.0 + }, + { + "x": 1.9615076086421546, + "y": -32.006634397186104, + "z": 0.0 + }, + { + "x": 1.9618936197168448, + "y": -31.004549672501913, + "z": 0.0 + }, + { + "x": 1.9622796307915356, + "y": -30.002464947817717, + "z": 0.0 + }, + { + "x": 1.9626656418662263, + "y": -29.000380223133526, + "z": 0.0 + }, + { + "x": 1.963051652940917, + "y": -27.998295498449334, + "z": 0.0 + }, + { + "x": 1.9634376640156077, + "y": -26.996210773765142, + "z": 0.0 + }, + { + "x": 1.9638236750902984, + "y": -25.99412604908095, + "z": 0.0 + }, + { + "x": 1.9642096861649887, + "y": -24.992041324396755, + "z": 0.0 + }, + { + "x": 1.9645956972396794, + "y": -23.989956599712563, + "z": 0.0 + }, + { + "x": 1.9649817083143701, + "y": -22.987871875028368, + "z": 0.0 + }, + { + "x": 1.9653677193890609, + "y": -21.985787150344173, + "z": 0.0 + }, + { + "x": 1.9657537304637516, + "y": -20.98370242565998, + "z": 0.0 + }, + { + "x": 1.9661397415384423, + "y": -19.981617700975786, + "z": 0.0 + }, + { + "x": 1.9665257526131326, + "y": -18.97953297629159, + "z": 0.0 + }, + { + "x": 1.9669117636878233, + "y": -17.9774482516074, + "z": 0.0 + }, + { + "x": 1.967297774762514, + "y": -16.975363526923203, + "z": 0.0 + }, + { + "x": 1.9676837858372047, + "y": -15.973278802239012, + "z": 0.0 + }, + { + "x": 1.9680697969118954, + "y": -14.971194077554818, + "z": 0.0 + }, + { + "x": 1.9684558079865861, + "y": -13.969109352870625, + "z": 0.0 + }, + { + "x": 1.9688418190612764, + "y": -12.967024628186431, + "z": 0.0 + }, + { + "x": 1.9692278301359671, + "y": -11.964939903502238, + "z": 0.0 + }, + { + "x": 1.9696138412106579, + "y": -10.962855178818044, + "z": 0.0 + }, + { + "x": 1.9699998522853486, + "y": -9.96077045413385, + "z": 0.0 + } + ] + }, + { + "id": 79, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": -2.029999850944244, + "y": -9.959229622160095, + "z": 0.0 + }, + { + "x": -2.0303858620189343, + "y": -10.961314346844288, + "z": 0.0 + }, + { + "x": -2.0307718730936255, + "y": -11.963399071528482, + "z": 0.0 + }, + { + "x": -2.0311578841683158, + "y": -12.965483796212675, + "z": 0.0 + }, + { + "x": -2.031543895243007, + "y": -13.967568520896869, + "z": 0.0 + }, + { + "x": -2.031929906317697, + "y": -14.969653245581062, + "z": 0.0 + }, + { + "x": -2.0323159173923884, + "y": -15.971737970265256, + "z": 0.0 + }, + { + "x": -2.0327019284670786, + "y": -16.973822694949448, + "z": 0.0 + }, + { + "x": -2.033087939541769, + "y": -17.975907419633643, + "z": 0.0 + }, + { + "x": -2.03347395061646, + "y": -18.977992144317835, + "z": 0.0 + }, + { + "x": -2.0338599616911504, + "y": -19.98007686900203, + "z": 0.0 + }, + { + "x": -2.0342459727658415, + "y": -20.982161593686225, + "z": 0.0 + }, + { + "x": -2.034631983840532, + "y": -21.984246318370417, + "z": 0.0 + }, + { + "x": -2.035017994915222, + "y": -22.986331043054612, + "z": 0.0 + }, + { + "x": -2.0354040059899132, + "y": -23.988415767738807, + "z": 0.0 + }, + { + "x": -2.0357900170646035, + "y": -24.990500492423, + "z": 0.0 + }, + { + "x": -2.0361760281392947, + "y": -25.992585217107194, + "z": 0.0 + }, + { + "x": -2.036562039213985, + "y": -26.994669941791386, + "z": 0.0 + }, + { + "x": -2.036948050288676, + "y": -27.996754666475578, + "z": 0.0 + }, + { + "x": -2.0373340613633664, + "y": -28.99883939115977, + "z": 0.0 + }, + { + "x": -2.0377200724380566, + "y": -30.00092411584396, + "z": 0.0 + }, + { + "x": -2.038106083512748, + "y": -31.003008840528157, + "z": 0.0 + }, + { + "x": -2.038492094587438, + "y": -32.00509356521235, + "z": 0.0 + }, + { + "x": -2.0388781056621292, + "y": -33.00717828989654, + "z": 0.0 + }, + { + "x": -2.0392641167368195, + "y": -34.00926301458073, + "z": 0.0 + }, + { + "x": -2.03965012781151, + "y": -35.01134773926493, + "z": 0.0 + }, + { + "x": -2.040036138886201, + "y": -36.013432463949115, + "z": 0.0 + }, + { + "x": -2.040422149960891, + "y": -37.01551718863331, + "z": 0.0 + }, + { + "x": -2.0408081610355824, + "y": -38.0176019133175, + "z": 0.0 + }, + { + "x": -2.0411941721102727, + "y": -39.019686638001694, + "z": 0.0 + }, + { + "x": -2.041580183184964, + "y": -40.02177136268589, + "z": 0.0 + }, + { + "x": -2.041966194259654, + "y": -41.02385608737008, + "z": 0.0 + }, + { + "x": -2.0423522053343444, + "y": -42.02594081205427, + "z": 0.0 + }, + { + "x": -2.0427382164090355, + "y": -43.02802553673847, + "z": 0.0 + }, + { + "x": -2.043124227483726, + "y": -44.030110261422664, + "z": 0.0 + }, + { + "x": -2.043510238558417, + "y": -45.03219498610686, + "z": 0.0 + }, + { + "x": -2.0438962496331072, + "y": -46.034279710791054, + "z": 0.0 + }, + { + "x": -2.0442822607077984, + "y": -47.03636443547525, + "z": 0.0 + }, + { + "x": -2.0446682717824887, + "y": -48.038449160159445, + "z": 0.0 + }, + { + "x": -2.045054282857179, + "y": -49.04053388484364, + "z": 0.0 + }, + { + "x": -2.04544029393187, + "y": -50.042618609527835, + "z": 0.0 + }, + { + "x": -2.0458263050065604, + "y": -51.04470333421203, + "z": 0.0 + }, + { + "x": -2.0462123160812515, + "y": -52.046788058896226, + "z": 0.0 + }, + { + "x": -2.046598327155942, + "y": -53.04887278358042, + "z": 0.0 + }, + { + "x": -2.046984338230632, + "y": -54.05095750826462, + "z": 0.0 + }, + { + "x": -2.0473703493053232, + "y": -55.05304223294881, + "z": 0.0 + }, + { + "x": -2.0477563603800135, + "y": -56.055126957633014, + "z": 0.0 + }, + { + "x": -2.0481423714547047, + "y": -57.05721168231721, + "z": 0.0 + }, + { + "x": -2.048528382529395, + "y": -58.059296407001405, + "z": 0.0 + }, + { + "x": -2.048914393604086, + "y": -59.0613811316856, + "z": 0.0 + }, + { + "x": -2.0493004046787764, + "y": -60.063465856369795, + "z": 0.0 + }, + { + "x": -2.0496864157534667, + "y": -61.06555058105399, + "z": 0.0 + }, + { + "x": -2.050072426828158, + "y": -62.067635305738186, + "z": 0.0 + }, + { + "x": -2.050458437902848, + "y": -63.06972003042238, + "z": 0.0 + }, + { + "x": -2.0508444489775393, + "y": -64.07180475510658, + "z": 0.0 + }, + { + "x": -2.0512304600522295, + "y": -65.07388947979078, + "z": 0.0 + }, + { + "x": -2.05161647112692, + "y": -66.07597420447497, + "z": 0.0 + }, + { + "x": -2.052002482201611, + "y": -67.07805892915917, + "z": 0.0 + }, + { + "x": -2.0523884932763012, + "y": -68.08014365384336, + "z": 0.0 + }, + { + "x": -2.0527745043509924, + "y": -69.08222837852756, + "z": 0.0 + }, + { + "x": -2.0531605154256827, + "y": -70.08431310321176, + "z": 0.0 + }, + { + "x": -2.053546526500374, + "y": -71.08639782789595, + "z": 0.0 + }, + { + "x": -2.053932537575064, + "y": -72.08848255258015, + "z": 0.0 + }, + { + "x": -2.0543185486497544, + "y": -73.09056727726434, + "z": 0.0 + }, + { + "x": -2.0547045597244455, + "y": -74.09265200194854, + "z": 0.0 + }, + { + "x": -2.055090570799136, + "y": -75.09473672663273, + "z": 0.0 + }, + { + "x": -2.055476581873827, + "y": -76.09682145131693, + "z": 0.0 + }, + { + "x": -2.0558625929485173, + "y": -77.09890617600111, + "z": 0.0 + }, + { + "x": -2.0562486040232084, + "y": -78.10099090068532, + "z": 0.0 + }, + { + "x": -2.0566346150978987, + "y": -79.10307562536951, + "z": 0.0 + }, + { + "x": -2.057020626172589, + "y": -80.10516035005371, + "z": 0.0 + }, + { + "x": -2.05740663724728, + "y": -81.10724507473789, + "z": 0.0 + }, + { + "x": -2.0577926483219704, + "y": -82.1093297994221, + "z": 0.0 + }, + { + "x": -2.0581786593966616, + "y": -83.1114145241063, + "z": 0.0 + }, + { + "x": -2.058564670471352, + "y": -84.11349924879049, + "z": 0.0 + }, + { + "x": -2.058950681546042, + "y": -85.11558397347467, + "z": 0.0 + }, + { + "x": -2.0593366926207333, + "y": -86.11766869815888, + "z": 0.0 + }, + { + "x": -2.0597228353699, + "y": -87.12026529887606, + "z": 0.0 + }, + { + "x": -2.0598521187622114, + "y": -88.12365318347021, + "z": 0.0 + }, + { + "x": -2.0593287344692395, + "y": -89.12573784582106, + "z": 0.0 + }, + { + "x": -2.0588053501762675, + "y": -90.12782250817193, + "z": 0.0 + }, + { + "x": -2.0582819658832956, + "y": -91.1299071705228, + "z": 0.0 + }, + { + "x": -2.0577585815903237, + "y": -92.13199183287364, + "z": 0.0 + }, + { + "x": -2.057235197297351, + "y": -93.13407649522449, + "z": 0.0 + }, + { + "x": -2.056711813004379, + "y": -94.13616115757536, + "z": 0.0 + }, + { + "x": -2.056188428711407, + "y": -95.13824581992623, + "z": 0.0 + }, + { + "x": -2.055665044418435, + "y": -96.14033048227708, + "z": 0.0 + }, + { + "x": -2.055141660125463, + "y": -97.14241514462792, + "z": 0.0 + }, + { + "x": -2.0546182758324902, + "y": -98.14449980697879, + "z": 0.0 + }, + { + "x": -2.0540948915395183, + "y": -99.14658446932965, + "z": 0.0 + }, + { + "x": -2.0535715072465464, + "y": -100.1486691316805, + "z": 0.0 + }, + { + "x": -2.0530481229535744, + "y": -101.15075379403136, + "z": 0.0 + }, + { + "x": -2.0525247386606025, + "y": -102.15283845638223, + "z": 0.0 + }, + { + "x": -2.0520013543676305, + "y": -103.15492311873308, + "z": 0.0 + }, + { + "x": -2.0514779700746577, + "y": -104.15700778108393, + "z": 0.0 + }, + { + "x": -2.0509545857816858, + "y": -105.15909244343479, + "z": 0.0 + }, + { + "x": -2.050431201488714, + "y": -106.16117710578565, + "z": 0.0 + }, + { + "x": -2.049907817195742, + "y": -107.16326176813652, + "z": 0.0 + }, + { + "x": -2.04938443290277, + "y": -108.16534643048738, + "z": 0.0 + }, + { + "x": -2.048861048609797, + "y": -109.16743109283821, + "z": 0.0 + }, + { + "x": -2.048337664316825, + "y": -110.16951575518908, + "z": 0.0 + }, + { + "x": -2.0478142800238532, + "y": -111.17160041753995, + "z": 0.0 + }, + { + "x": -2.0472908957308813, + "y": -112.1736850798908, + "z": 0.0 + }, + { + "x": -2.0467675114379094, + "y": -113.17576974224166, + "z": 0.0 + }, + { + "x": -2.0462441271449374, + "y": -114.17785440459252, + "z": 0.0 + }, + { + "x": -2.0457207428519646, + "y": -115.17993906694338, + "z": 0.0 + }, + { + "x": -2.0451973585589927, + "y": -116.18202372929423, + "z": 0.0 + }, + { + "x": -2.0446739742660207, + "y": -117.18410839164508, + "z": 0.0 + }, + { + "x": -2.0441505899730488, + "y": -118.18619305399595, + "z": 0.0 + }, + { + "x": -2.043627205680077, + "y": -119.18827771634682, + "z": 0.0 + }, + { + "x": -2.043103821387105, + "y": -120.19036237869767, + "z": 0.0 + }, + { + "x": -2.042580437094132, + "y": -121.19244704104851, + "z": 0.0 + }, + { + "x": -2.04205705280116, + "y": -122.19453170339938, + "z": 0.0 + }, + { + "x": -2.041533668508188, + "y": -123.19661636575024, + "z": 0.0 + }, + { + "x": -2.0410102842152162, + "y": -124.1987010281011, + "z": 0.0 + }, + { + "x": -2.0404868999222443, + "y": -125.20078569045195, + "z": 0.0 + }, + { + "x": -2.0399635156292715, + "y": -126.20287035280282, + "z": 0.0 + }, + { + "x": -2.0394401313362995, + "y": -127.20495501515367, + "z": 0.0 + }, + { + "x": -2.0389167470433276, + "y": -128.20703967750455, + "z": 0.0 + }, + { + "x": -2.0383933627503557, + "y": -129.2091243398554, + "z": 0.0 + }, + { + "x": -2.0378699784573837, + "y": -130.21120900220626, + "z": 0.0 + }, + { + "x": -2.0373465941644118, + "y": -131.2132936645571, + "z": 0.0 + }, + { + "x": -2.036823209871439, + "y": -132.21537832690797, + "z": 0.0 + }, + { + "x": -2.036299825578467, + "y": -133.21746298925882, + "z": 0.0 + }, + { + "x": -2.035776441285495, + "y": -134.21954765160967, + "z": 0.0 + }, + { + "x": -2.035253056992523, + "y": -135.22163231396053, + "z": 0.0 + }, + { + "x": -2.034729672699551, + "y": -136.22371697631138, + "z": 0.0 + }, + { + "x": -2.0342062884065784, + "y": -137.22580163866223, + "z": 0.0 + }, + { + "x": -2.0336829041136064, + "y": -138.2278863010131, + "z": 0.0 + }, + { + "x": -2.0331595198206345, + "y": -139.22997096336394, + "z": 0.0 + }, + { + "x": -2.0326361355276625, + "y": -140.2320556257148, + "z": 0.0 + }, + { + "x": -2.0321127512346906, + "y": -141.23414028806565, + "z": 0.0 + }, + { + "x": -2.0315893669417187, + "y": -142.2362249504165, + "z": 0.0 + }, + { + "x": -2.031065982648746, + "y": -143.23830961276735, + "z": 0.0 + }, + { + "x": -2.030542598355774, + "y": -144.24039427511815, + "z": 0.0 + }, + { + "x": -2.030019214062802, + "y": -145.242478937469, + "z": 0.0 + }, + { + "x": -2.02949582976983, + "y": -146.24456359981986, + "z": 0.0 + }, + { + "x": -2.028972445476858, + "y": -147.2466482621707, + "z": 0.0 + }, + { + "x": -2.028449061183886, + "y": -148.24873292452156, + "z": 0.0 + }, + { + "x": -2.0279256768909133, + "y": -149.25081758687236, + "z": 0.0 + }, + { + "x": -2.0274022925979414, + "y": -150.2529022492232, + "z": 0.0 + }, + { + "x": -2.0268789083049694, + "y": -151.25498691157406, + "z": 0.0 + }, + { + "x": -2.0263555240119975, + "y": -152.25707157392492, + "z": 0.0 + }, + { + "x": -2.0258321397190255, + "y": -153.25915623627577, + "z": 0.0 + }, + { + "x": -2.0253087554260536, + "y": -154.26124089862662, + "z": 0.0 + }, + { + "x": -2.0247853711330808, + "y": -155.26332556097748, + "z": 0.0 + }, + { + "x": -2.024261986840109, + "y": -156.26541022332833, + "z": 0.0 + }, + { + "x": -2.023738602547137, + "y": -157.26749488567913, + "z": 0.0 + }, + { + "x": -2.023215218254165, + "y": -158.26957954802998, + "z": 0.0 + }, + { + "x": -2.022691833961193, + "y": -159.27166421038083, + "z": 0.0 + }, + { + "x": -2.022168449668221, + "y": -160.27374887273163, + "z": 0.0 + }, + { + "x": -2.0216450653752482, + "y": -161.27583353508248, + "z": 0.0 + }, + { + "x": -2.0211216810822763, + "y": -162.27791819743334, + "z": 0.0 + }, + { + "x": -2.0205982967893044, + "y": -163.2800028597842, + "z": 0.0 + }, + { + "x": -2.0200749124963324, + "y": -164.28208752213504, + "z": 0.0 + }, + { + "x": -2.0195515282033605, + "y": -165.2841721844859, + "z": 0.0 + }, + { + "x": -2.0190281439103885, + "y": -166.28625684683675, + "z": 0.0 + }, + { + "x": -2.0185047596174157, + "y": -167.2883415091876, + "z": 0.0 + }, + { + "x": -2.0179813753244438, + "y": -168.2904261715384, + "z": 0.0 + }, + { + "x": -2.017457991031472, + "y": -169.29251083388925, + "z": 0.0 + }, + { + "x": -2.0169346067385, + "y": -170.2945954962401, + "z": 0.0 + }, + { + "x": -2.016411222445528, + "y": -171.29668015859096, + "z": 0.0 + }, + { + "x": -2.015887838152555, + "y": -172.2987648209418, + "z": 0.0 + }, + { + "x": -2.015364453859583, + "y": -173.3008494832926, + "z": 0.0 + }, + { + "x": -2.0148410695666112, + "y": -174.30293414564346, + "z": 0.0 + }, + { + "x": -2.0143176852736393, + "y": -175.30501880799432, + "z": 0.0 + }, + { + "x": -2.0137943009806674, + "y": -176.30710347034517, + "z": 0.0 + }, + { + "x": -2.0132709166876954, + "y": -177.30918813269602, + "z": 0.0 + }, + { + "x": -2.0127475323947226, + "y": -178.31127279504688, + "z": 0.0 + }, + { + "x": -2.0122241481017507, + "y": -179.31335745739773, + "z": 0.0 + }, + { + "x": -2.0117007638087787, + "y": -180.31544211974858, + "z": 0.0 + }, + { + "x": -2.0111773795158068, + "y": -181.31752678209938, + "z": 0.0 + }, + { + "x": -2.010653995222835, + "y": -182.31961144445023, + "z": 0.0 + }, + { + "x": -2.010130610929863, + "y": -183.32169610680108, + "z": 0.0 + }, + { + "x": -2.00960722663689, + "y": -184.32378076915188, + "z": 0.0 + }, + { + "x": -2.009083842343918, + "y": -185.32586543150273, + "z": 0.0 + }, + { + "x": -2.008560458050946, + "y": -186.3279500938536, + "z": 0.0 + }, + { + "x": -2.0080370737579742, + "y": -187.33003475620444, + "z": 0.0 + }, + { + "x": -2.0075136894650023, + "y": -188.3321194185553, + "z": 0.0 + }, + { + "x": -2.0069903051720304, + "y": -189.33420408090615, + "z": 0.0 + }, + { + "x": -2.0064669208790575, + "y": -190.336288743257, + "z": 0.0 + }, + { + "x": -2.0059435365860856, + "y": -191.33837340560785, + "z": 0.0 + }, + { + "x": -2.0054201522931137, + "y": -192.34045806795865, + "z": 0.0 + }, + { + "x": -2.0048967680001417, + "y": -193.3425427303095, + "z": 0.0 + }, + { + "x": -2.0043733837071698, + "y": -194.34462739266036, + "z": 0.0 + }, + { + "x": -2.003849999414198, + "y": -195.3467120550112, + "z": 0.0 + }, + { + "x": -2.003326615121225, + "y": -196.34879671736206, + "z": 0.0 + }, + { + "x": -2.002803230828253, + "y": -197.35088137971286, + "z": 0.0 + }, + { + "x": -2.002279846535281, + "y": -198.3529660420637, + "z": 0.0 + }, + { + "x": -2.001756462242309, + "y": -199.35505070441457, + "z": 0.0 + }, + { + "x": -2.0012330779493372, + "y": -200.35713536676542, + "z": 0.0 + }, + { + "x": -2.0007096936563653, + "y": -201.35922002911627, + "z": 0.0 + }, + { + "x": -2.0001863093633925, + "y": -202.36130469146713, + "z": 0.0 + }, + { + "x": -1.9996629250704205, + "y": -203.36338935381798, + "z": 0.0 + }, + { + "x": -1.9991395407774486, + "y": -204.36547401616883, + "z": 0.0 + }, + { + "x": -1.9986161564844767, + "y": -205.36755867851963, + "z": 0.0 + }, + { + "x": -1.9980927721915043, + "y": -206.36964334087048, + "z": 0.0 + }, + { + "x": -1.9975693878985323, + "y": -207.37172800322134, + "z": 0.0 + }, + { + "x": -1.9970460036055604, + "y": -208.37381266557213, + "z": 0.0 + }, + { + "x": -1.996522619312588, + "y": -209.37589732792298, + "z": 0.0 + }, + { + "x": -1.995999235019616, + "y": -210.37798199027384, + "z": 0.0 + }, + { + "x": -1.9954758507266441, + "y": -211.3800666526247, + "z": 0.0 + }, + { + "x": -1.9949524664336717, + "y": -212.38215131497554, + "z": 0.0 + }, + { + "x": -1.9944290821406998, + "y": -213.3842359773264, + "z": 0.0 + }, + { + "x": -1.9939056978477279, + "y": -214.38632063967725, + "z": 0.0 + }, + { + "x": -1.9933823135547555, + "y": -215.3884053020281, + "z": 0.0 + }, + { + "x": -1.9928589292617835, + "y": -216.3904899643789, + "z": 0.0 + }, + { + "x": -1.9923355449688116, + "y": -217.39257462672975, + "z": 0.0 + }, + { + "x": -1.9918121606758392, + "y": -218.3946592890806, + "z": 0.0 + }, + { + "x": -1.9912887763828673, + "y": -219.39674395143146, + "z": 0.0 + }, + { + "x": -1.9907653920898953, + "y": -220.3988286137823, + "z": 0.0 + }, + { + "x": -1.990242007796923, + "y": -221.4009132761331, + "z": 0.0 + }, + { + "x": -1.989718623503951, + "y": -222.40299793848396, + "z": 0.0 + }, + { + "x": -1.989195239210979, + "y": -223.40508260083482, + "z": 0.0 + }, + { + "x": -1.9886718549180067, + "y": -224.40716726318567, + "z": 0.0 + }, + { + "x": -1.9881484706250347, + "y": -225.40925192553652, + "z": 0.0 + }, + { + "x": -1.9876250863320628, + "y": -226.41133658788738, + "z": 0.0 + }, + { + "x": -1.9871017020390904, + "y": -227.41342125023823, + "z": 0.0 + }, + { + "x": -1.9865783177461185, + "y": -228.41550591258908, + "z": 0.0 + }, + { + "x": -1.9860549334531465, + "y": -229.41759057493988, + "z": 0.0 + }, + { + "x": -1.9855315491601742, + "y": -230.41967523729073, + "z": 0.0 + }, + { + "x": -1.9850081648672022, + "y": -231.4217598996416, + "z": 0.0 + }, + { + "x": -1.9844847805742303, + "y": -232.42384456199238, + "z": 0.0 + }, + { + "x": -1.983961396281258, + "y": -233.42592922434324, + "z": 0.0 + }, + { + "x": -1.983438011988286, + "y": -234.4280138866941, + "z": 0.0 + }, + { + "x": -1.9829146276953136, + "y": -235.43009854904494, + "z": 0.0 + }, + { + "x": -1.9823912434023416, + "y": -236.4321832113958, + "z": 0.0 + }, + { + "x": -1.9818678591093697, + "y": -237.43426787374665, + "z": 0.0 + }, + { + "x": -1.9813444748163973, + "y": -238.4363525360975, + "z": 0.0 + }, + { + "x": -1.9808210905234254, + "y": -239.43843719844836, + "z": 0.0 + }, + { + "x": -1.9802979208801939, + "y": -240.439959526235, + "z": 0.0 + }, + { + "x": -1.9800563311504915, + "y": -241.441300874255, + "z": 0.0 + }, + { + "x": -1.9801871686771089, + "y": -242.44338566474505, + "z": 0.0 + }, + { + "x": -1.9803180062037262, + "y": -243.4454704552351, + "z": 0.0 + }, + { + "x": -1.980448843730344, + "y": -244.44755524572514, + "z": 0.0 + }, + { + "x": -1.9805796812569614, + "y": -245.44964003621516, + "z": 0.0 + }, + { + "x": -1.9807105187835792, + "y": -246.4517248267052, + "z": 0.0 + }, + { + "x": -1.9808413563101965, + "y": -247.45380961719528, + "z": 0.0 + }, + { + "x": -1.9809721938368134, + "y": -248.4558944076853, + "z": 0.0 + }, + { + "x": -1.9811030313634312, + "y": -249.45797919817534, + "z": 0.0 + }, + { + "x": -1.9812338688900486, + "y": -250.46006398866538, + "z": 0.0 + }, + { + "x": -1.981364706416666, + "y": -251.46214877915543, + "z": 0.0 + }, + { + "x": -1.9814955439432838, + "y": -252.46423356964547, + "z": 0.0 + }, + { + "x": -1.981626381469901, + "y": -253.4663183601355, + "z": 0.0 + }, + { + "x": -1.9817572189965185, + "y": -254.46840315062553, + "z": 0.0 + }, + { + "x": -1.9818880565231358, + "y": -255.47048794111558, + "z": 0.0 + }, + { + "x": -1.9820188940497536, + "y": -256.47257273160557, + "z": 0.0 + }, + { + "x": -1.9821497315763714, + "y": -257.47465752209564, + "z": 0.0 + }, + { + "x": -1.9822805691029888, + "y": -258.4767423125857, + "z": 0.0 + }, + { + "x": -1.9824114066296061, + "y": -259.47882710307573, + "z": 0.0 + }, + { + "x": -1.982542244156224, + "y": -260.4809118935658, + "z": 0.0 + }, + { + "x": -1.9826730816828413, + "y": -261.4829966840558, + "z": 0.0 + }, + { + "x": -1.9828039192094586, + "y": -262.48508147454584, + "z": 0.0 + }, + { + "x": -1.982934756736076, + "y": -263.4871662650359, + "z": 0.0 + }, + { + "x": -1.9830655942626938, + "y": -264.4892510555259, + "z": 0.0 + }, + { + "x": -1.9831964317893112, + "y": -265.49133584601594, + "z": 0.0 + }, + { + "x": -1.9833272693159285, + "y": -266.493420636506, + "z": 0.0 + }, + { + "x": -1.9834581068425459, + "y": -267.4955054269961, + "z": 0.0 + }, + { + "x": -1.9835889443691637, + "y": -268.49759021748616, + "z": 0.0 + }, + { + "x": -1.983719781895781, + "y": -269.49967500797624, + "z": 0.0 + }, + { + "x": -1.9838506194223984, + "y": -270.5017597984663, + "z": 0.0 + }, + { + "x": -1.9839814569490157, + "y": -271.5038445889563, + "z": 0.0 + }, + { + "x": -1.9841122944756335, + "y": -272.5059293794464, + "z": 0.0 + }, + { + "x": -1.9842431320022509, + "y": -273.5080141699365, + "z": 0.0 + }, + { + "x": -1.9843739695288682, + "y": -274.51009896042655, + "z": 0.0 + }, + { + "x": -1.984504807055486, + "y": -275.5121837509166, + "z": 0.0 + }, + { + "x": -1.9846356445821034, + "y": -276.5142685414067, + "z": 0.0 + }, + { + "x": -1.9847664821087208, + "y": -277.51635333189677, + "z": 0.0 + }, + { + "x": -1.984897319635338, + "y": -278.5184381223868, + "z": 0.0 + }, + { + "x": -1.985028157161956, + "y": -279.52052291287686, + "z": 0.0 + }, + { + "x": -1.9851589946885733, + "y": -280.52260770336693, + "z": 0.0 + }, + { + "x": -1.9852898322151906, + "y": -281.524692493857, + "z": 0.0 + }, + { + "x": -1.985420669741808, + "y": -282.5267772843471, + "z": 0.0 + }, + { + "x": -1.9855515072684258, + "y": -283.52886207483715, + "z": 0.0 + }, + { + "x": -1.9856823447950431, + "y": -284.5309468653272, + "z": 0.0 + }, + { + "x": -1.9858131823216605, + "y": -285.5330316558173, + "z": 0.0 + }, + { + "x": -1.9859440198482783, + "y": -286.53511644630737, + "z": 0.0 + }, + { + "x": -1.9860748573748956, + "y": -287.53720123679744, + "z": 0.0 + }, + { + "x": -1.986205694901513, + "y": -288.5392860272875, + "z": 0.0 + }, + { + "x": -1.9863365324281304, + "y": -289.5413708177776, + "z": 0.0 + }, + { + "x": -1.9864673699547482, + "y": -290.54345560826766, + "z": 0.0 + }, + { + "x": -1.9865982074813655, + "y": -291.54554039875774, + "z": 0.0 + }, + { + "x": -1.9867290450079829, + "y": -292.5476251892478, + "z": 0.0 + }, + { + "x": -1.9868598825346002, + "y": -293.5497099797379, + "z": 0.0 + }, + { + "x": -1.986990720061218, + "y": -294.5517947702279, + "z": 0.0 + }, + { + "x": -1.9871215575878354, + "y": -295.553879560718, + "z": 0.0 + }, + { + "x": -1.9872523951144527, + "y": -296.55596435120805, + "z": 0.0 + }, + { + "x": -1.98738323264107, + "y": -297.5580491416981, + "z": 0.0 + }, + { + "x": -1.9875140701676879, + "y": -298.5601339321882, + "z": 0.0 + }, + { + "x": -1.9876449076943052, + "y": -299.56221872267827, + "z": 0.0 + }, + { + "x": -1.9877757452209226, + "y": -300.56430351316834, + "z": 0.0 + }, + { + "x": -1.9879065827475404, + "y": -301.5663883036584, + "z": 0.0 + }, + { + "x": -1.9880374202741578, + "y": -302.5684730941485, + "z": 0.0 + }, + { + "x": -1.988168257800775, + "y": -303.5705578846385, + "z": 0.0 + }, + { + "x": -1.9882990953273925, + "y": -304.5726426751286, + "z": 0.0 + }, + { + "x": -1.9884299328540103, + "y": -305.57472746561865, + "z": 0.0 + }, + { + "x": -1.9885607703806276, + "y": -306.5768122561087, + "z": 0.0 + }, + { + "x": -1.988691607907245, + "y": -307.5788970465988, + "z": 0.0 + }, + { + "x": -1.9888224454338623, + "y": -308.58098183708887, + "z": 0.0 + }, + { + "x": -1.9889532829604801, + "y": -309.58306662757894, + "z": 0.0 + }, + { + "x": -1.9890841204870975, + "y": -310.58515141806896, + "z": 0.0 + }, + { + "x": -1.9892149580137148, + "y": -311.58723620855903, + "z": 0.0 + }, + { + "x": -1.9893457955403326, + "y": -312.5893209990491, + "z": 0.0 + }, + { + "x": -1.98947663306695, + "y": -313.5914057895392, + "z": 0.0 + }, + { + "x": -1.9896074705935674, + "y": -314.59349058002925, + "z": 0.0 + }, + { + "x": -1.9897383081201847, + "y": -315.5955753705193, + "z": 0.0 + }, + { + "x": -1.9898691456468025, + "y": -316.5976601610094, + "z": 0.0 + }, + { + "x": -1.9899999831734199, + "y": -317.5997449514995, + "z": 0.0 + } + ] + }, + { + "id": 80, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 340.8718824984497, + "y": -46.422407556799655, + "z": 0.0 + }, + { + "x": 340.8724973815697, + "y": -45.40440774249774, + "z": 0.0 + }, + { + "x": 340.8731122646897, + "y": -44.38640792819581, + "z": 0.0 + }, + { + "x": 340.87372714780986, + "y": -43.36840811389433, + "z": 0.0 + }, + { + "x": 340.8743420309299, + "y": -42.35040829959196, + "z": 0.0 + }, + { + "x": 340.8749569140499, + "y": -41.33240848529005, + "z": 0.0 + }, + { + "x": 340.8755717971699, + "y": -40.314408670988115, + "z": 0.0 + }, + { + "x": 340.87618668029, + "y": -39.29640885668642, + "z": 0.0 + }, + { + "x": 340.8768015634101, + "y": -38.2784090423845, + "z": 0.0 + }, + { + "x": 340.8774164465301, + "y": -37.26040922808235, + "z": 0.0 + }, + { + "x": 340.8780313296501, + "y": -36.24240941378043, + "z": 0.0 + }, + { + "x": 340.8786462127702, + "y": -35.22440959947873, + "z": 0.0 + }, + { + "x": 340.87926109589023, + "y": -34.20640978517658, + "z": 0.0 + }, + { + "x": 340.8798759790103, + "y": -33.188409970874886, + "z": 0.0 + }, + { + "x": 340.88049086213033, + "y": -32.170410156572736, + "z": 0.0 + }, + { + "x": 340.8811057452504, + "y": -31.15241034227104, + "z": 0.0 + }, + { + "x": 340.88172062837043, + "y": -30.134410527968893, + "z": 0.0 + }, + { + "x": 340.88233551149045, + "y": -29.11641071366697, + "z": 0.0 + }, + { + "x": 340.88295039461053, + "y": -28.098410899365273, + "z": 0.0 + }, + { + "x": 340.8835652777306, + "y": -27.08041108506335, + "z": 0.0 + }, + { + "x": 340.88418016085063, + "y": -26.062411270761203, + "z": 0.0 + }, + { + "x": 340.88479504397066, + "y": -25.04441145645928, + "z": 0.0 + }, + { + "x": 340.88540992709073, + "y": -24.02641164215758, + "z": 0.0 + }, + { + "x": 340.8860248102108, + "y": -23.008411827855657, + "z": 0.0 + }, + { + "x": 340.88663969333084, + "y": -21.99041201355351, + "z": 0.0 + }, + { + "x": 340.88725457645086, + "y": -20.97241219925159, + "z": 0.0 + }, + { + "x": 340.88786945957094, + "y": -19.95441238494989, + "z": 0.0 + }, + { + "x": 340.88848434269096, + "y": -18.936412570647743, + "z": 0.0 + }, + { + "x": 340.88909922581104, + "y": -17.918412756346047, + "z": 0.0 + }, + { + "x": 340.88971410893106, + "y": -16.9004129420439, + "z": 0.0 + }, + { + "x": 340.89032899205114, + "y": -15.882413127742202, + "z": 0.0 + }, + { + "x": 340.89094387517116, + "y": -14.864413313440057, + "z": 0.0 + }, + { + "x": 340.8915587582912, + "y": -13.846413499138135, + "z": 0.0 + }, + { + "x": 340.89217364141126, + "y": -12.828413684836438, + "z": 0.0 + }, + { + "x": 340.89278852453134, + "y": -11.810413870534514, + "z": 0.0 + }, + { + "x": 340.89340340765136, + "y": -10.792414056232369, + "z": 0.0 + } + ] + }, + { + "id": 81, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 332.89340486696824, + "y": -10.787581968845162, + "z": 0.0 + }, + { + "x": 332.8927899838482, + "y": -11.80558178314686, + "z": 0.0 + }, + { + "x": 332.89217510072814, + "y": -12.823581597448783, + "z": 0.0 + }, + { + "x": 332.89156021760806, + "y": -13.841581411750928, + "z": 0.0 + }, + { + "x": 332.89094533448804, + "y": -14.85958122605285, + "z": 0.0 + }, + { + "x": 332.890330451368, + "y": -15.877581040354547, + "z": 0.0 + }, + { + "x": 332.88971556824794, + "y": -16.895580854656693, + "z": 0.0 + }, + { + "x": 332.8891006851279, + "y": -17.913580668958392, + "z": 0.0 + }, + { + "x": 332.88848580200784, + "y": -18.931580483260536, + "z": 0.0 + }, + { + "x": 332.8878709188878, + "y": -19.949580297562235, + "z": 0.0 + }, + { + "x": 332.88725603576773, + "y": -20.967580111864383, + "z": 0.0 + }, + { + "x": 332.8866411526477, + "y": -21.985579926166302, + "z": 0.0 + }, + { + "x": 332.8860262695277, + "y": -23.003579740468002, + "z": 0.0 + }, + { + "x": 332.8854113864076, + "y": -24.021579554769925, + "z": 0.0 + }, + { + "x": 332.88479650328753, + "y": -25.039579369072072, + "z": 0.0 + }, + { + "x": 332.8841816201675, + "y": -26.057579183373996, + "z": 0.0 + }, + { + "x": 332.8835667370475, + "y": -27.075578997675695, + "z": 0.0 + }, + { + "x": 332.8829518539274, + "y": -28.09357881197762, + "z": 0.0 + }, + { + "x": 332.88233697080733, + "y": -29.111578626279762, + "z": 0.0 + }, + { + "x": 332.8817220876873, + "y": -30.129578440581685, + "z": 0.0 + }, + { + "x": 332.8811072045673, + "y": -31.147578254883385, + "z": 0.0 + }, + { + "x": 332.8804923214472, + "y": -32.165578069185536, + "z": 0.0 + }, + { + "x": 332.8798774383272, + "y": -33.18357788348723, + "z": 0.0 + }, + { + "x": 332.8792625552071, + "y": -34.20157769778938, + "z": 0.0 + }, + { + "x": 332.8786476720871, + "y": -35.21957751209108, + "z": 0.0 + }, + { + "x": 332.878032788967, + "y": -36.23757732639323, + "z": 0.0 + }, + { + "x": 332.877417905847, + "y": -37.25557714069515, + "z": 0.0 + }, + { + "x": 332.87680302272696, + "y": -38.27357695499685, + "z": 0.0 + }, + { + "x": 332.8761881396069, + "y": -39.291576769298764, + "z": 0.0 + }, + { + "x": 332.8755732564868, + "y": -40.309576583600915, + "z": 0.0 + }, + { + "x": 332.8749583733668, + "y": -41.32757639790284, + "z": 0.0 + }, + { + "x": 332.87434349024676, + "y": -42.34557621220476, + "z": 0.0 + }, + { + "x": 332.87372860712674, + "y": -43.36357602650624, + "z": 0.0 + }, + { + "x": 332.8731137240066, + "y": -44.38157584080861, + "z": 0.0 + }, + { + "x": 332.8724988408866, + "y": -45.399575655110525, + "z": 0.0 + }, + { + "x": 332.87188395776656, + "y": -46.41757546941244, + "z": 0.0 + } + ] + }, + { + "id": 82, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 336.8934041373098, + "y": -10.789998012538765, + "z": 0.0 + }, + { + "x": 336.8927892541898, + "y": -11.807997826840687, + "z": 0.0 + }, + { + "x": 336.8921743710697, + "y": -12.82599764114261, + "z": 0.0 + }, + { + "x": 336.8915594879496, + "y": -13.843997455444532, + "z": 0.0 + }, + { + "x": 336.8909446048296, + "y": -14.861997269746453, + "z": 0.0 + }, + { + "x": 336.8903297217096, + "y": -15.879997084048375, + "z": 0.0 + }, + { + "x": 336.8897148385895, + "y": -16.897996898350296, + "z": 0.0 + }, + { + "x": 336.8890999554695, + "y": -17.91599671265222, + "z": 0.0 + }, + { + "x": 336.8884850723494, + "y": -18.93399652695414, + "z": 0.0 + }, + { + "x": 336.8878701892294, + "y": -19.951996341256063, + "z": 0.0 + }, + { + "x": 336.8872553061093, + "y": -20.969996155557986, + "z": 0.0 + }, + { + "x": 336.8866404229893, + "y": -21.987995969859906, + "z": 0.0 + }, + { + "x": 336.88602553986925, + "y": -23.00599578416183, + "z": 0.0 + }, + { + "x": 336.8854106567492, + "y": -24.023995598463753, + "z": 0.0 + }, + { + "x": 336.8847957736291, + "y": -25.041995412765676, + "z": 0.0 + }, + { + "x": 336.88418089050907, + "y": -26.0599952270676, + "z": 0.0 + }, + { + "x": 336.88356600738905, + "y": -27.077995041369523, + "z": 0.0 + }, + { + "x": 336.88295112426897, + "y": -28.095994855671446, + "z": 0.0 + }, + { + "x": 336.8823362411489, + "y": -29.113994669973366, + "z": 0.0 + }, + { + "x": 336.88172135802887, + "y": -30.13199448427529, + "z": 0.0 + }, + { + "x": 336.88110647490885, + "y": -31.149994298577212, + "z": 0.0 + }, + { + "x": 336.88049159178877, + "y": -32.167994112879136, + "z": 0.0 + }, + { + "x": 336.87987670866875, + "y": -33.18599392718106, + "z": 0.0 + }, + { + "x": 336.87926182554867, + "y": -34.20399374148298, + "z": 0.0 + }, + { + "x": 336.87864694242865, + "y": -35.221993555784906, + "z": 0.0 + }, + { + "x": 336.87803205930857, + "y": -36.23999337008683, + "z": 0.0 + }, + { + "x": 336.87741717618854, + "y": -37.25799318438875, + "z": 0.0 + }, + { + "x": 336.8768022930685, + "y": -38.275992998690676, + "z": 0.0 + }, + { + "x": 336.87618740994844, + "y": -39.29399281299259, + "z": 0.0 + }, + { + "x": 336.87557252682836, + "y": -40.311992627294515, + "z": 0.0 + }, + { + "x": 336.87495764370834, + "y": -41.329992441596445, + "z": 0.0 + }, + { + "x": 336.8743427605883, + "y": -42.34799225589836, + "z": 0.0 + }, + { + "x": 336.8737278774683, + "y": -43.365992070200285, + "z": 0.0 + }, + { + "x": 336.87311299434816, + "y": -44.38399188450221, + "z": 0.0 + }, + { + "x": 336.87249811122814, + "y": -45.40199169880413, + "z": 0.0 + }, + { + "x": 336.8718832281081, + "y": -46.41999151310605, + "z": 0.0 + } + ] + }, + { + "id": 83, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 338.87188286327887, + "y": -46.42119953495285, + "z": 0.0 + }, + { + "x": 338.87249774639895, + "y": -45.40319972065093, + "z": 0.0 + }, + { + "x": 338.8731126295189, + "y": -44.38519990634901, + "z": 0.0 + }, + { + "x": 338.8737275126391, + "y": -43.36720009204731, + "z": 0.0 + }, + { + "x": 338.8743423957591, + "y": -42.34920027774516, + "z": 0.0 + }, + { + "x": 338.87495727887915, + "y": -41.33120046344325, + "z": 0.0 + }, + { + "x": 338.8755721619991, + "y": -40.313200649141315, + "z": 0.0 + }, + { + "x": 338.8761870451192, + "y": -39.295200834839505, + "z": 0.0 + }, + { + "x": 338.8768019282393, + "y": -38.27720102053759, + "z": 0.0 + }, + { + "x": 338.87741681135935, + "y": -37.25920120623555, + "z": 0.0 + }, + { + "x": 338.8780316944793, + "y": -36.24120139193363, + "z": 0.0 + }, + { + "x": 338.8786465775994, + "y": -35.22320157763182, + "z": 0.0 + }, + { + "x": 338.8792614607195, + "y": -34.20520176332978, + "z": 0.0 + }, + { + "x": 338.87987634383956, + "y": -33.18720194902797, + "z": 0.0 + }, + { + "x": 338.8804912269595, + "y": -32.169202134725936, + "z": 0.0 + }, + { + "x": 338.8811061100796, + "y": -31.151202320424126, + "z": 0.0 + }, + { + "x": 338.8817209931997, + "y": -30.13320250612209, + "z": 0.0 + }, + { + "x": 338.88233587631964, + "y": -29.115202691820166, + "z": 0.0 + }, + { + "x": 338.8829507594397, + "y": -28.09720287751836, + "z": 0.0 + }, + { + "x": 338.8835656425598, + "y": -27.079203063216436, + "z": 0.0 + }, + { + "x": 338.8841805256799, + "y": -26.061203248914403, + "z": 0.0 + }, + { + "x": 338.88479540879985, + "y": -25.04320343461248, + "z": 0.0 + }, + { + "x": 338.8854102919199, + "y": -24.025203620310666, + "z": 0.0 + }, + { + "x": 338.88602517504, + "y": -23.007203806008743, + "z": 0.0 + }, + { + "x": 338.8866400581601, + "y": -21.98920399170671, + "z": 0.0 + }, + { + "x": 338.88725494128005, + "y": -20.971204177404786, + "z": 0.0 + }, + { + "x": 338.8878698244001, + "y": -19.953204363102977, + "z": 0.0 + }, + { + "x": 338.8884847075202, + "y": -18.93520454880094, + "z": 0.0 + }, + { + "x": 338.8890995906403, + "y": -17.917204734499133, + "z": 0.0 + }, + { + "x": 338.88971447376025, + "y": -16.8992049201971, + "z": 0.0 + }, + { + "x": 338.89032935688033, + "y": -15.881205105895289, + "z": 0.0 + }, + { + "x": 338.8909442400004, + "y": -14.863205291593255, + "z": 0.0 + }, + { + "x": 338.8915591231204, + "y": -13.845205477291334, + "z": 0.0 + }, + { + "x": 338.89217400624045, + "y": -12.827205662989524, + "z": 0.0 + }, + { + "x": 338.89278888936053, + "y": -11.8092058486876, + "z": 0.0 + }, + { + "x": 338.8934037724806, + "y": -10.791206034385567, + "z": 0.0 + } + ] + }, + { + "id": 84, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 334.893404502139, + "y": -10.788789990691964, + "z": 0.0 + }, + { + "x": 334.892789619019, + "y": -11.806789804993773, + "z": 0.0 + }, + { + "x": 334.89217473589895, + "y": -12.824789619295696, + "z": 0.0 + }, + { + "x": 334.89155985277887, + "y": -13.84278943359773, + "z": 0.0 + }, + { + "x": 334.8909449696588, + "y": -14.860789247899651, + "z": 0.0 + }, + { + "x": 334.8903300865388, + "y": -15.878789062201461, + "z": 0.0 + }, + { + "x": 334.88971520341875, + "y": -16.896788876503493, + "z": 0.0 + }, + { + "x": 334.88910032029867, + "y": -17.914788690805306, + "z": 0.0 + }, + { + "x": 334.8884854371786, + "y": -18.93278850510734, + "z": 0.0 + }, + { + "x": 334.8878705540586, + "y": -19.95078831940915, + "z": 0.0 + }, + { + "x": 334.88725567093854, + "y": -20.968788133711186, + "z": 0.0 + }, + { + "x": 334.88664078781846, + "y": -21.986787948013102, + "z": 0.0 + }, + { + "x": 334.8860259046985, + "y": -23.004787762314916, + "z": 0.0 + }, + { + "x": 334.8854110215784, + "y": -24.02278757661684, + "z": 0.0 + }, + { + "x": 334.88479613845834, + "y": -25.040787390918872, + "z": 0.0 + }, + { + "x": 334.88418125533826, + "y": -26.058787205220796, + "z": 0.0 + }, + { + "x": 334.8835663722183, + "y": -27.07678701952261, + "z": 0.0 + }, + { + "x": 334.8829514890982, + "y": -28.094786833824532, + "z": 0.0 + }, + { + "x": 334.88233660597814, + "y": -29.112786648126566, + "z": 0.0 + }, + { + "x": 334.88172172285806, + "y": -30.13078646242849, + "z": 0.0 + }, + { + "x": 334.8811068397381, + "y": -31.1487862767303, + "z": 0.0 + }, + { + "x": 334.880491956618, + "y": -32.166786091032336, + "z": 0.0 + }, + { + "x": 334.87987707349794, + "y": -33.184785905334145, + "z": 0.0 + }, + { + "x": 334.87926219037786, + "y": -34.20278571963618, + "z": 0.0 + }, + { + "x": 334.8786473072579, + "y": -35.22078553393799, + "z": 0.0 + }, + { + "x": 334.8780324241378, + "y": -36.23878534824003, + "z": 0.0 + }, + { + "x": 334.87741754101773, + "y": -37.25678516254195, + "z": 0.0 + }, + { + "x": 334.87680265789777, + "y": -38.27478497684376, + "z": 0.0 + }, + { + "x": 334.8761877747777, + "y": -39.29278479114568, + "z": 0.0 + }, + { + "x": 334.8755728916576, + "y": -40.310784605447715, + "z": 0.0 + }, + { + "x": 334.87495800853753, + "y": -41.32878441974964, + "z": 0.0 + }, + { + "x": 334.87434312541757, + "y": -42.34678423405156, + "z": 0.0 + }, + { + "x": 334.8737282422975, + "y": -43.36478404835326, + "z": 0.0 + }, + { + "x": 334.8731133591774, + "y": -44.38278386265541, + "z": 0.0 + }, + { + "x": 334.87249847605733, + "y": -45.40078367695733, + "z": 0.0 + }, + { + "x": 334.87188359293737, + "y": -46.41878349125925, + "z": 0.0 + } + ] + }, + { + "id": 85, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 340.8270890483683, + "y": -120.582394028932, + "z": 0.0 + }, + { + "x": 340.827699573135, + "y": -119.57160989958834, + "z": 0.0 + }, + { + "x": 340.82831009790175, + "y": -118.56082577024468, + "z": 0.0 + }, + { + "x": 340.8289206226685, + "y": -117.55004164090101, + "z": 0.0 + }, + { + "x": 340.8295311474352, + "y": -116.53925751155735, + "z": 0.0 + }, + { + "x": 340.8301416722019, + "y": -115.52847338221346, + "z": 0.0 + }, + { + "x": 340.8307521969686, + "y": -114.51768925287003, + "z": 0.0 + }, + { + "x": 340.83136272173533, + "y": -113.50690512352637, + "z": 0.0 + }, + { + "x": 340.83197324650206, + "y": -112.4961209941827, + "z": 0.0 + }, + { + "x": 340.8325837712688, + "y": -111.48533686483904, + "z": 0.0 + }, + { + "x": 340.8331942960355, + "y": -110.47455273549538, + "z": 0.0 + }, + { + "x": 340.8338048208022, + "y": -109.46376860615149, + "z": 0.0 + }, + { + "x": 340.8344153455689, + "y": -108.45298447680806, + "z": 0.0 + }, + { + "x": 340.83502587033564, + "y": -107.4422003474644, + "z": 0.0 + }, + { + "x": 340.83563639510237, + "y": -106.43141621812073, + "z": 0.0 + }, + { + "x": 340.8362469198691, + "y": -105.42063208877707, + "z": 0.0 + }, + { + "x": 340.83685744463577, + "y": -104.40984795943318, + "z": 0.0 + }, + { + "x": 340.8374679694025, + "y": -103.39906383008974, + "z": 0.0 + }, + { + "x": 340.8380784941692, + "y": -102.38827970074608, + "z": 0.0 + }, + { + "x": 340.83868901893595, + "y": -101.37749557140242, + "z": 0.0 + }, + { + "x": 340.8392995437027, + "y": -100.36671144205877, + "z": 0.0 + }, + { + "x": 340.8399100684694, + "y": -99.35592731271511, + "z": 0.0 + }, + { + "x": 340.84052059323614, + "y": -98.34514318337145, + "z": 0.0 + }, + { + "x": 340.84113111800286, + "y": -97.3343590540278, + "z": 0.0 + }, + { + "x": 340.84174164276953, + "y": -96.32357492468391, + "z": 0.0 + }, + { + "x": 340.84235216753626, + "y": -95.31279079534048, + "z": 0.0 + }, + { + "x": 340.842962692303, + "y": -94.30200666599681, + "z": 0.0 + }, + { + "x": 340.8435732170697, + "y": -93.29122253665317, + "z": 0.0 + }, + { + "x": 340.84418374183645, + "y": -92.2804384073095, + "z": 0.0 + }, + { + "x": 340.8447942666031, + "y": -91.26965427796561, + "z": 0.0 + }, + { + "x": 340.84540479136984, + "y": -90.25887014862218, + "z": 0.0 + }, + { + "x": 340.8460153161366, + "y": -89.24808601927853, + "z": 0.0 + }, + { + "x": 340.8466258409033, + "y": -88.23730188993487, + "z": 0.0 + }, + { + "x": 340.84723636567, + "y": -87.22651776059121, + "z": 0.0 + }, + { + "x": 340.84784689043676, + "y": -86.21573363124755, + "z": 0.0 + }, + { + "x": 340.8484574152035, + "y": -85.2049495019039, + "z": 0.0 + }, + { + "x": 340.84906793997015, + "y": -84.19416537256001, + "z": 0.0 + }, + { + "x": 340.84967846473694, + "y": -83.1833812432168, + "z": 0.0 + }, + { + "x": 340.8502889895036, + "y": -82.1725971138727, + "z": 0.0 + }, + { + "x": 340.85089951427034, + "y": -81.16181298452926, + "z": 0.0 + }, + { + "x": 340.85151003903707, + "y": -80.1510288551856, + "z": 0.0 + }, + { + "x": 340.85212056380374, + "y": -79.14024472584171, + "z": 0.0 + }, + { + "x": 340.85273108857047, + "y": -78.12946059649829, + "z": 0.0 + }, + { + "x": 340.8533416133372, + "y": -77.11867646715463, + "z": 0.0 + }, + { + "x": 340.8539521381039, + "y": -76.10789233781097, + "z": 0.0 + }, + { + "x": 340.85456266287065, + "y": -75.0971082084673, + "z": 0.0 + }, + { + "x": 340.8551731876374, + "y": -74.08632407912366, + "z": 0.0 + }, + { + "x": 340.8557837124041, + "y": -73.07553994978, + "z": 0.0 + }, + { + "x": 340.85639423717083, + "y": -72.06475582043633, + "z": 0.0 + }, + { + "x": 340.8570047619375, + "y": -71.05397169109244, + "z": 0.0 + }, + { + "x": 340.8576152867043, + "y": -70.04318756174925, + "z": 0.0 + }, + { + "x": 340.85822581147096, + "y": -69.03240343240513, + "z": 0.0 + } + ] + }, + { + "id": 86, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 332.85822727078784, + "y": -69.0275713450181, + "z": 0.0 + }, + { + "x": 332.85761674602116, + "y": -70.03835547436131, + "z": 0.0 + }, + { + "x": 332.8570062212544, + "y": -71.04913960370541, + "z": 0.0 + }, + { + "x": 332.8563956964877, + "y": -72.05992373304885, + "z": 0.0 + }, + { + "x": 332.855785171721, + "y": -73.07070786239251, + "z": 0.0 + }, + { + "x": 332.85517464695425, + "y": -74.08149199173617, + "z": 0.0 + }, + { + "x": 332.8545641221875, + "y": -75.09227612107982, + "z": 0.0 + }, + { + "x": 332.8539535974208, + "y": -76.10306025042348, + "z": 0.0 + }, + { + "x": 332.85334307265407, + "y": -77.11384437976714, + "z": 0.0 + }, + { + "x": 332.85273254788734, + "y": -78.1246285091108, + "z": 0.0 + }, + { + "x": 332.8521220231206, + "y": -79.13541263845468, + "z": 0.0 + }, + { + "x": 332.85151149835394, + "y": -80.14619676779812, + "z": 0.0 + }, + { + "x": 332.8509009735872, + "y": -81.15698089714178, + "z": 0.0 + }, + { + "x": 332.8502904488205, + "y": -82.16776502648567, + "z": 0.0 + }, + { + "x": 332.8496799240538, + "y": -83.17854915582886, + "z": 0.0 + }, + { + "x": 332.84906939928703, + "y": -84.18933328517298, + "z": 0.0 + }, + { + "x": 332.84845887452036, + "y": -85.20011741451641, + "z": 0.0 + }, + { + "x": 332.84784834975363, + "y": -86.21090154386006, + "z": 0.0 + }, + { + "x": 332.8472378249869, + "y": -87.22168567320372, + "z": 0.0 + }, + { + "x": 332.8466273002202, + "y": -88.23246980254739, + "z": 0.0 + }, + { + "x": 332.84601677545345, + "y": -89.24325393189105, + "z": 0.0 + }, + { + "x": 332.8454062506867, + "y": -90.2540380612347, + "z": 0.0 + }, + { + "x": 332.84479572592, + "y": -91.26482219057858, + "z": 0.0 + }, + { + "x": 332.8441852011533, + "y": -92.27560631992202, + "z": 0.0 + }, + { + "x": 332.8435746763866, + "y": -93.28639044926568, + "z": 0.0 + }, + { + "x": 332.84296415161987, + "y": -94.29717457860933, + "z": 0.0 + }, + { + "x": 332.84235362685314, + "y": -95.30795870795299, + "z": 0.0 + }, + { + "x": 332.8417431020864, + "y": -96.31874283729688, + "z": 0.0 + }, + { + "x": 332.84113257731974, + "y": -97.32952696664032, + "z": 0.0 + }, + { + "x": 332.840522052553, + "y": -98.34031109598396, + "z": 0.0 + }, + { + "x": 332.8399115277863, + "y": -99.35109522532763, + "z": 0.0 + }, + { + "x": 332.83930100301956, + "y": -100.36187935467129, + "z": 0.0 + }, + { + "x": 332.83869047825283, + "y": -101.37266348401494, + "z": 0.0 + }, + { + "x": 332.8380799534861, + "y": -102.3834476133586, + "z": 0.0 + }, + { + "x": 332.8374694287194, + "y": -103.39423174270226, + "z": 0.0 + }, + { + "x": 332.83685890395265, + "y": -104.40501587204615, + "z": 0.0 + }, + { + "x": 332.836248379186, + "y": -105.41580000138958, + "z": 0.0 + }, + { + "x": 332.83563785441925, + "y": -106.42658413073325, + "z": 0.0 + }, + { + "x": 332.8350273296525, + "y": -107.43736826007691, + "z": 0.0 + }, + { + "x": 332.8344168048858, + "y": -108.44815238942057, + "z": 0.0 + }, + { + "x": 332.83380628011906, + "y": -109.45893651876446, + "z": 0.0 + }, + { + "x": 332.8331957553524, + "y": -110.4697206481079, + "z": 0.0 + }, + { + "x": 332.83258523058566, + "y": -111.48050477745156, + "z": 0.0 + }, + { + "x": 332.83197470581894, + "y": -112.49128890679522, + "z": 0.0 + }, + { + "x": 332.8313641810522, + "y": -113.50207303613888, + "z": 0.0 + }, + { + "x": 332.8307536562855, + "y": -114.51285716548254, + "z": 0.0 + }, + { + "x": 332.83014313151875, + "y": -115.52364129482643, + "z": 0.0 + }, + { + "x": 332.8295326067521, + "y": -116.53442542416987, + "z": 0.0 + }, + { + "x": 332.82892208198535, + "y": -117.54520955351353, + "z": 0.0 + }, + { + "x": 332.8283115572186, + "y": -118.55599368285719, + "z": 0.0 + }, + { + "x": 332.8277010324519, + "y": -119.56677781220085, + "z": 0.0 + }, + { + "x": 332.82709050768517, + "y": -120.57756194154452, + "z": 0.0 + } + ] + }, + { + "id": 87, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 336.8582265411294, + "y": -69.02998738871162, + "z": 0.0 + }, + { + "x": 336.8576160163627, + "y": -70.04077151805528, + "z": 0.0 + }, + { + "x": 336.85700549159594, + "y": -71.05155564739893, + "z": 0.0 + }, + { + "x": 336.85639496682927, + "y": -72.06233977674259, + "z": 0.0 + }, + { + "x": 336.85578444206254, + "y": -73.07312390608625, + "z": 0.0 + }, + { + "x": 336.8551739172958, + "y": -74.08390803542991, + "z": 0.0 + }, + { + "x": 336.8545633925291, + "y": -75.09469216477356, + "z": 0.0 + }, + { + "x": 336.85395286776236, + "y": -76.10547629411722, + "z": 0.0 + }, + { + "x": 336.85334234299563, + "y": -77.11626042346089, + "z": 0.0 + }, + { + "x": 336.8527318182289, + "y": -78.12704455280455, + "z": 0.0 + }, + { + "x": 336.8521212934622, + "y": -79.1378286821482, + "z": 0.0 + }, + { + "x": 336.8515107686955, + "y": -80.14861281149186, + "z": 0.0 + }, + { + "x": 336.8509002439288, + "y": -81.15939694083552, + "z": 0.0 + }, + { + "x": 336.85028971916205, + "y": -82.17018107017918, + "z": 0.0 + }, + { + "x": 336.8496791943954, + "y": -83.18096519952283, + "z": 0.0 + }, + { + "x": 336.8490686696286, + "y": -84.19174932886649, + "z": 0.0 + }, + { + "x": 336.8484581448619, + "y": -85.20253345821016, + "z": 0.0 + }, + { + "x": 336.8478476200952, + "y": -86.2133175875538, + "z": 0.0 + }, + { + "x": 336.84723709532847, + "y": -87.22410171689747, + "z": 0.0 + }, + { + "x": 336.84662657056174, + "y": -88.23488584624113, + "z": 0.0 + }, + { + "x": 336.846016045795, + "y": -89.24566997558479, + "z": 0.0 + }, + { + "x": 336.8454055210283, + "y": -90.25645410492844, + "z": 0.0 + }, + { + "x": 336.84479499626156, + "y": -91.2672382342721, + "z": 0.0 + }, + { + "x": 336.8441844714949, + "y": -92.27802236361576, + "z": 0.0 + }, + { + "x": 336.84357394672816, + "y": -93.28880649295942, + "z": 0.0 + }, + { + "x": 336.84296342196143, + "y": -94.29959062230307, + "z": 0.0 + }, + { + "x": 336.8423528971947, + "y": -95.31037475164673, + "z": 0.0 + }, + { + "x": 336.841742372428, + "y": -96.3211588809904, + "z": 0.0 + }, + { + "x": 336.8411318476613, + "y": -97.33194301033406, + "z": 0.0 + }, + { + "x": 336.8405213228946, + "y": -98.3427271396777, + "z": 0.0 + }, + { + "x": 336.83991079812785, + "y": -99.35351126902137, + "z": 0.0 + }, + { + "x": 336.8393002733611, + "y": -100.36429539836503, + "z": 0.0 + }, + { + "x": 336.8386897485944, + "y": -101.37507952770868, + "z": 0.0 + }, + { + "x": 336.83807922382766, + "y": -102.38586365705234, + "z": 0.0 + }, + { + "x": 336.83746869906093, + "y": -103.396647786396, + "z": 0.0 + }, + { + "x": 336.8368581742942, + "y": -104.40743191573966, + "z": 0.0 + }, + { + "x": 336.83624764952754, + "y": -105.41821604508333, + "z": 0.0 + }, + { + "x": 336.8356371247608, + "y": -106.42900017442699, + "z": 0.0 + }, + { + "x": 336.8350265999941, + "y": -107.43978430377065, + "z": 0.0 + }, + { + "x": 336.83441607522735, + "y": -108.45056843311431, + "z": 0.0 + }, + { + "x": 336.8338055504606, + "y": -109.46135256245798, + "z": 0.0 + }, + { + "x": 336.83319502569395, + "y": -110.47213669180164, + "z": 0.0 + }, + { + "x": 336.8325845009272, + "y": -111.4829208211453, + "z": 0.0 + }, + { + "x": 336.8319739761605, + "y": -112.49370495048896, + "z": 0.0 + }, + { + "x": 336.83136345139377, + "y": -113.50448907983262, + "z": 0.0 + }, + { + "x": 336.83075292662704, + "y": -114.51527320917629, + "z": 0.0 + }, + { + "x": 336.8301424018603, + "y": -115.52605733851995, + "z": 0.0 + }, + { + "x": 336.82953187709364, + "y": -116.53684146786361, + "z": 0.0 + }, + { + "x": 336.8289213523269, + "y": -117.54762559720727, + "z": 0.0 + }, + { + "x": 336.8283108275602, + "y": -118.55840972655093, + "z": 0.0 + }, + { + "x": 336.82770030279346, + "y": -119.5691938558946, + "z": 0.0 + }, + { + "x": 336.82708977802673, + "y": -120.57997798523826, + "z": 0.0 + } + ] + }, + { + "id": 88, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 338.82708941319754, + "y": -120.58118600708514, + "z": 0.0 + }, + { + "x": 338.8276999379642, + "y": -119.57040187774146, + "z": 0.0 + }, + { + "x": 338.828310462731, + "y": -118.55961774839781, + "z": 0.0 + }, + { + "x": 338.82892098749767, + "y": -117.54883361905414, + "z": 0.0 + }, + { + "x": 338.82953151226445, + "y": -116.53804948971049, + "z": 0.0 + }, + { + "x": 338.8301420370311, + "y": -115.5272653603667, + "z": 0.0 + }, + { + "x": 338.8307525617978, + "y": -114.51648123102316, + "z": 0.0 + }, + { + "x": 338.8313630865646, + "y": -113.50569710167949, + "z": 0.0 + }, + { + "x": 338.83197361133125, + "y": -112.49491297233584, + "z": 0.0 + }, + { + "x": 338.83258413609803, + "y": -111.48412884299216, + "z": 0.0 + }, + { + "x": 338.8331946608647, + "y": -110.47334471364852, + "z": 0.0 + }, + { + "x": 338.8338051856314, + "y": -109.46256058430473, + "z": 0.0 + }, + { + "x": 338.83441571039816, + "y": -108.45177645496119, + "z": 0.0 + }, + { + "x": 338.83502623516483, + "y": -107.44099232561751, + "z": 0.0 + }, + { + "x": 338.8356367599316, + "y": -106.43020819627387, + "z": 0.0 + }, + { + "x": 338.8362472846983, + "y": -105.41942406693019, + "z": 0.0 + }, + { + "x": 338.83685780946496, + "y": -104.40863993758643, + "z": 0.0 + }, + { + "x": 338.83746833423174, + "y": -103.39785580824287, + "z": 0.0 + }, + { + "x": 338.8380788589984, + "y": -102.38707167889922, + "z": 0.0 + }, + { + "x": 338.8386893837652, + "y": -101.37628754955554, + "z": 0.0 + }, + { + "x": 338.83929990853187, + "y": -100.3655034202119, + "z": 0.0 + }, + { + "x": 338.83991043329866, + "y": -99.35471929086825, + "z": 0.0 + }, + { + "x": 338.8405209580653, + "y": -98.34393516152457, + "z": 0.0 + }, + { + "x": 338.8411314828321, + "y": -97.33315103218092, + "z": 0.0 + }, + { + "x": 338.8417420075988, + "y": -96.32236690283716, + "z": 0.0 + }, + { + "x": 338.84235253236545, + "y": -95.3115827734936, + "z": 0.0 + }, + { + "x": 338.84296305713224, + "y": -94.30079864414995, + "z": 0.0 + }, + { + "x": 338.8435735818989, + "y": -93.2900145148063, + "z": 0.0 + }, + { + "x": 338.8441841066657, + "y": -92.27923038546263, + "z": 0.0 + }, + { + "x": 338.84479463143236, + "y": -91.26844625611886, + "z": 0.0 + }, + { + "x": 338.84540515619904, + "y": -90.2576621267753, + "z": 0.0 + }, + { + "x": 338.8460156809658, + "y": -89.24687799743165, + "z": 0.0 + }, + { + "x": 338.8466262057325, + "y": -88.236093868088, + "z": 0.0 + }, + { + "x": 338.8472367304993, + "y": -87.22530973874433, + "z": 0.0 + }, + { + "x": 338.84784725526595, + "y": -86.21452560940068, + "z": 0.0 + }, + { + "x": 338.84845778003273, + "y": -85.20374148005703, + "z": 0.0 + }, + { + "x": 338.8490683047994, + "y": -84.19295735071324, + "z": 0.0 + }, + { + "x": 338.8496788295662, + "y": -83.18217322136982, + "z": 0.0 + }, + { + "x": 338.85028935433286, + "y": -82.17138909202595, + "z": 0.0 + }, + { + "x": 338.85089987909953, + "y": -81.16060496268238, + "z": 0.0 + }, + { + "x": 338.8515104038663, + "y": -80.14982083333874, + "z": 0.0 + }, + { + "x": 338.852120928633, + "y": -79.13903670399495, + "z": 0.0 + }, + { + "x": 338.85273145339966, + "y": -78.12825257465141, + "z": 0.0 + }, + { + "x": 338.85334197816644, + "y": -77.11746844530776, + "z": 0.0 + }, + { + "x": 338.8539525029331, + "y": -76.10668431596409, + "z": 0.0 + }, + { + "x": 338.8545630276999, + "y": -75.09590018662044, + "z": 0.0 + }, + { + "x": 338.85517355246657, + "y": -74.08511605727679, + "z": 0.0 + }, + { + "x": 338.85578407723335, + "y": -73.07433192793312, + "z": 0.0 + }, + { + "x": 338.856394602, + "y": -72.06354779858947, + "z": 0.0 + }, + { + "x": 338.8570051267667, + "y": -71.05276366924568, + "z": 0.0 + }, + { + "x": 338.8576156515335, + "y": -70.04197953990226, + "z": 0.0 + }, + { + "x": 338.85822617630015, + "y": -69.03119541055838, + "z": 0.0 + } + ] + }, + { + "id": 89, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 334.85822690595865, + "y": -69.02877936686485, + "z": 0.0 + }, + { + "x": 334.857616381192, + "y": -70.0395634962083, + "z": 0.0 + }, + { + "x": 334.8570058564252, + "y": -71.05034762555218, + "z": 0.0 + }, + { + "x": 334.8563953316585, + "y": -72.06113175489571, + "z": 0.0 + }, + { + "x": 334.85578480689173, + "y": -73.07191588423939, + "z": 0.0 + }, + { + "x": 334.85517428212506, + "y": -74.08270001358304, + "z": 0.0 + }, + { + "x": 334.8545637573583, + "y": -75.09348414292668, + "z": 0.0 + }, + { + "x": 334.8539532325916, + "y": -76.10426827227036, + "z": 0.0 + }, + { + "x": 334.8533427078248, + "y": -77.11505240161401, + "z": 0.0 + }, + { + "x": 334.85273218305815, + "y": -78.12583653095768, + "z": 0.0 + }, + { + "x": 334.85212165829137, + "y": -79.13662066030145, + "z": 0.0 + }, + { + "x": 334.8515111335247, + "y": -80.14740478964498, + "z": 0.0 + }, + { + "x": 334.850900608758, + "y": -81.15818891898866, + "z": 0.0 + }, + { + "x": 334.85029008399124, + "y": -82.16897304833242, + "z": 0.0 + }, + { + "x": 334.84967955922457, + "y": -83.17975717767584, + "z": 0.0 + }, + { + "x": 334.8490690344578, + "y": -84.19054130701974, + "z": 0.0 + }, + { + "x": 334.8484585096911, + "y": -85.20132543636328, + "z": 0.0 + }, + { + "x": 334.84784798492444, + "y": -86.21210956570692, + "z": 0.0 + }, + { + "x": 334.84723746015766, + "y": -87.2228936950506, + "z": 0.0 + }, + { + "x": 334.846626935391, + "y": -88.23367782439425, + "z": 0.0 + }, + { + "x": 334.8460164106242, + "y": -89.24446195373793, + "z": 0.0 + }, + { + "x": 334.84540588585753, + "y": -90.25524608308157, + "z": 0.0 + }, + { + "x": 334.84479536109075, + "y": -91.26603021242533, + "z": 0.0 + }, + { + "x": 334.8441848363241, + "y": -92.2768143417689, + "z": 0.0 + }, + { + "x": 334.8435743115574, + "y": -93.28759847111255, + "z": 0.0 + }, + { + "x": 334.8429637867906, + "y": -94.2983826004562, + "z": 0.0 + }, + { + "x": 334.84235326202395, + "y": -95.30916672979987, + "z": 0.0 + }, + { + "x": 334.84174273725716, + "y": -96.31995085914363, + "z": 0.0 + }, + { + "x": 334.8411322124905, + "y": -97.3307349884872, + "z": 0.0 + }, + { + "x": 334.8405216877238, + "y": -98.34151911783084, + "z": 0.0 + }, + { + "x": 334.83991116295704, + "y": -99.35230324717449, + "z": 0.0 + }, + { + "x": 334.83930063819037, + "y": -100.36308737651817, + "z": 0.0 + }, + { + "x": 334.8386901134236, + "y": -101.37387150586181, + "z": 0.0 + }, + { + "x": 334.8380795886569, + "y": -102.38465563520546, + "z": 0.0 + }, + { + "x": 334.8374690638901, + "y": -103.39543976454914, + "z": 0.0 + }, + { + "x": 334.83685853912345, + "y": -104.4062238938929, + "z": 0.0 + }, + { + "x": 334.8362480143568, + "y": -105.41700802323646, + "z": 0.0 + }, + { + "x": 334.83563748959, + "y": -106.42779215258011, + "z": 0.0 + }, + { + "x": 334.8350269648233, + "y": -107.43857628192379, + "z": 0.0 + }, + { + "x": 334.83441644005654, + "y": -108.44936041126743, + "z": 0.0 + }, + { + "x": 334.8338059152899, + "y": -109.46014454061122, + "z": 0.0 + }, + { + "x": 334.8331953905232, + "y": -110.47092866995476, + "z": 0.0 + }, + { + "x": 334.8325848657564, + "y": -111.48171279929844, + "z": 0.0 + }, + { + "x": 334.83197434098975, + "y": -112.49249692864208, + "z": 0.0 + }, + { + "x": 334.83136381622296, + "y": -113.50328105798576, + "z": 0.0 + }, + { + "x": 334.8307532914563, + "y": -114.51406518732941, + "z": 0.0 + }, + { + "x": 334.8301427666895, + "y": -115.5248493166732, + "z": 0.0 + }, + { + "x": 334.82953224192283, + "y": -116.53563344601673, + "z": 0.0 + }, + { + "x": 334.82892171715616, + "y": -117.54641757536041, + "z": 0.0 + }, + { + "x": 334.8283111923894, + "y": -118.55720170470406, + "z": 0.0 + }, + { + "x": 334.8277006676227, + "y": -119.56798583404773, + "z": 0.0 + }, + { + "x": 334.8270901428559, + "y": -120.57876996339138, + "z": 0.0 + } + ] + }, + { + "id": 90, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 340.78778605758094, + "y": -185.65238215921298, + "z": 0.0 + }, + { + "x": 340.7884045058386, + "y": -184.62847990696335, + "z": 0.0 + }, + { + "x": 340.78902295409637, + "y": -183.60457765471395, + "z": 0.0 + }, + { + "x": 340.789641402354, + "y": -182.5806754024639, + "z": 0.0 + }, + { + "x": 340.7902598506117, + "y": -181.5567731502145, + "z": 0.0 + }, + { + "x": 340.7908782988694, + "y": -180.5328708979651, + "z": 0.0 + }, + { + "x": 340.7914967471271, + "y": -179.50896864571524, + "z": 0.0 + }, + { + "x": 340.7921151953848, + "y": -178.48506639346562, + "z": 0.0 + }, + { + "x": 340.79273364364246, + "y": -177.461164141216, + "z": 0.0 + }, + { + "x": 340.79335209190015, + "y": -176.4372618889664, + "z": 0.0 + }, + { + "x": 340.7939705401579, + "y": -175.413359636717, + "z": 0.0 + }, + { + "x": 340.79458898841557, + "y": -174.38945738446714, + "z": 0.0 + }, + { + "x": 340.79520743667325, + "y": -173.3655551322175, + "z": 0.0 + }, + { + "x": 340.79582588493093, + "y": -172.34165287996788, + "z": 0.0 + }, + { + "x": 340.7964443331886, + "y": -171.31775062771825, + "z": 0.0 + }, + { + "x": 340.79706278144636, + "y": -170.29384837546888, + "z": 0.0 + }, + { + "x": 340.79768122970404, + "y": -169.26994612321903, + "z": 0.0 + }, + { + "x": 340.7982996779617, + "y": -168.2460438709694, + "z": 0.0 + }, + { + "x": 340.7989181262194, + "y": -167.22214161871977, + "z": 0.0 + }, + { + "x": 340.7995365744771, + "y": -166.19823936647015, + "z": 0.0 + }, + { + "x": 340.8001550227348, + "y": -165.17433711422075, + "z": 0.0 + }, + { + "x": 340.8007734709925, + "y": -164.1504348619709, + "z": 0.0 + }, + { + "x": 340.8013919192502, + "y": -163.1265326097213, + "z": 0.0 + }, + { + "x": 340.80201036750793, + "y": -162.1026303574719, + "z": 0.0 + }, + { + "x": 340.8026288157656, + "y": -161.07872810522204, + "z": 0.0 + }, + { + "x": 340.8032472640233, + "y": -160.0548258529724, + "z": 0.0 + }, + { + "x": 340.803865712281, + "y": -159.0309236007228, + "z": 0.0 + }, + { + "x": 340.80448416053866, + "y": -158.0070213484732, + "z": 0.0 + }, + { + "x": 340.8051026087964, + "y": -156.9831190962238, + "z": 0.0 + }, + { + "x": 340.8057210570541, + "y": -155.95921684397393, + "z": 0.0 + }, + { + "x": 340.80633950531177, + "y": -154.9353145917243, + "z": 0.0 + }, + { + "x": 340.80695795356945, + "y": -153.91141233947468, + "z": 0.0 + }, + { + "x": 340.80757640182713, + "y": -152.88751008722505, + "z": 0.0 + }, + { + "x": 340.8081948500849, + "y": -151.86360783497565, + "z": 0.0 + }, + { + "x": 340.80881329834256, + "y": -150.83970558272583, + "z": 0.0 + }, + { + "x": 340.80943174660024, + "y": -149.8158033304762, + "z": 0.0 + }, + { + "x": 340.8100501948579, + "y": -148.79190107822657, + "z": 0.0 + }, + { + "x": 340.8106686431156, + "y": -147.76799882597695, + "z": 0.0 + }, + { + "x": 340.81128709137334, + "y": -146.74409657372755, + "z": 0.0 + }, + { + "x": 340.81190553963097, + "y": -145.7201943214775, + "z": 0.0 + }, + { + "x": 340.8125239878887, + "y": -144.69629206922832, + "z": 0.0 + }, + { + "x": 340.8131424361464, + "y": -143.67238981697847, + "z": 0.0 + } + ] + }, + { + "id": 91, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 332.81314389546327, + "y": -143.66755772959112, + "z": 0.0 + }, + { + "x": 332.8125254472056, + "y": -144.69145998184052, + "z": 0.0 + }, + { + "x": 332.81190699894785, + "y": -145.7153622340906, + "z": 0.0 + }, + { + "x": 332.8112885506902, + "y": -146.73926448633975, + "z": 0.0 + }, + { + "x": 332.8106701024325, + "y": -147.7631667385896, + "z": 0.0 + }, + { + "x": 332.8100516541748, + "y": -148.78706899083923, + "z": 0.0 + }, + { + "x": 332.8094332059171, + "y": -149.81097124308886, + "z": 0.0 + }, + { + "x": 332.80881475765943, + "y": -150.83487349533848, + "z": 0.0 + }, + { + "x": 332.80819630940175, + "y": -151.85877574758786, + "z": 0.0 + }, + { + "x": 332.807577861144, + "y": -152.8826779998377, + "z": 0.0 + }, + { + "x": 332.80695941288633, + "y": -153.90658025208734, + "z": 0.0 + }, + { + "x": 332.80634096462865, + "y": -154.93048250433696, + "z": 0.0 + }, + { + "x": 332.80572251637096, + "y": -155.9543847565866, + "z": 0.0 + }, + { + "x": 332.8051040681133, + "y": -156.978287008836, + "z": 0.0 + }, + { + "x": 332.80448561985554, + "y": -158.00218926108585, + "z": 0.0 + }, + { + "x": 332.80386717159786, + "y": -159.02609151333544, + "z": 0.0 + }, + { + "x": 332.8032487233402, + "y": -160.04999376558507, + "z": 0.0 + }, + { + "x": 332.8026302750825, + "y": -161.0738960178347, + "z": 0.0 + }, + { + "x": 332.8020118268248, + "y": -162.0977982700841, + "z": 0.0 + }, + { + "x": 332.80139337856707, + "y": -163.12170052233395, + "z": 0.0 + }, + { + "x": 332.8007749303094, + "y": -164.14560277458355, + "z": 0.0 + }, + { + "x": 332.8001564820517, + "y": -165.16950502683295, + "z": 0.0 + }, + { + "x": 332.79953803379397, + "y": -166.1934072790828, + "z": 0.0 + }, + { + "x": 332.7989195855363, + "y": -167.21730953133243, + "z": 0.0 + }, + { + "x": 332.7983011372786, + "y": -168.24121178358206, + "z": 0.0 + }, + { + "x": 332.7976826890209, + "y": -169.2651140358317, + "z": 0.0 + }, + { + "x": 332.79706424076323, + "y": -170.2890162880811, + "z": 0.0 + }, + { + "x": 332.7964457925055, + "y": -171.3129185403309, + "z": 0.0 + }, + { + "x": 332.7958273442478, + "y": -172.33682079258054, + "z": 0.0 + }, + { + "x": 332.79520889599013, + "y": -173.36072304483017, + "z": 0.0 + }, + { + "x": 332.79459044773245, + "y": -174.3846252970798, + "z": 0.0 + }, + { + "x": 332.79397199947476, + "y": -175.4085275493292, + "z": 0.0 + }, + { + "x": 332.793353551217, + "y": -176.43242980157905, + "z": 0.0 + }, + { + "x": 332.79273510295934, + "y": -177.45633205382865, + "z": 0.0 + }, + { + "x": 332.79211665470166, + "y": -178.48023430607827, + "z": 0.0 + }, + { + "x": 332.791498206444, + "y": -179.5041365583279, + "z": 0.0 + }, + { + "x": 332.7908797581863, + "y": -180.5280388105773, + "z": 0.0 + }, + { + "x": 332.79026130992855, + "y": -181.55194106282715, + "z": 0.0 + }, + { + "x": 332.78964286167087, + "y": -182.575843315077, + "z": 0.0 + }, + { + "x": 332.78902441341324, + "y": -183.59974556732615, + "z": 0.0 + }, + { + "x": 332.7884059651555, + "y": -184.623647819576, + "z": 0.0 + }, + { + "x": 332.7877875168978, + "y": -185.64755007182563, + "z": 0.0 + } + ] + }, + { + "id": 92, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 336.81314316580483, + "y": -143.6699737732848, + "z": 0.0 + }, + { + "x": 336.81252471754715, + "y": -144.69387602553442, + "z": 0.0 + }, + { + "x": 336.8119062692894, + "y": -145.71777827778405, + "z": 0.0 + }, + { + "x": 336.8112878210318, + "y": -146.74168053003365, + "z": 0.0 + }, + { + "x": 336.81066937277404, + "y": -147.76558278228327, + "z": 0.0 + }, + { + "x": 336.81005092451636, + "y": -148.7894850345329, + "z": 0.0 + }, + { + "x": 336.8094324762587, + "y": -149.81338728678253, + "z": 0.0 + }, + { + "x": 336.808814028001, + "y": -150.83728953903216, + "z": 0.0 + }, + { + "x": 336.8081955797433, + "y": -151.86119179128175, + "z": 0.0 + }, + { + "x": 336.8075771314856, + "y": -152.88509404353138, + "z": 0.0 + }, + { + "x": 336.8069586832279, + "y": -153.908996295781, + "z": 0.0 + }, + { + "x": 336.8063402349702, + "y": -154.93289854803064, + "z": 0.0 + }, + { + "x": 336.8057217867125, + "y": -155.95680080028026, + "z": 0.0 + }, + { + "x": 336.80510333845484, + "y": -156.9807030525299, + "z": 0.0 + }, + { + "x": 336.8044848901971, + "y": -158.00460530477952, + "z": 0.0 + }, + { + "x": 336.8038664419394, + "y": -159.02850755702912, + "z": 0.0 + }, + { + "x": 336.80324799368174, + "y": -160.05240980927874, + "z": 0.0 + }, + { + "x": 336.80262954542405, + "y": -161.07631206152837, + "z": 0.0 + }, + { + "x": 336.80201109716637, + "y": -162.100214313778, + "z": 0.0 + }, + { + "x": 336.80139264890863, + "y": -163.12411656602762, + "z": 0.0 + }, + { + "x": 336.80077420065095, + "y": -164.14801881827722, + "z": 0.0 + }, + { + "x": 336.80015575239327, + "y": -165.17192107052685, + "z": 0.0 + }, + { + "x": 336.7995373041355, + "y": -166.19582332277648, + "z": 0.0 + }, + { + "x": 336.79891885587784, + "y": -167.2197255750261, + "z": 0.0 + }, + { + "x": 336.79830040762016, + "y": -168.24362782727573, + "z": 0.0 + }, + { + "x": 336.7976819593625, + "y": -169.26753007952536, + "z": 0.0 + }, + { + "x": 336.7970635111048, + "y": -170.29143233177498, + "z": 0.0 + }, + { + "x": 336.79644506284706, + "y": -171.31533458402458, + "z": 0.0 + }, + { + "x": 336.7958266145894, + "y": -172.3392368362742, + "z": 0.0 + }, + { + "x": 336.7952081663317, + "y": -173.36313908852384, + "z": 0.0 + }, + { + "x": 336.794589718074, + "y": -174.38704134077346, + "z": 0.0 + }, + { + "x": 336.7939712698163, + "y": -175.4109435930231, + "z": 0.0 + }, + { + "x": 336.7933528215586, + "y": -176.43484584527272, + "z": 0.0 + }, + { + "x": 336.7927343733009, + "y": -177.45874809752232, + "z": 0.0 + }, + { + "x": 336.7921159250432, + "y": -178.48265034977194, + "z": 0.0 + }, + { + "x": 336.79149747678554, + "y": -179.50655260202157, + "z": 0.0 + }, + { + "x": 336.79087902852785, + "y": -180.5304548542712, + "z": 0.0 + }, + { + "x": 336.7902605802701, + "y": -181.55435710652083, + "z": 0.0 + }, + { + "x": 336.78964213201243, + "y": -182.57825935877045, + "z": 0.0 + }, + { + "x": 336.7890236837548, + "y": -183.60216161102005, + "z": 0.0 + }, + { + "x": 336.78840523549707, + "y": -184.62606386326968, + "z": 0.0 + }, + { + "x": 336.7877867872394, + "y": -185.6499661155193, + "z": 0.0 + } + ] + }, + { + "id": 93, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 338.78778642241014, + "y": -185.65117413736613, + "z": 0.0 + }, + { + "x": 338.7884048706678, + "y": -184.6272718851165, + "z": 0.0 + }, + { + "x": 338.7890233189256, + "y": -183.603369632867, + "z": 0.0 + }, + { + "x": 338.7896417671832, + "y": -182.5794673806172, + "z": 0.0 + }, + { + "x": 338.79026021544087, + "y": -181.55556512836768, + "z": 0.0 + }, + { + "x": 338.79087866369866, + "y": -180.53166287611816, + "z": 0.0 + }, + { + "x": 338.79149711195635, + "y": -179.50776062386842, + "z": 0.0 + }, + { + "x": 338.79211556021403, + "y": -178.4838583716188, + "z": 0.0 + }, + { + "x": 338.7927340084717, + "y": -177.45995611936917, + "z": 0.0 + }, + { + "x": 338.7933524567294, + "y": -176.43605386711954, + "z": 0.0 + }, + { + "x": 338.7939709049871, + "y": -175.41215161487003, + "z": 0.0 + }, + { + "x": 338.79458935324476, + "y": -174.3882493626203, + "z": 0.0 + }, + { + "x": 338.79520780150244, + "y": -173.36434711037066, + "z": 0.0 + }, + { + "x": 338.7958262497601, + "y": -172.34044485812103, + "z": 0.0 + }, + { + "x": 338.7964446980178, + "y": -171.3165426058714, + "z": 0.0 + }, + { + "x": 338.7970631462756, + "y": -170.29264035362195, + "z": 0.0 + }, + { + "x": 338.7976815945333, + "y": -169.2687381013722, + "z": 0.0 + }, + { + "x": 338.79830004279097, + "y": -168.24483584912258, + "z": 0.0 + }, + { + "x": 338.79891849104865, + "y": -167.22093359687295, + "z": 0.0 + }, + { + "x": 338.79953693930634, + "y": -166.19703134462333, + "z": 0.0 + }, + { + "x": 338.800155387564, + "y": -165.1731290923738, + "z": 0.0 + }, + { + "x": 338.8007738358217, + "y": -164.14922684012407, + "z": 0.0 + }, + { + "x": 338.8013922840794, + "y": -163.12532458787445, + "z": 0.0 + }, + { + "x": 338.8020107323372, + "y": -162.10142233562493, + "z": 0.0 + }, + { + "x": 338.80262918059486, + "y": -161.0775200833752, + "z": 0.0 + }, + { + "x": 338.80324762885255, + "y": -160.05361783112556, + "z": 0.0 + }, + { + "x": 338.80386607711023, + "y": -159.02971557887594, + "z": 0.0 + }, + { + "x": 338.8044845253679, + "y": -158.00581332662637, + "z": 0.0 + }, + { + "x": 338.8051029736256, + "y": -156.98191107437685, + "z": 0.0 + }, + { + "x": 338.8057214218833, + "y": -155.9580088221271, + "z": 0.0 + }, + { + "x": 338.80633987014096, + "y": -154.93410656987749, + "z": 0.0 + }, + { + "x": 338.80695831839864, + "y": -153.91020431762786, + "z": 0.0 + }, + { + "x": 338.8075767666563, + "y": -152.88630206537823, + "z": 0.0 + }, + { + "x": 338.8081952149141, + "y": -151.86239981312872, + "z": 0.0 + }, + { + "x": 338.8088136631718, + "y": -150.83849756087898, + "z": 0.0 + }, + { + "x": 338.8094321114295, + "y": -149.81459530862935, + "z": 0.0 + }, + { + "x": 338.81005055968717, + "y": -148.79069305637972, + "z": 0.0 + }, + { + "x": 338.81066900794485, + "y": -147.7667908041301, + "z": 0.0 + }, + { + "x": 338.81128745620254, + "y": -146.74288855188058, + "z": 0.0 + }, + { + "x": 338.8119059044602, + "y": -145.71898629963079, + "z": 0.0 + }, + { + "x": 338.8125243527179, + "y": -144.69508404738139, + "z": 0.0 + }, + { + "x": 338.8131428009756, + "y": -143.67118179513164, + "z": 0.0 + } + ] + }, + { + "id": 94, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 334.8131435306341, + "y": -143.66876575143795, + "z": 0.0 + }, + { + "x": 334.8125250823764, + "y": -144.69266800368746, + "z": 0.0 + }, + { + "x": 334.8119066341186, + "y": -145.7165702559373, + "z": 0.0 + }, + { + "x": 334.81128818586103, + "y": -146.7404725081867, + "z": 0.0 + }, + { + "x": 334.81066973760323, + "y": -147.76437476043645, + "z": 0.0 + }, + { + "x": 334.81005128934555, + "y": -148.78827701268608, + "z": 0.0 + }, + { + "x": 334.80943284108787, + "y": -149.8121792649357, + "z": 0.0 + }, + { + "x": 334.8088143928302, + "y": -150.83608151718533, + "z": 0.0 + }, + { + "x": 334.8081959445725, + "y": -151.8599837694348, + "z": 0.0 + }, + { + "x": 334.8075774963148, + "y": -152.88388602168453, + "z": 0.0 + }, + { + "x": 334.80695904805714, + "y": -153.90778827393416, + "z": 0.0 + }, + { + "x": 334.80634059979946, + "y": -154.9316905261838, + "z": 0.0 + }, + { + "x": 334.8057221515418, + "y": -155.9555927784334, + "z": 0.0 + }, + { + "x": 334.8051037032841, + "y": -156.97949503068293, + "z": 0.0 + }, + { + "x": 334.8044852550263, + "y": -158.00339728293267, + "z": 0.0 + }, + { + "x": 334.8038668067686, + "y": -159.0272995351823, + "z": 0.0 + }, + { + "x": 334.8032483585109, + "y": -160.05120178743192, + "z": 0.0 + }, + { + "x": 334.80262991025324, + "y": -161.07510403968155, + "z": 0.0 + }, + { + "x": 334.80201146199556, + "y": -162.09900629193106, + "z": 0.0 + }, + { + "x": 334.8013930137379, + "y": -163.1229085441808, + "z": 0.0 + }, + { + "x": 334.8007745654802, + "y": -164.14681079643037, + "z": 0.0 + }, + { + "x": 334.8001561172225, + "y": -165.1707130486799, + "z": 0.0 + }, + { + "x": 334.7995376689647, + "y": -166.19461530092963, + "z": 0.0 + }, + { + "x": 334.79891922070703, + "y": -167.21851755317925, + "z": 0.0 + }, + { + "x": 334.79830077244935, + "y": -168.24241980542888, + "z": 0.0 + }, + { + "x": 334.79768232419167, + "y": -169.2663220576785, + "z": 0.0 + }, + { + "x": 334.797063875934, + "y": -170.29022430992802, + "z": 0.0 + }, + { + "x": 334.7964454276763, + "y": -171.31412656217776, + "z": 0.0 + }, + { + "x": 334.7958269794186, + "y": -172.3380288144274, + "z": 0.0 + }, + { + "x": 334.79520853116094, + "y": -173.36193106667702, + "z": 0.0 + }, + { + "x": 334.79459008290326, + "y": -174.38583331892664, + "z": 0.0 + }, + { + "x": 334.7939716346456, + "y": -175.40973557117616, + "z": 0.0 + }, + { + "x": 334.7933531863878, + "y": -176.4336378234259, + "z": 0.0 + }, + { + "x": 334.7927347381301, + "y": -177.45754007567547, + "z": 0.0 + }, + { + "x": 334.7921162898724, + "y": -178.4814423279251, + "z": 0.0 + }, + { + "x": 334.7914978416147, + "y": -179.50534458017472, + "z": 0.0 + }, + { + "x": 334.79087939335705, + "y": -180.52924683242423, + "z": 0.0 + }, + { + "x": 334.79026094509936, + "y": -181.55314908467398, + "z": 0.0 + }, + { + "x": 334.7896424968417, + "y": -182.57705133692372, + "z": 0.0 + }, + { + "x": 334.789024048584, + "y": -183.60095358917312, + "z": 0.0 + }, + { + "x": 334.7884056003263, + "y": -184.62485584142286, + "z": 0.0 + }, + { + "x": 334.78778715206863, + "y": -185.64875809367248, + "z": 0.0 + } + ] + }, + { + "id": 95, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 340.70817741787323, + "y": -317.4523581169669, + "z": 0.0 + }, + { + "x": 340.70878871079753, + "y": -316.44030222681437, + "z": 0.0 + }, + { + "x": 340.7094000037218, + "y": -315.4282463366616, + "z": 0.0 + }, + { + "x": 340.7100112966461, + "y": -314.4161904465093, + "z": 0.0 + }, + { + "x": 340.7106225895704, + "y": -313.4041345563567, + "z": 0.0 + }, + { + "x": 340.71123388249464, + "y": -312.392078666204, + "z": 0.0 + }, + { + "x": 340.71184517541894, + "y": -311.3800227760517, + "z": 0.0 + }, + { + "x": 340.7124564683432, + "y": -310.3679668858989, + "z": 0.0 + }, + { + "x": 340.7130677612675, + "y": -309.3559109957466, + "z": 0.0 + }, + { + "x": 340.71367905419174, + "y": -308.34385510559383, + "z": 0.0 + }, + { + "x": 340.71429034711605, + "y": -307.33179921544155, + "z": 0.0 + }, + { + "x": 340.7149016400403, + "y": -306.3197433252888, + "z": 0.0 + }, + { + "x": 340.7155129329646, + "y": -305.3076874351365, + "z": 0.0 + }, + { + "x": 340.7161242258889, + "y": -304.29563154498396, + "z": 0.0 + }, + { + "x": 340.71673551881315, + "y": -303.28357565483117, + "z": 0.0 + }, + { + "x": 340.71734681173746, + "y": -302.2715197646789, + "z": 0.0 + }, + { + "x": 340.7179581046617, + "y": -301.25946387452615, + "z": 0.0 + }, + { + "x": 340.718569397586, + "y": -300.2474079843738, + "z": 0.0 + }, + { + "x": 340.71918069051026, + "y": -299.23535209422107, + "z": 0.0 + }, + { + "x": 340.71979198343456, + "y": -298.22329620406873, + "z": 0.0 + }, + { + "x": 340.7204032763588, + "y": -297.211240313916, + "z": 0.0 + }, + { + "x": 340.7210145692831, + "y": -296.1991844237637, + "z": 0.0 + }, + { + "x": 340.7216258622074, + "y": -295.18712853361114, + "z": 0.0 + }, + { + "x": 340.72223715513167, + "y": -294.1750726434584, + "z": 0.0 + }, + { + "x": 340.72284844805597, + "y": -293.16301675330607, + "z": 0.0 + }, + { + "x": 340.7234597409802, + "y": -292.15096086315333, + "z": 0.0 + }, + { + "x": 340.7240710339045, + "y": -291.13890497300105, + "z": 0.0 + }, + { + "x": 340.72468232682877, + "y": -290.12684908284825, + "z": 0.0 + }, + { + "x": 340.7252936197531, + "y": -289.11479319269597, + "z": 0.0 + }, + { + "x": 340.7259049126773, + "y": -288.10273730254323, + "z": 0.0 + }, + { + "x": 340.7265162056016, + "y": -287.0906814123909, + "z": 0.0 + }, + { + "x": 340.72712749852593, + "y": -286.0786255222384, + "z": 0.0 + }, + { + "x": 340.7277387914502, + "y": -285.0665696320856, + "z": 0.0 + }, + { + "x": 340.7283500843745, + "y": -284.0545137419333, + "z": 0.0 + }, + { + "x": 340.72896137729873, + "y": -283.04245785178057, + "z": 0.0 + }, + { + "x": 340.72957267022304, + "y": -282.03040196162823, + "z": 0.0 + }, + { + "x": 340.7301839631473, + "y": -281.0183460714755, + "z": 0.0 + }, + { + "x": 340.7307952560716, + "y": -280.00629018132315, + "z": 0.0 + }, + { + "x": 340.73140654899584, + "y": -278.9942342911704, + "z": 0.0 + }, + { + "x": 340.73201784192014, + "y": -277.98217840101813, + "z": 0.0 + }, + { + "x": 340.73262913484444, + "y": -276.97012251086556, + "z": 0.0 + }, + { + "x": 340.7332404277687, + "y": -275.9580666207128, + "z": 0.0 + }, + { + "x": 340.733851720693, + "y": -274.94601073056054, + "z": 0.0 + }, + { + "x": 340.73446301361724, + "y": -273.93395484040775, + "z": 0.0 + }, + { + "x": 340.73507430654155, + "y": -272.92189895025547, + "z": 0.0 + }, + { + "x": 340.7356855994658, + "y": -271.9098430601027, + "z": 0.0 + }, + { + "x": 340.7362968923901, + "y": -270.8977871699504, + "z": 0.0 + }, + { + "x": 340.7369081853144, + "y": -269.8857312797978, + "z": 0.0 + }, + { + "x": 340.73751947823865, + "y": -268.8736753896451, + "z": 0.0 + }, + { + "x": 340.73813077116296, + "y": -267.86161949949275, + "z": 0.0 + }, + { + "x": 340.7387420640872, + "y": -266.84956360934, + "z": 0.0 + }, + { + "x": 340.7393533570115, + "y": -265.83750771918767, + "z": 0.0 + }, + { + "x": 340.73996464993576, + "y": -264.82545182903493, + "z": 0.0 + }, + { + "x": 340.74057594286006, + "y": -263.8133959388826, + "z": 0.0 + }, + { + "x": 340.7411872357843, + "y": -262.80134004872986, + "z": 0.0 + }, + { + "x": 340.7417985287086, + "y": -261.7892841585775, + "z": 0.0 + }, + { + "x": 340.7424098216329, + "y": -260.777228268425, + "z": 0.0 + }, + { + "x": 340.74302111455717, + "y": -259.7651723782722, + "z": 0.0 + }, + { + "x": 340.74363240748147, + "y": -258.75311648811993, + "z": 0.0 + }, + { + "x": 340.7442437004057, + "y": -257.74106059796713, + "z": 0.0 + }, + { + "x": 340.74485499333, + "y": -256.72900470781485, + "z": 0.0 + }, + { + "x": 340.74546628625427, + "y": -255.71694881766206, + "z": 0.0 + }, + { + "x": 340.7460775791786, + "y": -254.70489292750975, + "z": 0.0 + }, + { + "x": 340.7466888721028, + "y": -253.69283703735698, + "z": 0.0 + }, + { + "x": 340.7473001650271, + "y": -252.68078114720467, + "z": 0.0 + }, + { + "x": 340.74791145795143, + "y": -251.66872525705213, + "z": 0.0 + }, + { + "x": 340.7485227508757, + "y": -250.65666936689937, + "z": 0.0 + }, + { + "x": 340.7491340438, + "y": -249.64461347674705, + "z": 0.0 + }, + { + "x": 340.74974533672423, + "y": -248.6325575865943, + "z": 0.0 + }, + { + "x": 340.75035662964854, + "y": -247.62050169644198, + "z": 0.0 + }, + { + "x": 340.7509679225728, + "y": -246.6084458062892, + "z": 0.0 + }, + { + "x": 340.7515792154971, + "y": -245.5963899161369, + "z": 0.0 + }, + { + "x": 340.75219050842134, + "y": -244.58433402598413, + "z": 0.0 + }, + { + "x": 340.75280180134564, + "y": -243.57227813583182, + "z": 0.0 + }, + { + "x": 340.75341309426994, + "y": -242.56022224567928, + "z": 0.0 + }, + { + "x": 340.7540243871942, + "y": -241.54816635552652, + "z": 0.0 + }, + { + "x": 340.7546356801185, + "y": -240.5361104653742, + "z": 0.0 + }, + { + "x": 340.75524697304274, + "y": -239.52405457522144, + "z": 0.0 + }, + { + "x": 340.75585826596705, + "y": -238.51199868506913, + "z": 0.0 + }, + { + "x": 340.7564695588913, + "y": -237.49994279491636, + "z": 0.0 + }, + { + "x": 340.7570808518156, + "y": -236.48788690476405, + "z": 0.0 + }, + { + "x": 340.75769214473985, + "y": -235.4758310146113, + "z": 0.0 + }, + { + "x": 340.75830343766415, + "y": -234.46377512445898, + "z": 0.0 + }, + { + "x": 340.75891473058846, + "y": -233.45171923430644, + "z": 0.0 + }, + { + "x": 340.7595260235127, + "y": -232.43966334415367, + "z": 0.0 + }, + { + "x": 340.760137316437, + "y": -231.42760745400136, + "z": 0.0 + }, + { + "x": 340.76074860936126, + "y": -230.4155515638486, + "z": 0.0 + }, + { + "x": 340.76135990228556, + "y": -229.40349567369628, + "z": 0.0 + }, + { + "x": 340.7619711952098, + "y": -228.39143978354352, + "z": 0.0 + }, + { + "x": 340.7625824881341, + "y": -227.3793838933912, + "z": 0.0 + }, + { + "x": 340.7631937810584, + "y": -226.36732800323867, + "z": 0.0 + }, + { + "x": 340.76380507398267, + "y": -225.3552721130859, + "z": 0.0 + }, + { + "x": 340.76441636690697, + "y": -224.3432162229336, + "z": 0.0 + }, + { + "x": 340.7650276598312, + "y": -223.33116033278083, + "z": 0.0 + }, + { + "x": 340.7656389527555, + "y": -222.31910444262851, + "z": 0.0 + }, + { + "x": 340.76625024567977, + "y": -221.30704855247575, + "z": 0.0 + }, + { + "x": 340.7668615386041, + "y": -220.29499266232344, + "z": 0.0 + }, + { + "x": 340.7674728315283, + "y": -219.28293677217067, + "z": 0.0 + }, + { + "x": 340.7680841244526, + "y": -218.27088088201836, + "z": 0.0 + }, + { + "x": 340.76869541737693, + "y": -217.25882499186582, + "z": 0.0 + }, + { + "x": 340.7693067103012, + "y": -216.24676910171306, + "z": 0.0 + }, + { + "x": 340.7699180032255, + "y": -215.23471321156075, + "z": 0.0 + }, + { + "x": 340.77052929614973, + "y": -214.22265732140798, + "z": 0.0 + }, + { + "x": 340.77114058907404, + "y": -213.21060143125567, + "z": 0.0 + }, + { + "x": 340.7717518819983, + "y": -212.1985455411029, + "z": 0.0 + }, + { + "x": 340.7723631749226, + "y": -211.1864896509506, + "z": 0.0 + }, + { + "x": 340.77297446784684, + "y": -210.17443376079783, + "z": 0.0 + }, + { + "x": 340.77358576077114, + "y": -209.1623778706455, + "z": 0.0 + } + ] + }, + { + "id": 96, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 332.773587220088, + "y": -209.1575457832579, + "z": 0.0 + }, + { + "x": 332.7729759271637, + "y": -210.16960167341065, + "z": 0.0 + }, + { + "x": 332.77236463423947, + "y": -211.18165756356296, + "z": 0.0 + }, + { + "x": 332.77175334131516, + "y": -212.19371345371573, + "z": 0.0 + }, + { + "x": 332.7711420483909, + "y": -213.20576934386804, + "z": 0.0 + }, + { + "x": 332.7705307554666, + "y": -214.2178252340208, + "z": 0.0 + }, + { + "x": 332.76991946254236, + "y": -215.22988112417312, + "z": 0.0 + }, + { + "x": 332.76930816961806, + "y": -216.24193701432588, + "z": 0.0 + }, + { + "x": 332.7686968766938, + "y": -217.2539929044782, + "z": 0.0 + }, + { + "x": 332.7680855837695, + "y": -218.26604879463073, + "z": 0.0 + }, + { + "x": 332.7674742908452, + "y": -219.2781046847835, + "z": 0.0 + }, + { + "x": 332.76686299792095, + "y": -220.2901605749358, + "z": 0.0 + }, + { + "x": 332.76625170499665, + "y": -221.30221646508858, + "z": 0.0 + }, + { + "x": 332.7656404120724, + "y": -222.3142723552409, + "z": 0.0 + }, + { + "x": 332.7650291191481, + "y": -223.32632824539365, + "z": 0.0 + }, + { + "x": 332.76441782622385, + "y": -224.33838413554597, + "z": 0.0 + }, + { + "x": 332.76380653329954, + "y": -225.35044002569873, + "z": 0.0 + }, + { + "x": 332.7631952403753, + "y": -226.36249591585104, + "z": 0.0 + }, + { + "x": 332.762583947451, + "y": -227.37455180600358, + "z": 0.0 + }, + { + "x": 332.7619726545267, + "y": -228.38660769615635, + "z": 0.0 + }, + { + "x": 332.76136136160244, + "y": -229.39866358630866, + "z": 0.0 + }, + { + "x": 332.76075006867813, + "y": -230.41071947646142, + "z": 0.0 + }, + { + "x": 332.7601387757539, + "y": -231.42277536661373, + "z": 0.0 + }, + { + "x": 332.7595274828296, + "y": -232.4348312567665, + "z": 0.0 + }, + { + "x": 332.75891618990534, + "y": -233.4468871469188, + "z": 0.0 + }, + { + "x": 332.75830489698103, + "y": -234.45894303707135, + "z": 0.0 + }, + { + "x": 332.7576936040567, + "y": -235.47099892722412, + "z": 0.0 + }, + { + "x": 332.7570823111325, + "y": -236.48305481737643, + "z": 0.0 + }, + { + "x": 332.7564710182082, + "y": -237.4951107075292, + "z": 0.0 + }, + { + "x": 332.7558597252839, + "y": -238.5071665976815, + "z": 0.0 + }, + { + "x": 332.7552484323596, + "y": -239.51922248783427, + "z": 0.0 + }, + { + "x": 332.7546371394354, + "y": -240.53127837798658, + "z": 0.0 + }, + { + "x": 332.75402584651107, + "y": -241.54333426813935, + "z": 0.0 + }, + { + "x": 332.7534145535868, + "y": -242.55539015829166, + "z": 0.0 + }, + { + "x": 332.7528032606625, + "y": -243.5674460484442, + "z": 0.0 + }, + { + "x": 332.7521919677382, + "y": -244.57950193859696, + "z": 0.0 + }, + { + "x": 332.75158067481397, + "y": -245.59155782874927, + "z": 0.0 + }, + { + "x": 332.75096938188966, + "y": -246.60361371890204, + "z": 0.0 + }, + { + "x": 332.7503580889654, + "y": -247.61566960905435, + "z": 0.0 + }, + { + "x": 332.7497467960411, + "y": -248.62772549920712, + "z": 0.0 + }, + { + "x": 332.74913550311686, + "y": -249.63978138935943, + "z": 0.0 + }, + { + "x": 332.74852421019256, + "y": -250.6518372795122, + "z": 0.0 + }, + { + "x": 332.7479129172683, + "y": -251.6638931696645, + "z": 0.0 + }, + { + "x": 332.747301624344, + "y": -252.67594905981704, + "z": 0.0 + }, + { + "x": 332.7466903314197, + "y": -253.6880049499698, + "z": 0.0 + }, + { + "x": 332.74607903849545, + "y": -254.70006084012212, + "z": 0.0 + }, + { + "x": 332.74546774557115, + "y": -255.7121167302749, + "z": 0.0 + }, + { + "x": 332.7448564526469, + "y": -256.7241726204272, + "z": 0.0 + }, + { + "x": 332.7442451597226, + "y": -257.73622851057996, + "z": 0.0 + }, + { + "x": 332.74363386679835, + "y": -258.7482844007323, + "z": 0.0 + }, + { + "x": 332.74302257387404, + "y": -259.76034029088504, + "z": 0.0 + }, + { + "x": 332.7424112809498, + "y": -260.7723961810374, + "z": 0.0 + }, + { + "x": 332.7417999880255, + "y": -261.7844520711899, + "z": 0.0 + }, + { + "x": 332.7411886951012, + "y": -262.7965079613427, + "z": 0.0 + }, + { + "x": 332.74057740217694, + "y": -263.80856385149497, + "z": 0.0 + }, + { + "x": 332.73996610925263, + "y": -264.82061974164776, + "z": 0.0 + }, + { + "x": 332.7393548163284, + "y": -265.83267563180004, + "z": 0.0 + }, + { + "x": 332.7387435234041, + "y": -266.84473152195284, + "z": 0.0 + }, + { + "x": 332.73813223047983, + "y": -267.8567874121051, + "z": 0.0 + }, + { + "x": 332.73752093755553, + "y": -268.8688433022579, + "z": 0.0 + }, + { + "x": 332.7369096446313, + "y": -269.8808991924102, + "z": 0.0 + }, + { + "x": 332.736298351707, + "y": -270.89295508256276, + "z": 0.0 + }, + { + "x": 332.7356870587827, + "y": -271.9050109727155, + "z": 0.0 + }, + { + "x": 332.7350757658584, + "y": -272.91706686286784, + "z": 0.0 + }, + { + "x": 332.7344644729341, + "y": -273.9291227530206, + "z": 0.0 + }, + { + "x": 332.7338531800099, + "y": -274.9411786431729, + "z": 0.0 + }, + { + "x": 332.73324188708557, + "y": -275.95323453332566, + "z": 0.0 + }, + { + "x": 332.7326305941613, + "y": -276.96529042347794, + "z": 0.0 + }, + { + "x": 332.732019301237, + "y": -277.9773463136305, + "z": 0.0 + }, + { + "x": 332.7314080083127, + "y": -278.98940220378324, + "z": 0.0 + }, + { + "x": 332.73079671538846, + "y": -280.0014580939355, + "z": 0.0 + }, + { + "x": 332.73018542246416, + "y": -281.0135139840883, + "z": 0.0 + }, + { + "x": 332.7295741295399, + "y": -282.0255698742406, + "z": 0.0 + }, + { + "x": 332.7289628366156, + "y": -283.0376257643934, + "z": 0.0 + }, + { + "x": 332.72835154369136, + "y": -284.0496816545457, + "z": 0.0 + }, + { + "x": 332.72774025076706, + "y": -285.0617375446984, + "z": 0.0 + }, + { + "x": 332.7271289578428, + "y": -286.07379343485076, + "z": 0.0 + }, + { + "x": 332.7265176649185, + "y": -287.08584932500327, + "z": 0.0 + }, + { + "x": 332.7259063719942, + "y": -288.09790521515606, + "z": 0.0 + }, + { + "x": 332.72529507906995, + "y": -289.10996110530834, + "z": 0.0 + }, + { + "x": 332.72468378614565, + "y": -290.1220169954611, + "z": 0.0 + }, + { + "x": 332.7240724932214, + "y": -291.1340728856134, + "z": 0.0 + }, + { + "x": 332.7234612002971, + "y": -292.14612877576616, + "z": 0.0 + }, + { + "x": 332.72284990737285, + "y": -293.15818466591844, + "z": 0.0 + }, + { + "x": 332.72223861444854, + "y": -294.17024055607124, + "z": 0.0 + }, + { + "x": 332.7216273215243, + "y": -295.1822964462235, + "z": 0.0 + }, + { + "x": 332.7210160286, + "y": -296.1943523363761, + "z": 0.0 + }, + { + "x": 332.7204047356757, + "y": -297.2064082265288, + "z": 0.0 + }, + { + "x": 332.71979344275144, + "y": -298.2184641166811, + "z": 0.0 + }, + { + "x": 332.71918214982713, + "y": -299.2305200068339, + "z": 0.0 + }, + { + "x": 332.7185708569029, + "y": -300.2425758969862, + "z": 0.0 + }, + { + "x": 332.7179595639786, + "y": -301.254631787139, + "z": 0.0 + }, + { + "x": 332.71734827105433, + "y": -302.26668767729126, + "z": 0.0 + }, + { + "x": 332.71673697813003, + "y": -303.278743567444, + "z": 0.0 + }, + { + "x": 332.7161256852058, + "y": -304.29079945759634, + "z": 0.0 + }, + { + "x": 332.7155143922815, + "y": -305.30285534774885, + "z": 0.0 + }, + { + "x": 332.7149030993572, + "y": -306.31491123790164, + "z": 0.0 + }, + { + "x": 332.7142918064329, + "y": -307.3269671280539, + "z": 0.0 + }, + { + "x": 332.7136805135086, + "y": -308.33902301820666, + "z": 0.0 + }, + { + "x": 332.7130692205844, + "y": -309.351078908359, + "z": 0.0 + }, + { + "x": 332.71245792766007, + "y": -310.36313479851174, + "z": 0.0 + }, + { + "x": 332.7118466347358, + "y": -311.3751906886641, + "z": 0.0 + }, + { + "x": 332.7112353418115, + "y": -312.3872465788168, + "z": 0.0 + }, + { + "x": 332.71062404888727, + "y": -313.3993024689691, + "z": 0.0 + }, + { + "x": 332.71001275596296, + "y": -314.41135835912166, + "z": 0.0 + }, + { + "x": 332.70940146303866, + "y": -315.4234142492744, + "z": 0.0 + }, + { + "x": 332.7087901701144, + "y": -316.43547013942674, + "z": 0.0 + }, + { + "x": 332.7081788771901, + "y": -317.44752602957925, + "z": 0.0 + } + ] + }, + { + "id": 97, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 336.7735864904296, + "y": -209.1599618269517, + "z": 0.0 + }, + { + "x": 336.7729751975053, + "y": -210.17201771710424, + "z": 0.0 + }, + { + "x": 336.772363904581, + "y": -211.18407360725678, + "z": 0.0 + }, + { + "x": 336.7717526116567, + "y": -212.19612949740932, + "z": 0.0 + }, + { + "x": 336.7711413187325, + "y": -213.20818538756185, + "z": 0.0 + }, + { + "x": 336.77053002580817, + "y": -214.2202412777144, + "z": 0.0 + }, + { + "x": 336.7699187328839, + "y": -215.23229716786693, + "z": 0.0 + }, + { + "x": 336.7693074399596, + "y": -216.24435305801947, + "z": 0.0 + }, + { + "x": 336.76869614703537, + "y": -217.256408948172, + "z": 0.0 + }, + { + "x": 336.76808485411107, + "y": -218.26846483832455, + "z": 0.0 + }, + { + "x": 336.76747356118676, + "y": -219.2805207284771, + "z": 0.0 + }, + { + "x": 336.7668622682625, + "y": -220.29257661862962, + "z": 0.0 + }, + { + "x": 336.7662509753382, + "y": -221.30463250878216, + "z": 0.0 + }, + { + "x": 336.76563968241396, + "y": -222.3166883989347, + "z": 0.0 + }, + { + "x": 336.76502838948966, + "y": -223.32874428908724, + "z": 0.0 + }, + { + "x": 336.7644170965654, + "y": -224.34080017923978, + "z": 0.0 + }, + { + "x": 336.7638058036411, + "y": -225.35285606939232, + "z": 0.0 + }, + { + "x": 336.76319451071686, + "y": -226.36491195954486, + "z": 0.0 + }, + { + "x": 336.76258321779255, + "y": -227.3769678496974, + "z": 0.0 + }, + { + "x": 336.76197192486825, + "y": -228.38902373984993, + "z": 0.0 + }, + { + "x": 336.761360631944, + "y": -229.40107963000247, + "z": 0.0 + }, + { + "x": 336.7607493390197, + "y": -230.413135520155, + "z": 0.0 + }, + { + "x": 336.76013804609545, + "y": -231.42519141030755, + "z": 0.0 + }, + { + "x": 336.75952675317114, + "y": -232.4372473004601, + "z": 0.0 + }, + { + "x": 336.7589154602469, + "y": -233.44930319061262, + "z": 0.0 + }, + { + "x": 336.7583041673226, + "y": -234.46135908076516, + "z": 0.0 + }, + { + "x": 336.7576928743983, + "y": -235.4734149709177, + "z": 0.0 + }, + { + "x": 336.75708158147404, + "y": -236.48547086107024, + "z": 0.0 + }, + { + "x": 336.75647028854974, + "y": -237.49752675122278, + "z": 0.0 + }, + { + "x": 336.7558589956255, + "y": -238.50958264137532, + "z": 0.0 + }, + { + "x": 336.7552477027012, + "y": -239.52163853152786, + "z": 0.0 + }, + { + "x": 336.75463640977694, + "y": -240.5336944216804, + "z": 0.0 + }, + { + "x": 336.75402511685263, + "y": -241.54575031183293, + "z": 0.0 + }, + { + "x": 336.7534138239284, + "y": -242.55780620198547, + "z": 0.0 + }, + { + "x": 336.7528025310041, + "y": -243.569862092138, + "z": 0.0 + }, + { + "x": 336.7521912380798, + "y": -244.58191798229055, + "z": 0.0 + }, + { + "x": 336.7515799451555, + "y": -245.5939738724431, + "z": 0.0 + }, + { + "x": 336.7509686522312, + "y": -246.60602976259563, + "z": 0.0 + }, + { + "x": 336.750357359307, + "y": -247.61808565274816, + "z": 0.0 + }, + { + "x": 336.74974606638267, + "y": -248.6301415429007, + "z": 0.0 + }, + { + "x": 336.7491347734584, + "y": -249.64219743305324, + "z": 0.0 + }, + { + "x": 336.7485234805341, + "y": -250.65425332320578, + "z": 0.0 + }, + { + "x": 336.74791218760987, + "y": -251.66630921335832, + "z": 0.0 + }, + { + "x": 336.74730089468557, + "y": -252.67836510351086, + "z": 0.0 + }, + { + "x": 336.74668960176126, + "y": -253.6904209936634, + "z": 0.0 + }, + { + "x": 336.746078308837, + "y": -254.70247688381593, + "z": 0.0 + }, + { + "x": 336.7454670159127, + "y": -255.71453277396847, + "z": 0.0 + }, + { + "x": 336.74485572298846, + "y": -256.72658866412104, + "z": 0.0 + }, + { + "x": 336.74424443006416, + "y": -257.73864455427355, + "z": 0.0 + }, + { + "x": 336.7436331371399, + "y": -258.7507004444261, + "z": 0.0 + }, + { + "x": 336.7430218442156, + "y": -259.7627563345786, + "z": 0.0 + }, + { + "x": 336.74241055129136, + "y": -260.7748122247312, + "z": 0.0 + }, + { + "x": 336.74179925836705, + "y": -261.7868681148837, + "z": 0.0 + }, + { + "x": 336.74118796544275, + "y": -262.79892400503627, + "z": 0.0 + }, + { + "x": 336.7405766725185, + "y": -263.8109798951888, + "z": 0.0 + }, + { + "x": 336.7399653795942, + "y": -264.82303578534135, + "z": 0.0 + }, + { + "x": 336.73935408666995, + "y": -265.83509167549386, + "z": 0.0 + }, + { + "x": 336.73874279374564, + "y": -266.8471475656464, + "z": 0.0 + }, + { + "x": 336.7381315008214, + "y": -267.85920345579893, + "z": 0.0 + }, + { + "x": 336.7375202078971, + "y": -268.8712593459515, + "z": 0.0 + }, + { + "x": 336.73690891497284, + "y": -269.883315236104, + "z": 0.0 + }, + { + "x": 336.73629762204854, + "y": -270.8953711262566, + "z": 0.0 + }, + { + "x": 336.73568632912423, + "y": -271.9074270164091, + "z": 0.0 + }, + { + "x": 336.7350750362, + "y": -272.91948290656165, + "z": 0.0 + }, + { + "x": 336.7344637432757, + "y": -273.93153879671416, + "z": 0.0 + }, + { + "x": 336.73385245035143, + "y": -274.94359468686673, + "z": 0.0 + }, + { + "x": 336.73324115742713, + "y": -275.95565057701924, + "z": 0.0 + }, + { + "x": 336.7326298645029, + "y": -276.96770646717175, + "z": 0.0 + }, + { + "x": 336.7320185715786, + "y": -277.9797623573243, + "z": 0.0 + }, + { + "x": 336.7314072786543, + "y": -278.99181824747683, + "z": 0.0 + }, + { + "x": 336.73079598573, + "y": -280.00387413762934, + "z": 0.0 + }, + { + "x": 336.7301846928057, + "y": -281.0159300277819, + "z": 0.0 + }, + { + "x": 336.7295733998815, + "y": -282.0279859179344, + "z": 0.0 + }, + { + "x": 336.72896210695717, + "y": -283.040041808087, + "z": 0.0 + }, + { + "x": 336.7283508140329, + "y": -284.0520976982395, + "z": 0.0 + }, + { + "x": 336.7277395211086, + "y": -285.064153588392, + "z": 0.0 + }, + { + "x": 336.72712822818437, + "y": -286.07620947854457, + "z": 0.0 + }, + { + "x": 336.72651693526007, + "y": -287.0882653686971, + "z": 0.0 + }, + { + "x": 336.72590564233576, + "y": -288.10032125884965, + "z": 0.0 + }, + { + "x": 336.7252943494115, + "y": -289.11237714900216, + "z": 0.0 + }, + { + "x": 336.7246830564872, + "y": -290.12443303915467, + "z": 0.0 + }, + { + "x": 336.72407176356296, + "y": -291.13648892930723, + "z": 0.0 + }, + { + "x": 336.72346047063866, + "y": -292.14854481945974, + "z": 0.0 + }, + { + "x": 336.7228491777144, + "y": -293.16060070961225, + "z": 0.0 + }, + { + "x": 336.7222378847901, + "y": -294.1726565997648, + "z": 0.0 + }, + { + "x": 336.72162659186586, + "y": -295.18471248991733, + "z": 0.0 + }, + { + "x": 336.72101529894155, + "y": -296.1967683800699, + "z": 0.0 + }, + { + "x": 336.72040400601725, + "y": -297.2088242702224, + "z": 0.0 + }, + { + "x": 336.719792713093, + "y": -298.2208801603749, + "z": 0.0 + }, + { + "x": 336.7191814201687, + "y": -299.2329360505275, + "z": 0.0 + }, + { + "x": 336.71857012724445, + "y": -300.24499194068, + "z": 0.0 + }, + { + "x": 336.71795883432014, + "y": -301.25704783083256, + "z": 0.0 + }, + { + "x": 336.7173475413959, + "y": -302.2691037209851, + "z": 0.0 + }, + { + "x": 336.7167362484716, + "y": -303.2811596111376, + "z": 0.0 + }, + { + "x": 336.71612495554734, + "y": -304.29321550129015, + "z": 0.0 + }, + { + "x": 336.71551366262304, + "y": -305.30527139144266, + "z": 0.0 + }, + { + "x": 336.71490236969873, + "y": -306.3173272815952, + "z": 0.0 + }, + { + "x": 336.7142910767745, + "y": -307.32938317174774, + "z": 0.0 + }, + { + "x": 336.7136797838502, + "y": -308.34143906190025, + "z": 0.0 + }, + { + "x": 336.71306849092593, + "y": -309.3534949520528, + "z": 0.0 + }, + { + "x": 336.71245719800163, + "y": -310.3655508422053, + "z": 0.0 + }, + { + "x": 336.7118459050774, + "y": -311.3776067323579, + "z": 0.0 + }, + { + "x": 336.7112346121531, + "y": -312.3896626225104, + "z": 0.0 + }, + { + "x": 336.71062331922883, + "y": -313.4017185126629, + "z": 0.0 + }, + { + "x": 336.7100120263045, + "y": -314.4137744028155, + "z": 0.0 + }, + { + "x": 336.7094007333802, + "y": -315.425830292968, + "z": 0.0 + }, + { + "x": 336.708789440456, + "y": -316.43788618312055, + "z": 0.0 + }, + { + "x": 336.70817814753167, + "y": -317.44994207327306, + "z": 0.0 + } + ] + }, + { + "id": 98, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 338.7081777827025, + "y": -317.45115009511994, + "z": 0.0 + }, + { + "x": 338.7087890756268, + "y": -316.43909420496743, + "z": 0.0 + }, + { + "x": 338.709400368551, + "y": -315.4270383148148, + "z": 0.0 + }, + { + "x": 338.7100116614753, + "y": -314.4149824246624, + "z": 0.0 + }, + { + "x": 338.7106229543996, + "y": -313.4029265345098, + "z": 0.0 + }, + { + "x": 338.7112342473239, + "y": -312.39087064435716, + "z": 0.0 + }, + { + "x": 338.7118455402482, + "y": -311.37881475420477, + "z": 0.0 + }, + { + "x": 338.7124568331724, + "y": -310.36675886405214, + "z": 0.0 + }, + { + "x": 338.7130681260967, + "y": -309.35470297389975, + "z": 0.0 + }, + { + "x": 338.713679419021, + "y": -308.342647083747, + "z": 0.0 + }, + { + "x": 338.7142907119453, + "y": -307.3305911935946, + "z": 0.0 + }, + { + "x": 338.7149020048695, + "y": -306.318535303442, + "z": 0.0 + }, + { + "x": 338.7155132977938, + "y": -305.3064794132896, + "z": 0.0 + }, + { + "x": 338.7161245907181, + "y": -304.2944235231371, + "z": 0.0 + }, + { + "x": 338.7167358836424, + "y": -303.28236763298435, + "z": 0.0 + }, + { + "x": 338.7173471765667, + "y": -302.27031174283195, + "z": 0.0 + }, + { + "x": 338.7179584694909, + "y": -301.2582558526793, + "z": 0.0 + }, + { + "x": 338.7185697624152, + "y": -300.24619996252693, + "z": 0.0 + }, + { + "x": 338.7191810553395, + "y": -299.2341440723743, + "z": 0.0 + }, + { + "x": 338.7197923482638, + "y": -298.2220881822218, + "z": 0.0 + }, + { + "x": 338.720403641188, + "y": -297.2100322920692, + "z": 0.0 + }, + { + "x": 338.7210149341123, + "y": -296.1979764019168, + "z": 0.0 + }, + { + "x": 338.7216262270366, + "y": -295.18592051176427, + "z": 0.0 + }, + { + "x": 338.7222375199609, + "y": -294.17386462161164, + "z": 0.0 + }, + { + "x": 338.7228488128852, + "y": -293.16180873145913, + "z": 0.0 + }, + { + "x": 338.7234601058094, + "y": -292.1497528413065, + "z": 0.0 + }, + { + "x": 338.7240713987337, + "y": -291.1376969511541, + "z": 0.0 + }, + { + "x": 338.724682691658, + "y": -290.1256410610015, + "z": 0.0 + }, + { + "x": 338.7252939845823, + "y": -289.1135851708491, + "z": 0.0 + }, + { + "x": 338.7259052775065, + "y": -288.10152928069647, + "z": 0.0 + }, + { + "x": 338.7265165704308, + "y": -287.08947339054396, + "z": 0.0 + }, + { + "x": 338.7271278633551, + "y": -286.07741750039145, + "z": 0.0 + }, + { + "x": 338.7277391562794, + "y": -285.0653616102388, + "z": 0.0 + }, + { + "x": 338.72835044920373, + "y": -284.0533057200864, + "z": 0.0 + }, + { + "x": 338.7289617421279, + "y": -283.0412498299338, + "z": 0.0 + }, + { + "x": 338.7295730350522, + "y": -282.0291939397813, + "z": 0.0 + }, + { + "x": 338.73018432797653, + "y": -281.01713804962867, + "z": 0.0 + }, + { + "x": 338.73079562090084, + "y": -280.0050821594763, + "z": 0.0 + }, + { + "x": 338.731406913825, + "y": -278.99302626932365, + "z": 0.0 + }, + { + "x": 338.73201820674933, + "y": -277.98097037917125, + "z": 0.0 + }, + { + "x": 338.73262949967364, + "y": -276.96891448901863, + "z": 0.0 + }, + { + "x": 338.73324079259794, + "y": -275.956858598866, + "z": 0.0 + }, + { + "x": 338.73385208552224, + "y": -274.9448027087136, + "z": 0.0 + }, + { + "x": 338.73446337844643, + "y": -273.932746818561, + "z": 0.0 + }, + { + "x": 338.73507467137074, + "y": -272.9206909284086, + "z": 0.0 + }, + { + "x": 338.73568596429504, + "y": -271.90863503825585, + "z": 0.0 + }, + { + "x": 338.73629725721935, + "y": -270.89657914810346, + "z": 0.0 + }, + { + "x": 338.73690855014365, + "y": -269.88452325795095, + "z": 0.0 + }, + { + "x": 338.73751984306784, + "y": -268.8724673677983, + "z": 0.0 + }, + { + "x": 338.73813113599215, + "y": -267.8604114776458, + "z": 0.0 + }, + { + "x": 338.73874242891645, + "y": -266.8483555874932, + "z": 0.0 + }, + { + "x": 338.73935372184076, + "y": -265.8362996973408, + "z": 0.0 + }, + { + "x": 338.73996501476495, + "y": -264.82424380718817, + "z": 0.0 + }, + { + "x": 338.74057630768925, + "y": -263.81218791703566, + "z": 0.0 + }, + { + "x": 338.74118760061356, + "y": -262.80013202688303, + "z": 0.0 + }, + { + "x": 338.74179889353786, + "y": -261.78807613673064, + "z": 0.0 + }, + { + "x": 338.74241018646217, + "y": -260.7760202465781, + "z": 0.0 + }, + { + "x": 338.74302147938636, + "y": -259.7639643564254, + "z": 0.0 + }, + { + "x": 338.74363277231066, + "y": -258.751908466273, + "z": 0.0 + }, + { + "x": 338.74424406523497, + "y": -257.73985257612037, + "z": 0.0 + }, + { + "x": 338.74485535815927, + "y": -256.727796685968, + "z": 0.0 + }, + { + "x": 338.74546665108346, + "y": -255.71574079581526, + "z": 0.0 + }, + { + "x": 338.74607794400777, + "y": -254.70368490566284, + "z": 0.0 + }, + { + "x": 338.74668923693207, + "y": -253.6916290155102, + "z": 0.0 + }, + { + "x": 338.7473005298564, + "y": -252.67957312535776, + "z": 0.0 + }, + { + "x": 338.7479118227807, + "y": -251.66751723520522, + "z": 0.0 + }, + { + "x": 338.74852311570487, + "y": -250.65546134505257, + "z": 0.0 + }, + { + "x": 338.7491344086292, + "y": -249.64340545490015, + "z": 0.0 + }, + { + "x": 338.7497457015535, + "y": -248.6313495647475, + "z": 0.0 + }, + { + "x": 338.7503569944778, + "y": -247.61929367459507, + "z": 0.0 + }, + { + "x": 338.750968287402, + "y": -246.60723778444242, + "z": 0.0 + }, + { + "x": 338.7515795803263, + "y": -245.59518189429, + "z": 0.0 + }, + { + "x": 338.7521908732506, + "y": -244.58312600413734, + "z": 0.0 + }, + { + "x": 338.7528021661749, + "y": -243.57107011398492, + "z": 0.0 + }, + { + "x": 338.7534134590992, + "y": -242.55901422383238, + "z": 0.0 + }, + { + "x": 338.7540247520234, + "y": -241.54695833367973, + "z": 0.0 + }, + { + "x": 338.7546360449477, + "y": -240.5349024435273, + "z": 0.0 + }, + { + "x": 338.755247337872, + "y": -239.52284655337465, + "z": 0.0 + }, + { + "x": 338.7558586307963, + "y": -238.51079066322222, + "z": 0.0 + }, + { + "x": 338.7564699237205, + "y": -237.49873477306957, + "z": 0.0 + }, + { + "x": 338.7570812166448, + "y": -236.48667888291715, + "z": 0.0 + }, + { + "x": 338.7576925095691, + "y": -235.4746229927645, + "z": 0.0 + }, + { + "x": 338.7583038024934, + "y": -234.46256710261207, + "z": 0.0 + }, + { + "x": 338.7589150954177, + "y": -233.45051121245953, + "z": 0.0 + }, + { + "x": 338.7595263883419, + "y": -232.43845532230688, + "z": 0.0 + }, + { + "x": 338.7601376812662, + "y": -231.42639943215445, + "z": 0.0 + }, + { + "x": 338.7607489741905, + "y": -230.4143435420018, + "z": 0.0 + }, + { + "x": 338.7613602671148, + "y": -229.40228765184938, + "z": 0.0 + }, + { + "x": 338.761971560039, + "y": -228.39023176169673, + "z": 0.0 + }, + { + "x": 338.7625828529633, + "y": -227.3781758715443, + "z": 0.0 + }, + { + "x": 338.7631941458876, + "y": -226.36611998139176, + "z": 0.0 + }, + { + "x": 338.7638054388119, + "y": -225.3540640912391, + "z": 0.0 + }, + { + "x": 338.7644167317362, + "y": -224.34200820108668, + "z": 0.0 + }, + { + "x": 338.7650280246604, + "y": -223.32995231093403, + "z": 0.0 + }, + { + "x": 338.7656393175847, + "y": -222.3178964207816, + "z": 0.0 + }, + { + "x": 338.766250610509, + "y": -221.30584053062896, + "z": 0.0 + }, + { + "x": 338.7668619034333, + "y": -220.29378464047653, + "z": 0.0 + }, + { + "x": 338.7674731963575, + "y": -219.28172875032388, + "z": 0.0 + }, + { + "x": 338.7680844892818, + "y": -218.26967286017145, + "z": 0.0 + }, + { + "x": 338.7686957822061, + "y": -217.25761697001892, + "z": 0.0 + }, + { + "x": 338.7693070751304, + "y": -216.24556107986626, + "z": 0.0 + }, + { + "x": 338.76991836805473, + "y": -215.23350518971384, + "z": 0.0 + }, + { + "x": 338.7705296609789, + "y": -214.2214492995612, + "z": 0.0 + }, + { + "x": 338.7711409539032, + "y": -213.20939340940876, + "z": 0.0 + }, + { + "x": 338.77175224682753, + "y": -212.1973375192561, + "z": 0.0 + }, + { + "x": 338.77236353975184, + "y": -211.18528162910368, + "z": 0.0 + }, + { + "x": 338.772974832676, + "y": -210.17322573895103, + "z": 0.0 + }, + { + "x": 338.77358612560033, + "y": -209.1611698487986, + "z": 0.0 + } + ] + }, + { + "id": 99, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 334.7735868552588, + "y": -209.1587538051048, + "z": 0.0 + }, + { + "x": 334.7729755623345, + "y": -210.17080969525745, + "z": 0.0 + }, + { + "x": 334.7723642694102, + "y": -211.18286558540987, + "z": 0.0 + }, + { + "x": 334.7717529764859, + "y": -212.19492147556252, + "z": 0.0 + }, + { + "x": 334.7711416835617, + "y": -213.20697736571495, + "z": 0.0 + }, + { + "x": 334.7705303906374, + "y": -214.2190332558676, + "z": 0.0 + }, + { + "x": 334.7699190977131, + "y": -215.23108914602003, + "z": 0.0 + }, + { + "x": 334.7693078047888, + "y": -216.24314503617268, + "z": 0.0 + }, + { + "x": 334.7686965118646, + "y": -217.2552009263251, + "z": 0.0 + }, + { + "x": 334.7680852189403, + "y": -218.26725681647764, + "z": 0.0 + }, + { + "x": 334.767473926016, + "y": -219.2793127066303, + "z": 0.0 + }, + { + "x": 334.7668626330917, + "y": -220.29136859678272, + "z": 0.0 + }, + { + "x": 334.7662513401674, + "y": -221.30342448693537, + "z": 0.0 + }, + { + "x": 334.7656400472432, + "y": -222.3154803770878, + "z": 0.0 + }, + { + "x": 334.7650287543189, + "y": -223.32753626724045, + "z": 0.0 + }, + { + "x": 334.7644174613946, + "y": -224.33959215739287, + "z": 0.0 + }, + { + "x": 334.7638061684703, + "y": -225.35164804754552, + "z": 0.0 + }, + { + "x": 334.7631948755461, + "y": -226.36370393769795, + "z": 0.0 + }, + { + "x": 334.7625835826218, + "y": -227.3757598278505, + "z": 0.0 + }, + { + "x": 334.7619722896975, + "y": -228.38781571800314, + "z": 0.0 + }, + { + "x": 334.7613609967732, + "y": -229.39987160815556, + "z": 0.0 + }, + { + "x": 334.7607497038489, + "y": -230.41192749830822, + "z": 0.0 + }, + { + "x": 334.7601384109247, + "y": -231.42398338846064, + "z": 0.0 + }, + { + "x": 334.7595271180004, + "y": -232.4360392786133, + "z": 0.0 + }, + { + "x": 334.7589158250761, + "y": -233.44809516876572, + "z": 0.0 + }, + { + "x": 334.7583045321518, + "y": -234.46015105891826, + "z": 0.0 + }, + { + "x": 334.7576932392275, + "y": -235.4722069490709, + "z": 0.0 + }, + { + "x": 334.7570819463033, + "y": -236.48426283922333, + "z": 0.0 + }, + { + "x": 334.756470653379, + "y": -237.496318729376, + "z": 0.0 + }, + { + "x": 334.7558593604547, + "y": -238.5083746195284, + "z": 0.0 + }, + { + "x": 334.7552480675304, + "y": -239.52043050968106, + "z": 0.0 + }, + { + "x": 334.7546367746062, + "y": -240.5324863998335, + "z": 0.0 + }, + { + "x": 334.7540254816819, + "y": -241.54454228998614, + "z": 0.0 + }, + { + "x": 334.7534141887576, + "y": -242.55659818013856, + "z": 0.0 + }, + { + "x": 334.75280289583327, + "y": -243.5686540702911, + "z": 0.0 + }, + { + "x": 334.75219160290897, + "y": -244.58070996044376, + "z": 0.0 + }, + { + "x": 334.7515803099848, + "y": -245.59276585059618, + "z": 0.0 + }, + { + "x": 334.75096901706047, + "y": -246.60482174074883, + "z": 0.0 + }, + { + "x": 334.75035772413617, + "y": -247.61687763090126, + "z": 0.0 + }, + { + "x": 334.74974643121186, + "y": -248.6289335210539, + "z": 0.0 + }, + { + "x": 334.74913513828767, + "y": -249.64098941120633, + "z": 0.0 + }, + { + "x": 334.74852384536337, + "y": -250.653045301359, + "z": 0.0 + }, + { + "x": 334.74791255243906, + "y": -251.6651011915114, + "z": 0.0 + }, + { + "x": 334.74730125951476, + "y": -252.67715708166395, + "z": 0.0 + }, + { + "x": 334.74668996659045, + "y": -253.6892129718166, + "z": 0.0 + }, + { + "x": 334.74607867366626, + "y": -254.70126886196903, + "z": 0.0 + }, + { + "x": 334.74546738074196, + "y": -255.71332475212168, + "z": 0.0 + }, + { + "x": 334.74485608781765, + "y": -256.7253806422741, + "z": 0.0 + }, + { + "x": 334.74424479489335, + "y": -257.7374365324267, + "z": 0.0 + }, + { + "x": 334.74363350196916, + "y": -258.74949242257924, + "z": 0.0 + }, + { + "x": 334.74302220904485, + "y": -259.76154831273186, + "z": 0.0 + }, + { + "x": 334.74241091612055, + "y": -260.77360420288426, + "z": 0.0 + }, + { + "x": 334.74179962319624, + "y": -261.78566009303677, + "z": 0.0 + }, + { + "x": 334.74118833027194, + "y": -262.7977159831895, + "z": 0.0 + }, + { + "x": 334.74057703734775, + "y": -263.8097718733419, + "z": 0.0 + }, + { + "x": 334.73996574442344, + "y": -264.8218277634945, + "z": 0.0 + }, + { + "x": 334.73935445149914, + "y": -265.8338836536469, + "z": 0.0 + }, + { + "x": 334.73874315857483, + "y": -266.84593954379966, + "z": 0.0 + }, + { + "x": 334.73813186565064, + "y": -267.85799543395206, + "z": 0.0 + }, + { + "x": 334.73752057272634, + "y": -268.8700513241047, + "z": 0.0 + }, + { + "x": 334.73690927980203, + "y": -269.8821072142571, + "z": 0.0 + }, + { + "x": 334.73629798687773, + "y": -270.8941631044097, + "z": 0.0 + }, + { + "x": 334.7356866939534, + "y": -271.9062189945623, + "z": 0.0 + }, + { + "x": 334.73507540102923, + "y": -272.9182748847147, + "z": 0.0 + }, + { + "x": 334.73446410810493, + "y": -273.93033077486734, + "z": 0.0 + }, + { + "x": 334.7338528151806, + "y": -274.94238666501985, + "z": 0.0 + }, + { + "x": 334.7332415222563, + "y": -275.9544425551725, + "z": 0.0 + }, + { + "x": 334.73263022933213, + "y": -276.9664984453249, + "z": 0.0 + }, + { + "x": 334.7320189364078, + "y": -277.9785543354774, + "z": 0.0 + }, + { + "x": 334.7314076434835, + "y": -278.99061022563, + "z": 0.0 + }, + { + "x": 334.7307963505592, + "y": -280.0026661157824, + "z": 0.0 + }, + { + "x": 334.7301850576349, + "y": -281.01472200593514, + "z": 0.0 + }, + { + "x": 334.7295737647107, + "y": -282.02677789608754, + "z": 0.0 + }, + { + "x": 334.7289624717864, + "y": -283.03883378624016, + "z": 0.0 + }, + { + "x": 334.7283511788621, + "y": -284.05088967639256, + "z": 0.0 + }, + { + "x": 334.7277398859378, + "y": -285.0629455665452, + "z": 0.0 + }, + { + "x": 334.7271285930136, + "y": -286.0750014566977, + "z": 0.0 + }, + { + "x": 334.7265173000893, + "y": -287.0870573468502, + "z": 0.0 + }, + { + "x": 334.725906007165, + "y": -288.0991132370028, + "z": 0.0 + }, + { + "x": 334.7252947142407, + "y": -289.1111691271552, + "z": 0.0 + }, + { + "x": 334.7246834213164, + "y": -290.12322501730785, + "z": 0.0 + }, + { + "x": 334.7240721283922, + "y": -291.13528090746036, + "z": 0.0 + }, + { + "x": 334.7234608354679, + "y": -292.147336797613, + "z": 0.0 + }, + { + "x": 334.7228495425436, + "y": -293.1593926877654, + "z": 0.0 + }, + { + "x": 334.7222382496193, + "y": -294.171448577918, + "z": 0.0 + }, + { + "x": 334.7216269566951, + "y": -295.1835044680704, + "z": 0.0 + }, + { + "x": 334.7210156637708, + "y": -296.195560358223, + "z": 0.0 + }, + { + "x": 334.7204043708465, + "y": -297.20761624837564, + "z": 0.0 + }, + { + "x": 334.7197930779222, + "y": -298.21967213852804, + "z": 0.0 + }, + { + "x": 334.7191817849979, + "y": -299.23172802868066, + "z": 0.0 + }, + { + "x": 334.7185704920737, + "y": -300.24378391883306, + "z": 0.0 + }, + { + "x": 334.7179591991494, + "y": -301.2558398089858, + "z": 0.0 + }, + { + "x": 334.7173479062251, + "y": -302.2678956991382, + "z": 0.0 + }, + { + "x": 334.7167366133008, + "y": -303.2799515892908, + "z": 0.0 + }, + { + "x": 334.7161253203766, + "y": -304.2920074794432, + "z": 0.0 + }, + { + "x": 334.7155140274523, + "y": -305.3040633695957, + "z": 0.0 + }, + { + "x": 334.714902734528, + "y": -306.31611925974846, + "z": 0.0 + }, + { + "x": 334.7142914416037, + "y": -307.32817514990086, + "z": 0.0 + }, + { + "x": 334.7136801486794, + "y": -308.3402310400535, + "z": 0.0 + }, + { + "x": 334.7130688557552, + "y": -309.3522869302059, + "z": 0.0 + }, + { + "x": 334.7124575628309, + "y": -310.3643428203585, + "z": 0.0 + }, + { + "x": 334.7118462699066, + "y": -311.376398710511, + "z": 0.0 + }, + { + "x": 334.71123497698227, + "y": -312.38845460066364, + "z": 0.0 + }, + { + "x": 334.7106236840581, + "y": -313.40051049081603, + "z": 0.0 + }, + { + "x": 334.7100123911338, + "y": -314.41256638096854, + "z": 0.0 + }, + { + "x": 334.70940109820947, + "y": -315.42462227112117, + "z": 0.0 + }, + { + "x": 334.70878980528516, + "y": -316.4366781612737, + "z": 0.0 + }, + { + "x": 334.70817851236086, + "y": -317.4487340514262, + "z": 0.0 + } + ] + }, + { + "id": 100, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": -3.987604267005838, + "y": -317.73882523260744, + "z": 0.0 + }, + { + "x": -3.9515143703865285, + "y": -318.7810983745968, + "z": 0.0 + }, + { + "x": -3.8357237138442493, + "y": -320.0628235375496, + "z": 0.0 + }, + { + "x": -3.6035435046796116, + "y": -321.42014727038304, + "z": 0.0 + }, + { + "x": -3.2131749323592027, + "y": -322.83156756042615, + "z": 0.0 + }, + { + "x": -2.7092233918898647, + "y": -324.14949690005676, + "z": 0.0 + }, + { + "x": -2.1098992234032172, + "y": -325.3878357724527, + "z": 0.0 + }, + { + "x": -1.409105747859908, + "y": -326.5720532697058, + "z": 0.0 + }, + { + "x": -0.6105033054651816, + "y": -327.6951555653618, + "z": 0.0 + }, + { + "x": 0.43807983625093394, + "y": -328.8516649130274, + "z": 0.0 + }, + { + "x": 1.5705790610352346, + "y": -329.83579929197316, + "z": 0.0 + }, + { + "x": 2.80235614833182, + "y": -330.68122629595655, + "z": 0.0 + }, + { + "x": 4.122257124910212, + "y": -331.3817673703651, + "z": 0.0 + }, + { + "x": 5.514762444971803, + "y": -331.9288192605436, + "z": 0.0 + }, + { + "x": 7.049720839454694, + "y": -332.31271128481416, + "z": 0.0 + }, + { + "x": 8.585458950714365, + "y": -332.4921951397266, + "z": 0.0 + }, + { + "x": 9.896942070360003, + "y": -332.53837993970717, + "z": 0.0 + } + ] + }, + { + "id": 101, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 10.123058387403669, + "y": -324.54157611498033, + "z": 0.0 + }, + { + "x": 9.350105318731895, + "y": -324.5288217382166, + "z": 0.0 + }, + { + "x": 8.811596495545004, + "y": -324.5091355549019, + "z": 0.0 + }, + { + "x": 8.311184096648525, + "y": -324.43348564915357, + "z": 0.0 + }, + { + "x": 7.750386387471255, + "y": -324.25178293460726, + "z": 0.0 + }, + { + "x": 7.2149908856266585, + "y": -324.00824685081966, + "z": 0.0 + }, + { + "x": 6.710985586909846, + "y": -323.7058546960779, + "z": 0.0 + }, + { + "x": 6.247647921620716, + "y": -323.3517632174102, + "z": 0.0 + }, + { + "x": 5.861716980926192, + "y": -322.9929896214138, + "z": 0.0 + }, + { + "x": 5.4339661146776255, + "y": -322.42809773372966, + "z": 0.0 + }, + { + "x": 5.055313250704519, + "y": -321.82978431120443, + "z": 0.0 + }, + { + "x": 4.728104996227859, + "y": -321.2022699920468, + "z": 0.0 + }, + { + "x": 4.464117028182713, + "y": -320.58230364692054, + "z": 0.0 + }, + { + "x": 4.267820431277832, + "y": -319.99129115876485, + "z": 0.0 + }, + { + "x": 4.127488182559836, + "y": -319.29649704514026, + "z": 0.0 + }, + { + "x": 4.0436940593728075, + "y": -318.5042551613782, + "z": 0.0 + }, + { + "x": 4.007604162753498, + "y": -317.4619820193888, + "z": 0.0 + } + ] + }, + { + "id": 102, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 10.010000228881836, + "y": -328.53997802734375, + "z": 0.0 + }, + { + "x": 8.96778213472313, + "y": -328.5105084389716, + "z": 0.0 + }, + { + "x": 7.9306586674998485, + "y": -328.410923419858, + "z": 0.0 + }, + { + "x": 6.912973270810164, + "y": -328.1811524548486, + "z": 0.0 + }, + { + "x": 5.9363217561907335, + "y": -327.8167751524862, + "z": 0.0 + }, + { + "x": 5.008673516979239, + "y": -327.3447365733881, + "z": 0.0 + }, + { + "x": 4.14078232397254, + "y": -326.7708269940255, + "z": 0.0 + }, + { + "x": 3.3428638789358254, + "y": -326.1017140652188, + "z": 0.0 + }, + { + "x": 2.6256068377305053, + "y": -325.3440725933878, + "z": 0.0 + }, + { + "x": 2.012430183408859, + "y": -324.50007550171773, + "z": 0.0 + }, + { + "x": 1.4727070136506513, + "y": -323.6088100418286, + "z": 0.0 + }, + { + "x": 1.0094408021689976, + "y": -322.6758834460518, + "z": 0.0 + }, + { + "x": 0.6254710479117551, + "y": -321.70693560367334, + "z": 0.0 + }, + { + "x": 0.3321384632991102, + "y": -320.70571921457395, + "z": 0.0 + }, + { + "x": 0.14588223435779368, + "y": -319.67966029134493, + "z": 0.0 + }, + { + "x": 0.04608984449313969, + "y": -318.6426767679875, + "z": 0.0 + }, + { + "x": 0.009999947873830324, + "y": -317.6004036259981, + "z": 0.0 + } + ] + }, + { + "id": 103, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": -1.988802159566004, + "y": -317.6696144293028, + "z": 0.0 + }, + { + "x": -1.9527122629466944, + "y": -318.71188757129215, + "z": 0.0 + }, + { + "x": -1.8449207397432277, + "y": -319.8712419144473, + "z": 0.0 + }, + { + "x": -1.6357025206902507, + "y": -321.0629332424785, + "z": 0.0 + }, + { + "x": -1.2938519422237238, + "y": -322.2692515820497, + "z": 0.0 + }, + { + "x": -0.8498912948604336, + "y": -323.4126901730543, + "z": 0.0 + }, + { + "x": -0.318596104876283, + "y": -324.4983229071406, + "z": 0.0 + }, + { + "x": 0.30166221777447544, + "y": -325.53606438571177, + "z": 0.0 + }, + { + "x": 1.0075517661326618, + "y": -326.51961407937483, + "z": 0.0 + }, + { + "x": 1.8904718575933797, + "y": -327.4766894891231, + "z": 0.0 + }, + { + "x": 2.8556806925038876, + "y": -328.30331314299934, + "z": 0.0 + }, + { + "x": 3.9055148326555296, + "y": -329.0129814346723, + "z": 0.0 + }, + { + "x": 5.029289440550473, + "y": -329.59927126142566, + "z": 0.0 + }, + { + "x": 6.213867857890984, + "y": -330.0549858576961, + "z": 0.0 + }, + { + "x": 7.490189753477271, + "y": -330.36181735233606, + "z": 0.0 + }, + { + "x": 8.776620542718748, + "y": -330.5013517893491, + "z": 0.0 + }, + { + "x": 9.95347114962092, + "y": -330.53917898352546, + "z": 0.0 + } + ] + }, + { + "id": 104, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 10.066529308142751, + "y": -326.54077707116204, + "z": 0.0 + }, + { + "x": 9.158943726727513, + "y": -326.51966508859414, + "z": 0.0 + }, + { + "x": 8.371127581522426, + "y": -326.46002948738, + "z": 0.0 + }, + { + "x": 7.612078683729344, + "y": -326.30731905200105, + "z": 0.0 + }, + { + "x": 6.843354071830994, + "y": -326.0342790435467, + "z": 0.0 + }, + { + "x": 6.111832201302949, + "y": -325.6764917121039, + "z": 0.0 + }, + { + "x": 5.4258839554411935, + "y": -325.2383408450517, + "z": 0.0 + }, + { + "x": 4.795255900278271, + "y": -324.7267386413145, + "z": 0.0 + }, + { + "x": 4.243661909328349, + "y": -324.1685311074008, + "z": 0.0 + }, + { + "x": 3.723198149043242, + "y": -323.4640866177237, + "z": 0.0 + }, + { + "x": 3.264010132177585, + "y": -322.71929717651653, + "z": 0.0 + }, + { + "x": 2.8687728991984285, + "y": -321.9390767190493, + "z": 0.0 + }, + { + "x": 2.5447940380472343, + "y": -321.14461962529697, + "z": 0.0 + }, + { + "x": 2.2999794472884707, + "y": -320.3485051866694, + "z": 0.0 + }, + { + "x": 2.136685208458815, + "y": -319.48807866824257, + "z": 0.0 + }, + { + "x": 2.0448919519329736, + "y": -318.57346596468284, + "z": 0.0 + }, + { + "x": 2.0088020553136645, + "y": -317.53119282269347, + "z": 0.0 + } + ] + }, + { + "id": 105, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 94.37701805715766, + "y": -46.14939141843673, + "z": 0.0 + }, + { + "x": 94.37686197589477, + "y": -45.122626724417536, + "z": 0.0 + }, + { + "x": 94.37670589463187, + "y": -44.0958620303983, + "z": 0.0 + }, + { + "x": 94.37654981336898, + "y": -43.069097336379166, + "z": 0.0 + }, + { + "x": 94.3763937321061, + "y": -42.04233264235998, + "z": 0.0 + }, + { + "x": 94.3762376508432, + "y": -41.01556794834073, + "z": 0.0 + }, + { + "x": 94.37608156958031, + "y": -39.9888032543216, + "z": 0.0 + }, + { + "x": 94.37592548831742, + "y": -38.96203856030242, + "z": 0.0 + }, + { + "x": 94.37576940705453, + "y": -37.93527386628323, + "z": 0.0 + }, + { + "x": 94.37561332579165, + "y": -36.90850917226405, + "z": 0.0 + }, + { + "x": 94.37545724452875, + "y": -35.8817444782448, + "z": 0.0 + }, + { + "x": 94.37530116326586, + "y": -34.85497978422568, + "z": 0.0 + }, + { + "x": 94.37514508200297, + "y": -33.82821509020649, + "z": 0.0 + }, + { + "x": 94.37498900074007, + "y": -32.80145039618724, + "z": 0.0 + }, + { + "x": 94.37483291947719, + "y": -31.774685702168114, + "z": 0.0 + }, + { + "x": 94.3746768382143, + "y": -30.74792100814893, + "z": 0.0 + }, + { + "x": 94.3745207569514, + "y": -29.721156314129683, + "z": 0.0 + }, + { + "x": 94.37436467568851, + "y": -28.694391620110554, + "z": 0.0 + }, + { + "x": 94.37420859442562, + "y": -27.667626926091366, + "z": 0.0 + }, + { + "x": 94.37405251316274, + "y": -26.64086223207218, + "z": 0.0 + }, + { + "x": 94.37389643189984, + "y": -25.614097538052935, + "z": 0.0 + }, + { + "x": 94.37374035063695, + "y": -24.587332844033806, + "z": 0.0 + }, + { + "x": 94.37358426937405, + "y": -23.56056815001456, + "z": 0.0 + }, + { + "x": 94.37342818811116, + "y": -22.533803455995436, + "z": 0.0 + }, + { + "x": 94.37327210684828, + "y": -21.507038761976247, + "z": 0.0 + }, + { + "x": 94.37311602558538, + "y": -20.480274067957005, + "z": 0.0 + }, + { + "x": 94.3729599443225, + "y": -19.453509373937926, + "z": 0.0 + }, + { + "x": 94.3728038630596, + "y": -18.42674467991863, + "z": 0.0 + }, + { + "x": 94.37264778179672, + "y": -17.3999799858995, + "z": 0.0 + }, + { + "x": 94.37249170053383, + "y": -16.373215291880314, + "z": 0.0 + }, + { + "x": 94.37233561927093, + "y": -15.346450597861072, + "z": 0.0 + }, + { + "x": 94.37217953800804, + "y": -14.31968590384194, + "z": 0.0 + }, + { + "x": 94.37202345674515, + "y": -13.292921209822753, + "z": 0.0 + }, + { + "x": 94.37186737548225, + "y": -12.26615651580351, + "z": 0.0 + }, + { + "x": 94.37171129421937, + "y": -11.239391821784379, + "z": 0.0 + } + ] + }, + { + "id": 106, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 86.3717113866508, + "y": -11.240607923288396, + "z": 0.0 + }, + { + "x": 86.37186746791369, + "y": -12.267372617307638, + "z": 0.0 + }, + { + "x": 86.37202354917659, + "y": -13.29413731132677, + "z": 0.0 + }, + { + "x": 86.37217963043948, + "y": -14.320902005345957, + "z": 0.0 + }, + { + "x": 86.37233571170236, + "y": -15.347666699365199, + "z": 0.0 + }, + { + "x": 86.37249179296526, + "y": -16.374431393384327, + "z": 0.0 + }, + { + "x": 86.37264787422815, + "y": -17.401196087403513, + "z": 0.0 + }, + { + "x": 86.37280395549104, + "y": -18.427960781422758, + "z": 0.0 + }, + { + "x": 86.37296003675394, + "y": -19.454725475441833, + "z": 0.0 + }, + { + "x": 86.37311611801681, + "y": -20.481490169461132, + "z": 0.0 + }, + { + "x": 86.37327219927971, + "y": -21.50825486348026, + "z": 0.0 + }, + { + "x": 86.3734282805426, + "y": -22.53501955749945, + "z": 0.0 + }, + { + "x": 86.37358436180548, + "y": -23.561784251518688, + "z": 0.0 + }, + { + "x": 86.37374044306839, + "y": -24.58854894553782, + "z": 0.0 + }, + { + "x": 86.37389652433127, + "y": -25.615313639557062, + "z": 0.0 + }, + { + "x": 86.37405260559417, + "y": -26.642078333576194, + "z": 0.0 + }, + { + "x": 86.37420868685706, + "y": -27.66884302759538, + "z": 0.0 + }, + { + "x": 86.37436476811995, + "y": -28.695607721614568, + "z": 0.0 + }, + { + "x": 86.37452084938283, + "y": -29.72237241563381, + "z": 0.0 + }, + { + "x": 86.37467693064573, + "y": -30.749137109652942, + "z": 0.0 + }, + { + "x": 86.37483301190862, + "y": -31.775901803672127, + "z": 0.0 + }, + { + "x": 86.37498909317151, + "y": -32.80266649769137, + "z": 0.0 + }, + { + "x": 86.37514517443441, + "y": -33.829431191710505, + "z": 0.0 + }, + { + "x": 86.3753012556973, + "y": -34.85619588572969, + "z": 0.0 + }, + { + "x": 86.37545733696018, + "y": -35.882960579748925, + "z": 0.0 + }, + { + "x": 86.37561341822308, + "y": -36.90972527376806, + "z": 0.0 + }, + { + "x": 86.37576949948597, + "y": -37.936489967787246, + "z": 0.0 + }, + { + "x": 86.37592558074886, + "y": -38.96325466180643, + "z": 0.0 + }, + { + "x": 86.37608166201174, + "y": -39.990019355825616, + "z": 0.0 + }, + { + "x": 86.37623774327463, + "y": -41.01678404984486, + "z": 0.0 + }, + { + "x": 86.37639382453753, + "y": -42.043548743863994, + "z": 0.0 + }, + { + "x": 86.37654990580042, + "y": -43.07031343788318, + "z": 0.0 + }, + { + "x": 86.3767059870633, + "y": -44.09707813190243, + "z": 0.0 + }, + { + "x": 86.3768620683262, + "y": -45.12384282592155, + "z": 0.0 + }, + { + "x": 86.37701814958909, + "y": -46.15060751994074, + "z": 0.0 + } + ] + }, + { + "id": 107, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 90.37171134043508, + "y": -11.239999872536387, + "z": 0.0 + }, + { + "x": 90.37186742169797, + "y": -12.266764566555574, + "z": 0.0 + }, + { + "x": 90.37202350296087, + "y": -13.293529260574761, + "z": 0.0 + }, + { + "x": 90.37217958422376, + "y": -14.320293954593948, + "z": 0.0 + }, + { + "x": 90.37233566548664, + "y": -15.347058648613135, + "z": 0.0 + }, + { + "x": 90.37249174674955, + "y": -16.37382334263232, + "z": 0.0 + }, + { + "x": 90.37264782801243, + "y": -17.400588036651506, + "z": 0.0 + }, + { + "x": 90.37280390927532, + "y": -18.427352730670695, + "z": 0.0 + }, + { + "x": 90.37295999053822, + "y": -19.45411742468988, + "z": 0.0 + }, + { + "x": 90.37311607180109, + "y": -20.48088211870907, + "z": 0.0 + }, + { + "x": 90.373272153064, + "y": -21.507646812728254, + "z": 0.0 + }, + { + "x": 90.37342823432688, + "y": -22.534411506747443, + "z": 0.0 + }, + { + "x": 90.37358431558977, + "y": -23.561176200766624, + "z": 0.0 + }, + { + "x": 90.37374039685267, + "y": -24.587940894785813, + "z": 0.0 + }, + { + "x": 90.37389647811555, + "y": -25.614705588805, + "z": 0.0 + }, + { + "x": 90.37405255937846, + "y": -26.641470282824187, + "z": 0.0 + }, + { + "x": 90.37420864064134, + "y": -27.668234976843372, + "z": 0.0 + }, + { + "x": 90.37436472190423, + "y": -28.69499967086256, + "z": 0.0 + }, + { + "x": 90.37452080316712, + "y": -29.721764364881746, + "z": 0.0 + }, + { + "x": 90.37467688443002, + "y": -30.748529058900935, + "z": 0.0 + }, + { + "x": 90.3748329656929, + "y": -31.77529375292012, + "z": 0.0 + }, + { + "x": 90.37498904695579, + "y": -32.802058446939306, + "z": 0.0 + }, + { + "x": 90.37514512821869, + "y": -33.8288231409585, + "z": 0.0 + }, + { + "x": 90.37530120948158, + "y": -34.85558783497768, + "z": 0.0 + }, + { + "x": 90.37545729074446, + "y": -35.88235252899686, + "z": 0.0 + }, + { + "x": 90.37561337200736, + "y": -36.909117223016054, + "z": 0.0 + }, + { + "x": 90.37576945327025, + "y": -37.93588191703524, + "z": 0.0 + }, + { + "x": 90.37592553453314, + "y": -38.962646611054424, + "z": 0.0 + }, + { + "x": 90.37608161579602, + "y": -39.98941130507361, + "z": 0.0 + }, + { + "x": 90.37623769705891, + "y": -41.016175999092795, + "z": 0.0 + }, + { + "x": 90.37639377832181, + "y": -42.04294069311199, + "z": 0.0 + }, + { + "x": 90.3765498595847, + "y": -43.06970538713117, + "z": 0.0 + }, + { + "x": 90.37670594084759, + "y": -44.096470081150365, + "z": 0.0 + }, + { + "x": 90.37686202211049, + "y": -45.12323477516954, + "z": 0.0 + }, + { + "x": 90.37701810337337, + "y": -46.149999469188735, + "z": 0.0 + } + ] + }, + { + "id": 108, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 92.37701808026551, + "y": -46.14969544381273, + "z": 0.0 + }, + { + "x": 92.37686199900263, + "y": -45.12293074979354, + "z": 0.0 + }, + { + "x": 92.37670591773973, + "y": -44.09616605577433, + "z": 0.0 + }, + { + "x": 92.37654983647684, + "y": -43.06940136175517, + "z": 0.0 + }, + { + "x": 92.37639375521395, + "y": -42.042636667735984, + "z": 0.0 + }, + { + "x": 92.37623767395105, + "y": -41.01587197371676, + "z": 0.0 + }, + { + "x": 92.37608159268817, + "y": -39.989107279697606, + "z": 0.0 + }, + { + "x": 92.37592551142528, + "y": -38.96234258567842, + "z": 0.0 + }, + { + "x": 92.37576943016239, + "y": -37.935577891659236, + "z": 0.0 + }, + { + "x": 92.3756133488995, + "y": -36.90881319764005, + "z": 0.0 + }, + { + "x": 92.3754572676366, + "y": -35.88204850362083, + "z": 0.0 + }, + { + "x": 92.37530118637372, + "y": -34.85528380960168, + "z": 0.0 + }, + { + "x": 92.37514510511083, + "y": -33.828519115582495, + "z": 0.0 + }, + { + "x": 92.37498902384793, + "y": -32.801754421563274, + "z": 0.0 + }, + { + "x": 92.37483294258504, + "y": -31.774989727544117, + "z": 0.0 + }, + { + "x": 92.37467686132216, + "y": -30.748225033524932, + "z": 0.0 + }, + { + "x": 92.37452078005926, + "y": -29.721460339505715, + "z": 0.0 + }, + { + "x": 92.37436469879637, + "y": -28.694695645486558, + "z": 0.0 + }, + { + "x": 92.37420861753348, + "y": -27.66793095146737, + "z": 0.0 + }, + { + "x": 92.3740525362706, + "y": -26.641166257448184, + "z": 0.0 + }, + { + "x": 92.3738964550077, + "y": -25.614401563428967, + "z": 0.0 + }, + { + "x": 92.37374037374481, + "y": -24.58763686940981, + "z": 0.0 + }, + { + "x": 92.37358429248191, + "y": -23.560872175390593, + "z": 0.0 + }, + { + "x": 92.37342821121902, + "y": -22.53410748137144, + "z": 0.0 + }, + { + "x": 92.37327212995613, + "y": -21.50734278735225, + "z": 0.0 + }, + { + "x": 92.37311604869323, + "y": -20.480578093333037, + "z": 0.0 + }, + { + "x": 92.37295996743036, + "y": -19.4538133993139, + "z": 0.0 + }, + { + "x": 92.37280388616746, + "y": -18.427048705294663, + "z": 0.0 + }, + { + "x": 92.37264780490457, + "y": -17.400284011275502, + "z": 0.0 + }, + { + "x": 92.37249172364169, + "y": -16.373519317256317, + "z": 0.0 + }, + { + "x": 92.37233564237879, + "y": -15.346754623237103, + "z": 0.0 + }, + { + "x": 92.3721795611159, + "y": -14.319989929217943, + "z": 0.0 + }, + { + "x": 92.37202347985301, + "y": -13.293225235198758, + "z": 0.0 + }, + { + "x": 92.37186739859011, + "y": -12.266460541179542, + "z": 0.0 + }, + { + "x": 92.37171131732723, + "y": -11.239695847160384, + "z": 0.0 + } + ] + }, + { + "id": 109, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 88.37171136354294, + "y": -11.24030389791239, + "z": 0.0 + }, + { + "x": 88.37186744480583, + "y": -12.267068591931606, + "z": 0.0 + }, + { + "x": 88.37202352606873, + "y": -13.293833285950765, + "z": 0.0 + }, + { + "x": 88.37217960733162, + "y": -14.320597979969953, + "z": 0.0 + }, + { + "x": 88.3723356885945, + "y": -15.347362673989167, + "z": 0.0 + }, + { + "x": 88.3724917698574, + "y": -16.374127368008324, + "z": 0.0 + }, + { + "x": 88.37264785112029, + "y": -17.40089206202751, + "z": 0.0 + }, + { + "x": 88.37280393238318, + "y": -18.427656756046726, + "z": 0.0 + }, + { + "x": 88.37296001364608, + "y": -19.45442145006586, + "z": 0.0 + }, + { + "x": 88.37311609490895, + "y": -20.4811861440851, + "z": 0.0 + }, + { + "x": 88.37327217617185, + "y": -21.507950838104257, + "z": 0.0 + }, + { + "x": 88.37342825743474, + "y": -22.534715532123446, + "z": 0.0 + }, + { + "x": 88.37358433869763, + "y": -23.561480226142656, + "z": 0.0 + }, + { + "x": 88.37374041996053, + "y": -24.588244920161817, + "z": 0.0 + }, + { + "x": 88.37389650122341, + "y": -25.61500961418103, + "z": 0.0 + }, + { + "x": 88.37405258248631, + "y": -26.64177430820019, + "z": 0.0 + }, + { + "x": 88.3742086637492, + "y": -27.668539002219376, + "z": 0.0 + }, + { + "x": 88.37436474501209, + "y": -28.695303696238565, + "z": 0.0 + }, + { + "x": 88.37452082627497, + "y": -29.72206839025778, + "z": 0.0 + }, + { + "x": 88.37467690753788, + "y": -30.74883308427694, + "z": 0.0 + }, + { + "x": 88.37483298880076, + "y": -31.775597778296124, + "z": 0.0 + }, + { + "x": 88.37498907006365, + "y": -32.80236247231534, + "z": 0.0 + }, + { + "x": 88.37514515132655, + "y": -33.8291271663345, + "z": 0.0 + }, + { + "x": 88.37530123258944, + "y": -34.85589186035369, + "z": 0.0 + }, + { + "x": 88.37545731385232, + "y": -35.88265655437289, + "z": 0.0 + }, + { + "x": 88.37561339511522, + "y": -36.90942124839206, + "z": 0.0 + }, + { + "x": 88.37576947637811, + "y": -37.93618594241124, + "z": 0.0 + }, + { + "x": 88.375925557641, + "y": -38.96295063643043, + "z": 0.0 + }, + { + "x": 88.37608163890388, + "y": -39.98971533044961, + "z": 0.0 + }, + { + "x": 88.37623772016677, + "y": -41.01648002446883, + "z": 0.0 + }, + { + "x": 88.37639380142967, + "y": -42.04324471848799, + "z": 0.0 + }, + { + "x": 88.37654988269256, + "y": -43.070009412507176, + "z": 0.0 + }, + { + "x": 88.37670596395544, + "y": -44.0967741065264, + "z": 0.0 + }, + { + "x": 88.37686204521835, + "y": -45.123538800545546, + "z": 0.0 + }, + { + "x": 88.37701812648123, + "y": -46.15030349456474, + "z": 0.0 + } + ] + }, + { + "id": 110, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 94.38821987213683, + "y": -119.83939056702773, + "z": 0.0 + }, + { + "x": 94.38806580280658, + "y": -118.82586116697327, + "z": 0.0 + }, + { + "x": 94.38791173347632, + "y": -117.81233176691876, + "z": 0.0 + }, + { + "x": 94.38775766414606, + "y": -116.79880236686435, + "z": 0.0 + }, + { + "x": 94.38760359481581, + "y": -115.7852729668099, + "z": 0.0 + }, + { + "x": 94.38744952548556, + "y": -114.77174356675543, + "z": 0.0 + }, + { + "x": 94.3872954561553, + "y": -113.75821416670092, + "z": 0.0 + }, + { + "x": 94.38714138682504, + "y": -112.74468476664646, + "z": 0.0 + }, + { + "x": 94.38698731749479, + "y": -111.73115536659205, + "z": 0.0 + }, + { + "x": 94.38683324816454, + "y": -110.7176259665376, + "z": 0.0 + }, + { + "x": 94.38667917883427, + "y": -109.70409656648307, + "z": 0.0 + }, + { + "x": 94.38652510950402, + "y": -108.69056716642868, + "z": 0.0 + }, + { + "x": 94.38637104017377, + "y": -107.67703776637423, + "z": 0.0 + }, + { + "x": 94.3862169708435, + "y": -106.6635083663197, + "z": 0.0 + }, + { + "x": 94.38606290151326, + "y": -105.6499789662653, + "z": 0.0 + }, + { + "x": 94.385908832183, + "y": -104.63644956621084, + "z": 0.0 + }, + { + "x": 94.38575476285276, + "y": -103.62292016615638, + "z": 0.0 + }, + { + "x": 94.38560069352249, + "y": -102.60939076610187, + "z": 0.0 + }, + { + "x": 94.38544662419223, + "y": -101.5958613660474, + "z": 0.0 + }, + { + "x": 94.38529255486198, + "y": -100.582331965993, + "z": 0.0 + }, + { + "x": 94.38513848553173, + "y": -99.56880256593854, + "z": 0.0 + }, + { + "x": 94.38498441620146, + "y": -98.55527316588402, + "z": 0.0 + }, + { + "x": 94.38483034687121, + "y": -97.54174376582962, + "z": 0.0 + }, + { + "x": 94.38467627754096, + "y": -96.52821436577517, + "z": 0.0 + }, + { + "x": 94.3845222082107, + "y": -95.51468496572065, + "z": 0.0 + }, + { + "x": 94.38436813888045, + "y": -94.50115556566624, + "z": 0.0 + }, + { + "x": 94.3842140695502, + "y": -93.48762616561179, + "z": 0.0 + }, + { + "x": 94.38406000021993, + "y": -92.47409676555726, + "z": 0.0 + }, + { + "x": 94.38390593088967, + "y": -91.46056736550281, + "z": 0.0 + }, + { + "x": 94.38375186155942, + "y": -90.4470379654484, + "z": 0.0 + }, + { + "x": 94.38359779222917, + "y": -89.43350856539395, + "z": 0.0 + }, + { + "x": 94.3834437228989, + "y": -88.41997916533943, + "z": 0.0 + }, + { + "x": 94.38328965356865, + "y": -87.40644976528503, + "z": 0.0 + }, + { + "x": 94.3831355842384, + "y": -86.39292036523057, + "z": 0.0 + }, + { + "x": 94.38298151490815, + "y": -85.37939096517611, + "z": 0.0 + }, + { + "x": 94.38282744557789, + "y": -84.36586156512159, + "z": 0.0 + }, + { + "x": 94.38267337624764, + "y": -83.3523321650672, + "z": 0.0 + }, + { + "x": 94.38251930691737, + "y": -82.33880276501267, + "z": 0.0 + }, + { + "x": 94.38236523758712, + "y": -81.32527336495828, + "z": 0.0 + }, + { + "x": 94.38221116825686, + "y": -80.31174396490375, + "z": 0.0 + }, + { + "x": 94.38205709892661, + "y": -79.29821456484936, + "z": 0.0 + }, + { + "x": 94.38190302959636, + "y": -78.2846851647949, + "z": 0.0 + }, + { + "x": 94.3817489602661, + "y": -77.27115576474037, + "z": 0.0 + }, + { + "x": 94.38159489093584, + "y": -76.25762636468598, + "z": 0.0 + }, + { + "x": 94.3814408216056, + "y": -75.24409696463151, + "z": 0.0 + }, + { + "x": 94.38128675227534, + "y": -74.23056756457706, + "z": 0.0 + }, + { + "x": 94.38113268294508, + "y": -73.21703816452253, + "z": 0.0 + }, + { + "x": 94.38097861361481, + "y": -72.20350876446808, + "z": 0.0 + }, + { + "x": 94.38082454428456, + "y": -71.18997936441367, + "z": 0.0 + }, + { + "x": 94.38067047495431, + "y": -70.17644996435922, + "z": 0.0 + }, + { + "x": 94.38051640562405, + "y": -69.1629205643047, + "z": 0.0 + }, + { + "x": 94.3803623362938, + "y": -68.1493911642503, + "z": 0.0 + } + ] + }, + { + "id": 111, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 86.38036242872523, + "y": -68.15060726575432, + "z": 0.0 + }, + { + "x": 86.38051649805548, + "y": -69.16413666580883, + "z": 0.0 + }, + { + "x": 86.38067056738575, + "y": -70.17766606586324, + "z": 0.0 + }, + { + "x": 86.380824636716, + "y": -71.19119546591769, + "z": 0.0 + }, + { + "x": 86.38097870604625, + "y": -72.20472486597221, + "z": 0.0 + }, + { + "x": 86.38113277537651, + "y": -73.21825426602666, + "z": 0.0 + }, + { + "x": 86.38128684470678, + "y": -74.23178366608107, + "z": 0.0 + }, + { + "x": 86.38144091403703, + "y": -75.24531306613552, + "z": 0.0 + }, + { + "x": 86.38159498336728, + "y": -76.25884246618999, + "z": 0.0 + }, + { + "x": 86.38174905269753, + "y": -77.2723718662445, + "z": 0.0 + }, + { + "x": 86.3819031220278, + "y": -78.28590126629891, + "z": 0.0 + }, + { + "x": 86.38205719135804, + "y": -79.29943066635337, + "z": 0.0 + }, + { + "x": 86.3822112606883, + "y": -80.31296006640788, + "z": 0.0 + }, + { + "x": 86.38236533001856, + "y": -81.32648946646229, + "z": 0.0 + }, + { + "x": 86.38251939934881, + "y": -82.3400188665168, + "z": 0.0 + }, + { + "x": 86.38267346867907, + "y": -83.35354826657121, + "z": 0.0 + }, + { + "x": 86.38282753800932, + "y": -84.36707766662572, + "z": 0.0 + }, + { + "x": 86.38298160733959, + "y": -85.38060706668013, + "z": 0.0 + }, + { + "x": 86.38313567666984, + "y": -86.39413646673458, + "z": 0.0 + }, + { + "x": 86.38328974600009, + "y": -87.40766586678905, + "z": 0.0 + }, + { + "x": 86.38344381533034, + "y": -88.42119526684355, + "z": 0.0 + }, + { + "x": 86.3835978846606, + "y": -89.43472466689796, + "z": 0.0 + }, + { + "x": 86.38375195399085, + "y": -90.44825406695242, + "z": 0.0 + }, + { + "x": 86.3839060233211, + "y": -91.46178346700694, + "z": 0.0 + }, + { + "x": 86.38406009265137, + "y": -92.47531286706139, + "z": 0.0 + }, + { + "x": 86.38421416198163, + "y": -93.4888422671158, + "z": 0.0 + }, + { + "x": 86.38436823131188, + "y": -94.50237166717025, + "z": 0.0 + }, + { + "x": 86.38452230064213, + "y": -95.51590106722477, + "z": 0.0 + }, + { + "x": 86.3846763699724, + "y": -96.52943046727918, + "z": 0.0 + }, + { + "x": 86.38483043930265, + "y": -97.54295986733364, + "z": 0.0 + }, + { + "x": 86.3849845086329, + "y": -98.55648926738814, + "z": 0.0 + }, + { + "x": 86.38513857796316, + "y": -99.57001866744255, + "z": 0.0 + }, + { + "x": 86.38529264729341, + "y": -100.58354806749702, + "z": 0.0 + }, + { + "x": 86.38544671662366, + "y": -101.59707746755153, + "z": 0.0 + }, + { + "x": 86.38560078595393, + "y": -102.610606867606, + "z": 0.0 + }, + { + "x": 86.38575485528419, + "y": -103.62413626766039, + "z": 0.0 + }, + { + "x": 86.38590892461444, + "y": -104.63766566771486, + "z": 0.0 + }, + { + "x": 86.38606299394469, + "y": -105.65119506776931, + "z": 0.0 + }, + { + "x": 86.38621706327494, + "y": -106.66472446782383, + "z": 0.0 + }, + { + "x": 86.3863711326052, + "y": -107.67825386787824, + "z": 0.0 + }, + { + "x": 86.38652520193546, + "y": -108.69178326793269, + "z": 0.0 + }, + { + "x": 86.3866792712657, + "y": -109.7053126679872, + "z": 0.0 + }, + { + "x": 86.38683334059597, + "y": -110.71884206804161, + "z": 0.0 + }, + { + "x": 86.38698740992622, + "y": -111.73237146809606, + "z": 0.0 + }, + { + "x": 86.38714147925647, + "y": -112.74590086815058, + "z": 0.0 + }, + { + "x": 86.38729554858674, + "y": -113.75943026820505, + "z": 0.0 + }, + { + "x": 86.387449617917, + "y": -114.77295966825945, + "z": 0.0 + }, + { + "x": 86.38760368724725, + "y": -115.78648906831391, + "z": 0.0 + }, + { + "x": 86.3877577565775, + "y": -116.80001846836836, + "z": 0.0 + }, + { + "x": 86.38791182590775, + "y": -117.81354786842289, + "z": 0.0 + }, + { + "x": 86.38806589523801, + "y": -118.82707726847728, + "z": 0.0 + }, + { + "x": 86.38821996456826, + "y": -119.84060666853175, + "z": 0.0 + } + ] + }, + { + "id": 112, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 90.38036238250952, + "y": -68.14999921500231, + "z": 0.0 + }, + { + "x": 90.38051645183977, + "y": -69.16352861505676, + "z": 0.0 + }, + { + "x": 90.38067052117003, + "y": -70.17705801511123, + "z": 0.0 + }, + { + "x": 90.38082459050028, + "y": -71.19058741516568, + "z": 0.0 + }, + { + "x": 90.38097865983053, + "y": -72.20411681522015, + "z": 0.0 + }, + { + "x": 90.3811327291608, + "y": -73.2176462152746, + "z": 0.0 + }, + { + "x": 90.38128679849106, + "y": -74.23117561532906, + "z": 0.0 + }, + { + "x": 90.38144086782131, + "y": -75.24470501538352, + "z": 0.0 + }, + { + "x": 90.38159493715156, + "y": -76.25823441543798, + "z": 0.0 + }, + { + "x": 90.38174900648181, + "y": -77.27176381549243, + "z": 0.0 + }, + { + "x": 90.38190307581208, + "y": -78.2852932155469, + "z": 0.0 + }, + { + "x": 90.38205714514233, + "y": -79.29882261560137, + "z": 0.0 + }, + { + "x": 90.38221121447258, + "y": -80.31235201565582, + "z": 0.0 + }, + { + "x": 90.38236528380284, + "y": -81.32588141571028, + "z": 0.0 + }, + { + "x": 90.38251935313309, + "y": -82.33941081576474, + "z": 0.0 + }, + { + "x": 90.38267342246336, + "y": -83.3529402158192, + "z": 0.0 + }, + { + "x": 90.3828274917936, + "y": -84.36646961587365, + "z": 0.0 + }, + { + "x": 90.38298156112387, + "y": -85.37999901592812, + "z": 0.0 + }, + { + "x": 90.38313563045412, + "y": -86.39352841598257, + "z": 0.0 + }, + { + "x": 90.38328969978437, + "y": -87.40705781603704, + "z": 0.0 + }, + { + "x": 90.38344376911462, + "y": -88.42058721609149, + "z": 0.0 + }, + { + "x": 90.38359783844489, + "y": -89.43411661614596, + "z": 0.0 + }, + { + "x": 90.38375190777514, + "y": -90.44764601620041, + "z": 0.0 + }, + { + "x": 90.38390597710539, + "y": -91.46117541625487, + "z": 0.0 + }, + { + "x": 90.38406004643565, + "y": -92.47470481630933, + "z": 0.0 + }, + { + "x": 90.38421411576591, + "y": -93.4882342163638, + "z": 0.0 + }, + { + "x": 90.38436818509616, + "y": -94.50176361641824, + "z": 0.0 + }, + { + "x": 90.38452225442641, + "y": -95.51529301647271, + "z": 0.0 + }, + { + "x": 90.38467632375668, + "y": -96.52882241652718, + "z": 0.0 + }, + { + "x": 90.38483039308693, + "y": -97.54235181658163, + "z": 0.0 + }, + { + "x": 90.38498446241718, + "y": -98.55588121663608, + "z": 0.0 + }, + { + "x": 90.38513853174744, + "y": -99.56941061669055, + "z": 0.0 + }, + { + "x": 90.3852926010777, + "y": -100.58294001674501, + "z": 0.0 + }, + { + "x": 90.38544667040794, + "y": -101.59646941679947, + "z": 0.0 + }, + { + "x": 90.38560073973821, + "y": -102.60999881685393, + "z": 0.0 + }, + { + "x": 90.38575480906847, + "y": -103.62352821690838, + "z": 0.0 + }, + { + "x": 90.38590887839872, + "y": -104.63705761696285, + "z": 0.0 + }, + { + "x": 90.38606294772897, + "y": -105.6505870170173, + "z": 0.0 + }, + { + "x": 90.38621701705922, + "y": -106.66411641707177, + "z": 0.0 + }, + { + "x": 90.38637108638949, + "y": -107.67764581712623, + "z": 0.0 + }, + { + "x": 90.38652515571974, + "y": -108.69117521718069, + "z": 0.0 + }, + { + "x": 90.38667922504999, + "y": -109.70470461723514, + "z": 0.0 + }, + { + "x": 90.38683329438025, + "y": -110.7182340172896, + "z": 0.0 + }, + { + "x": 90.3869873637105, + "y": -111.73176341734406, + "z": 0.0 + }, + { + "x": 90.38714143304075, + "y": -112.74529281739852, + "z": 0.0 + }, + { + "x": 90.38729550237102, + "y": -113.75882221745299, + "z": 0.0 + }, + { + "x": 90.38744957170128, + "y": -114.77235161750744, + "z": 0.0 + }, + { + "x": 90.38760364103153, + "y": -115.7858810175619, + "z": 0.0 + }, + { + "x": 90.38775771036178, + "y": -116.79941041761636, + "z": 0.0 + }, + { + "x": 90.38791177969203, + "y": -117.81293981767082, + "z": 0.0 + }, + { + "x": 90.3880658490223, + "y": -118.82646921772528, + "z": 0.0 + }, + { + "x": 90.38821991835255, + "y": -119.83999861777974, + "z": 0.0 + } + ] + }, + { + "id": 113, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 92.38821989524469, + "y": -119.83969459240373, + "z": 0.0 + }, + { + "x": 92.38806582591444, + "y": -118.82616519234926, + "z": 0.0 + }, + { + "x": 92.38791175658417, + "y": -117.8126357922948, + "z": 0.0 + }, + { + "x": 92.38775768725392, + "y": -116.79910639224036, + "z": 0.0 + }, + { + "x": 92.38760361792367, + "y": -115.7855769921859, + "z": 0.0 + }, + { + "x": 92.38744954859342, + "y": -114.77204759213143, + "z": 0.0 + }, + { + "x": 92.38729547926316, + "y": -113.75851819207696, + "z": 0.0 + }, + { + "x": 92.3871414099329, + "y": -112.7449887920225, + "z": 0.0 + }, + { + "x": 92.38698734060264, + "y": -111.73145939196806, + "z": 0.0 + }, + { + "x": 92.3868332712724, + "y": -110.71792999191359, + "z": 0.0 + }, + { + "x": 92.38667920194213, + "y": -109.7044005918591, + "z": 0.0 + }, + { + "x": 92.38652513261188, + "y": -108.69087119180469, + "z": 0.0 + }, + { + "x": 92.38637106328163, + "y": -107.67734179175022, + "z": 0.0 + }, + { + "x": 92.38621699395136, + "y": -106.66381239169573, + "z": 0.0 + }, + { + "x": 92.38606292462111, + "y": -105.65028299164129, + "z": 0.0 + }, + { + "x": 92.38590885529086, + "y": -104.63675359158685, + "z": 0.0 + }, + { + "x": 92.38575478596061, + "y": -103.62322419153239, + "z": 0.0 + }, + { + "x": 92.38560071663035, + "y": -102.60969479147789, + "z": 0.0 + }, + { + "x": 92.38544664730009, + "y": -101.59616539142343, + "z": 0.0 + }, + { + "x": 92.38529257796984, + "y": -100.58263599136902, + "z": 0.0 + }, + { + "x": 92.38513850863959, + "y": -99.56910659131455, + "z": 0.0 + }, + { + "x": 92.38498443930932, + "y": -98.55557719126006, + "z": 0.0 + }, + { + "x": 92.38483036997907, + "y": -97.54204779120562, + "z": 0.0 + }, + { + "x": 92.38467630064882, + "y": -96.52851839115118, + "z": 0.0 + }, + { + "x": 92.38452223131856, + "y": -95.51498899109669, + "z": 0.0 + }, + { + "x": 92.3843681619883, + "y": -94.50145959104225, + "z": 0.0 + }, + { + "x": 92.38421409265806, + "y": -93.48793019098778, + "z": 0.0 + }, + { + "x": 92.38406002332779, + "y": -92.47440079093329, + "z": 0.0 + }, + { + "x": 92.38390595399753, + "y": -91.46087139087885, + "z": 0.0 + }, + { + "x": 92.38375188466728, + "y": -90.44734199082441, + "z": 0.0 + }, + { + "x": 92.38359781533703, + "y": -89.43381259076995, + "z": 0.0 + }, + { + "x": 92.38344374600676, + "y": -88.42028319071545, + "z": 0.0 + }, + { + "x": 92.38328967667651, + "y": -87.40675379066104, + "z": 0.0 + }, + { + "x": 92.38313560734626, + "y": -86.39322439060658, + "z": 0.0 + }, + { + "x": 92.38298153801601, + "y": -85.37969499055211, + "z": 0.0 + }, + { + "x": 92.38282746868575, + "y": -84.36616559049762, + "z": 0.0 + }, + { + "x": 92.3826733993555, + "y": -83.3526361904432, + "z": 0.0 + }, + { + "x": 92.38251933002523, + "y": -82.33910679038871, + "z": 0.0 + }, + { + "x": 92.38236526069498, + "y": -81.32557739033427, + "z": 0.0 + }, + { + "x": 92.38221119136472, + "y": -80.31204799027978, + "z": 0.0 + }, + { + "x": 92.38205712203447, + "y": -79.29851859022537, + "z": 0.0 + }, + { + "x": 92.38190305270422, + "y": -78.2849891901709, + "z": 0.0 + }, + { + "x": 92.38174898337395, + "y": -77.27145979011641, + "z": 0.0 + }, + { + "x": 92.3815949140437, + "y": -76.25793039006197, + "z": 0.0 + }, + { + "x": 92.38144084471345, + "y": -75.2444009900075, + "z": 0.0 + }, + { + "x": 92.3812867753832, + "y": -74.23087158995307, + "z": 0.0 + }, + { + "x": 92.38113270605294, + "y": -73.21734218989857, + "z": 0.0 + }, + { + "x": 92.38097863672267, + "y": -72.20381278984411, + "z": 0.0 + }, + { + "x": 92.38082456739242, + "y": -71.19028338978967, + "z": 0.0 + }, + { + "x": 92.38067049806217, + "y": -70.17675398973523, + "z": 0.0 + }, + { + "x": 92.38051642873191, + "y": -69.16322458968074, + "z": 0.0 + }, + { + "x": 92.38036235940166, + "y": -68.1496951896263, + "z": 0.0 + } + ] + }, + { + "id": 114, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 88.38036240561738, + "y": -68.15030324037832, + "z": 0.0 + }, + { + "x": 88.38051647494763, + "y": -69.16383264043279, + "z": 0.0 + }, + { + "x": 88.38067054427789, + "y": -70.17736204048722, + "z": 0.0 + }, + { + "x": 88.38082461360814, + "y": -71.19089144054169, + "z": 0.0 + }, + { + "x": 88.38097868293839, + "y": -72.20442084059619, + "z": 0.0 + }, + { + "x": 88.38113275226866, + "y": -73.21795024065062, + "z": 0.0 + }, + { + "x": 88.38128682159892, + "y": -74.23147964070506, + "z": 0.0 + }, + { + "x": 88.38144089092917, + "y": -75.24500904075953, + "z": 0.0 + }, + { + "x": 88.38159496025942, + "y": -76.258538440814, + "z": 0.0 + }, + { + "x": 88.38174902958967, + "y": -77.27206784086846, + "z": 0.0 + }, + { + "x": 88.38190309891993, + "y": -78.2855972409229, + "z": 0.0 + }, + { + "x": 88.38205716825018, + "y": -79.29912664097736, + "z": 0.0 + }, + { + "x": 88.38221123758044, + "y": -80.31265604103186, + "z": 0.0 + }, + { + "x": 88.3823653069107, + "y": -81.3261854410863, + "z": 0.0 + }, + { + "x": 88.38251937624095, + "y": -82.33971484114076, + "z": 0.0 + }, + { + "x": 88.38267344557121, + "y": -83.3532442411952, + "z": 0.0 + }, + { + "x": 88.38282751490146, + "y": -84.3667736412497, + "z": 0.0 + }, + { + "x": 88.38298158423173, + "y": -85.38030304130413, + "z": 0.0 + }, + { + "x": 88.38313565356198, + "y": -86.39383244135857, + "z": 0.0 + }, + { + "x": 88.38328972289223, + "y": -87.40736184141304, + "z": 0.0 + }, + { + "x": 88.38344379222248, + "y": -88.42089124146753, + "z": 0.0 + }, + { + "x": 88.38359786155274, + "y": -89.43442064152197, + "z": 0.0 + }, + { + "x": 88.383751930883, + "y": -90.4479500415764, + "z": 0.0 + }, + { + "x": 88.38390600021324, + "y": -91.4614794416309, + "z": 0.0 + }, + { + "x": 88.38406006954351, + "y": -92.47500884168537, + "z": 0.0 + }, + { + "x": 88.38421413887377, + "y": -93.4885382417398, + "z": 0.0 + }, + { + "x": 88.38436820820402, + "y": -94.50206764179424, + "z": 0.0 + }, + { + "x": 88.38452227753427, + "y": -95.51559704184874, + "z": 0.0 + }, + { + "x": 88.38467634686454, + "y": -96.52912644190317, + "z": 0.0 + }, + { + "x": 88.38483041619479, + "y": -97.54265584195764, + "z": 0.0 + }, + { + "x": 88.38498448552504, + "y": -98.5561852420121, + "z": 0.0 + }, + { + "x": 88.3851385548553, + "y": -99.56971464206654, + "z": 0.0 + }, + { + "x": 88.38529262418555, + "y": -100.58324404212101, + "z": 0.0 + }, + { + "x": 88.3854466935158, + "y": -101.5967734421755, + "z": 0.0 + }, + { + "x": 88.38560076284607, + "y": -102.61030284222997, + "z": 0.0 + }, + { + "x": 88.38575483217633, + "y": -103.62383224228438, + "z": 0.0 + }, + { + "x": 88.38590890150658, + "y": -104.63736164233885, + "z": 0.0 + }, + { + "x": 88.38606297083683, + "y": -105.65089104239331, + "z": 0.0 + }, + { + "x": 88.38621704016708, + "y": -106.6644204424478, + "z": 0.0 + }, + { + "x": 88.38637110949735, + "y": -107.67794984250224, + "z": 0.0 + }, + { + "x": 88.3865251788276, + "y": -108.69147924255668, + "z": 0.0 + }, + { + "x": 88.38667924815785, + "y": -109.70500864261118, + "z": 0.0 + }, + { + "x": 88.38683331748811, + "y": -110.71853804266561, + "z": 0.0 + }, + { + "x": 88.38698738681836, + "y": -111.73206744272005, + "z": 0.0 + }, + { + "x": 88.38714145614861, + "y": -112.74559684277455, + "z": 0.0 + }, + { + "x": 88.38729552547888, + "y": -113.75912624282901, + "z": 0.0 + }, + { + "x": 88.38744959480914, + "y": -114.77265564288345, + "z": 0.0 + }, + { + "x": 88.38760366413939, + "y": -115.78618504293792, + "z": 0.0 + }, + { + "x": 88.38775773346964, + "y": -116.79971444299235, + "z": 0.0 + }, + { + "x": 88.38791180279989, + "y": -117.81324384304685, + "z": 0.0 + }, + { + "x": 88.38806587213016, + "y": -118.82677324310129, + "z": 0.0 + }, + { + "x": 88.3882199414604, + "y": -119.84030264315575, + "z": 0.0 + } + ] + }, + { + "id": 115, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 94.39832719576235, + "y": -186.329389798807, + "z": 0.0 + }, + { + "x": 94.39816991565795, + "y": -185.29473864797058, + "z": 0.0 + }, + { + "x": 94.39801263555354, + "y": -184.26008749713418, + "z": 0.0 + }, + { + "x": 94.39785535544914, + "y": -183.22543634629776, + "z": 0.0 + }, + { + "x": 94.39769807534474, + "y": -182.19078519546136, + "z": 0.0 + }, + { + "x": 94.39754079524033, + "y": -181.15613404462493, + "z": 0.0 + }, + { + "x": 94.39738351513593, + "y": -180.12148289378854, + "z": 0.0 + }, + { + "x": 94.39722623503152, + "y": -179.0868317429521, + "z": 0.0 + }, + { + "x": 94.39706895492711, + "y": -178.05218059211563, + "z": 0.0 + }, + { + "x": 94.3969116748227, + "y": -177.0175294412793, + "z": 0.0 + }, + { + "x": 94.3967543947183, + "y": -175.98287829044287, + "z": 0.0 + }, + { + "x": 94.3965971146139, + "y": -174.94822713960644, + "z": 0.0 + }, + { + "x": 94.3964398345095, + "y": -173.91357598877005, + "z": 0.0 + }, + { + "x": 94.39628255440509, + "y": -172.87892483793362, + "z": 0.0 + }, + { + "x": 94.39612527430069, + "y": -171.84427368709723, + "z": 0.0 + }, + { + "x": 94.39596799419628, + "y": -170.8096225362608, + "z": 0.0 + }, + { + "x": 94.39581071409188, + "y": -169.7749713854244, + "z": 0.0 + }, + { + "x": 94.39565343398748, + "y": -168.74032023458798, + "z": 0.0 + }, + { + "x": 94.39549615388307, + "y": -167.70566908375156, + "z": 0.0 + }, + { + "x": 94.39533887377867, + "y": -166.67101793291516, + "z": 0.0 + }, + { + "x": 94.39518159367427, + "y": -165.63636678207874, + "z": 0.0 + }, + { + "x": 94.39502431356986, + "y": -164.6017156312423, + "z": 0.0 + }, + { + "x": 94.39486703346545, + "y": -163.56706448040586, + "z": 0.0 + }, + { + "x": 94.39470975336104, + "y": -162.5324133295695, + "z": 0.0 + }, + { + "x": 94.39455247325664, + "y": -161.4977621787331, + "z": 0.0 + }, + { + "x": 94.39439519315223, + "y": -160.46311102789667, + "z": 0.0 + }, + { + "x": 94.39423791304783, + "y": -159.42845987706028, + "z": 0.0 + }, + { + "x": 94.39408063294343, + "y": -158.39380872622385, + "z": 0.0 + }, + { + "x": 94.39392335283902, + "y": -157.35915757538743, + "z": 0.0 + }, + { + "x": 94.39376607273462, + "y": -156.32450642455103, + "z": 0.0 + }, + { + "x": 94.39360879263022, + "y": -155.2898552737146, + "z": 0.0 + }, + { + "x": 94.39345151252581, + "y": -154.2552041228782, + "z": 0.0 + }, + { + "x": 94.39329423242141, + "y": -153.2205529720418, + "z": 0.0 + }, + { + "x": 94.39313695231701, + "y": -152.1859018212054, + "z": 0.0 + }, + { + "x": 94.3929796722126, + "y": -151.15125067036897, + "z": 0.0 + }, + { + "x": 94.3928223921082, + "y": -150.11659951953254, + "z": 0.0 + }, + { + "x": 94.39266511200378, + "y": -149.0819483686961, + "z": 0.0 + }, + { + "x": 94.39250783189938, + "y": -148.04729721785972, + "z": 0.0 + }, + { + "x": 94.39235055179498, + "y": -147.01264606702333, + "z": 0.0 + }, + { + "x": 94.39219327169057, + "y": -145.9779949161869, + "z": 0.0 + }, + { + "x": 94.39203599158617, + "y": -144.9433437653505, + "z": 0.0 + }, + { + "x": 94.39187871148177, + "y": -143.90869261451408, + "z": 0.0 + }, + { + "x": 94.39172143137736, + "y": -142.87404146367768, + "z": 0.0 + }, + { + "x": 94.39156415127296, + "y": -141.83939031284126, + "z": 0.0 + } + ] + }, + { + "id": 116, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 86.3915642437044, + "y": -141.8406064143453, + "z": 0.0 + }, + { + "x": 86.3917215238088, + "y": -142.87525756518173, + "z": 0.0 + }, + { + "x": 86.3918788039132, + "y": -143.90990871601812, + "z": 0.0 + }, + { + "x": 86.3920360840176, + "y": -144.94455986685455, + "z": 0.0 + }, + { + "x": 86.39219336412201, + "y": -145.97921101769094, + "z": 0.0 + }, + { + "x": 86.39235064422641, + "y": -147.01386216852737, + "z": 0.0 + }, + { + "x": 86.39250792433081, + "y": -148.04851331936376, + "z": 0.0 + }, + { + "x": 86.39266520443522, + "y": -149.08316447020024, + "z": 0.0 + }, + { + "x": 86.39282248453964, + "y": -150.11781562103658, + "z": 0.0 + }, + { + "x": 86.39297976464404, + "y": -151.152466771873, + "z": 0.0 + }, + { + "x": 86.39313704474844, + "y": -152.18711792270943, + "z": 0.0 + }, + { + "x": 86.39329432485285, + "y": -153.22176907354583, + "z": 0.0 + }, + { + "x": 86.39345160495725, + "y": -154.25642022438225, + "z": 0.0 + }, + { + "x": 86.39360888506165, + "y": -155.29107137521865, + "z": 0.0 + }, + { + "x": 86.39376616516606, + "y": -156.32572252605507, + "z": 0.0 + }, + { + "x": 86.39392344527046, + "y": -157.36037367689147, + "z": 0.0 + }, + { + "x": 86.39408072537486, + "y": -158.3950248277279, + "z": 0.0 + }, + { + "x": 86.39423800547927, + "y": -159.42967597856432, + "z": 0.0 + }, + { + "x": 86.39439528558367, + "y": -160.46432712940071, + "z": 0.0 + }, + { + "x": 86.39455256568807, + "y": -161.49897828023714, + "z": 0.0 + }, + { + "x": 86.39470984579248, + "y": -162.53362943107354, + "z": 0.0 + }, + { + "x": 86.39486712589688, + "y": -163.56828058191002, + "z": 0.0 + }, + { + "x": 86.3950244060013, + "y": -164.60293173274636, + "z": 0.0 + }, + { + "x": 86.3951816861057, + "y": -165.63758288358278, + "z": 0.0 + }, + { + "x": 86.3953389662101, + "y": -166.6722340344192, + "z": 0.0 + }, + { + "x": 86.39549624631451, + "y": -167.7068851852556, + "z": 0.0 + }, + { + "x": 86.39565352641891, + "y": -168.74153633609203, + "z": 0.0 + }, + { + "x": 86.39581080652331, + "y": -169.77618748692845, + "z": 0.0 + }, + { + "x": 86.39596808662772, + "y": -170.81083863776485, + "z": 0.0 + }, + { + "x": 86.39612536673212, + "y": -171.84548978860127, + "z": 0.0 + }, + { + "x": 86.39628264683653, + "y": -172.88014093943767, + "z": 0.0 + }, + { + "x": 86.39643992694093, + "y": -173.9147920902741, + "z": 0.0 + }, + { + "x": 86.39659720704533, + "y": -174.9494432411105, + "z": 0.0 + }, + { + "x": 86.39675448714974, + "y": -175.9840943919469, + "z": 0.0 + }, + { + "x": 86.39691176725414, + "y": -177.01874554278334, + "z": 0.0 + }, + { + "x": 86.39706904735854, + "y": -178.0533966936198, + "z": 0.0 + }, + { + "x": 86.39722632746296, + "y": -179.08804784445616, + "z": 0.0 + }, + { + "x": 86.39738360756736, + "y": -180.12269899529258, + "z": 0.0 + }, + { + "x": 86.39754088767177, + "y": -181.15735014612898, + "z": 0.0 + }, + { + "x": 86.39769816777617, + "y": -182.1920012969654, + "z": 0.0 + }, + { + "x": 86.39785544788057, + "y": -183.2266524478018, + "z": 0.0 + }, + { + "x": 86.39801272798498, + "y": -184.26130359863822, + "z": 0.0 + }, + { + "x": 86.39817000808938, + "y": -185.29595474947462, + "z": 0.0 + }, + { + "x": 86.39832728819378, + "y": -186.33060590031104, + "z": 0.0 + } + ] + }, + { + "id": 117, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 90.39156419748868, + "y": -141.83999836359328, + "z": 0.0 + }, + { + "x": 90.39172147759308, + "y": -142.8746495144297, + "z": 0.0 + }, + { + "x": 90.39187875769748, + "y": -143.9093006652661, + "z": 0.0 + }, + { + "x": 90.39203603780189, + "y": -144.94395181610253, + "z": 0.0 + }, + { + "x": 90.39219331790629, + "y": -145.97860296693892, + "z": 0.0 + }, + { + "x": 90.3923505980107, + "y": -147.01325411777535, + "z": 0.0 + }, + { + "x": 90.3925078781151, + "y": -148.04790526861174, + "z": 0.0 + }, + { + "x": 90.3926651582195, + "y": -149.08255641944817, + "z": 0.0 + }, + { + "x": 90.39282243832392, + "y": -150.11720757028456, + "z": 0.0 + }, + { + "x": 90.39297971842832, + "y": -151.151858721121, + "z": 0.0 + }, + { + "x": 90.39313699853273, + "y": -152.1865098719574, + "z": 0.0 + }, + { + "x": 90.39329427863713, + "y": -153.2211610227938, + "z": 0.0 + }, + { + "x": 90.39345155874153, + "y": -154.25581217363023, + "z": 0.0 + }, + { + "x": 90.39360883884594, + "y": -155.29046332446663, + "z": 0.0 + }, + { + "x": 90.39376611895034, + "y": -156.32511447530305, + "z": 0.0 + }, + { + "x": 90.39392339905474, + "y": -157.35976562613945, + "z": 0.0 + }, + { + "x": 90.39408067915915, + "y": -158.39441677697587, + "z": 0.0 + }, + { + "x": 90.39423795926355, + "y": -159.4290679278123, + "z": 0.0 + }, + { + "x": 90.39439523936795, + "y": -160.4637190786487, + "z": 0.0 + }, + { + "x": 90.39455251947236, + "y": -161.49837022948512, + "z": 0.0 + }, + { + "x": 90.39470979957676, + "y": -162.53302138032151, + "z": 0.0 + }, + { + "x": 90.39486707968116, + "y": -163.56767253115794, + "z": 0.0 + }, + { + "x": 90.39502435978558, + "y": -164.60232368199433, + "z": 0.0 + }, + { + "x": 90.39518163988998, + "y": -165.63697483283076, + "z": 0.0 + }, + { + "x": 90.39533891999439, + "y": -166.67162598366718, + "z": 0.0 + }, + { + "x": 90.39549620009879, + "y": -167.70627713450358, + "z": 0.0 + }, + { + "x": 90.3956534802032, + "y": -168.74092828534, + "z": 0.0 + }, + { + "x": 90.3958107603076, + "y": -169.77557943617643, + "z": 0.0 + }, + { + "x": 90.395968040412, + "y": -170.81023058701282, + "z": 0.0 + }, + { + "x": 90.3961253205164, + "y": -171.84488173784925, + "z": 0.0 + }, + { + "x": 90.39628260062081, + "y": -172.87953288868565, + "z": 0.0 + }, + { + "x": 90.39643988072521, + "y": -173.91418403952207, + "z": 0.0 + }, + { + "x": 90.39659716082961, + "y": -174.94883519035847, + "z": 0.0 + }, + { + "x": 90.39675444093402, + "y": -175.9834863411949, + "z": 0.0 + }, + { + "x": 90.39691172103842, + "y": -177.01813749203131, + "z": 0.0 + }, + { + "x": 90.39706900114282, + "y": -178.0527886428677, + "z": 0.0 + }, + { + "x": 90.39722628124724, + "y": -179.08743979370414, + "z": 0.0 + }, + { + "x": 90.39738356135165, + "y": -180.12209094454056, + "z": 0.0 + }, + { + "x": 90.39754084145605, + "y": -181.15674209537696, + "z": 0.0 + }, + { + "x": 90.39769812156045, + "y": -182.19139324621338, + "z": 0.0 + }, + { + "x": 90.39785540166486, + "y": -183.22604439704978, + "z": 0.0 + }, + { + "x": 90.39801268176926, + "y": -184.2606955478862, + "z": 0.0 + }, + { + "x": 90.39816996187366, + "y": -185.2953466987226, + "z": 0.0 + }, + { + "x": 90.39832724197807, + "y": -186.32999784955902, + "z": 0.0 + } + ] + }, + { + "id": 118, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 92.39832721887021, + "y": -186.329693824183, + "z": 0.0 + }, + { + "x": 92.3981699387658, + "y": -185.2950426733466, + "z": 0.0 + }, + { + "x": 92.3980126586614, + "y": -184.2603915225102, + "z": 0.0 + }, + { + "x": 92.397855378557, + "y": -183.22574037167377, + "z": 0.0 + }, + { + "x": 92.3976980984526, + "y": -182.19108922083737, + "z": 0.0 + }, + { + "x": 92.39754081834819, + "y": -181.15643807000095, + "z": 0.0 + }, + { + "x": 92.39738353824379, + "y": -180.12178691916455, + "z": 0.0 + }, + { + "x": 92.39722625813938, + "y": -179.08713576832812, + "z": 0.0 + }, + { + "x": 92.39706897803497, + "y": -178.05248461749167, + "z": 0.0 + }, + { + "x": 92.39691169793056, + "y": -177.0178334666553, + "z": 0.0 + }, + { + "x": 92.39675441782616, + "y": -175.98318231581888, + "z": 0.0 + }, + { + "x": 92.39659713772176, + "y": -174.94853116498246, + "z": 0.0 + }, + { + "x": 92.39643985761735, + "y": -173.91388001414606, + "z": 0.0 + }, + { + "x": 92.39628257751295, + "y": -172.87922886330963, + "z": 0.0 + }, + { + "x": 92.39612529740855, + "y": -171.84457771247324, + "z": 0.0 + }, + { + "x": 92.39596801730414, + "y": -170.80992656163681, + "z": 0.0 + }, + { + "x": 92.39581073719974, + "y": -169.77527541080042, + "z": 0.0 + }, + { + "x": 92.39565345709534, + "y": -168.740624259964, + "z": 0.0 + }, + { + "x": 92.39549617699093, + "y": -167.70597310912757, + "z": 0.0 + }, + { + "x": 92.39533889688653, + "y": -166.67132195829117, + "z": 0.0 + }, + { + "x": 92.39518161678212, + "y": -165.63667080745475, + "z": 0.0 + }, + { + "x": 92.39502433667772, + "y": -164.60201965661832, + "z": 0.0 + }, + { + "x": 92.3948670565733, + "y": -163.5673685057819, + "z": 0.0 + }, + { + "x": 92.3947097764689, + "y": -162.5327173549455, + "z": 0.0 + }, + { + "x": 92.3945524963645, + "y": -161.4980662041091, + "z": 0.0 + }, + { + "x": 92.3943952162601, + "y": -160.46341505327268, + "z": 0.0 + }, + { + "x": 92.39423793615569, + "y": -159.4287639024363, + "z": 0.0 + }, + { + "x": 92.39408065605129, + "y": -158.39411275159986, + "z": 0.0 + }, + { + "x": 92.39392337594688, + "y": -157.35946160076344, + "z": 0.0 + }, + { + "x": 92.39376609584248, + "y": -156.32481044992704, + "z": 0.0 + }, + { + "x": 92.39360881573808, + "y": -155.29015929909062, + "z": 0.0 + }, + { + "x": 92.39345153563367, + "y": -154.25550814825422, + "z": 0.0 + }, + { + "x": 92.39329425552927, + "y": -153.2208569974178, + "z": 0.0 + }, + { + "x": 92.39313697542487, + "y": -152.1862058465814, + "z": 0.0 + }, + { + "x": 92.39297969532046, + "y": -151.15155469574498, + "z": 0.0 + }, + { + "x": 92.39282241521606, + "y": -150.11690354490855, + "z": 0.0 + }, + { + "x": 92.39266513511164, + "y": -149.08225239407213, + "z": 0.0 + }, + { + "x": 92.39250785500724, + "y": -148.04760124323573, + "z": 0.0 + }, + { + "x": 92.39235057490284, + "y": -147.01295009239934, + "z": 0.0 + }, + { + "x": 92.39219329479843, + "y": -145.9782989415629, + "z": 0.0 + }, + { + "x": 92.39203601469403, + "y": -144.94364779072652, + "z": 0.0 + }, + { + "x": 92.39187873458962, + "y": -143.9089966398901, + "z": 0.0 + }, + { + "x": 92.39172145448522, + "y": -142.8743454890537, + "z": 0.0 + }, + { + "x": 92.39156417438082, + "y": -141.83969433821727, + "z": 0.0 + } + ] + }, + { + "id": 119, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 88.39156422059654, + "y": -141.8403023889693, + "z": 0.0 + }, + { + "x": 88.39172150070094, + "y": -142.87495353980572, + "z": 0.0 + }, + { + "x": 88.39187878080534, + "y": -143.9096046906421, + "z": 0.0 + }, + { + "x": 88.39203606090975, + "y": -144.94425584147854, + "z": 0.0 + }, + { + "x": 88.39219334101415, + "y": -145.97890699231493, + "z": 0.0 + }, + { + "x": 88.39235062111855, + "y": -147.01355814315136, + "z": 0.0 + }, + { + "x": 88.39250790122296, + "y": -148.04820929398775, + "z": 0.0 + }, + { + "x": 88.39266518132736, + "y": -149.0828604448242, + "z": 0.0 + }, + { + "x": 88.39282246143178, + "y": -150.11751159566057, + "z": 0.0 + }, + { + "x": 88.39297974153618, + "y": -151.152162746497, + "z": 0.0 + }, + { + "x": 88.39313702164058, + "y": -152.18681389733342, + "z": 0.0 + }, + { + "x": 88.39329430174499, + "y": -153.22146504816982, + "z": 0.0 + }, + { + "x": 88.39345158184939, + "y": -154.25611619900624, + "z": 0.0 + }, + { + "x": 88.3936088619538, + "y": -155.29076734984264, + "z": 0.0 + }, + { + "x": 88.3937661420582, + "y": -156.32541850067906, + "z": 0.0 + }, + { + "x": 88.3939234221626, + "y": -157.36006965151546, + "z": 0.0 + }, + { + "x": 88.394080702267, + "y": -158.39472080235188, + "z": 0.0 + }, + { + "x": 88.39423798237141, + "y": -159.4293719531883, + "z": 0.0 + }, + { + "x": 88.39439526247581, + "y": -160.4640231040247, + "z": 0.0 + }, + { + "x": 88.39455254258021, + "y": -161.49867425486113, + "z": 0.0 + }, + { + "x": 88.39470982268462, + "y": -162.53332540569752, + "z": 0.0 + }, + { + "x": 88.39486710278902, + "y": -163.56797655653398, + "z": 0.0 + }, + { + "x": 88.39502438289344, + "y": -164.60262770737035, + "z": 0.0 + }, + { + "x": 88.39518166299784, + "y": -165.63727885820677, + "z": 0.0 + }, + { + "x": 88.39533894310225, + "y": -166.6719300090432, + "z": 0.0 + }, + { + "x": 88.39549622320665, + "y": -167.7065811598796, + "z": 0.0 + }, + { + "x": 88.39565350331105, + "y": -168.74123231071601, + "z": 0.0 + }, + { + "x": 88.39581078341546, + "y": -169.77588346155244, + "z": 0.0 + }, + { + "x": 88.39596806351986, + "y": -170.81053461238884, + "z": 0.0 + }, + { + "x": 88.39612534362426, + "y": -171.84518576322526, + "z": 0.0 + }, + { + "x": 88.39628262372867, + "y": -172.87983691406166, + "z": 0.0 + }, + { + "x": 88.39643990383307, + "y": -173.91448806489808, + "z": 0.0 + }, + { + "x": 88.39659718393747, + "y": -174.94913921573448, + "z": 0.0 + }, + { + "x": 88.39675446404188, + "y": -175.9837903665709, + "z": 0.0 + }, + { + "x": 88.39691174414628, + "y": -177.01844151740733, + "z": 0.0 + }, + { + "x": 88.39706902425068, + "y": -178.05309266824375, + "z": 0.0 + }, + { + "x": 88.3972263043551, + "y": -179.08774381908015, + "z": 0.0 + }, + { + "x": 88.3973835844595, + "y": -180.12239496991657, + "z": 0.0 + }, + { + "x": 88.39754086456391, + "y": -181.15704612075297, + "z": 0.0 + }, + { + "x": 88.39769814466831, + "y": -182.1916972715894, + "z": 0.0 + }, + { + "x": 88.39785542477271, + "y": -183.2263484224258, + "z": 0.0 + }, + { + "x": 88.39801270487712, + "y": -184.2609995732622, + "z": 0.0 + }, + { + "x": 88.39816998498152, + "y": -185.2956507240986, + "z": 0.0 + }, + { + "x": 88.39832726508592, + "y": -186.33030187493503, + "z": 0.0 + } + ] + }, + { + "id": 120, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 94.4182362975105, + "y": -317.299388285589, + "z": 0.0 + }, + { + "x": 94.41808291952336, + "y": -316.2904068157652, + "z": 0.0 + }, + { + "x": 94.4179295415362, + "y": -315.28142534594133, + "z": 0.0 + }, + { + "x": 94.41777616354905, + "y": -314.2724438761176, + "z": 0.0 + }, + { + "x": 94.4176227855619, + "y": -313.26346240629385, + "z": 0.0 + }, + { + "x": 94.41746940757476, + "y": -312.25448093647003, + "z": 0.0 + }, + { + "x": 94.41731602958761, + "y": -311.24549946664627, + "z": 0.0 + }, + { + "x": 94.41716265160046, + "y": -310.2365179968225, + "z": 0.0 + }, + { + "x": 94.41700927361332, + "y": -309.2275365269987, + "z": 0.0 + }, + { + "x": 94.41685589562616, + "y": -308.21855505717485, + "z": 0.0 + }, + { + "x": 94.41670251763901, + "y": -307.2095735873511, + "z": 0.0 + }, + { + "x": 94.41654913965186, + "y": -306.2005921175273, + "z": 0.0 + }, + { + "x": 94.41639576166472, + "y": -305.19161064770356, + "z": 0.0 + }, + { + "x": 94.41624238367757, + "y": -304.18262917787973, + "z": 0.0 + }, + { + "x": 94.41608900569042, + "y": -303.17364770805597, + "z": 0.0 + }, + { + "x": 94.41593562770328, + "y": -302.1646662382322, + "z": 0.0 + }, + { + "x": 94.41578224971612, + "y": -301.1556847684083, + "z": 0.0 + }, + { + "x": 94.41562887172897, + "y": -300.1467032985846, + "z": 0.0 + }, + { + "x": 94.41547549374182, + "y": -299.13772182876085, + "z": 0.0 + }, + { + "x": 94.41532211575468, + "y": -298.128740358937, + "z": 0.0 + }, + { + "x": 94.41516873776753, + "y": -297.11975888911326, + "z": 0.0 + }, + { + "x": 94.41501535978038, + "y": -296.1107774192895, + "z": 0.0 + }, + { + "x": 94.41486198179324, + "y": -295.10179594946567, + "z": 0.0 + }, + { + "x": 94.41470860380609, + "y": -294.0928144796419, + "z": 0.0 + }, + { + "x": 94.41455522581893, + "y": -293.0838330098181, + "z": 0.0 + }, + { + "x": 94.4144018478318, + "y": -292.07485153999437, + "z": 0.0 + }, + { + "x": 94.41424846984464, + "y": -291.0658700701705, + "z": 0.0 + }, + { + "x": 94.41409509185749, + "y": -290.0568886003467, + "z": 0.0 + }, + { + "x": 94.41394171387034, + "y": -289.04790713052296, + "z": 0.0 + }, + { + "x": 94.4137883358832, + "y": -288.0389256606992, + "z": 0.0 + }, + { + "x": 94.41363495789605, + "y": -287.02994419087537, + "z": 0.0 + }, + { + "x": 94.41348157990889, + "y": -286.02096272105155, + "z": 0.0 + }, + { + "x": 94.41332820192176, + "y": -285.0119812512279, + "z": 0.0 + }, + { + "x": 94.41317482393461, + "y": -284.002999781404, + "z": 0.0 + }, + { + "x": 94.41302144594745, + "y": -282.9940183115802, + "z": 0.0 + }, + { + "x": 94.4128680679603, + "y": -281.9850368417565, + "z": 0.0 + }, + { + "x": 94.41271468997316, + "y": -280.97605537193266, + "z": 0.0 + }, + { + "x": 94.41256131198601, + "y": -279.9670739021089, + "z": 0.0 + }, + { + "x": 94.41240793399886, + "y": -278.9580924322851, + "z": 0.0 + }, + { + "x": 94.41225455601172, + "y": -277.9491109624613, + "z": 0.0 + }, + { + "x": 94.41210117802457, + "y": -276.94012949263754, + "z": 0.0 + }, + { + "x": 94.41194780003741, + "y": -275.9311480228137, + "z": 0.0 + }, + { + "x": 94.41179442205026, + "y": -274.92216655298995, + "z": 0.0 + }, + { + "x": 94.41164104406312, + "y": -273.9131850831662, + "z": 0.0 + }, + { + "x": 94.41148766607597, + "y": -272.9042036133424, + "z": 0.0 + }, + { + "x": 94.41133428808882, + "y": -271.8952221435186, + "z": 0.0 + }, + { + "x": 94.41118091010168, + "y": -270.88624067369483, + "z": 0.0 + }, + { + "x": 94.41102753211453, + "y": -269.87725920387106, + "z": 0.0 + }, + { + "x": 94.41087415412737, + "y": -268.86827773404724, + "z": 0.0 + }, + { + "x": 94.41072077614024, + "y": -267.85929626422353, + "z": 0.0 + }, + { + "x": 94.41056739815309, + "y": -266.8503147943997, + "z": 0.0 + }, + { + "x": 94.41041402016593, + "y": -265.8413333245759, + "z": 0.0 + }, + { + "x": 94.41026064217878, + "y": -264.8323518547522, + "z": 0.0 + }, + { + "x": 94.41010726419164, + "y": -263.82337038492835, + "z": 0.0 + }, + { + "x": 94.40995388620449, + "y": -262.8143889151046, + "z": 0.0 + }, + { + "x": 94.40980050821734, + "y": -261.8054074452808, + "z": 0.0 + }, + { + "x": 94.4096471302302, + "y": -260.79642597545705, + "z": 0.0 + }, + { + "x": 94.40949375224305, + "y": -259.7874445056333, + "z": 0.0 + }, + { + "x": 94.40934037425589, + "y": -258.7784630358094, + "z": 0.0 + }, + { + "x": 94.40918699626874, + "y": -257.7694815659857, + "z": 0.0 + }, + { + "x": 94.4090336182816, + "y": -256.76050009616193, + "z": 0.0 + }, + { + "x": 94.40888024029445, + "y": -255.75151862633814, + "z": 0.0 + }, + { + "x": 94.4087268623073, + "y": -254.74253715651437, + "z": 0.0 + }, + { + "x": 94.40857348432014, + "y": -253.73355568669052, + "z": 0.0 + }, + { + "x": 94.408420106333, + "y": -252.7245742168668, + "z": 0.0 + }, + { + "x": 94.40826672834586, + "y": -251.71559274704308, + "z": 0.0 + }, + { + "x": 94.4081133503587, + "y": -250.7066112772192, + "z": 0.0 + }, + { + "x": 94.40795997237156, + "y": -249.6976298073955, + "z": 0.0 + }, + { + "x": 94.40780659438441, + "y": -248.6886483375717, + "z": 0.0 + }, + { + "x": 94.40765321639726, + "y": -247.67966686774793, + "z": 0.0 + }, + { + "x": 94.4074998384101, + "y": -246.67068539792407, + "z": 0.0 + }, + { + "x": 94.40734646042296, + "y": -245.66170392810037, + "z": 0.0 + }, + { + "x": 94.40719308243582, + "y": -244.65272245827663, + "z": 0.0 + }, + { + "x": 94.40703970444866, + "y": -243.64374098845275, + "z": 0.0 + }, + { + "x": 94.40688632646152, + "y": -242.634759518629, + "z": 0.0 + }, + { + "x": 94.40673294847437, + "y": -241.62577804880524, + "z": 0.0 + }, + { + "x": 94.40657957048722, + "y": -240.61679657898145, + "z": 0.0 + }, + { + "x": 94.40642619250008, + "y": -239.60781510915768, + "z": 0.0 + }, + { + "x": 94.40627281451292, + "y": -238.59883363933383, + "z": 0.0 + }, + { + "x": 94.40611943652578, + "y": -237.58985216951018, + "z": 0.0 + }, + { + "x": 94.40596605853862, + "y": -236.5808706996863, + "z": 0.0 + }, + { + "x": 94.40581268055148, + "y": -235.57188922986256, + "z": 0.0 + }, + { + "x": 94.40565930256435, + "y": -234.56290776003885, + "z": 0.0 + }, + { + "x": 94.40550592457718, + "y": -233.55392629021495, + "z": 0.0 + }, + { + "x": 94.40535254659004, + "y": -232.54494482039124, + "z": 0.0 + }, + { + "x": 94.40519916860289, + "y": -231.53596335056744, + "z": 0.0 + }, + { + "x": 94.40504579061574, + "y": -230.52698188074368, + "z": 0.0 + }, + { + "x": 94.4048924126286, + "y": -229.51800041091988, + "z": 0.0 + }, + { + "x": 94.40473903464144, + "y": -228.50901894109606, + "z": 0.0 + }, + { + "x": 94.4045856566543, + "y": -227.50003747127238, + "z": 0.0 + }, + { + "x": 94.40443227866714, + "y": -226.4910560014485, + "z": 0.0 + }, + { + "x": 94.40427890068, + "y": -225.4820745316248, + "z": 0.0 + }, + { + "x": 94.40412552269285, + "y": -224.473093061801, + "z": 0.0 + }, + { + "x": 94.4039721447057, + "y": -223.46411159197723, + "z": 0.0 + }, + { + "x": 94.40381876671856, + "y": -222.45513012215343, + "z": 0.0 + }, + { + "x": 94.4036653887314, + "y": -221.4461486523296, + "z": 0.0 + }, + { + "x": 94.40351201074427, + "y": -220.43716718250593, + "z": 0.0 + }, + { + "x": 94.4033586327571, + "y": -219.42818571268205, + "z": 0.0 + }, + { + "x": 94.40320525476996, + "y": -218.4192042428583, + "z": 0.0 + }, + { + "x": 94.40305187678281, + "y": -217.41022277303452, + "z": 0.0 + }, + { + "x": 94.40289849879566, + "y": -216.40124130321075, + "z": 0.0 + }, + { + "x": 94.40274512080852, + "y": -215.39225983338696, + "z": 0.0 + }, + { + "x": 94.40259174282136, + "y": -214.38327836356314, + "z": 0.0 + }, + { + "x": 94.40243836483423, + "y": -213.37429689373946, + "z": 0.0 + }, + { + "x": 94.40228498684708, + "y": -212.36531542391563, + "z": 0.0 + }, + { + "x": 94.40213160885992, + "y": -211.35633395409178, + "z": 0.0 + }, + { + "x": 94.40197823087277, + "y": -210.34735248426807, + "z": 0.0 + }, + { + "x": 94.40182485288562, + "y": -209.33837101444428, + "z": 0.0 + }, + { + "x": 94.40167147489848, + "y": -208.3293895446205, + "z": 0.0 + } + ] + }, + { + "id": 121, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 86.40167156732991, + "y": -208.33060564612455, + "z": 0.0 + }, + { + "x": 86.40182494531706, + "y": -209.33958711594832, + "z": 0.0 + }, + { + "x": 86.4019783233042, + "y": -210.3485685857721, + "z": 0.0 + }, + { + "x": 86.40213170129135, + "y": -211.35755005559594, + "z": 0.0 + }, + { + "x": 86.40228507927851, + "y": -212.36653152541967, + "z": 0.0 + }, + { + "x": 86.40243845726566, + "y": -213.37551299524338, + "z": 0.0 + }, + { + "x": 86.40259183525279, + "y": -214.3844944650673, + "z": 0.0 + }, + { + "x": 86.40274521323995, + "y": -215.393475934891, + "z": 0.0 + }, + { + "x": 86.4028985912271, + "y": -216.4024574047148, + "z": 0.0 + }, + { + "x": 86.40305196921425, + "y": -217.41143887453856, + "z": 0.0 + }, + { + "x": 86.40320534720139, + "y": -218.42042034436236, + "z": 0.0 + }, + { + "x": 86.40335872518854, + "y": -219.4294018141862, + "z": 0.0 + }, + { + "x": 86.4035121031757, + "y": -220.43838328400986, + "z": 0.0 + }, + { + "x": 86.40366548116283, + "y": -221.44736475383377, + "z": 0.0 + }, + { + "x": 86.40381885915, + "y": -222.45634622365748, + "z": 0.0 + }, + { + "x": 86.40397223713714, + "y": -223.46532769348127, + "z": 0.0 + }, + { + "x": 86.40412561512429, + "y": -224.47430916330504, + "z": 0.0 + }, + { + "x": 86.40427899311143, + "y": -225.48329063312883, + "z": 0.0 + }, + { + "x": 86.40443237109858, + "y": -226.49227210295265, + "z": 0.0 + }, + { + "x": 86.40458574908574, + "y": -227.5012535727763, + "z": 0.0 + }, + { + "x": 86.40473912707287, + "y": -228.51023504260021, + "z": 0.0 + }, + { + "x": 86.40489250506003, + "y": -229.51921651242392, + "z": 0.0 + }, + { + "x": 86.40504588304718, + "y": -230.52819798224772, + "z": 0.0 + }, + { + "x": 86.40519926103433, + "y": -231.53717945207148, + "z": 0.0 + }, + { + "x": 86.40535263902147, + "y": -232.54616092189528, + "z": 0.0 + }, + { + "x": 86.40550601700862, + "y": -233.5551423917191, + "z": 0.0 + }, + { + "x": 86.40565939499578, + "y": -234.56412386154278, + "z": 0.0 + }, + { + "x": 86.40581277298291, + "y": -235.5731053313666, + "z": 0.0 + }, + { + "x": 86.40596615097006, + "y": -236.58208680119046, + "z": 0.0 + }, + { + "x": 86.40611952895722, + "y": -237.5910682710141, + "z": 0.0 + }, + { + "x": 86.40627290694435, + "y": -238.600049740838, + "z": 0.0 + }, + { + "x": 86.40642628493151, + "y": -239.60903121066173, + "z": 0.0 + }, + { + "x": 86.40657966291866, + "y": -240.6180126804855, + "z": 0.0 + }, + { + "x": 86.4067330409058, + "y": -241.6269941503093, + "z": 0.0 + }, + { + "x": 86.40688641889295, + "y": -242.63597562013305, + "z": 0.0 + }, + { + "x": 86.4070397968801, + "y": -243.6449570899569, + "z": 0.0 + }, + { + "x": 86.40719317486726, + "y": -244.65393855978056, + "z": 0.0 + }, + { + "x": 86.40734655285439, + "y": -245.6629200296044, + "z": 0.0 + }, + { + "x": 86.40749993084154, + "y": -246.67190149942823, + "z": 0.0 + }, + { + "x": 86.4076533088287, + "y": -247.68088296925197, + "z": 0.0 + }, + { + "x": 86.40780668681585, + "y": -248.68986443907573, + "z": 0.0 + }, + { + "x": 86.40796006480299, + "y": -249.69884590889953, + "z": 0.0 + }, + { + "x": 86.40811344279014, + "y": -250.70782737872335, + "z": 0.0 + }, + { + "x": 86.4082668207773, + "y": -251.716808848547, + "z": 0.0 + }, + { + "x": 86.40842019876443, + "y": -252.72579031837085, + "z": 0.0 + }, + { + "x": 86.40857357675158, + "y": -253.73477178819468, + "z": 0.0 + }, + { + "x": 86.40872695473874, + "y": -254.74375325801842, + "z": 0.0 + }, + { + "x": 86.40888033272589, + "y": -255.75273472784218, + "z": 0.0 + }, + { + "x": 86.40903371071303, + "y": -256.761716197666, + "z": 0.0 + }, + { + "x": 86.40918708870018, + "y": -257.77069766748974, + "z": 0.0 + }, + { + "x": 86.40934046668733, + "y": -258.77967913731356, + "z": 0.0 + }, + { + "x": 86.40949384467449, + "y": -259.78866060713733, + "z": 0.0 + }, + { + "x": 86.40964722266163, + "y": -260.7976420769611, + "z": 0.0 + }, + { + "x": 86.40980060064878, + "y": -261.80662354678486, + "z": 0.0 + }, + { + "x": 86.40995397863593, + "y": -262.81560501660863, + "z": 0.0 + }, + { + "x": 86.41010735662307, + "y": -263.8245864864324, + "z": 0.0 + }, + { + "x": 86.41026073461022, + "y": -264.8335679562562, + "z": 0.0 + }, + { + "x": 86.41041411259737, + "y": -265.84254942608004, + "z": 0.0 + }, + { + "x": 86.41056749058453, + "y": -266.85153089590375, + "z": 0.0 + }, + { + "x": 86.41072086857167, + "y": -267.86051236572746, + "z": 0.0 + }, + { + "x": 86.4108742465588, + "y": -268.8694938355514, + "z": 0.0 + }, + { + "x": 86.41102762454597, + "y": -269.8784753053751, + "z": 0.0 + }, + { + "x": 86.41118100253311, + "y": -270.88745677519887, + "z": 0.0 + }, + { + "x": 86.41133438052026, + "y": -271.89643824502264, + "z": 0.0 + }, + { + "x": 86.4114877585074, + "y": -272.90541971484646, + "z": 0.0 + }, + { + "x": 86.41164113649455, + "y": -273.9144011846702, + "z": 0.0 + }, + { + "x": 86.4117945144817, + "y": -274.923382654494, + "z": 0.0 + }, + { + "x": 86.41194789246885, + "y": -275.93236412431787, + "z": 0.0 + }, + { + "x": 86.412101270456, + "y": -276.9413455941416, + "z": 0.0 + }, + { + "x": 86.41225464844315, + "y": -277.95032706396535, + "z": 0.0 + }, + { + "x": 86.4124080264303, + "y": -278.95930853378917, + "z": 0.0 + }, + { + "x": 86.41256140441745, + "y": -279.96829000361294, + "z": 0.0 + }, + { + "x": 86.41271478240459, + "y": -280.9772714734367, + "z": 0.0 + }, + { + "x": 86.41286816039174, + "y": -281.9862529432605, + "z": 0.0 + }, + { + "x": 86.41302153837889, + "y": -282.99523441308435, + "z": 0.0 + }, + { + "x": 86.41317491636605, + "y": -284.00421588290806, + "z": 0.0 + }, + { + "x": 86.41332829435319, + "y": -285.0131973527318, + "z": 0.0 + }, + { + "x": 86.41348167234032, + "y": -286.0221788225557, + "z": 0.0 + }, + { + "x": 86.41363505032749, + "y": -287.0311602923794, + "z": 0.0 + }, + { + "x": 86.41378842831463, + "y": -288.04014176220323, + "z": 0.0 + }, + { + "x": 86.41394180630178, + "y": -289.049123232027, + "z": 0.0 + }, + { + "x": 86.41409518428893, + "y": -290.05810470185077, + "z": 0.0 + }, + { + "x": 86.41424856227607, + "y": -291.06708617167465, + "z": 0.0 + }, + { + "x": 86.41440194026323, + "y": -292.0760676414983, + "z": 0.0 + }, + { + "x": 86.41455531825036, + "y": -293.08504911132223, + "z": 0.0 + }, + { + "x": 86.41470869623753, + "y": -294.09403058114594, + "z": 0.0 + }, + { + "x": 86.41486207422467, + "y": -295.1030120509697, + "z": 0.0 + }, + { + "x": 86.41501545221182, + "y": -296.11199352079353, + "z": 0.0 + }, + { + "x": 86.41516883019897, + "y": -297.1209749906173, + "z": 0.0 + }, + { + "x": 86.41532220818611, + "y": -298.12995646044106, + "z": 0.0 + }, + { + "x": 86.41547558617326, + "y": -299.1389379302649, + "z": 0.0 + }, + { + "x": 86.4156289641604, + "y": -300.14791940008865, + "z": 0.0 + }, + { + "x": 86.41578234214755, + "y": -301.1569008699125, + "z": 0.0 + }, + { + "x": 86.41593572013471, + "y": -302.16588233973624, + "z": 0.0 + }, + { + "x": 86.41608909812186, + "y": -303.17486380956, + "z": 0.0 + }, + { + "x": 86.416242476109, + "y": -304.1838452793838, + "z": 0.0 + }, + { + "x": 86.41639585409615, + "y": -305.1928267492076, + "z": 0.0 + }, + { + "x": 86.4165492320833, + "y": -306.20180821903136, + "z": 0.0 + }, + { + "x": 86.41670261007044, + "y": -307.21078968885513, + "z": 0.0 + }, + { + "x": 86.41685598805759, + "y": -308.219771158679, + "z": 0.0 + }, + { + "x": 86.41700936604475, + "y": -309.2287526285027, + "z": 0.0 + }, + { + "x": 86.4171627440319, + "y": -310.23773409832654, + "z": 0.0 + }, + { + "x": 86.41731612201905, + "y": -311.2467155681503, + "z": 0.0 + }, + { + "x": 86.41746950000619, + "y": -312.2556970379741, + "z": 0.0 + }, + { + "x": 86.41762287799334, + "y": -313.2646785077979, + "z": 0.0 + }, + { + "x": 86.41777625598048, + "y": -314.27365997762166, + "z": 0.0 + }, + { + "x": 86.41792963396763, + "y": -315.2826414474455, + "z": 0.0 + }, + { + "x": 86.41808301195479, + "y": -316.29162291726925, + "z": 0.0 + }, + { + "x": 86.41823638994194, + "y": -317.300604387093, + "z": 0.0 + } + ] + }, + { + "id": 122, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 90.4016715211142, + "y": -208.32999759537253, + "z": 0.0 + }, + { + "x": 90.40182489910134, + "y": -209.3389790651963, + "z": 0.0 + }, + { + "x": 90.40197827708849, + "y": -210.3479605350201, + "z": 0.0 + }, + { + "x": 90.40213165507564, + "y": -211.35694200484386, + "z": 0.0 + }, + { + "x": 90.4022850330628, + "y": -212.36592347466765, + "z": 0.0 + }, + { + "x": 90.40243841104994, + "y": -213.37490494449142, + "z": 0.0 + }, + { + "x": 90.40259178903707, + "y": -214.3838864143152, + "z": 0.0 + }, + { + "x": 90.40274516702424, + "y": -215.39286788413898, + "z": 0.0 + }, + { + "x": 90.40289854501138, + "y": -216.40184935396277, + "z": 0.0 + }, + { + "x": 90.40305192299853, + "y": -217.41083082378654, + "z": 0.0 + }, + { + "x": 90.40320530098568, + "y": -218.41981229361033, + "z": 0.0 + }, + { + "x": 90.40335867897282, + "y": -219.42879376343413, + "z": 0.0 + }, + { + "x": 90.40351205695998, + "y": -220.4377752332579, + "z": 0.0 + }, + { + "x": 90.40366543494711, + "y": -221.4467567030817, + "z": 0.0 + }, + { + "x": 90.40381881293428, + "y": -222.45573817290546, + "z": 0.0 + }, + { + "x": 90.40397219092142, + "y": -223.46471964272925, + "z": 0.0 + }, + { + "x": 90.40412556890857, + "y": -224.47370111255302, + "z": 0.0 + }, + { + "x": 90.40427894689572, + "y": -225.4826825823768, + "z": 0.0 + }, + { + "x": 90.40443232488286, + "y": -226.49166405220058, + "z": 0.0 + }, + { + "x": 90.40458570287002, + "y": -227.50064552202434, + "z": 0.0 + }, + { + "x": 90.40473908085715, + "y": -228.50962699184814, + "z": 0.0 + }, + { + "x": 90.40489245884432, + "y": -229.5186084616719, + "z": 0.0 + }, + { + "x": 90.40504583683146, + "y": -230.5275899314957, + "z": 0.0 + }, + { + "x": 90.40519921481861, + "y": -231.53657140131946, + "z": 0.0 + }, + { + "x": 90.40535259280576, + "y": -232.54555287114326, + "z": 0.0 + }, + { + "x": 90.4055059707929, + "y": -233.55453434096702, + "z": 0.0 + }, + { + "x": 90.40565934878006, + "y": -234.56351581079082, + "z": 0.0 + }, + { + "x": 90.4058127267672, + "y": -235.57249728061458, + "z": 0.0 + }, + { + "x": 90.40596610475434, + "y": -236.58147875043838, + "z": 0.0 + }, + { + "x": 90.4061194827415, + "y": -237.59046022026214, + "z": 0.0 + }, + { + "x": 90.40627286072863, + "y": -238.5994416900859, + "z": 0.0 + }, + { + "x": 90.4064262387158, + "y": -239.6084231599097, + "z": 0.0 + }, + { + "x": 90.40657961670294, + "y": -240.61740462973347, + "z": 0.0 + }, + { + "x": 90.40673299469009, + "y": -241.62638609955727, + "z": 0.0 + }, + { + "x": 90.40688637267723, + "y": -242.63536756938103, + "z": 0.0 + }, + { + "x": 90.40703975066438, + "y": -243.64434903920483, + "z": 0.0 + }, + { + "x": 90.40719312865154, + "y": -244.6533305090286, + "z": 0.0 + }, + { + "x": 90.40734650663867, + "y": -245.6623119788524, + "z": 0.0 + }, + { + "x": 90.40749988462582, + "y": -246.67129344867615, + "z": 0.0 + }, + { + "x": 90.40765326261298, + "y": -247.68027491849995, + "z": 0.0 + }, + { + "x": 90.40780664060013, + "y": -248.6892563883237, + "z": 0.0 + }, + { + "x": 90.40796001858727, + "y": -249.6982378581475, + "z": 0.0 + }, + { + "x": 90.40811339657442, + "y": -250.70721932797127, + "z": 0.0 + }, + { + "x": 90.40826677456158, + "y": -251.71620079779504, + "z": 0.0 + }, + { + "x": 90.40842015254871, + "y": -252.72518226761883, + "z": 0.0 + }, + { + "x": 90.40857353053586, + "y": -253.7341637374426, + "z": 0.0 + }, + { + "x": 90.40872690852302, + "y": -254.7431452072664, + "z": 0.0 + }, + { + "x": 90.40888028651017, + "y": -255.75212667709016, + "z": 0.0 + }, + { + "x": 90.40903366449731, + "y": -256.76110814691395, + "z": 0.0 + }, + { + "x": 90.40918704248446, + "y": -257.7700896167377, + "z": 0.0 + }, + { + "x": 90.40934042047161, + "y": -258.7790710865615, + "z": 0.0 + }, + { + "x": 90.40949379845877, + "y": -259.7880525563853, + "z": 0.0 + }, + { + "x": 90.40964717644592, + "y": -260.7970340262091, + "z": 0.0 + }, + { + "x": 90.40980055443306, + "y": -261.80601549603284, + "z": 0.0 + }, + { + "x": 90.40995393242021, + "y": -262.8149969658566, + "z": 0.0 + }, + { + "x": 90.41010731040735, + "y": -263.8239784356804, + "z": 0.0 + }, + { + "x": 90.4102606883945, + "y": -264.8329599055042, + "z": 0.0 + }, + { + "x": 90.41041406638165, + "y": -265.84194137532796, + "z": 0.0 + }, + { + "x": 90.41056744436881, + "y": -266.85092284515173, + "z": 0.0 + }, + { + "x": 90.41072082235596, + "y": -267.8599043149755, + "z": 0.0 + }, + { + "x": 90.41087420034309, + "y": -268.8688857847993, + "z": 0.0 + }, + { + "x": 90.41102757833025, + "y": -269.8778672546231, + "z": 0.0 + }, + { + "x": 90.4111809563174, + "y": -270.88684872444685, + "z": 0.0 + }, + { + "x": 90.41133433430454, + "y": -271.8958301942706, + "z": 0.0 + }, + { + "x": 90.41148771229169, + "y": -272.90481166409444, + "z": 0.0 + }, + { + "x": 90.41164109027883, + "y": -273.9137931339182, + "z": 0.0 + }, + { + "x": 90.41179446826598, + "y": -274.92277460374197, + "z": 0.0 + }, + { + "x": 90.41194784625313, + "y": -275.9317560735658, + "z": 0.0 + }, + { + "x": 90.41210122424029, + "y": -276.94073754338956, + "z": 0.0 + }, + { + "x": 90.41225460222743, + "y": -277.9497190132133, + "z": 0.0 + }, + { + "x": 90.41240798021458, + "y": -278.95870048303715, + "z": 0.0 + }, + { + "x": 90.41256135820173, + "y": -279.9676819528609, + "z": 0.0 + }, + { + "x": 90.41271473618887, + "y": -280.9766634226847, + "z": 0.0 + }, + { + "x": 90.41286811417602, + "y": -281.9856448925085, + "z": 0.0 + }, + { + "x": 90.41302149216317, + "y": -282.99462636233227, + "z": 0.0 + }, + { + "x": 90.41317487015033, + "y": -284.00360783215604, + "z": 0.0 + }, + { + "x": 90.41332824813747, + "y": -285.01258930197986, + "z": 0.0 + }, + { + "x": 90.41348162612461, + "y": -286.0215707718036, + "z": 0.0 + }, + { + "x": 90.41363500411177, + "y": -287.0305522416274, + "z": 0.0 + }, + { + "x": 90.41378838209891, + "y": -288.0395337114512, + "z": 0.0 + }, + { + "x": 90.41394176008606, + "y": -289.048515181275, + "z": 0.0 + }, + { + "x": 90.41409513807321, + "y": -290.05749665109875, + "z": 0.0 + }, + { + "x": 90.41424851606035, + "y": -291.06647812092257, + "z": 0.0 + }, + { + "x": 90.41440189404751, + "y": -292.07545959074633, + "z": 0.0 + }, + { + "x": 90.41455527203465, + "y": -293.08444106057016, + "z": 0.0 + }, + { + "x": 90.41470865002181, + "y": -294.0934225303939, + "z": 0.0 + }, + { + "x": 90.41486202800895, + "y": -295.1024040002177, + "z": 0.0 + }, + { + "x": 90.4150154059961, + "y": -296.1113854700415, + "z": 0.0 + }, + { + "x": 90.41516878398325, + "y": -297.1203669398653, + "z": 0.0 + }, + { + "x": 90.4153221619704, + "y": -298.12934840968904, + "z": 0.0 + }, + { + "x": 90.41547553995754, + "y": -299.13832987951287, + "z": 0.0 + }, + { + "x": 90.41562891794469, + "y": -300.14731134933663, + "z": 0.0 + }, + { + "x": 90.41578229593183, + "y": -301.1562928191604, + "z": 0.0 + }, + { + "x": 90.415935673919, + "y": -302.1652742889842, + "z": 0.0 + }, + { + "x": 90.41608905190614, + "y": -303.174255758808, + "z": 0.0 + }, + { + "x": 90.41624242989329, + "y": -304.18323722863175, + "z": 0.0 + }, + { + "x": 90.41639580788043, + "y": -305.1922186984556, + "z": 0.0 + }, + { + "x": 90.41654918586758, + "y": -306.20120016827934, + "z": 0.0 + }, + { + "x": 90.41670256385473, + "y": -307.2101816381031, + "z": 0.0 + }, + { + "x": 90.41685594184187, + "y": -308.21916310792693, + "z": 0.0 + }, + { + "x": 90.41700931982903, + "y": -309.2281445777507, + "z": 0.0 + }, + { + "x": 90.41716269781618, + "y": -310.2371260475745, + "z": 0.0 + }, + { + "x": 90.41731607580333, + "y": -311.2461075173983, + "z": 0.0 + }, + { + "x": 90.41746945379047, + "y": -312.25508898722205, + "z": 0.0 + }, + { + "x": 90.41762283177762, + "y": -313.2640704570459, + "z": 0.0 + }, + { + "x": 90.41777620976477, + "y": -314.27305192686964, + "z": 0.0 + }, + { + "x": 90.41792958775191, + "y": -315.2820333966934, + "z": 0.0 + }, + { + "x": 90.41808296573907, + "y": -316.29101486651723, + "z": 0.0 + }, + { + "x": 90.41823634372622, + "y": -317.299996336341, + "z": 0.0 + } + ] + }, + { + "id": 123, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 92.41823632061836, + "y": -317.299692310965, + "z": 0.0 + }, + { + "x": 92.41808294263122, + "y": -316.2907108411412, + "z": 0.0 + }, + { + "x": 92.41792956464406, + "y": -315.2817293713174, + "z": 0.0 + }, + { + "x": 92.41777618665691, + "y": -314.27274790149363, + "z": 0.0 + }, + { + "x": 92.41762280866976, + "y": -313.26376643166986, + "z": 0.0 + }, + { + "x": 92.41746943068262, + "y": -312.25478496184604, + "z": 0.0 + }, + { + "x": 92.41731605269547, + "y": -311.2458034920223, + "z": 0.0 + }, + { + "x": 92.41716267470832, + "y": -310.2368220221985, + "z": 0.0 + }, + { + "x": 92.41700929672118, + "y": -309.2278405523747, + "z": 0.0 + }, + { + "x": 92.41685591873402, + "y": -308.2188590825509, + "z": 0.0 + }, + { + "x": 92.41670254074687, + "y": -307.2098776127271, + "z": 0.0 + }, + { + "x": 92.41654916275972, + "y": -306.20089614290333, + "z": 0.0 + }, + { + "x": 92.41639578477258, + "y": -305.19191467307957, + "z": 0.0 + }, + { + "x": 92.41624240678543, + "y": -304.18293320325574, + "z": 0.0 + }, + { + "x": 92.41608902879828, + "y": -303.173951733432, + "z": 0.0 + }, + { + "x": 92.41593565081114, + "y": -302.1649702636082, + "z": 0.0 + }, + { + "x": 92.41578227282398, + "y": -301.15598879378433, + "z": 0.0 + }, + { + "x": 92.41562889483683, + "y": -300.1470073239606, + "z": 0.0 + }, + { + "x": 92.41547551684968, + "y": -299.13802585413686, + "z": 0.0 + }, + { + "x": 92.41532213886254, + "y": -298.12904438431303, + "z": 0.0 + }, + { + "x": 92.41516876087539, + "y": -297.12006291448927, + "z": 0.0 + }, + { + "x": 92.41501538288824, + "y": -296.1110814446655, + "z": 0.0 + }, + { + "x": 92.4148620049011, + "y": -295.1020999748417, + "z": 0.0 + }, + { + "x": 92.41470862691395, + "y": -294.0931185050179, + "z": 0.0 + }, + { + "x": 92.41455524892679, + "y": -293.0841370351941, + "z": 0.0 + }, + { + "x": 92.41440187093966, + "y": -292.0751555653703, + "z": 0.0 + }, + { + "x": 92.4142484929525, + "y": -291.06617409554656, + "z": 0.0 + }, + { + "x": 92.41409511496535, + "y": -290.05719262572273, + "z": 0.0 + }, + { + "x": 92.4139417369782, + "y": -289.04821115589897, + "z": 0.0 + }, + { + "x": 92.41378835899106, + "y": -288.0392296860752, + "z": 0.0 + }, + { + "x": 92.41363498100391, + "y": -287.0302482162514, + "z": 0.0 + }, + { + "x": 92.41348160301675, + "y": -286.0212667464276, + "z": 0.0 + }, + { + "x": 92.41332822502962, + "y": -285.01228527660385, + "z": 0.0 + }, + { + "x": 92.41317484704247, + "y": -284.00330380678, + "z": 0.0 + }, + { + "x": 92.41302146905531, + "y": -282.9943223369562, + "z": 0.0 + }, + { + "x": 92.41286809106816, + "y": -281.9853408671325, + "z": 0.0 + }, + { + "x": 92.41271471308102, + "y": -280.97635939730867, + "z": 0.0 + }, + { + "x": 92.41256133509387, + "y": -279.9673779274849, + "z": 0.0 + }, + { + "x": 92.41240795710672, + "y": -278.95839645766114, + "z": 0.0 + }, + { + "x": 92.41225457911958, + "y": -277.9494149878373, + "z": 0.0 + }, + { + "x": 92.41210120113243, + "y": -276.94043351801355, + "z": 0.0 + }, + { + "x": 92.41194782314527, + "y": -275.9314520481897, + "z": 0.0 + }, + { + "x": 92.41179444515812, + "y": -274.92247057836596, + "z": 0.0 + }, + { + "x": 92.41164106717098, + "y": -273.9134891085422, + "z": 0.0 + }, + { + "x": 92.41148768918383, + "y": -272.9045076387184, + "z": 0.0 + }, + { + "x": 92.41133431119668, + "y": -271.8955261688946, + "z": 0.0 + }, + { + "x": 92.41118093320954, + "y": -270.88654469907084, + "z": 0.0 + }, + { + "x": 92.41102755522239, + "y": -269.8775632292471, + "z": 0.0 + }, + { + "x": 92.41087417723523, + "y": -268.86858175942325, + "z": 0.0 + }, + { + "x": 92.4107207992481, + "y": -267.8596002895995, + "z": 0.0 + }, + { + "x": 92.41056742126095, + "y": -266.8506188197757, + "z": 0.0 + }, + { + "x": 92.41041404327379, + "y": -265.84163734995195, + "z": 0.0 + }, + { + "x": 92.41026066528664, + "y": -264.8326558801282, + "z": 0.0 + }, + { + "x": 92.4101072872995, + "y": -263.82367441030436, + "z": 0.0 + }, + { + "x": 92.40995390931235, + "y": -262.8146929404806, + "z": 0.0 + }, + { + "x": 92.4098005313252, + "y": -261.80571147065683, + "z": 0.0 + }, + { + "x": 92.40964715333806, + "y": -260.79673000083307, + "z": 0.0 + }, + { + "x": 92.40949377535091, + "y": -259.7877485310093, + "z": 0.0 + }, + { + "x": 92.40934039736375, + "y": -258.7787670611855, + "z": 0.0 + }, + { + "x": 92.4091870193766, + "y": -257.7697855913617, + "z": 0.0 + }, + { + "x": 92.40903364138946, + "y": -256.76080412153794, + "z": 0.0 + }, + { + "x": 92.40888026340231, + "y": -255.75182265171415, + "z": 0.0 + }, + { + "x": 92.40872688541516, + "y": -254.74284118189038, + "z": 0.0 + }, + { + "x": 92.408573507428, + "y": -253.73385971206656, + "z": 0.0 + }, + { + "x": 92.40842012944086, + "y": -252.72487824224282, + "z": 0.0 + }, + { + "x": 92.40826675145372, + "y": -251.71589677241906, + "z": 0.0 + }, + { + "x": 92.40811337346656, + "y": -250.70691530259523, + "z": 0.0 + }, + { + "x": 92.40795999547942, + "y": -249.6979338327715, + "z": 0.0 + }, + { + "x": 92.40780661749227, + "y": -248.6889523629477, + "z": 0.0 + }, + { + "x": 92.40765323950512, + "y": -247.67997089312394, + "z": 0.0 + }, + { + "x": 92.40749986151796, + "y": -246.6709894233001, + "z": 0.0 + }, + { + "x": 92.40734648353082, + "y": -245.66200795347638, + "z": 0.0 + }, + { + "x": 92.40719310554368, + "y": -244.6530264836526, + "z": 0.0 + }, + { + "x": 92.40703972755652, + "y": -243.6440450138288, + "z": 0.0 + }, + { + "x": 92.40688634956938, + "y": -242.63506354400502, + "z": 0.0 + }, + { + "x": 92.40673297158223, + "y": -241.62608207418126, + "z": 0.0 + }, + { + "x": 92.40657959359508, + "y": -240.61710060435746, + "z": 0.0 + }, + { + "x": 92.40642621560794, + "y": -239.6081191345337, + "z": 0.0 + }, + { + "x": 92.40627283762078, + "y": -238.59913766470987, + "z": 0.0 + }, + { + "x": 92.40611945963364, + "y": -237.59015619488616, + "z": 0.0 + }, + { + "x": 92.40596608164648, + "y": -236.58117472506234, + "z": 0.0 + }, + { + "x": 92.40581270365934, + "y": -235.57219325523857, + "z": 0.0 + }, + { + "x": 92.4056593256722, + "y": -234.56321178541484, + "z": 0.0 + }, + { + "x": 92.40550594768504, + "y": -233.55423031559098, + "z": 0.0 + }, + { + "x": 92.4053525696979, + "y": -232.54524884576725, + "z": 0.0 + }, + { + "x": 92.40519919171075, + "y": -231.53626737594345, + "z": 0.0 + }, + { + "x": 92.4050458137236, + "y": -230.5272859061197, + "z": 0.0 + }, + { + "x": 92.40489243573646, + "y": -229.5183044362959, + "z": 0.0 + }, + { + "x": 92.4047390577493, + "y": -228.5093229664721, + "z": 0.0 + }, + { + "x": 92.40458567976216, + "y": -227.50034149664836, + "z": 0.0 + }, + { + "x": 92.404432301775, + "y": -226.49136002682454, + "z": 0.0 + }, + { + "x": 92.40427892378786, + "y": -225.4823785570008, + "z": 0.0 + }, + { + "x": 92.40412554580071, + "y": -224.473397087177, + "z": 0.0 + }, + { + "x": 92.40397216781356, + "y": -223.46441561735324, + "z": 0.0 + }, + { + "x": 92.40381878982642, + "y": -222.45543414752944, + "z": 0.0 + }, + { + "x": 92.40366541183926, + "y": -221.44645267770565, + "z": 0.0 + }, + { + "x": 92.40351203385212, + "y": -220.4374712078819, + "z": 0.0 + }, + { + "x": 92.40335865586496, + "y": -219.4284897380581, + "z": 0.0 + }, + { + "x": 92.40320527787782, + "y": -218.41950826823432, + "z": 0.0 + }, + { + "x": 92.40305189989067, + "y": -217.41052679841053, + "z": 0.0 + }, + { + "x": 92.40289852190352, + "y": -216.40154532858676, + "z": 0.0 + }, + { + "x": 92.40274514391638, + "y": -215.39256385876297, + "z": 0.0 + }, + { + "x": 92.40259176592922, + "y": -214.38358238893917, + "z": 0.0 + }, + { + "x": 92.40243838794208, + "y": -213.37460091911544, + "z": 0.0 + }, + { + "x": 92.40228500995494, + "y": -212.36561944929164, + "z": 0.0 + }, + { + "x": 92.40213163196778, + "y": -211.35663797946782, + "z": 0.0 + }, + { + "x": 92.40197825398063, + "y": -210.34765650964408, + "z": 0.0 + }, + { + "x": 92.40182487599348, + "y": -209.3386750398203, + "z": 0.0 + }, + { + "x": 92.40167149800634, + "y": -208.32969356999652, + "z": 0.0 + } + ] + }, + { + "id": 124, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 88.40167154422205, + "y": -208.33030162074854, + "z": 0.0 + }, + { + "x": 88.4018249222092, + "y": -209.3392830905723, + "z": 0.0 + }, + { + "x": 88.40197830019635, + "y": -210.3482645603961, + "z": 0.0 + }, + { + "x": 88.4021316781835, + "y": -211.3572460302199, + "z": 0.0 + }, + { + "x": 88.40228505617065, + "y": -212.36622750004366, + "z": 0.0 + }, + { + "x": 88.4024384341578, + "y": -213.3752089698674, + "z": 0.0 + }, + { + "x": 88.40259181214493, + "y": -214.38419043969125, + "z": 0.0 + }, + { + "x": 88.4027451901321, + "y": -215.393171909515, + "z": 0.0 + }, + { + "x": 88.40289856811924, + "y": -216.40215337933878, + "z": 0.0 + }, + { + "x": 88.40305194610639, + "y": -217.41113484916255, + "z": 0.0 + }, + { + "x": 88.40320532409353, + "y": -218.42011631898635, + "z": 0.0 + }, + { + "x": 88.40335870208068, + "y": -219.42909778881017, + "z": 0.0 + }, + { + "x": 88.40351208006784, + "y": -220.43807925863388, + "z": 0.0 + }, + { + "x": 88.40366545805497, + "y": -221.44706072845773, + "z": 0.0 + }, + { + "x": 88.40381883604213, + "y": -222.45604219828147, + "z": 0.0 + }, + { + "x": 88.40397221402928, + "y": -223.46502366810526, + "z": 0.0 + }, + { + "x": 88.40412559201643, + "y": -224.47400513792903, + "z": 0.0 + }, + { + "x": 88.40427897000357, + "y": -225.48298660775282, + "z": 0.0 + }, + { + "x": 88.40443234799072, + "y": -226.49196807757662, + "z": 0.0 + }, + { + "x": 88.40458572597788, + "y": -227.50094954740032, + "z": 0.0 + }, + { + "x": 88.40473910396501, + "y": -228.50993101722418, + "z": 0.0 + }, + { + "x": 88.40489248195217, + "y": -229.5189124870479, + "z": 0.0 + }, + { + "x": 88.40504585993932, + "y": -230.5278939568717, + "z": 0.0 + }, + { + "x": 88.40519923792647, + "y": -231.53687542669547, + "z": 0.0 + }, + { + "x": 88.40535261591361, + "y": -232.54585689651927, + "z": 0.0 + }, + { + "x": 88.40550599390076, + "y": -233.55483836634306, + "z": 0.0 + }, + { + "x": 88.40565937188792, + "y": -234.5638198361668, + "z": 0.0 + }, + { + "x": 88.40581274987505, + "y": -235.5728013059906, + "z": 0.0 + }, + { + "x": 88.4059661278622, + "y": -236.58178277581442, + "z": 0.0 + }, + { + "x": 88.40611950584936, + "y": -237.59076424563813, + "z": 0.0 + }, + { + "x": 88.4062728838365, + "y": -238.59974571546195, + "z": 0.0 + }, + { + "x": 88.40642626182365, + "y": -239.60872718528572, + "z": 0.0 + }, + { + "x": 88.4065796398108, + "y": -240.61770865510948, + "z": 0.0 + }, + { + "x": 88.40673301779795, + "y": -241.62669012493328, + "z": 0.0 + }, + { + "x": 88.4068863957851, + "y": -242.63567159475704, + "z": 0.0 + }, + { + "x": 88.40703977377224, + "y": -243.64465306458087, + "z": 0.0 + }, + { + "x": 88.4071931517594, + "y": -244.65363453440457, + "z": 0.0 + }, + { + "x": 88.40734652974653, + "y": -245.6626160042284, + "z": 0.0 + }, + { + "x": 88.40749990773368, + "y": -246.6715974740522, + "z": 0.0 + }, + { + "x": 88.40765328572084, + "y": -247.68057894387596, + "z": 0.0 + }, + { + "x": 88.40780666370799, + "y": -248.68956041369972, + "z": 0.0 + }, + { + "x": 88.40796004169513, + "y": -249.69854188352352, + "z": 0.0 + }, + { + "x": 88.40811341968228, + "y": -250.7075233533473, + "z": 0.0 + }, + { + "x": 88.40826679766944, + "y": -251.71650482317102, + "z": 0.0 + }, + { + "x": 88.40842017565657, + "y": -252.72548629299484, + "z": 0.0 + }, + { + "x": 88.40857355364372, + "y": -253.73446776281864, + "z": 0.0 + }, + { + "x": 88.40872693163088, + "y": -254.7434492326424, + "z": 0.0 + }, + { + "x": 88.40888030961803, + "y": -255.75243070246617, + "z": 0.0 + }, + { + "x": 88.40903368760517, + "y": -256.76141217228997, + "z": 0.0 + }, + { + "x": 88.40918706559232, + "y": -257.77039364211373, + "z": 0.0 + }, + { + "x": 88.40934044357947, + "y": -258.7793751119375, + "z": 0.0 + }, + { + "x": 88.40949382156663, + "y": -259.7883565817613, + "z": 0.0 + }, + { + "x": 88.40964719955377, + "y": -260.7973380515851, + "z": 0.0 + }, + { + "x": 88.40980057754092, + "y": -261.80631952140885, + "z": 0.0 + }, + { + "x": 88.40995395552807, + "y": -262.8153009912326, + "z": 0.0 + }, + { + "x": 88.41010733351521, + "y": -263.8242824610564, + "z": 0.0 + }, + { + "x": 88.41026071150236, + "y": -264.8332639308802, + "z": 0.0 + }, + { + "x": 88.4104140894895, + "y": -265.842245400704, + "z": 0.0 + }, + { + "x": 88.41056746747667, + "y": -266.85122687052774, + "z": 0.0 + }, + { + "x": 88.41072084546381, + "y": -267.8602083403515, + "z": 0.0 + }, + { + "x": 88.41087422345095, + "y": -268.8691898101754, + "z": 0.0 + }, + { + "x": 88.41102760143811, + "y": -269.8781712799991, + "z": 0.0 + }, + { + "x": 88.41118097942525, + "y": -270.88715274982286, + "z": 0.0 + }, + { + "x": 88.4113343574124, + "y": -271.8961342196466, + "z": 0.0 + }, + { + "x": 88.41148773539955, + "y": -272.90511568947045, + "z": 0.0 + }, + { + "x": 88.4116411133867, + "y": -273.9140971592942, + "z": 0.0 + }, + { + "x": 88.41179449137384, + "y": -274.923078629118, + "z": 0.0 + }, + { + "x": 88.41194786936099, + "y": -275.93206009894186, + "z": 0.0 + }, + { + "x": 88.41210124734815, + "y": -276.94104156876557, + "z": 0.0 + }, + { + "x": 88.4122546253353, + "y": -277.95002303858934, + "z": 0.0 + }, + { + "x": 88.41240800332244, + "y": -278.95900450841316, + "z": 0.0 + }, + { + "x": 88.41256138130959, + "y": -279.9679859782369, + "z": 0.0 + }, + { + "x": 88.41271475929673, + "y": -280.9769674480607, + "z": 0.0 + }, + { + "x": 88.41286813728388, + "y": -281.9859489178845, + "z": 0.0 + }, + { + "x": 88.41302151527103, + "y": -282.99493038770834, + "z": 0.0 + }, + { + "x": 88.41317489325819, + "y": -284.00391185753205, + "z": 0.0 + }, + { + "x": 88.41332827124533, + "y": -285.01289332735587, + "z": 0.0 + }, + { + "x": 88.41348164923247, + "y": -286.02187479717963, + "z": 0.0 + }, + { + "x": 88.41363502721963, + "y": -287.0308562670034, + "z": 0.0 + }, + { + "x": 88.41378840520677, + "y": -288.0398377368272, + "z": 0.0 + }, + { + "x": 88.41394178319392, + "y": -289.048819206651, + "z": 0.0 + }, + { + "x": 88.41409516118107, + "y": -290.05780067647476, + "z": 0.0 + }, + { + "x": 88.41424853916821, + "y": -291.0667821462986, + "z": 0.0 + }, + { + "x": 88.41440191715537, + "y": -292.07576361612234, + "z": 0.0 + }, + { + "x": 88.4145552951425, + "y": -293.0847450859462, + "z": 0.0 + }, + { + "x": 88.41470867312967, + "y": -294.09372655576993, + "z": 0.0 + }, + { + "x": 88.41486205111681, + "y": -295.1027080255937, + "z": 0.0 + }, + { + "x": 88.41501542910396, + "y": -296.1116894954175, + "z": 0.0 + }, + { + "x": 88.4151688070911, + "y": -297.1206709652413, + "z": 0.0 + }, + { + "x": 88.41532218507825, + "y": -298.12965243506505, + "z": 0.0 + }, + { + "x": 88.4154755630654, + "y": -299.1386339048889, + "z": 0.0 + }, + { + "x": 88.41562894105255, + "y": -300.14761537471264, + "z": 0.0 + }, + { + "x": 88.41578231903969, + "y": -301.15659684453647, + "z": 0.0 + }, + { + "x": 88.41593569702685, + "y": -302.16557831436023, + "z": 0.0 + }, + { + "x": 88.416089075014, + "y": -303.174559784184, + "z": 0.0 + }, + { + "x": 88.41624245300115, + "y": -304.18354125400776, + "z": 0.0 + }, + { + "x": 88.4163958309883, + "y": -305.1925227238316, + "z": 0.0 + }, + { + "x": 88.41654920897544, + "y": -306.20150419365535, + "z": 0.0 + }, + { + "x": 88.41670258696259, + "y": -307.2104856634791, + "z": 0.0 + }, + { + "x": 88.41685596494973, + "y": -308.21946713330294, + "z": 0.0 + }, + { + "x": 88.4170093429369, + "y": -309.2284486031267, + "z": 0.0 + }, + { + "x": 88.41716272092404, + "y": -310.23743007295053, + "z": 0.0 + }, + { + "x": 88.41731609891119, + "y": -311.2464115427743, + "z": 0.0 + }, + { + "x": 88.41746947689833, + "y": -312.25539301259806, + "z": 0.0 + }, + { + "x": 88.41762285488548, + "y": -313.2643744824219, + "z": 0.0 + }, + { + "x": 88.41777623287263, + "y": -314.27335595224565, + "z": 0.0 + }, + { + "x": 88.41792961085977, + "y": -315.2823374220694, + "z": 0.0 + }, + { + "x": 88.41808298884693, + "y": -316.29131889189324, + "z": 0.0 + }, + { + "x": 88.41823636683408, + "y": -317.300300361717, + "z": 0.0 + } + ] + }, + { + "id": 125, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 160.02380355703423, + "y": -46.204824954497035, + "z": 0.0 + }, + { + "x": 160.02506048809644, + "y": -45.17011983558629, + "z": 0.0 + }, + { + "x": 160.02631741915866, + "y": -44.135414716675555, + "z": 0.0 + }, + { + "x": 160.02757435022087, + "y": -43.10070959776482, + "z": 0.0 + }, + { + "x": 160.02883128128312, + "y": -42.06600447885419, + "z": 0.0 + }, + { + "x": 160.03008821234533, + "y": -41.03129935994334, + "z": 0.0 + }, + { + "x": 160.03134514340755, + "y": -39.996594241032604, + "z": 0.0 + }, + { + "x": 160.03260207446976, + "y": -38.96188912212187, + "z": 0.0 + }, + { + "x": 160.03385900553198, + "y": -37.927184003211124, + "z": 0.0 + }, + { + "x": 160.0351159365942, + "y": -36.89247888430038, + "z": 0.0 + }, + { + "x": 160.0363728676564, + "y": -35.857773765389645, + "z": 0.0 + }, + { + "x": 160.03762979871863, + "y": -34.82306864647891, + "z": 0.0 + }, + { + "x": 160.03888672978084, + "y": -33.78836352756817, + "z": 0.0 + }, + { + "x": 160.04014366084309, + "y": -32.75365840865754, + "z": 0.0 + }, + { + "x": 160.0414005919053, + "y": -31.7189532897467, + "z": 0.0 + }, + { + "x": 160.04265752296752, + "y": -30.68424817083596, + "z": 0.0 + }, + { + "x": 160.04391445402973, + "y": -29.649543051925225, + "z": 0.0 + }, + { + "x": 160.04517138509195, + "y": -28.61483793301449, + "z": 0.0 + }, + { + "x": 160.04642831615416, + "y": -27.580132814103752, + "z": 0.0 + }, + { + "x": 160.04768524721638, + "y": -26.545427695193016, + "z": 0.0 + }, + { + "x": 160.0489421782786, + "y": -25.51072257628228, + "z": 0.0 + }, + { + "x": 160.05019910934084, + "y": -24.476017457371654, + "z": 0.0 + }, + { + "x": 160.05145604040305, + "y": -23.441312338460804, + "z": 0.0 + }, + { + "x": 160.05271297146527, + "y": -22.406607219550068, + "z": 0.0 + }, + { + "x": 160.05396990252748, + "y": -21.371902100639332, + "z": 0.0 + }, + { + "x": 160.0552268335897, + "y": -20.337196981728592, + "z": 0.0 + }, + { + "x": 160.05648376465192, + "y": -19.302491862817856, + "z": 0.0 + }, + { + "x": 160.05774069571413, + "y": -18.26778674390712, + "z": 0.0 + }, + { + "x": 160.05899762677635, + "y": -17.233081624996384, + "z": 0.0 + }, + { + "x": 160.06025455783856, + "y": -16.198376506085648, + "z": 0.0 + }, + { + "x": 160.0615114889008, + "y": -15.16367138717502, + "z": 0.0 + }, + { + "x": 160.06276841996302, + "y": -14.128966268264172, + "z": 0.0 + }, + { + "x": 160.06402535102524, + "y": -13.094261149353436, + "z": 0.0 + }, + { + "x": 160.06528228208745, + "y": -12.059556030442698, + "z": 0.0 + }, + { + "x": 160.06653921314967, + "y": -11.024850911531962, + "z": 0.0 + } + ] + }, + { + "id": 126, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 152.06654511582957, + "y": -11.015132740726886, + "z": 0.0 + }, + { + "x": 152.06528818476735, + "y": -12.049837859637622, + "z": 0.0 + }, + { + "x": 152.06403125370514, + "y": -13.08454297854836, + "z": 0.0 + }, + { + "x": 152.06277432264292, + "y": -14.119248097459096, + "z": 0.0 + }, + { + "x": 152.0615173915807, + "y": -15.153953216369723, + "z": 0.0 + }, + { + "x": 152.06026046051846, + "y": -16.188658335280568, + "z": 0.0 + }, + { + "x": 152.05900352945625, + "y": -17.223363454191304, + "z": 0.0 + }, + { + "x": 152.05774659839403, + "y": -18.25806857310204, + "z": 0.0 + }, + { + "x": 152.05648966733182, + "y": -19.292773692012776, + "z": 0.0 + }, + { + "x": 152.0552327362696, + "y": -20.327478810923512, + "z": 0.0 + }, + { + "x": 152.0539758052074, + "y": -21.362183929834252, + "z": 0.0 + }, + { + "x": 152.05271887414517, + "y": -22.39688904874499, + "z": 0.0 + }, + { + "x": 152.05146194308296, + "y": -23.431594167655724, + "z": 0.0 + }, + { + "x": 152.05020501202074, + "y": -24.466299286566354, + "z": 0.0 + }, + { + "x": 152.0489480809585, + "y": -25.5010044054772, + "z": 0.0 + }, + { + "x": 152.04769114989628, + "y": -26.535709524387936, + "z": 0.0 + }, + { + "x": 152.04643421883407, + "y": -27.570414643298673, + "z": 0.0 + }, + { + "x": 152.04517728777185, + "y": -28.60511976220941, + "z": 0.0 + }, + { + "x": 152.04392035670963, + "y": -29.639824881120145, + "z": 0.0 + }, + { + "x": 152.04266342564742, + "y": -30.67453000003088, + "z": 0.0 + }, + { + "x": 152.0414064945852, + "y": -31.70923511894162, + "z": 0.0 + }, + { + "x": 152.040149563523, + "y": -32.74394023785224, + "z": 0.0 + }, + { + "x": 152.03889263246074, + "y": -33.7786453567631, + "z": 0.0 + }, + { + "x": 152.03763570139853, + "y": -34.813350475673836, + "z": 0.0 + }, + { + "x": 152.0363787703363, + "y": -35.84805559458457, + "z": 0.0 + }, + { + "x": 152.0351218392741, + "y": -36.88276071349531, + "z": 0.0 + }, + { + "x": 152.03386490821188, + "y": -37.91746583240605, + "z": 0.0 + }, + { + "x": 152.03260797714967, + "y": -38.952170951316795, + "z": 0.0 + }, + { + "x": 152.03135104608745, + "y": -39.98687607022753, + "z": 0.0 + }, + { + "x": 152.03009411502524, + "y": -41.02158118913827, + "z": 0.0 + }, + { + "x": 152.02883718396302, + "y": -42.05628630804889, + "z": 0.0 + }, + { + "x": 152.02758025290078, + "y": -43.09099142695975, + "z": 0.0 + }, + { + "x": 152.02632332183856, + "y": -44.12569654587048, + "z": 0.0 + }, + { + "x": 152.02506639077635, + "y": -45.16040166478122, + "z": 0.0 + }, + { + "x": 152.02380945971413, + "y": -46.19510678369196, + "z": 0.0 + } + ] + }, + { + "id": 127, + "map_element_id": 6, + "type": "road_line", + "geometry": [ + { + "x": 156.06654216448962, + "y": -11.019991826129424, + "z": 0.0 + }, + { + "x": 156.0652852334274, + "y": -12.05469694504016, + "z": 0.0 + }, + { + "x": 156.0640283023652, + "y": -13.089402063950898, + "z": 0.0 + }, + { + "x": 156.06277137130297, + "y": -14.124107182861634, + "z": 0.0 + }, + { + "x": 156.06151444024076, + "y": -15.158812301772372, + "z": 0.0 + }, + { + "x": 156.0602575091785, + "y": -16.193517420683108, + "z": 0.0 + }, + { + "x": 156.0590005781163, + "y": -17.228222539593844, + "z": 0.0 + }, + { + "x": 156.05774364705408, + "y": -18.26292765850458, + "z": 0.0 + }, + { + "x": 156.05648671599187, + "y": -19.297632777415316, + "z": 0.0 + }, + { + "x": 156.05522978492965, + "y": -20.332337896326052, + "z": 0.0 + }, + { + "x": 156.05397285386744, + "y": -21.367043015236792, + "z": 0.0 + }, + { + "x": 156.05271592280522, + "y": -22.401748134147528, + "z": 0.0 + }, + { + "x": 156.051458991743, + "y": -23.436453253058264, + "z": 0.0 + }, + { + "x": 156.0502020606808, + "y": -24.471158371969004, + "z": 0.0 + }, + { + "x": 156.04894512961855, + "y": -25.50586349087974, + "z": 0.0 + }, + { + "x": 156.04768819855633, + "y": -26.540568609790476, + "z": 0.0 + }, + { + "x": 156.0464312674941, + "y": -27.575273728701212, + "z": 0.0 + }, + { + "x": 156.0451743364319, + "y": -28.60997884761195, + "z": 0.0 + }, + { + "x": 156.04391740536968, + "y": -29.644683966522685, + "z": 0.0 + }, + { + "x": 156.04266047430747, + "y": -30.67938908543342, + "z": 0.0 + }, + { + "x": 156.04140354324525, + "y": -31.71409420434416, + "z": 0.0 + }, + { + "x": 156.04014661218304, + "y": -32.74879932325489, + "z": 0.0 + }, + { + "x": 156.0388896811208, + "y": -33.783504442165636, + "z": 0.0 + }, + { + "x": 156.03763275005858, + "y": -34.81820956107637, + "z": 0.0 + }, + { + "x": 156.03637581899636, + "y": -35.85291467998711, + "z": 0.0 + }, + { + "x": 156.03511888793415, + "y": -36.887619798897845, + "z": 0.0 + }, + { + "x": 156.03386195687193, + "y": -37.92232491780859, + "z": 0.0 + }, + { + "x": 156.03260502580972, + "y": -38.95703003671933, + "z": 0.0 + }, + { + "x": 156.0313480947475, + "y": -39.99173515563007, + "z": 0.0 + }, + { + "x": 156.03009116368528, + "y": -41.0264402745408, + "z": 0.0 + }, + { + "x": 156.02883423262307, + "y": -42.06114539345154, + "z": 0.0 + }, + { + "x": 156.02757730156083, + "y": -43.09585051236228, + "z": 0.0 + }, + { + "x": 156.0263203704986, + "y": -44.13055563127302, + "z": 0.0 + }, + { + "x": 156.0250634394364, + "y": -45.165260750183755, + "z": 0.0 + }, + { + "x": 156.02380650837418, + "y": -46.1999658690945, + "z": 0.0 + } + ] + }, + { + "id": 128, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 158.02380503270422, + "y": -46.20239541179576, + "z": 0.0 + }, + { + "x": 158.0250619637664, + "y": -45.16769029288503, + "z": 0.0 + }, + { + "x": 158.02631889482865, + "y": -44.13298517397429, + "z": 0.0 + }, + { + "x": 158.02757582589084, + "y": -43.098280055063555, + "z": 0.0 + }, + { + "x": 158.02883275695308, + "y": -42.06357493615286, + "z": 0.0 + }, + { + "x": 158.03008968801532, + "y": -41.02886981724207, + "z": 0.0 + }, + { + "x": 158.0313466190775, + "y": -39.99416469833133, + "z": 0.0 + }, + { + "x": 158.03260355013975, + "y": -38.959459579420596, + "z": 0.0 + }, + { + "x": 158.03386048120194, + "y": -37.92475446050986, + "z": 0.0 + }, + { + "x": 158.03511741226419, + "y": -36.89004934159911, + "z": 0.0 + }, + { + "x": 158.03637434332637, + "y": -35.85534422268837, + "z": 0.0 + }, + { + "x": 158.03763127438862, + "y": -34.82063910377764, + "z": 0.0 + }, + { + "x": 158.0388882054508, + "y": -33.7859339848669, + "z": 0.0 + }, + { + "x": 158.04014513651305, + "y": -32.75122886595622, + "z": 0.0 + }, + { + "x": 158.0414020675753, + "y": -31.71652374704543, + "z": 0.0 + }, + { + "x": 158.04265899863748, + "y": -30.681818628134693, + "z": 0.0 + }, + { + "x": 158.04391592969972, + "y": -29.647113509223956, + "z": 0.0 + }, + { + "x": 158.0451728607619, + "y": -28.61240839031322, + "z": 0.0 + }, + { + "x": 158.04642979182415, + "y": -27.577703271402484, + "z": 0.0 + }, + { + "x": 158.04768672288634, + "y": -26.542998152491748, + "z": 0.0 + }, + { + "x": 158.04894365394858, + "y": -25.508293033581012, + "z": 0.0 + }, + { + "x": 158.05020058501083, + "y": -24.47358791467033, + "z": 0.0 + }, + { + "x": 158.05145751607301, + "y": -23.438882795759532, + "z": 0.0 + }, + { + "x": 158.05271444713526, + "y": -22.404177676848796, + "z": 0.0 + }, + { + "x": 158.05397137819745, + "y": -21.36947255793806, + "z": 0.0 + }, + { + "x": 158.0552283092597, + "y": -20.334767439027324, + "z": 0.0 + }, + { + "x": 158.05648524032188, + "y": -19.300062320116588, + "z": 0.0 + }, + { + "x": 158.05774217138412, + "y": -18.265357201205852, + "z": 0.0 + }, + { + "x": 158.0589991024463, + "y": -17.230652082295116, + "z": 0.0 + }, + { + "x": 158.06025603350855, + "y": -16.19594696338438, + "z": 0.0 + }, + { + "x": 158.0615129645708, + "y": -15.161241844473697, + "z": 0.0 + }, + { + "x": 158.06276989563298, + "y": -14.126536725562904, + "z": 0.0 + }, + { + "x": 158.06402682669523, + "y": -13.091831606652168, + "z": 0.0 + }, + { + "x": 158.0652837577574, + "y": -12.057126487741428, + "z": 0.0 + }, + { + "x": 158.06654068881966, + "y": -11.022421368830692, + "z": 0.0 + } + ] + }, + { + "id": 129, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 154.06654364015958, + "y": -11.017562283428155, + "z": 0.0 + }, + { + "x": 154.0652867090974, + "y": -12.052267402338892, + "z": 0.0 + }, + { + "x": 154.06402977803515, + "y": -13.086972521249628, + "z": 0.0 + }, + { + "x": 154.06277284697296, + "y": -14.121677640160364, + "z": 0.0 + }, + { + "x": 154.06151591591072, + "y": -15.156382759071047, + "z": 0.0 + }, + { + "x": 154.06025898484847, + "y": -16.191087877981836, + "z": 0.0 + }, + { + "x": 154.0590020537863, + "y": -17.225792996892572, + "z": 0.0 + }, + { + "x": 154.05774512272404, + "y": -18.26049811580331, + "z": 0.0 + }, + { + "x": 154.05648819166186, + "y": -19.295203234714045, + "z": 0.0 + }, + { + "x": 154.0552312605996, + "y": -20.32990835362478, + "z": 0.0 + }, + { + "x": 154.05397432953743, + "y": -21.364613472535524, + "z": 0.0 + }, + { + "x": 154.05271739847518, + "y": -22.39931859144626, + "z": 0.0 + }, + { + "x": 154.051460467413, + "y": -23.434023710356996, + "z": 0.0 + }, + { + "x": 154.05020353635075, + "y": -24.46872882926768, + "z": 0.0 + }, + { + "x": 154.0489466052885, + "y": -25.50343394817847, + "z": 0.0 + }, + { + "x": 154.04768967422632, + "y": -26.538139067089205, + "z": 0.0 + }, + { + "x": 154.04643274316408, + "y": -27.57284418599994, + "z": 0.0 + }, + { + "x": 154.0451758121019, + "y": -28.607549304910677, + "z": 0.0 + }, + { + "x": 154.04391888103964, + "y": -29.642254423821413, + "z": 0.0 + }, + { + "x": 154.04266194997746, + "y": -30.67695954273215, + "z": 0.0 + }, + { + "x": 154.0414050189152, + "y": -31.711664661642892, + "z": 0.0 + }, + { + "x": 154.04014808785303, + "y": -32.746369780553565, + "z": 0.0 + }, + { + "x": 154.03889115679078, + "y": -33.78107489946437, + "z": 0.0 + }, + { + "x": 154.03763422572854, + "y": -34.81578001837511, + "z": 0.0 + }, + { + "x": 154.03637729466635, + "y": -35.850485137285844, + "z": 0.0 + }, + { + "x": 154.0351203636041, + "y": -36.88519025619658, + "z": 0.0 + }, + { + "x": 154.03386343254192, + "y": -37.919895375107316, + "z": 0.0 + }, + { + "x": 154.03260650147968, + "y": -38.95460049401807, + "z": 0.0 + }, + { + "x": 154.0313495704175, + "y": -39.9893056129288, + "z": 0.0 + }, + { + "x": 154.03009263935525, + "y": -41.02401073183954, + "z": 0.0 + }, + { + "x": 154.02883570829306, + "y": -42.05871585075022, + "z": 0.0 + }, + { + "x": 154.02757877723081, + "y": -43.09342096966101, + "z": 0.0 + }, + { + "x": 154.02632184616857, + "y": -44.12812608857175, + "z": 0.0 + }, + { + "x": 154.02506491510638, + "y": -45.16283120748248, + "z": 0.0 + }, + { + "x": 154.02380798404414, + "y": -46.197536326393234, + "z": 0.0 + } + ] + }, + { + "id": 132, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.6289421841928, + "y": -1.9886780038783365, + "z": 0.0 + }, + { + "x": 326.6656086716041, + "y": -1.9892287191981524, + "z": 0.0 + }, + { + "x": 327.7022751590154, + "y": -1.9897794345179682, + "z": 0.0 + }, + { + "x": 328.7389416464267, + "y": -1.9903301498377841, + "z": 0.0 + }, + { + "x": 329.6481209673265, + "y": -2.051642925567623, + "z": 0.0 + }, + { + "x": 330.4498985439327, + "y": -2.203155677126415, + "z": 0.0 + }, + { + "x": 331.1978530249937, + "y": -2.4472767584409145, + "z": 0.0 + }, + { + "x": 331.91071142888325, + "y": -2.782292263691531, + "z": 0.0 + }, + { + "x": 332.5781554916712, + "y": -3.2037777983596696, + "z": 0.0 + }, + { + "x": 333.1259408932245, + "y": -3.691726022653432, + "z": 0.0 + }, + { + "x": 333.6427405093016, + "y": -4.274703225647427, + "z": 0.0 + }, + { + "x": 334.0803469879803, + "y": -4.918202194072655, + "z": 0.0 + }, + { + "x": 334.43130677011334, + "y": -5.611689089596034, + "z": 0.0 + }, + { + "x": 334.6907444176936, + "y": -6.345222294572525, + "z": 0.0 + }, + { + "x": 334.85430406670866, + "y": -7.107636665231244, + "z": 0.0 + }, + { + "x": 334.8887622144692, + "y": -7.838413889011973, + "z": 0.0 + }, + { + "x": 334.89479441876426, + "y": -8.739828728813038, + "z": 0.0 + }, + { + "x": 334.8940308483802, + "y": -9.751811845644003, + "z": 0.0 + }, + { + "x": 334.8934046904095, + "y": -10.788478290232261, + "z": 0.0 + } + ] + }, + { + "id": 135, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 338.8934037724806, + "y": -10.791206034385668, + "z": 0.0 + }, + { + "x": 338.89405960289776, + "y": -9.705413920194768, + "z": 0.0 + }, + { + "x": 338.8947154333149, + "y": -8.619621806003762, + "z": 0.0 + }, + { + "x": 338.85649157978924, + "y": -7.465933222116847, + "z": 0.0 + }, + { + "x": 338.71233106740794, + "y": -6.217633808411568, + "z": 0.0 + }, + { + "x": 338.3765877565555, + "y": -4.891298316001286, + "z": 0.0 + }, + { + "x": 337.798941246716, + "y": -3.5812481318554616, + "z": 0.0 + }, + { + "x": 337.0732723618795, + "y": -2.428622935502248, + "z": 0.0 + }, + { + "x": 336.19506370583065, + "y": -1.3895071817883942, + "z": 0.0 + }, + { + "x": 335.1955535115176, + "y": -0.4858140473350383, + "z": 0.0 + }, + { + "x": 334.1183015498897, + "y": 0.27518596346270763, + "z": 0.0 + }, + { + "x": 332.9558134017866, + "y": 0.9052869162020982, + "z": 0.0 + }, + { + "x": 331.70985610521825, + "y": 1.390851007829021, + "z": 0.0 + }, + { + "x": 330.4587621046933, + "y": 1.7266710094051807, + "z": 0.0 + }, + { + "x": 329.17953238403936, + "y": 1.928092642384523, + "z": 0.0 + }, + { + "x": 327.9131502261558, + "y": 2.007072758973851, + "z": 0.0 + }, + { + "x": 326.71719543516656, + "y": 2.0107444404429113, + "z": 0.0 + }, + { + "x": 325.6314032761233, + "y": 2.0113212531241174, + "z": 0.0 + } + ] + }, + { + "id": 136, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 348.23212641515147, + "y": 3.9993152009727924, + "z": 0.0 + }, + { + "x": 347.2048538328333, + "y": 3.9998609259051396, + "z": 0.0 + }, + { + "x": 346.1775812505151, + "y": 4.000406650837487, + "z": 0.0 + }, + { + "x": 345.15030866819694, + "y": 4.0009523757698355, + "z": 0.0 + }, + { + "x": 344.12303608587877, + "y": 4.001498100702182, + "z": 0.0 + }, + { + "x": 343.0957635035606, + "y": 4.002043825634529, + "z": 0.0 + }, + { + "x": 342.0684909212424, + "y": 4.002589550566876, + "z": 0.0 + }, + { + "x": 341.04121833892424, + "y": 4.003135275499223, + "z": 0.0 + }, + { + "x": 340.01394575660606, + "y": 4.00368100043157, + "z": 0.0 + }, + { + "x": 338.9866731742879, + "y": 4.0042267253639166, + "z": 0.0 + }, + { + "x": 337.9594005919697, + "y": 4.004772450296263, + "z": 0.0 + }, + { + "x": 336.9321280096516, + "y": 4.005318175228612, + "z": 0.0 + }, + { + "x": 335.9048554273334, + "y": 4.005863900160959, + "z": 0.0 + }, + { + "x": 334.87758284501524, + "y": 4.006409625093306, + "z": 0.0 + }, + { + "x": 333.85031026269706, + "y": 4.0069553500256525, + "z": 0.0 + }, + { + "x": 332.8230376803789, + "y": 4.007501074957999, + "z": 0.0 + }, + { + "x": 331.7957650980607, + "y": 4.008046799890346, + "z": 0.0 + }, + { + "x": 330.76849251574254, + "y": 4.008592524822693, + "z": 0.0 + }, + { + "x": 329.74121993342436, + "y": 4.00913824975504, + "z": 0.0 + }, + { + "x": 328.7139473511062, + "y": 4.009683974687387, + "z": 0.0 + }, + { + "x": 327.686674768788, + "y": 4.010229699619733, + "z": 0.0 + }, + { + "x": 326.65940218646983, + "y": 4.0107754245520795, + "z": 0.0 + }, + { + "x": 325.63212960415166, + "y": 4.011321149484425, + "z": 0.0 + } + ] + }, + { + "id": 138, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 348.23106394183185, + "y": 1.9993154831852011, + "z": 0.0 + }, + { + "x": 347.2037913595137, + "y": 1.9998612081175484, + "z": 0.0 + }, + { + "x": 346.1765187771955, + "y": 2.0004069330498955, + "z": 0.0 + }, + { + "x": 345.1492461948773, + "y": 2.0009526579822445, + "z": 0.0 + }, + { + "x": 344.12197361255915, + "y": 2.0014983829145914, + "z": 0.0 + }, + { + "x": 343.09470103024097, + "y": 2.002044107846938, + "z": 0.0 + }, + { + "x": 342.0674284479228, + "y": 2.002589832779285, + "z": 0.0 + }, + { + "x": 341.0401558656046, + "y": 2.003135557711632, + "z": 0.0 + }, + { + "x": 340.01288328328644, + "y": 2.0036812826439783, + "z": 0.0 + }, + { + "x": 338.98561070096827, + "y": 2.004227007576325, + "z": 0.0 + }, + { + "x": 337.9583381186501, + "y": 2.004772732508672, + "z": 0.0 + }, + { + "x": 336.93106553633197, + "y": 2.005318457441021, + "z": 0.0 + }, + { + "x": 335.9037929540138, + "y": 2.0058641823733674, + "z": 0.0 + }, + { + "x": 334.8765203716956, + "y": 2.0064099073057142, + "z": 0.0 + }, + { + "x": 333.84924778937744, + "y": 2.006955632238061, + "z": 0.0 + }, + { + "x": 332.82197520705927, + "y": 2.007501357170408, + "z": 0.0 + }, + { + "x": 331.7947026247411, + "y": 2.0080470821027547, + "z": 0.0 + }, + { + "x": 330.7674300424229, + "y": 2.0085928070351016, + "z": 0.0 + }, + { + "x": 329.74015746010474, + "y": 2.0091385319674484, + "z": 0.0 + }, + { + "x": 328.71288487778656, + "y": 2.0096842568997952, + "z": 0.0 + }, + { + "x": 327.6856122954684, + "y": 2.0102299818321416, + "z": 0.0 + }, + { + "x": 326.6583397131502, + "y": 2.010775706764488, + "z": 0.0 + }, + { + "x": 325.63106713083204, + "y": 2.0113214316968344, + "z": 0.0 + } + ] + }, + { + "id": 141, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.6289421841928, + "y": -1.9886780038783478, + "z": 0.0 + }, + { + "x": 326.65621476651097, + "y": -1.9892237288106946, + "z": 0.0 + }, + { + "x": 327.68348734882915, + "y": -1.9897694537430406, + "z": 0.0 + }, + { + "x": 328.7107599311473, + "y": -1.9903151786753874, + "z": 0.0 + }, + { + "x": 329.7380325134655, + "y": -1.9908609036077343, + "z": 0.0 + }, + { + "x": 330.7653050957837, + "y": -1.991406628540081, + "z": 0.0 + }, + { + "x": 331.79257767810185, + "y": -1.991952353472428, + "z": 0.0 + }, + { + "x": 332.81985026042, + "y": -1.9924980784047743, + "z": 0.0 + }, + { + "x": 333.8471228427382, + "y": -1.9930438033371212, + "z": 0.0 + }, + { + "x": 334.8743954250564, + "y": -1.993589528269468, + "z": 0.0 + }, + { + "x": 335.90166800737455, + "y": -1.9941352532018148, + "z": 0.0 + }, + { + "x": 336.92894058969273, + "y": -1.9946809781341617, + "z": 0.0 + }, + { + "x": 337.95621317201085, + "y": -1.9952267030665103, + "z": 0.0 + }, + { + "x": 338.983485754329, + "y": -1.9957724279988571, + "z": 0.0 + }, + { + "x": 340.0107583366472, + "y": -1.996318152931204, + "z": 0.0 + }, + { + "x": 341.0380309189654, + "y": -1.9968638778635508, + "z": 0.0 + }, + { + "x": 342.06530350128355, + "y": -1.9974096027958976, + "z": 0.0 + }, + { + "x": 343.0925760836017, + "y": -1.9979553277282445, + "z": 0.0 + }, + { + "x": 344.1198486659199, + "y": -1.9985010526605913, + "z": 0.0 + }, + { + "x": 345.1471212482381, + "y": -1.9990467775929377, + "z": 0.0 + }, + { + "x": 346.17439383055626, + "y": -1.9995925025252872, + "z": 0.0 + }, + { + "x": 347.20166641287443, + "y": -2.000138227457634, + "z": 0.0 + }, + { + "x": 348.2289389951926, + "y": -2.000683952389981, + "z": 0.0 + } + ] + }, + { + "id": 144, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 348.23106394183185, + "y": 1.9993154831852011, + "z": 0.0 + }, + { + "x": 347.1918410730398, + "y": 1.9998675565487212, + "z": 0.0 + }, + { + "x": 346.15261820424786, + "y": 2.000419629912234, + "z": 0.0 + }, + { + "x": 344.98014390717617, + "y": 1.9965987241811827, + "z": 0.0 + }, + { + "x": 343.7230281627808, + "y": 1.9009683922471656, + "z": 0.0 + }, + { + "x": 342.47012348855634, + "y": 1.6620026224745803, + "z": 0.0 + }, + { + "x": 341.2550498957666, + "y": 1.2752840500252611, + "z": 0.0 + }, + { + "x": 340.09415370705904, + "y": 0.7459549510153185, + "z": 0.0 + }, + { + "x": 338.97008553424934, + "y": 0.0547038951790324, + "z": 0.0 + }, + { + "x": 337.9618192359494, + "y": -0.7794300190888428, + "z": 0.0 + }, + { + "x": 337.0809376728373, + "y": -1.7338534646852155, + "z": 0.0 + }, + { + "x": 336.3322477308536, + "y": -2.7953125992055945, + "z": 0.0 + }, + { + "x": 335.729628727284, + "y": -3.9456065362702066, + "z": 0.0 + }, + { + "x": 335.2830505480407, + "y": -5.165868569711307, + "z": 0.0 + }, + { + "x": 334.9969996904255, + "y": -6.47215966779638, + "z": 0.0 + }, + { + "x": 334.9048119411275, + "y": -7.653043324408491, + "z": 0.0 + }, + { + "x": 334.89466009567434, + "y": -8.710030720693538, + "z": 0.0 + }, + { + "x": 334.89403239362105, + "y": -9.749253546557007, + "z": 0.0 + }, + { + "x": 334.89340469156787, + "y": -10.788476372420362, + "z": 0.0 + } + ] + }, + { + "id": 147, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 338.8934037724806, + "y": -10.791206034385581, + "z": 0.0 + }, + { + "x": 338.8940361484256, + "y": -9.7442451184274, + "z": 0.0 + }, + { + "x": 338.89466852437056, + "y": -8.697284202469334, + "z": 0.0 + }, + { + "x": 338.89530090031553, + "y": -7.650323286511048, + "z": 0.0 + }, + { + "x": 338.9559455676802, + "y": -6.729071264869208, + "z": 0.0 + }, + { + "x": 339.0867936424396, + "y": -5.853662244728881, + "z": 0.0 + }, + { + "x": 339.34005866146424, + "y": -5.243106847878202, + "z": 0.0 + }, + { + "x": 339.70660160297115, + "y": -4.618405976128673, + "z": 0.0 + }, + { + "x": 340.17828589458026, + "y": -3.994347784720262, + "z": 0.0 + }, + { + "x": 340.7131255868176, + "y": -3.4921935668140875, + "z": 0.0 + }, + { + "x": 341.31833084755374, + "y": -3.081911018620925, + "z": 0.0 + }, + { + "x": 342.03155256917285, + "y": -2.6966663594310103, + "z": 0.0 + }, + { + "x": 342.7922949514217, + "y": -2.3886302465492624, + "z": 0.0 + }, + { + "x": 343.58289861139315, + "y": -2.167658509517684, + "z": 0.0 + }, + { + "x": 344.39393511088724, + "y": -2.036496984348239, + "z": 0.0 + }, + { + "x": 345.2195099685739, + "y": -1.9947606781298046, + "z": 0.0 + }, + { + "x": 346.13501707677966, + "y": -1.9995715841471782, + "z": 0.0 + }, + { + "x": 347.1819780359861, + "y": -2.000127768268577, + "z": 0.0 + }, + { + "x": 348.2289389951926, + "y": -2.000683952389981, + "z": 0.0 + } + ] + }, + { + "id": 150, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 144.95979698585384, + "y": -1.9544698149348096, + "z": 0.0 + }, + { + "x": 146.01070607077742, + "y": -1.9545819776888724, + "z": 0.0 + }, + { + "x": 147.061615155701, + "y": -1.9546941404429357, + "z": 0.0 + }, + { + "x": 148.11252424062454, + "y": -1.9548063031969989, + "z": 0.0 + }, + { + "x": 149.1634333255481, + "y": -1.9549184659510621, + "z": 0.0 + }, + { + "x": 150.2143424104717, + "y": -1.9550306287051253, + "z": 0.0 + }, + { + "x": 151.26525149539526, + "y": -1.9551427914591881, + "z": 0.0 + }, + { + "x": 152.3161605803188, + "y": -1.9552549542132514, + "z": 0.0 + }, + { + "x": 153.36706966524238, + "y": -1.9553671169673146, + "z": 0.0 + }, + { + "x": 154.41797875016596, + "y": -1.9554792797213778, + "z": 0.0 + }, + { + "x": 155.46888783508953, + "y": -1.955591442475441, + "z": 0.0 + }, + { + "x": 156.5197969200131, + "y": -1.9557036052295038, + "z": 0.0 + }, + { + "x": 157.57070600493665, + "y": -1.955815767983567, + "z": 0.0 + }, + { + "x": 158.62161508986023, + "y": -1.9559279307376303, + "z": 0.0 + }, + { + "x": 159.6725241747838, + "y": -1.9560400934916935, + "z": 0.0 + }, + { + "x": 160.72343325970738, + "y": -1.9561522562457565, + "z": 0.0 + }, + { + "x": 161.77434234463095, + "y": -1.9562644189998195, + "z": 0.0 + }, + { + "x": 162.8252514295545, + "y": -1.9563765817538827, + "z": 0.0 + }, + { + "x": 163.87616051447807, + "y": -1.956488744507946, + "z": 0.0 + }, + { + "x": 164.92706959940165, + "y": -1.9566009072620092, + "z": 0.0 + }, + { + "x": 165.9779786843252, + "y": -1.956713070016072, + "z": 0.0 + }, + { + "x": 167.02888776924877, + "y": -1.9568252327701352, + "z": 0.0 + }, + { + "x": 168.07979685417234, + "y": -1.9569373955241984, + "z": 0.0 + } + ] + }, + { + "id": 151, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 168.08043722975782, + "y": 4.043062570302394, + "z": 0.0 + }, + { + "x": 167.02952814483425, + "y": 4.043174733056457, + "z": 0.0 + }, + { + "x": 165.97861905991067, + "y": 4.04328689581052, + "z": 0.0 + }, + { + "x": 164.92770997498712, + "y": 4.043399058564583, + "z": 0.0 + }, + { + "x": 163.87680089006355, + "y": 4.043511221318647, + "z": 0.0 + }, + { + "x": 162.82589180513997, + "y": 4.04362338407271, + "z": 0.0 + }, + { + "x": 161.77498272021643, + "y": 4.043735546826773, + "z": 0.0 + }, + { + "x": 160.72407363529285, + "y": 4.043847709580836, + "z": 0.0 + }, + { + "x": 159.67316455036928, + "y": 4.0439598723348995, + "z": 0.0 + }, + { + "x": 158.6222554654457, + "y": 4.044072035088963, + "z": 0.0 + }, + { + "x": 157.57134638052213, + "y": 4.044184197843025, + "z": 0.0 + }, + { + "x": 156.52043729559858, + "y": 4.044296360597088, + "z": 0.0 + }, + { + "x": 155.469528210675, + "y": 4.0444085233511515, + "z": 0.0 + }, + { + "x": 154.41861912575143, + "y": 4.044520686105215, + "z": 0.0 + }, + { + "x": 153.36771004082786, + "y": 4.044632848859278, + "z": 0.0 + }, + { + "x": 152.31680095590428, + "y": 4.044745011613341, + "z": 0.0 + }, + { + "x": 151.26589187098074, + "y": 4.044857174367404, + "z": 0.0 + }, + { + "x": 150.21498278605716, + "y": 4.044969337121468, + "z": 0.0 + }, + { + "x": 149.1640737011336, + "y": 4.045081499875531, + "z": 0.0 + }, + { + "x": 148.11316461621, + "y": 4.045193662629594, + "z": 0.0 + }, + { + "x": 147.06225553128647, + "y": 4.0453058253836565, + "z": 0.0 + }, + { + "x": 146.0113464463629, + "y": 4.04541798813772, + "z": 0.0 + }, + { + "x": 144.96043736143932, + "y": 4.045530150891783, + "z": 0.0 + } + ] + }, + { + "id": 153, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 168.08022377122933, + "y": 2.0430625816935297, + "z": 0.0 + }, + { + "x": 167.02931468630575, + "y": 2.043174744447593, + "z": 0.0 + }, + { + "x": 165.97840560138218, + "y": 2.043286907201656, + "z": 0.0 + }, + { + "x": 164.92749651645863, + "y": 2.0433990699557194, + "z": 0.0 + }, + { + "x": 163.87658743153506, + "y": 2.0435112327097826, + "z": 0.0 + }, + { + "x": 162.82567834661148, + "y": 2.0436233954638454, + "z": 0.0 + }, + { + "x": 161.77476926168794, + "y": 2.0437355582179086, + "z": 0.0 + }, + { + "x": 160.72386017676436, + "y": 2.043847720971972, + "z": 0.0 + }, + { + "x": 159.6729510918408, + "y": 2.043959883726035, + "z": 0.0 + }, + { + "x": 158.6220420069172, + "y": 2.0440720464800983, + "z": 0.0 + }, + { + "x": 157.57113292199364, + "y": 2.044184209234161, + "z": 0.0 + }, + { + "x": 156.5202238370701, + "y": 2.0442963719882243, + "z": 0.0 + }, + { + "x": 155.46931475214652, + "y": 2.0444085347422876, + "z": 0.0 + }, + { + "x": 154.41840566722294, + "y": 2.044520697496351, + "z": 0.0 + }, + { + "x": 153.36749658229937, + "y": 2.044632860250414, + "z": 0.0 + }, + { + "x": 152.3165874973758, + "y": 2.044745023004477, + "z": 0.0 + }, + { + "x": 151.26567841245225, + "y": 2.04485718575854, + "z": 0.0 + }, + { + "x": 150.21476932752867, + "y": 2.0449693485126033, + "z": 0.0 + }, + { + "x": 149.1638602426051, + "y": 2.0450815112666665, + "z": 0.0 + }, + { + "x": 148.11295115768152, + "y": 2.0451936740207297, + "z": 0.0 + }, + { + "x": 147.06204207275798, + "y": 2.0453058367747925, + "z": 0.0 + }, + { + "x": 146.0111329878344, + "y": 2.0454179995288557, + "z": 0.0 + }, + { + "x": 144.96022390291083, + "y": 2.045530162282919, + "z": 0.0 + } + ] + }, + { + "id": 156, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 168.08022377122933, + "y": 2.0430625816935297, + "z": 0.0 + }, + { + "x": 167.03215555648666, + "y": 2.043174441243607, + "z": 0.0 + }, + { + "x": 165.98408734174396, + "y": 2.0432863007936906, + "z": 0.0 + }, + { + "x": 164.93601912700126, + "y": 2.043398160343768, + "z": 0.0 + }, + { + "x": 163.8132961915106, + "y": 2.0421241757558866, + "z": 0.0 + }, + { + "x": 162.63554538749878, + "y": 1.9938964723664097, + "z": 0.0 + }, + { + "x": 161.18924212443812, + "y": 1.8012417543674824, + "z": 0.0 + }, + { + "x": 159.94561456457726, + "y": 1.3847026814330234, + "z": 0.0 + }, + { + "x": 158.77286559370378, + "y": 0.8105879617646823, + "z": 0.0 + }, + { + "x": 157.65797728841068, + "y": 0.0634867955019085, + "z": 0.0 + }, + { + "x": 156.6259186782699, + "y": -0.8908683303096292, + "z": 0.0 + }, + { + "x": 155.84478339365012, + "y": -1.903125565677636, + "z": 0.0 + }, + { + "x": 155.18869595419164, + "y": -2.9949613928402687, + "z": 0.0 + }, + { + "x": 154.63742025976387, + "y": -4.235427124345479, + "z": 0.0 + }, + { + "x": 154.28840923354022, + "y": -5.5261527234395516, + "z": 0.0 + }, + { + "x": 154.13300640008842, + "y": -6.7169851437406916, + "z": 0.0 + }, + { + "x": 154.07036312990368, + "y": -7.8733599411963, + "z": 0.0 + }, + { + "x": 154.06908996665567, + "y": -8.921427388606872, + "z": 0.0 + }, + { + "x": 154.06781680340765, + "y": -9.9694948360175, + "z": 0.0 + }, + { + "x": 154.06654364015958, + "y": -11.017562283428129, + "z": 0.0 + } + ] + }, + { + "id": 159, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 158.06654068881966, + "y": -11.022421368830695, + "z": 0.0 + }, + { + "x": 158.0678149424262, + "y": -9.973456338759608, + "z": 0.0 + }, + { + "x": 158.06908919603273, + "y": -8.924491308688518, + "z": 0.0 + }, + { + "x": 158.07036344963927, + "y": -7.87552627861743, + "z": 0.0 + }, + { + "x": 158.12809867190316, + "y": -6.943618912423863, + "z": 0.0 + }, + { + "x": 158.25659403393146, + "y": -6.067036922589827, + "z": 0.0 + }, + { + "x": 158.48513964793386, + "y": -5.323581087143358, + "z": 0.0 + }, + { + "x": 158.8149636244475, + "y": -4.673993089845661, + "z": 0.0 + }, + { + "x": 159.2522144804559, + "y": -3.9833813152728115, + "z": 0.0 + }, + { + "x": 159.76566167994648, + "y": -3.3493286804224094, + "z": 0.0 + }, + { + "x": 160.31090892520865, + "y": -2.8948529552645708, + "z": 0.0 + }, + { + "x": 160.9297561931375, + "y": -2.5283305588664016, + "z": 0.0 + }, + { + "x": 161.63741261604633, + "y": -2.2190824547515597, + "z": 0.0 + }, + { + "x": 162.38408928138767, + "y": -2.0077331023102722, + "z": 0.0 + }, + { + "x": 163.04644832238787, + "y": -1.9759052621068007, + "z": 0.0 + }, + { + "x": 163.94224135337973, + "y": -1.9556456724994467, + "z": 0.0 + }, + { + "x": 164.93289945999143, + "y": -1.956601529478737, + "z": 0.0 + }, + { + "x": 165.98186525805173, + "y": -1.956713484827222, + "z": 0.0 + }, + { + "x": 167.03083105611205, + "y": -1.9568254401757135, + "z": 0.0 + }, + { + "x": 168.07979685417234, + "y": -1.9569373955241982, + "z": 0.0 + } + ] + }, + { + "id": 162, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 144.95979698426007, + "y": -1.9544698149346282, + "z": 0.0 + }, + { + "x": 146.0214304459259, + "y": -1.9545831222935375, + "z": 0.0 + }, + { + "x": 147.08306390759168, + "y": -1.9546964296524467, + "z": 0.0 + }, + { + "x": 148.1446973692575, + "y": -1.9548097370113564, + "z": 0.0 + }, + { + "x": 149.13221486047848, + "y": -1.9919571126258255, + "z": 0.0 + }, + { + "x": 150.0485746823283, + "y": -2.0938982287508408, + "z": 0.0 + }, + { + "x": 150.72698021097798, + "y": -2.3205231525512633, + "z": 0.0 + }, + { + "x": 151.4330047742707, + "y": -2.655849370064583, + "z": 0.0 + }, + { + "x": 152.11319400930614, + "y": -3.086961486560563, + "z": 0.0 + }, + { + "x": 152.7333467146321, + "y": -3.601554210063868, + "z": 0.0 + }, + { + "x": 153.17817257834116, + "y": -4.154904237046136, + "z": 0.0 + }, + { + "x": 153.54286408029446, + "y": -4.790277305034675, + "z": 0.0 + }, + { + "x": 153.83492186558323, + "y": -5.5043381450725715, + "z": 0.0 + }, + { + "x": 154.02291814670855, + "y": -6.254922652969147, + "z": 0.0 + }, + { + "x": 154.0679879528459, + "y": -6.977786630399157, + "z": 0.0 + }, + { + "x": 154.07055697560375, + "y": -7.8592499339717055, + "z": 0.0 + }, + { + "x": 154.0691229240025, + "y": -8.894296914623997, + "z": 0.0 + }, + { + "x": 154.06783328208104, + "y": -9.95592959902604, + "z": 0.0 + }, + { + "x": 154.06654364015958, + "y": -11.017562283428138, + "z": 0.0 + } + ] + }, + { + "id": 165, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 158.06654068881966, + "y": -11.022421368830686, + "z": 0.0 + }, + { + "x": 158.06781259403397, + "y": -9.975389534245748, + "z": 0.0 + }, + { + "x": 158.06908449924828, + "y": -8.928357699660815, + "z": 0.0 + }, + { + "x": 158.0703564044626, + "y": -7.88132586507588, + "z": 0.0 + }, + { + "x": 158.0176154167112, + "y": -6.737594738473985, + "z": 0.0 + }, + { + "x": 157.83319850763831, + "y": -5.492078756666, + "z": 0.0 + }, + { + "x": 157.4608111181561, + "y": -4.216004162987613, + "z": 0.0 + }, + { + "x": 156.909643893399, + "y": -3.004761201228715, + "z": 0.0 + }, + { + "x": 156.18182551246588, + "y": -1.8783912339856603, + "z": 0.0 + }, + { + "x": 155.26022549620535, + "y": -0.8584486238655522, + "z": 0.0 + }, + { + "x": 154.2540718633539, + "y": -0.017169875023373082, + "z": 0.0 + }, + { + "x": 153.17022787065991, + "y": 0.6805135933196025, + "z": 0.0 + }, + { + "x": 152.0142007369439, + "y": 1.2406282699886293, + "z": 0.0 + }, + { + "x": 150.79886301081518, + "y": 1.657965068421548, + "z": 0.0 + }, + { + "x": 149.54106696154486, + "y": 1.926489243790637, + "z": 0.0 + }, + { + "x": 148.24689406538863, + "y": 2.0368968292090828, + "z": 0.0 + }, + { + "x": 147.06031264460555, + "y": 2.0452978532285533, + "z": 0.0 + }, + { + "x": 146.007564063204, + "y": 2.045418380437568, + "z": 0.0 + }, + { + "x": 144.96053146204522, + "y": 2.0455301294573687, + "z": 0.0 + } + ] + }, + { + "id": 168, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 101.62105848392994, + "y": -326.5890537873581, + "z": 0.0 + }, + { + "x": 100.57439196744656, + "y": -326.5884930880701, + "z": 0.0 + }, + { + "x": 99.52772545096343, + "y": -326.58793238878195, + "z": 0.0 + }, + { + "x": 98.48105893447985, + "y": -326.5873716894939, + "z": 0.0 + }, + { + "x": 97.43439241799669, + "y": -326.5868109902058, + "z": 0.0 + }, + { + "x": 96.38772590151311, + "y": -326.58625029091775, + "z": 0.0 + }, + { + "x": 95.34105938502998, + "y": -326.5856895916296, + "z": 0.0 + }, + { + "x": 94.2943928685465, + "y": -326.5851288923415, + "z": 0.0 + }, + { + "x": 93.24772635206314, + "y": -326.5845681930534, + "z": 0.0 + }, + { + "x": 92.20105983557977, + "y": -326.58400749376534, + "z": 0.0 + }, + { + "x": 91.15439331909641, + "y": -326.58344679447725, + "z": 0.0 + }, + { + "x": 90.10772680261304, + "y": -326.58288609518917, + "z": 0.0 + }, + { + "x": 89.06106028612967, + "y": -326.5823253959011, + "z": 0.0 + }, + { + "x": 88.01439376964632, + "y": -326.581764696613, + "z": 0.0 + }, + { + "x": 86.96772725316295, + "y": -326.5812039973249, + "z": 0.0 + }, + { + "x": 85.92106073667959, + "y": -326.5806432980368, + "z": 0.0 + }, + { + "x": 84.87439422019622, + "y": -326.58008259874873, + "z": 0.0 + }, + { + "x": 83.82772770371285, + "y": -326.57952189946064, + "z": 0.0 + }, + { + "x": 82.7810611872295, + "y": -326.57896120017256, + "z": 0.0 + }, + { + "x": 81.73439467074613, + "y": -326.57840050088447, + "z": 0.0 + }, + { + "x": 80.68772815426277, + "y": -326.5778398015964, + "z": 0.0 + }, + { + "x": 79.6410616377794, + "y": -326.5772791023083, + "z": 0.0 + } + ] + }, + { + "id": 169, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 79.63784743803878, + "y": -332.57727824138493, + "z": 0.0 + }, + { + "x": 80.68451395452215, + "y": -332.577838940673, + "z": 0.0 + }, + { + "x": 81.7311804710055, + "y": -332.5783996399611, + "z": 0.0 + }, + { + "x": 82.77784698748887, + "y": -332.5789603392492, + "z": 0.0 + }, + { + "x": 83.82451350397223, + "y": -332.5795210385373, + "z": 0.0 + }, + { + "x": 84.8711800204556, + "y": -332.58008173782537, + "z": 0.0 + }, + { + "x": 85.91784653693897, + "y": -332.58064243711345, + "z": 0.0 + }, + { + "x": 86.96451305342232, + "y": -332.58120313640154, + "z": 0.0 + }, + { + "x": 88.01117956990569, + "y": -332.5817638356896, + "z": 0.0 + }, + { + "x": 89.05784608638905, + "y": -332.5823245349777, + "z": 0.0 + }, + { + "x": 90.10451260287242, + "y": -332.5828852342658, + "z": 0.0 + }, + { + "x": 91.15117911935579, + "y": -332.5834459335539, + "z": 0.0 + }, + { + "x": 92.19784563583914, + "y": -332.584006632842, + "z": 0.0 + }, + { + "x": 93.24451215232251, + "y": -332.58456733213006, + "z": 0.0 + }, + { + "x": 94.29117866880587, + "y": -332.58512803141815, + "z": 0.0 + }, + { + "x": 95.33784518528903, + "y": -332.58568873070624, + "z": 0.0 + }, + { + "x": 96.38451170177281, + "y": -332.5862494299944, + "z": 0.0 + }, + { + "x": 97.43117821825575, + "y": -332.5868101292824, + "z": 0.0 + }, + { + "x": 98.47784473473953, + "y": -332.58737082857056, + "z": 0.0 + }, + { + "x": 99.52451125122248, + "y": -332.5879315278586, + "z": 0.0 + }, + { + "x": 100.57117776770626, + "y": -332.58849222714673, + "z": 0.0 + }, + { + "x": 101.61784428418963, + "y": -332.58905292643476, + "z": 0.0 + } + ] + }, + { + "id": 171, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 79.63891883795232, + "y": -330.5772785283594, + "z": 0.0 + }, + { + "x": 80.68558535443569, + "y": -330.5778392276475, + "z": 0.0 + }, + { + "x": 81.73225187091904, + "y": -330.57839992693556, + "z": 0.0 + }, + { + "x": 82.77891838740241, + "y": -330.57896062622365, + "z": 0.0 + }, + { + "x": 83.82558490388577, + "y": -330.57952132551173, + "z": 0.0 + }, + { + "x": 84.87225142036914, + "y": -330.5800820247998, + "z": 0.0 + }, + { + "x": 85.91891793685251, + "y": -330.5806427240879, + "z": 0.0 + }, + { + "x": 86.96558445333586, + "y": -330.581203423376, + "z": 0.0 + }, + { + "x": 88.01225096981923, + "y": -330.5817641226641, + "z": 0.0 + }, + { + "x": 89.05891748630259, + "y": -330.58232482195217, + "z": 0.0 + }, + { + "x": 90.10558400278596, + "y": -330.58288552124026, + "z": 0.0 + }, + { + "x": 91.15225051926933, + "y": -330.58344622052834, + "z": 0.0 + }, + { + "x": 92.19891703575269, + "y": -330.58400691981643, + "z": 0.0 + }, + { + "x": 93.24558355223606, + "y": -330.5845676191045, + "z": 0.0 + }, + { + "x": 94.29225006871941, + "y": -330.5851283183926, + "z": 0.0 + }, + { + "x": 95.33891658520267, + "y": -330.5856890176807, + "z": 0.0 + }, + { + "x": 96.38558310168625, + "y": -330.58624971696884, + "z": 0.0 + }, + { + "x": 97.43224961816941, + "y": -330.58681041625687, + "z": 0.0 + }, + { + "x": 98.47891613465296, + "y": -330.587371115545, + "z": 0.0 + }, + { + "x": 99.52558265113612, + "y": -330.58793181483304, + "z": 0.0 + }, + { + "x": 100.5722491676197, + "y": -330.5884925141212, + "z": 0.0 + }, + { + "x": 101.61891568410306, + "y": -330.5890532134092, + "z": 0.0 + } + ] + }, + { + "id": 174, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 79.73656143631914, + "y": -330.57494595568255, + "z": 0.0 + }, + { + "x": 81.01078991817974, + "y": -330.5043945565061, + "z": 0.0 + }, + { + "x": 82.29098389026342, + "y": -330.30913395288894, + "z": 0.0 + }, + { + "x": 83.54349472443971, + "y": -329.9812404475023, + "z": 0.0 + }, + { + "x": 84.75481203058489, + "y": -329.52429641276865, + "z": 0.0 + }, + { + "x": 85.91185841679498, + "y": -328.9432312187754, + "z": 0.0 + }, + { + "x": 87.0021200663951, + "y": -328.24427205410035, + "z": 0.0 + }, + { + "x": 88.01341728803806, + "y": -327.435227246739, + "z": 0.0 + }, + { + "x": 88.93900969128816, + "y": -326.5202515246551, + "z": 0.0 + }, + { + "x": 89.75107560959849, + "y": -325.5266666688634, + "z": 0.0 + }, + { + "x": 90.45728298426096, + "y": -324.46701305568627, + "z": 0.0 + }, + { + "x": 91.06141501298855, + "y": -323.34667243019805, + "z": 0.0 + }, + { + "x": 91.5584014223586, + "y": -322.1752631134002, + "z": 0.0 + }, + { + "x": 91.94405223561498, + "y": -320.96281181528263, + "z": 0.0 + }, + { + "x": 92.21508908431153, + "y": -319.7196762819973, + "z": 0.0 + }, + { + "x": 92.3684513758152, + "y": -318.47466801576627, + "z": 0.0 + }, + { + "x": 92.41629889872712, + "y": -317.38843814933017, + "z": 0.0 + } + ] + }, + { + "id": 177, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 88.42017200487301, + "y": -317.2120253308748, + "z": 0.0 + }, + { + "x": 88.38681659765516, + "y": -318.1305891502018, + "z": 0.0 + }, + { + "x": 88.28041774537446, + "y": -319.0242218600872, + "z": 0.0 + }, + { + "x": 88.09128024053727, + "y": -319.90385005448945, + "z": 0.0 + }, + { + "x": 87.82103436358267, + "y": -320.7620070632413, + "z": 0.0 + }, + { + "x": 87.47196227942555, + "y": -321.5913992565817, + "z": 0.0 + }, + { + "x": 87.04698127144358, + "y": -322.3849604018104, + "z": 0.0 + }, + { + "x": 86.55563133951622, + "y": -323.1286292338267, + "z": 0.0 + }, + { + "x": 86.00674941604638, + "y": -323.8080489871936, + "z": 0.0 + }, + { + "x": 85.38404558626888, + "y": -324.4280697582773, + "z": 0.0 + }, + { + "x": 84.70104078243725, + "y": -324.97909432431106, + "z": 0.0 + }, + { + "x": 83.96458694724586, + "y": -325.4554743391213, + "z": 0.0 + }, + { + "x": 83.18264360482415, + "y": -325.8521635843414, + "z": 0.0 + }, + { + "x": 82.36363121688173, + "y": -326.16493986710304, + "z": 0.0 + }, + { + "x": 81.51634906459863, + "y": -326.3904453991263, + "z": 0.0 + }, + { + "x": 80.62976620677989, + "y": -326.5270911532118, + "z": 0.0 + }, + { + "x": 79.54380142545668, + "y": -326.57961414999033, + "z": 0.0 + } + ] + }, + { + "id": 180, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 101.71306615229395, + "y": -326.59122060270465, + "z": 0.0 + }, + { + "x": 100.67112994207008, + "y": -326.54267677716007, + "z": 0.0 + }, + { + "x": 99.80014390413483, + "y": -326.4238790735774, + "z": 0.0 + }, + { + "x": 98.96460511255336, + "y": -326.22842132801753, + "z": 0.0 + }, + { + "x": 98.15019178427023, + "y": -325.95695891031085, + "z": 0.0 + }, + { + "x": 97.3634224837516, + "y": -325.61153041774634, + "z": 0.0 + }, + { + "x": 96.64176504893888, + "y": -325.1957672182933, + "z": 0.0 + }, + { + "x": 95.955335319999, + "y": -324.70501710099404, + "z": 0.0 + }, + { + "x": 95.30486246131848, + "y": -324.14508005625663, + "z": 0.0 + }, + { + "x": 94.70767658356107, + "y": -323.5275983878604, + "z": 0.0 + }, + { + "x": 94.16755299214661, + "y": -322.857239798076, + "z": 0.0 + }, + { + "x": 93.68910215437192, + "y": -322.13971373665186, + "z": 0.0 + }, + { + "x": 93.28929316726665, + "y": -321.38958509793605, + "z": 0.0 + }, + { + "x": 92.97766384421965, + "y": -320.61591701150184, + "z": 0.0 + }, + { + "x": 92.72595349426187, + "y": -319.7915731229868, + "z": 0.0 + }, + { + "x": 92.549602496984, + "y": -318.9482323186387, + "z": 0.0 + }, + { + "x": 92.44993108110532, + "y": -318.0923460328693, + "z": 0.0 + }, + { + "x": 92.41617104017382, + "y": -317.2095624415087, + "z": 0.0 + } + ] + }, + { + "id": 183, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 88.42029960539836, + "y": -317.390819183904, + "z": 0.0 + }, + { + "x": 88.48128925622473, + "y": -318.5919860417332, + "z": 0.0 + }, + { + "x": 88.64210023950311, + "y": -319.8033681384539, + "z": 0.0 + }, + { + "x": 88.91137574924393, + "y": -320.9952761314796, + "z": 0.0 + }, + { + "x": 89.28707508064065, + "y": -322.1584901807639, + "z": 0.0 + }, + { + "x": 89.78011362258745, + "y": -323.3093921488408, + "z": 0.0 + }, + { + "x": 90.38193707085415, + "y": -324.38967433746575, + "z": 0.0 + }, + { + "x": 91.07657134093074, + "y": -325.3960522968648, + "z": 0.0 + }, + { + "x": 91.8592434071351, + "y": -326.3358427502742, + "z": 0.0 + }, + { + "x": 92.72486614969797, + "y": -327.20179380010893, + "z": 0.0 + }, + { + "x": 93.66694103194341, + "y": -327.98574947899647, + "z": 0.0 + }, + { + "x": 94.69099899029271, + "y": -328.68783136059267, + "z": 0.0 + }, + { + "x": 95.79103375491582, + "y": -329.2894683383839, + "z": 0.0 + }, + { + "x": 96.92223094720762, + "y": -329.763771091042, + "z": 0.0 + }, + { + "x": 98.09135668384951, + "y": -330.1319091695889, + "z": 0.0 + }, + { + "x": 99.28896330206895, + "y": -330.39106296260303, + "z": 0.0 + }, + { + "x": 100.48449007762834, + "y": -330.5383155470995, + "z": 0.0 + }, + { + "x": 101.52642557922788, + "y": -330.58688396887624, + "z": 0.0 + } + ] + }, + { + "id": 186, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 79.38066375782434, + "y": -1.9577239538036761, + "z": 0.0 + }, + { + "x": 80.44020915609882, + "y": -1.9573786375497457, + "z": 0.0 + }, + { + "x": 81.4997545543733, + "y": -1.9570333212958153, + "z": 0.0 + }, + { + "x": 82.55929995264778, + "y": -1.956688005041885, + "z": 0.0 + }, + { + "x": 83.61884535092224, + "y": -1.9563426887879551, + "z": 0.0 + }, + { + "x": 84.67839074919672, + "y": -1.9559973725340245, + "z": 0.0 + }, + { + "x": 85.7379361474712, + "y": -1.955652056280094, + "z": 0.0 + }, + { + "x": 86.79748154574567, + "y": -1.955306740026164, + "z": 0.0 + }, + { + "x": 87.85702694402015, + "y": -1.9549614237722337, + "z": 0.0 + }, + { + "x": 88.91657234229463, + "y": -1.9546161075183033, + "z": 0.0 + }, + { + "x": 89.97611774056911, + "y": -1.9542707912643729, + "z": 0.0 + }, + { + "x": 91.03566313884357, + "y": -1.9539254750104427, + "z": 0.0 + }, + { + "x": 92.09520853711805, + "y": -1.9535801587565125, + "z": 0.0 + }, + { + "x": 93.15475393539253, + "y": -1.953234842502582, + "z": 0.0 + }, + { + "x": 94.214299333667, + "y": -1.9528895262486519, + "z": 0.0 + }, + { + "x": 95.27384473194148, + "y": -1.9525442099947212, + "z": 0.0 + }, + { + "x": 96.33339013021596, + "y": -1.9521988937407913, + "z": 0.0 + }, + { + "x": 97.39293552849043, + "y": -1.951853577486861, + "z": 0.0 + }, + { + "x": 98.4524809267649, + "y": -1.9515082612329304, + "z": 0.0 + }, + { + "x": 99.51202632503939, + "y": -1.951162944979, + "z": 0.0 + }, + { + "x": 100.57157172331387, + "y": -1.95081762872507, + "z": 0.0 + }, + { + "x": 101.63111712158833, + "y": -1.9504723124711398, + "z": 0.0 + }, + { + "x": 102.69066251986281, + "y": -1.9501269962172092, + "z": 0.0 + } + ] + }, + { + "id": 187, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 102.68870706102459, + "y": 4.049872685131176, + "z": 0.0 + }, + { + "x": 101.6291616627501, + "y": 4.049527368877246, + "z": 0.0 + }, + { + "x": 100.56961626447564, + "y": 4.0491820526233155, + "z": 0.0 + }, + { + "x": 99.51007086620116, + "y": 4.048836736369386, + "z": 0.0 + }, + { + "x": 98.45052546792668, + "y": 4.048491420115455, + "z": 0.0 + }, + { + "x": 97.3909800696522, + "y": 4.048146103861526, + "z": 0.0 + }, + { + "x": 96.33143467137774, + "y": 4.047800787607595, + "z": 0.0 + }, + { + "x": 95.27188927310326, + "y": 4.047455471353664, + "z": 0.0 + }, + { + "x": 94.21234387482878, + "y": 4.047110155099734, + "z": 0.0 + }, + { + "x": 93.15279847655431, + "y": 4.046764838845804, + "z": 0.0 + }, + { + "x": 92.09325307827983, + "y": 4.046419522591873, + "z": 0.0 + }, + { + "x": 91.03370768000535, + "y": 4.046074206337943, + "z": 0.0 + }, + { + "x": 89.97416228173088, + "y": 4.045728890084012, + "z": 0.0 + }, + { + "x": 88.9146168834564, + "y": 4.045383573830082, + "z": 0.0 + }, + { + "x": 87.85507148518192, + "y": 4.045038257576152, + "z": 0.0 + }, + { + "x": 86.79552608690744, + "y": 4.044692941322222, + "z": 0.0 + }, + { + "x": 85.73598068863298, + "y": 4.0443476250682915, + "z": 0.0 + }, + { + "x": 84.6764352903585, + "y": 4.0440023088143615, + "z": 0.0 + }, + { + "x": 83.61688989208402, + "y": 4.0436569925604315, + "z": 0.0 + }, + { + "x": 82.55734449380955, + "y": 4.043311676306501, + "z": 0.0 + }, + { + "x": 81.49779909553507, + "y": 4.04296636005257, + "z": 0.0 + }, + { + "x": 80.43825369726059, + "y": 4.04262104379864, + "z": 0.0 + }, + { + "x": 79.37870829898611, + "y": 4.04227572754471, + "z": 0.0 + } + ] + }, + { + "id": 189, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 102.68935888063733, + "y": 2.049872791348381, + "z": 0.0 + }, + { + "x": 101.62981348236285, + "y": 2.049527475094451, + "z": 0.0 + }, + { + "x": 100.57026808408838, + "y": 2.0491821588405204, + "z": 0.0 + }, + { + "x": 99.5107226858139, + "y": 2.0488368425865904, + "z": 0.0 + }, + { + "x": 98.45117728753942, + "y": 2.0484915263326595, + "z": 0.0 + }, + { + "x": 97.39163188926494, + "y": 2.04814621007873, + "z": 0.0 + }, + { + "x": 96.33208649099048, + "y": 2.0478008938247996, + "z": 0.0 + }, + { + "x": 95.272541092716, + "y": 2.0474555775708687, + "z": 0.0 + }, + { + "x": 94.21299569444152, + "y": 2.0471102613169387, + "z": 0.0 + }, + { + "x": 93.15345029616705, + "y": 2.0467649450630088, + "z": 0.0 + }, + { + "x": 92.09390489789257, + "y": 2.046419628809078, + "z": 0.0 + }, + { + "x": 91.03435949961809, + "y": 2.046074312555148, + "z": 0.0 + }, + { + "x": 89.97481410134363, + "y": 2.045728996301217, + "z": 0.0 + }, + { + "x": 88.91526870306915, + "y": 2.045383680047287, + "z": 0.0 + }, + { + "x": 87.85572330479467, + "y": 2.045038363793357, + "z": 0.0 + }, + { + "x": 86.79617790652019, + "y": 2.0446930475394267, + "z": 0.0 + }, + { + "x": 85.73663250824572, + "y": 2.0443477312854963, + "z": 0.0 + }, + { + "x": 84.67708710997124, + "y": 2.0440024150315663, + "z": 0.0 + }, + { + "x": 83.61754171169676, + "y": 2.043657098777636, + "z": 0.0 + }, + { + "x": 82.5579963134223, + "y": 2.0433117825237055, + "z": 0.0 + }, + { + "x": 81.49845091514781, + "y": 2.0429664662697746, + "z": 0.0 + }, + { + "x": 80.43890551687333, + "y": 2.0426211500158447, + "z": 0.0 + }, + { + "x": 79.37936011859885, + "y": 2.0422758337619147, + "z": 0.0 + } + ] + }, + { + "id": 192, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 102.68935888063733, + "y": 2.049872791348381, + "z": 0.0 + }, + { + "x": 101.65832930984283, + "y": 2.0495367686827572, + "z": 0.0 + }, + { + "x": 100.62729973904831, + "y": 2.0492007460171333, + "z": 0.0 + }, + { + "x": 99.5962701682538, + "y": 2.0488647233515085, + "z": 0.0 + }, + { + "x": 98.5652405974593, + "y": 2.0485287006858846, + "z": 0.0 + }, + { + "x": 97.38922935584577, + "y": 2.0428834586190012, + "z": 0.0 + }, + { + "x": 96.14515386216075, + "y": 1.9400805582782434, + "z": 0.0 + }, + { + "x": 94.8730511827662, + "y": 1.6869661986496554, + "z": 0.0 + }, + { + "x": 93.5702008365092, + "y": 1.22505021256522, + "z": 0.0 + }, + { + "x": 92.40006126093198, + "y": 0.5649586460659338, + "z": 0.0 + }, + { + "x": 91.38046677094792, + "y": -0.23641945572233425, + "z": 0.0 + }, + { + "x": 90.48038520357372, + "y": -1.1647799831877466, + "z": 0.0 + }, + { + "x": 89.68231525354273, + "y": -2.2587983061839196, + "z": 0.0 + }, + { + "x": 89.07111740293382, + "y": -3.4722343436080396, + "z": 0.0 + }, + { + "x": 88.67845588237262, + "y": -4.704909506053416, + "z": 0.0 + }, + { + "x": 88.45581325061647, + "y": -5.935592458876994, + "z": 0.0 + }, + { + "x": 88.37108444520378, + "y": -7.116185443357953, + "z": 0.0 + }, + { + "x": 88.37124117478857, + "y": -8.14721505699659, + "z": 0.0 + }, + { + "x": 88.37139790437337, + "y": -9.17824467063517, + "z": 0.0 + }, + { + "x": 88.37155463395816, + "y": -10.20927428427378, + "z": 0.0 + }, + { + "x": 88.37171136354294, + "y": -11.240303897912387, + "z": 0.0 + } + ] + }, + { + "id": 195, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 92.37171131732724, + "y": -11.239695847160373, + "z": 0.0 + }, + { + "x": 92.37155114114427, + "y": -10.185993138367436, + "z": 0.0 + }, + { + "x": 92.3713909649613, + "y": -9.1322904295745, + "z": 0.0 + }, + { + "x": 92.39046094699293, + "y": -8.116508097385378, + "z": 0.0 + }, + { + "x": 92.46620178948825, + "y": -7.18354460785133, + "z": 0.0 + }, + { + "x": 92.6608232529945, + "y": -6.463353461590874, + "z": 0.0 + }, + { + "x": 92.95346991422174, + "y": -5.700548846361753, + "z": 0.0 + }, + { + "x": 93.33315107195224, + "y": -4.977802134021738, + "z": 0.0 + }, + { + "x": 93.79523274275404, + "y": -4.303944248276251, + "z": 0.0 + }, + { + "x": 94.33434349854011, + "y": -3.687590563228103, + "z": 0.0 + }, + { + "x": 94.91530511508498, + "y": -3.212018734025133, + "z": 0.0 + }, + { + "x": 95.58835243785953, + "y": -2.7800965407806846, + "z": 0.0 + }, + { + "x": 96.31607581087863, + "y": -2.4276423861668794, + "z": 0.0 + }, + { + "x": 97.08151497626868, + "y": -2.1656349088898588, + "z": 0.0 + }, + { + "x": 97.87475166175554, + "y": -1.9978261145678717, + "z": 0.0 + }, + { + "x": 98.63542969358136, + "y": -1.9584385980081804, + "z": 0.0 + }, + { + "x": 99.55485470219124, + "y": -1.950988954958867, + "z": 0.0 + }, + { + "x": 100.58325718984946, + "y": -1.950813820316731, + "z": 0.0 + }, + { + "x": 101.63695985485614, + "y": -1.9504704082669708, + "z": 0.0 + }, + { + "x": 102.69066251986281, + "y": -1.9501269962172094, + "z": 0.0 + } + ] + }, + { + "id": 198, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 79.38066375454355, + "y": -1.9577239538047368, + "z": 0.0 + }, + { + "x": 80.4388549865507, + "y": -1.9573790788868963, + "z": 0.0 + }, + { + "x": 81.49704621855781, + "y": -1.9570342039690558, + "z": 0.0 + }, + { + "x": 82.55091250262038, + "y": -1.9589222555269905, + "z": 0.0 + }, + { + "x": 83.43200894284189, + "y": -2.0445247038874914, + "z": 0.0 + }, + { + "x": 84.24925844510989, + "y": -2.220497821692533, + "z": 0.0 + }, + { + "x": 85.05338347029272, + "y": -2.4832087265729244, + "z": 0.0 + }, + { + "x": 85.74791954430364, + "y": -2.834730304320984, + "z": 0.0 + }, + { + "x": 86.3801868279096, + "y": -3.2781724066689217, + "z": 0.0 + }, + { + "x": 87.00721396453173, + "y": -3.82053723236728, + "z": 0.0 + }, + { + "x": 87.55047028720435, + "y": -4.425529897110538, + "z": 0.0 + }, + { + "x": 87.83924838450032, + "y": -4.996065916476047, + "z": 0.0 + }, + { + "x": 88.12498548627755, + "y": -5.719537641098558, + "z": 0.0 + }, + { + "x": 88.31493852913333, + "y": -6.482889975872659, + "z": 0.0 + }, + { + "x": 88.36973463992086, + "y": -7.223142553947042, + "z": 0.0 + }, + { + "x": 88.37138235691452, + "y": -8.090212015485726, + "z": 0.0 + }, + { + "x": 88.37138964653866, + "y": -9.123921345952521, + "z": 0.0 + }, + { + "x": 88.3715505050408, + "y": -10.182112621932458, + "z": 0.0 + }, + { + "x": 88.37171136354294, + "y": -11.240303897912394, + "z": 0.0 + } + ] + }, + { + "id": 201, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 92.37171131732723, + "y": -11.239695847160402, + "z": 0.0 + }, + { + "x": 92.37155054141259, + "y": -10.182047864601843, + "z": 0.0 + }, + { + "x": 92.37138976549794, + "y": -9.124399882043246, + "z": 0.0 + }, + { + "x": 92.37122898958329, + "y": -8.066751899484675, + "z": 0.0 + }, + { + "x": 92.32627910480849, + "y": -6.929613012356661, + "z": 0.0 + }, + { + "x": 92.20804645699295, + "y": -5.75344116010853, + "z": 0.0 + }, + { + "x": 91.82483457880105, + "y": -4.366599844967185, + "z": 0.0 + }, + { + "x": 91.30775741146184, + "y": -3.1709171435836234, + "z": 0.0 + }, + { + "x": 90.65535366129677, + "y": -2.054612645824859, + "z": 0.0 + }, + { + "x": 89.81302843243145, + "y": -0.9956783172598629, + "z": 0.0 + }, + { + "x": 88.78088189318728, + "y": -0.06351850988216023, + "z": 0.0 + }, + { + "x": 87.7192830400309, + "y": 0.671605878433852, + "z": 0.0 + }, + { + "x": 86.57424660191658, + "y": 1.2764731160905984, + "z": 0.0 + }, + { + "x": 85.22679612447331, + "y": 1.7184868629338879, + "z": 0.0 + }, + { + "x": 83.92383958195423, + "y": 1.9457360202381637, + "z": 0.0 + }, + { + "x": 82.69024866530056, + "y": 2.0386125518403038, + "z": 0.0 + }, + { + "x": 81.49495166259359, + "y": 2.0429653258289995, + "z": 0.0 + }, + { + "x": 80.43730372398524, + "y": 2.042620627975815, + "z": 0.0 + }, + { + "x": 79.37965578537688, + "y": 2.0422759301226296, + "z": 0.0 + } + ] + }, + { + "id": 204, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 347.7299857691685, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 346.65641965126474, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 345.5941204708103, + "y": -326.6040779914478, + "z": 0.0 + }, + { + "x": 344.648505329607, + "y": -326.5354346959316, + "z": 0.0 + }, + { + "x": 343.85970768027084, + "y": -326.3567253110556, + "z": 0.0 + }, + { + "x": 343.0776092882985, + "y": -326.0795876674798, + "z": 0.0 + }, + { + "x": 342.3354907746227, + "y": -325.70986091698387, + "z": 0.0 + }, + { + "x": 341.64405761177926, + "y": -325.2530356144291, + "z": 0.0 + }, + { + "x": 341.01329565219686, + "y": -324.71580515294767, + "z": 0.0 + }, + { + "x": 340.44702812359935, + "y": -324.10413828561445, + "z": 0.0 + }, + { + "x": 339.94535168652635, + "y": -323.423605878501, + "z": 0.0 + }, + { + "x": 339.51734115447863, + "y": -322.6864068001786, + "z": 0.0 + }, + { + "x": 339.1727150952545, + "y": -321.9059384428799, + "z": 0.0 + }, + { + "x": 338.9277300987599, + "y": -321.1031441814349, + "z": 0.0 + }, + { + "x": 338.7795076133734, + "y": -320.27874964250066, + "z": 0.0 + }, + { + "x": 338.71982898421777, + "y": -319.42841040751057, + "z": 0.0 + }, + { + "x": 338.70720255662206, + "y": -318.48770881866005, + "z": 0.0 + }, + { + "x": 338.70817756430256, + "y": -317.45151167767597, + "z": 0.0 + } + ] + }, + { + "id": 207, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 334.70817851236086, + "y": -317.44873405142624, + "z": 0.0 + }, + { + "x": 334.7075762305461, + "y": -318.5436553177717, + "z": 0.0 + }, + { + "x": 334.7195177420323, + "y": -319.7406104743982, + "z": 0.0 + }, + { + "x": 334.82049530304073, + "y": -321.0539438473358, + "z": 0.0 + }, + { + "x": 335.0761563021257, + "y": -322.3434839951809, + "z": 0.0 + }, + { + "x": 335.47768807384915, + "y": -323.58519337120737, + "z": 0.0 + }, + { + "x": 336.01658897447584, + "y": -324.77308093046884, + "z": 0.0 + }, + { + "x": 336.68589773112495, + "y": -325.8921318270369, + "z": 0.0 + }, + { + "x": 337.49447840776554, + "y": -326.94649206913607, + "z": 0.0 + }, + { + "x": 338.40328770494233, + "y": -327.87004125241145, + "z": 0.0 + }, + { + "x": 339.4213558134485, + "y": -328.69749319947175, + "z": 0.0 + }, + { + "x": 340.60990333464713, + "y": -329.43703225907564, + "z": 0.0 + }, + { + "x": 341.8285278971893, + "y": -329.9562320320991, + "z": 0.0 + }, + { + "x": 343.0891858483319, + "y": -330.3197665843113, + "z": 0.0 + }, + { + "x": 344.35589618935245, + "y": -330.53065971257524, + "z": 0.0 + }, + { + "x": 345.57053106457437, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 346.650082156251, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 347.7296332479276, + "y": -330.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 208, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 325.71998576749917, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 326.7680810055944, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 327.81617624368965, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 328.8642714817849, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 329.91236671988014, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 330.9604619579754, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 332.0085571960706, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 333.05665243416587, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 334.1047476722611, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 335.15284291035636, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 336.2009381484516, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 337.2490333865468, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 338.297128624642, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 339.34522386273727, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 340.3933191008325, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 341.44141433892776, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 342.489509577023, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 343.53760481511824, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 344.5857000532135, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 345.63379529130873, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 346.681890529404, + "y": -332.6099853515625, + "z": 0.0 + }, + { + "x": 347.7299857674992, + "y": -332.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 210, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.71998576749917, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 326.7680810055944, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 327.81617624368965, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 328.8642714817849, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 329.91236671988014, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 330.9604619579754, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 332.0085571960706, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 333.05665243416587, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 334.1047476722611, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 335.15284291035636, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 336.2009381484516, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 337.2490333865468, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 338.297128624642, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 339.34522386273727, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 340.3933191008325, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 341.44141433892776, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 342.489509577023, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 343.53760481511824, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 344.5857000532135, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 345.63379529130873, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 346.681890529404, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 347.7299857674992, + "y": -330.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 213, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 347.7299857674992, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 346.681890529404, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 345.63379529130873, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 344.5857000532135, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 343.53760481511824, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 342.489509577023, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 341.44141433892776, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 340.3933191008325, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 339.34522386273727, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 338.297128624642, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 337.2490333865468, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 336.2009381484516, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 335.15284291035636, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 334.1047476722611, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 333.05665243416587, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 332.0085571960706, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 330.9604619579754, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 329.91236671988014, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 328.8642714817849, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 327.81617624368965, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 326.7680810055944, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 325.71998576749917, + "y": -326.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 216, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.71998576749917, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 326.75488808239726, + "y": -330.6099853515625, + "z": 0.0 + }, + { + "x": 327.8118675524266, + "y": -330.60986349765574, + "z": 0.0 + }, + { + "x": 328.9873159954276, + "y": -330.59190530437644, + "z": 0.0 + }, + { + "x": 330.30964508378855, + "y": -330.46197316532766, + "z": 0.0 + }, + { + "x": 331.556025593915, + "y": -330.15541174962823, + "z": 0.0 + }, + { + "x": 332.7525040323843, + "y": -329.69632142549915, + "z": 0.0 + }, + { + "x": 333.88208912167863, + "y": -329.0916278346175, + "z": 0.0 + }, + { + "x": 334.9359359378983, + "y": -328.34315517349506, + "z": 0.0 + }, + { + "x": 335.913383204102, + "y": -327.4289099766568, + "z": 0.0 + }, + { + "x": 336.7008226662732, + "y": -326.4421863771143, + "z": 0.0 + }, + { + "x": 337.3694306959815, + "y": -325.3743482667254, + "z": 0.0 + }, + { + "x": 337.9121140564023, + "y": -324.2379684904723, + "z": 0.0 + }, + { + "x": 338.3230020237536, + "y": -323.0439917139242, + "z": 0.0 + }, + { + "x": 338.60091078909, + "y": -321.7401436542182, + "z": 0.0 + }, + { + "x": 338.6862609570376, + "y": -320.5934350532335, + "z": 0.0 + }, + { + "x": 338.7069274034519, + "y": -319.5212766008853, + "z": 0.0 + }, + { + "x": 338.70755249575484, + "y": -318.4863744747684, + "z": 0.0 + }, + { + "x": 338.70817758805777, + "y": -317.45147234865163, + "z": 0.0 + } + ] + }, + { + "id": 219, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 334.70817851236086, + "y": -317.44873405142624, + "z": 0.0 + }, + { + "x": 334.70752421679254, + "y": -318.53198507169066, + "z": 0.0 + }, + { + "x": 334.7108944649408, + "y": -319.48962363322096, + "z": 0.0 + }, + { + "x": 334.6645566804101, + "y": -320.3735075264175, + "z": 0.0 + }, + { + "x": 334.53815197133923, + "y": -321.22153723351005, + "z": 0.0 + }, + { + "x": 334.31797944922545, + "y": -322.0503964585138, + "z": 0.0 + }, + { + "x": 334.0371918614085, + "y": -322.7960531500664, + "z": 0.0 + }, + { + "x": 333.62261883383894, + "y": -323.5325454764164, + "z": 0.0 + }, + { + "x": 333.11819234412405, + "y": -324.21935487342756, + "z": 0.0 + }, + { + "x": 332.54625711396557, + "y": -324.83716484905676, + "z": 0.0 + }, + { + "x": 331.9093734688107, + "y": -325.3796459158115, + "z": 0.0 + }, + { + "x": 331.2743947648346, + "y": -325.81212613380285, + "z": 0.0 + }, + { + "x": 330.51884277883306, + "y": -326.1556341844773, + "z": 0.0 + }, + { + "x": 329.7185175964627, + "y": -326.4014722846573, + "z": 0.0 + }, + { + "x": 328.849860451563, + "y": -326.5499418368728, + "z": 0.0 + }, + { + "x": 327.8864882032299, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 326.8032369853645, + "y": -326.6099853515625, + "z": 0.0 + }, + { + "x": 325.71998576749917, + "y": -326.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 220, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 86.37701814958909, + "y": -46.15060751994074, + "z": 0.0 + }, + { + "x": 86.37717740097652, + "y": -47.19822655545584, + "z": 0.0 + }, + { + "x": 86.377336652364, + "y": -48.24584559097058, + "z": 0.0 + }, + { + "x": 86.37749590375142, + "y": -49.29346462648557, + "z": 0.0 + }, + { + "x": 86.37765515513887, + "y": -50.34108366200046, + "z": 0.0 + }, + { + "x": 86.3778144065263, + "y": -51.38870269751539, + "z": 0.0 + }, + { + "x": 86.37797365791373, + "y": -52.436321733030326, + "z": 0.0 + }, + { + "x": 86.37813290930116, + "y": -53.48394076854531, + "z": 0.0 + }, + { + "x": 86.3782921606886, + "y": -54.531559804060194, + "z": 0.0 + }, + { + "x": 86.37845141207603, + "y": -55.579178839575135, + "z": 0.0 + }, + { + "x": 86.37861066346346, + "y": -56.62679787509001, + "z": 0.0 + }, + { + "x": 86.37876991485088, + "y": -57.67441691060498, + "z": 0.0 + }, + { + "x": 86.37892916623831, + "y": -58.722035946119966, + "z": 0.0 + }, + { + "x": 86.37908841762575, + "y": -59.76965498163485, + "z": 0.0 + }, + { + "x": 86.37924766901318, + "y": -60.817274017149835, + "z": 0.0 + }, + { + "x": 86.37940692040063, + "y": -61.86489305266472, + "z": 0.0 + }, + { + "x": 86.37956617178806, + "y": -62.91251208817966, + "z": 0.0 + }, + { + "x": 86.37972542317549, + "y": -63.960131123694644, + "z": 0.0 + }, + { + "x": 86.37988467456293, + "y": -65.00775015920952, + "z": 0.0 + }, + { + "x": 86.38004392595036, + "y": -66.05536919472452, + "z": 0.0 + }, + { + "x": 86.3802031773378, + "y": -67.10298823023938, + "z": 0.0 + }, + { + "x": 86.38036242872523, + "y": -68.15060726575432, + "z": 0.0 + } + ] + }, + { + "id": 222, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 88.37701812648123, + "y": -46.15030349456474, + "z": 0.0 + }, + { + "x": 88.37717737786866, + "y": -47.19792253007975, + "z": 0.0 + }, + { + "x": 88.37733662925613, + "y": -48.24554156559458, + "z": 0.0 + }, + { + "x": 88.37749588064356, + "y": -49.29316060110955, + "z": 0.0 + }, + { + "x": 88.37765513203101, + "y": -50.340779636624454, + "z": 0.0 + }, + { + "x": 88.37781438341844, + "y": -51.38839867213939, + "z": 0.0 + }, + { + "x": 88.37797363480587, + "y": -52.43601770765432, + "z": 0.0 + }, + { + "x": 88.3781328861933, + "y": -53.483636743169285, + "z": 0.0 + }, + { + "x": 88.37829213758074, + "y": -54.53125577868419, + "z": 0.0 + }, + { + "x": 88.37845138896817, + "y": -55.57887481419913, + "z": 0.0 + }, + { + "x": 88.3786106403556, + "y": -56.62649384971404, + "z": 0.0 + }, + { + "x": 88.37876989174302, + "y": -57.67411288522898, + "z": 0.0 + }, + { + "x": 88.37892914313045, + "y": -58.721731920743935, + "z": 0.0 + }, + { + "x": 88.3790883945179, + "y": -59.76935095625885, + "z": 0.0 + }, + { + "x": 88.37924764590532, + "y": -60.8169699917738, + "z": 0.0 + }, + { + "x": 88.37940689729277, + "y": -61.864589027288716, + "z": 0.0 + }, + { + "x": 88.3795661486802, + "y": -62.91220806280366, + "z": 0.0 + }, + { + "x": 88.37972540006763, + "y": -63.95982709831861, + "z": 0.0 + }, + { + "x": 88.37988465145507, + "y": -65.00744613383353, + "z": 0.0 + }, + { + "x": 88.3800439028425, + "y": -66.0550651693485, + "z": 0.0 + }, + { + "x": 88.38020315422995, + "y": -67.10268420486338, + "z": 0.0 + }, + { + "x": 88.38036240561738, + "y": -68.15030324037832, + "z": 0.0 + } + ] + }, + { + "id": 225, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 92.38036235940166, + "y": -68.1496951896263, + "z": 0.0 + }, + { + "x": 92.38020310801423, + "y": -67.10207615411136, + "z": 0.0 + }, + { + "x": 92.38004385662678, + "y": -66.05445711859642, + "z": 0.0 + }, + { + "x": 92.37988460523935, + "y": -65.0068380830815, + "z": 0.0 + }, + { + "x": 92.37972535385191, + "y": -63.95921904756656, + "z": 0.0 + }, + { + "x": 92.37956610246448, + "y": -62.91160001205165, + "z": 0.0 + }, + { + "x": 92.37940685107705, + "y": -61.86398097653671, + "z": 0.0 + }, + { + "x": 92.3792475996896, + "y": -60.81636194102175, + "z": 0.0 + }, + { + "x": 92.37908834830218, + "y": -59.76874290550684, + "z": 0.0 + }, + { + "x": 92.37892909691473, + "y": -58.721123869991885, + "z": 0.0 + }, + { + "x": 92.3787698455273, + "y": -57.67350483447697, + "z": 0.0 + }, + { + "x": 92.37861059413989, + "y": -56.62588579896209, + "z": 0.0 + }, + { + "x": 92.37845134275246, + "y": -55.578266763447125, + "z": 0.0 + }, + { + "x": 92.37829209136503, + "y": -54.530647727932184, + "z": 0.0 + }, + { + "x": 92.37813283997758, + "y": -53.48302869241722, + "z": 0.0 + }, + { + "x": 92.37797358859015, + "y": -52.435409656902316, + "z": 0.0 + }, + { + "x": 92.37781433720272, + "y": -51.38779062138738, + "z": 0.0 + }, + { + "x": 92.37765508581529, + "y": -50.34017158587245, + "z": 0.0 + }, + { + "x": 92.37749583442785, + "y": -49.292552550357485, + "z": 0.0 + }, + { + "x": 92.37733658304042, + "y": -48.24493351484257, + "z": 0.0 + }, + { + "x": 92.37717733165294, + "y": -47.19731447932759, + "z": 0.0 + }, + { + "x": 92.37701808026551, + "y": -46.14969544381273, + "z": 0.0 + } + ] + }, + { + "id": 228, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 92.38036235940167, + "y": -68.14969518962627, + "z": 0.0 + }, + { + "x": 92.38020563148586, + "y": -67.11867655529974, + "z": 0.0 + }, + { + "x": 92.38004890357007, + "y": -66.08765792097321, + "z": 0.0 + }, + { + "x": 92.37989217565426, + "y": -65.05663928664663, + "z": 0.0 + }, + { + "x": 92.41679137427337, + "y": -64.10235778117132, + "z": 0.0 + }, + { + "x": 92.51763841393722, + "y": -63.2185243615093, + "z": 0.0 + }, + { + "x": 92.75249091121461, + "y": -62.65696816837448, + "z": 0.0 + }, + { + "x": 93.10227471287547, + "y": -61.994795466111924, + "z": 0.0 + }, + { + "x": 93.54091380759029, + "y": -61.38592526043152, + "z": 0.0 + }, + { + "x": 94.05085061454383, + "y": -60.88220034541138, + "z": 0.0 + }, + { + "x": 94.61177279804552, + "y": -60.50871182938417, + "z": 0.0 + }, + { + "x": 95.31745354601713, + "y": -60.11314605700607, + "z": 0.0 + }, + { + "x": 96.06655349456925, + "y": -59.79291989053375, + "z": 0.0 + }, + { + "x": 96.77291820728992, + "y": -59.62570533772009, + "z": 0.0 + }, + { + "x": 97.53533400954645, + "y": -59.54021825949611, + "z": 0.0 + }, + { + "x": 98.41138621242084, + "y": -59.49574533581123, + "z": 0.0 + }, + { + "x": 99.32791510795805, + "y": -59.498913341565384, + "z": 0.0 + }, + { + "x": 100.35893374654256, + "y": -59.49878770907209, + "z": 0.0 + }, + { + "x": 101.3899523851271, + "y": -59.49866207657878, + "z": 0.0 + } + ] + }, + { + "id": 231, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 101.38975224562901, + "y": -55.49866207127013, + "z": 0.0 + }, + { + "x": 100.32582394992707, + "y": -55.498791713896836, + "z": 0.0 + }, + { + "x": 99.2618956542251, + "y": -55.49892135652354, + "z": 0.0 + }, + { + "x": 98.1054862504992, + "y": -55.551454169643684, + "z": 0.0 + }, + { + "x": 96.88035293790236, + "y": -55.709600800613835, + "z": 0.0 + }, + { + "x": 95.62580516803563, + "y": -56.01536736447157, + "z": 0.0 + }, + { + "x": 94.39865342573762, + "y": -56.47985266677764, + "z": 0.0 + }, + { + "x": 93.22010770181319, + "y": -57.12204012206544, + "z": 0.0 + }, + { + "x": 92.16829161636967, + "y": -57.86982439322365, + "z": 0.0 + }, + { + "x": 91.20693933306167, + "y": -58.74018071847535, + "z": 0.0 + }, + { + "x": 90.35163011330322, + "y": -59.732371836590005, + "z": 0.0 + }, + { + "x": 89.62431031515885, + "y": -60.834491340795715, + "z": 0.0 + }, + { + "x": 89.04863263105773, + "y": -62.08959445679456, + "z": 0.0 + }, + { + "x": 88.66727497953346, + "y": -63.36411188416538, + "z": 0.0 + }, + { + "x": 88.45615541789783, + "y": -64.66441986249069, + "z": 0.0 + }, + { + "x": 88.38263386183175, + "y": -65.91996545091644, + "z": 0.0 + }, + { + "x": 88.38020062513496, + "y": -67.08604681103495, + "z": 0.0 + }, + { + "x": 88.38036235573624, + "y": -68.149975102343, + "z": 0.0 + } + ] + }, + { + "id": 234, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 88.37701812648125, + "y": -46.15030349456475, + "z": 0.0 + }, + { + "x": 88.37717693375423, + "y": -47.195000968393984, + "z": 0.0 + }, + { + "x": 88.37777555539165, + "y": -48.2813367156901, + "z": 0.0 + }, + { + "x": 88.40536174558581, + "y": -49.43975162297693, + "z": 0.0 + }, + { + "x": 88.52949263747234, + "y": -50.762481608388775, + "z": 0.0 + }, + { + "x": 88.82128865116036, + "y": -52.00236474058616, + "z": 0.0 + }, + { + "x": 89.2484022072504, + "y": -53.190350440385586, + "z": 0.0 + }, + { + "x": 89.80299449894832, + "y": -54.32344184045015, + "z": 0.0 + }, + { + "x": 90.47934840662556, + "y": -55.389785788630775, + "z": 0.0 + }, + { + "x": 91.33162733593136, + "y": -56.43659369078458, + "z": 0.0 + }, + { + "x": 92.29930560058293, + "y": -57.31710245789597, + "z": 0.0 + }, + { + "x": 93.36514677863966, + "y": -58.05707488016186, + "z": 0.0 + }, + { + "x": 94.51557849293877, + "y": -58.65445385888668, + "z": 0.0 + }, + { + "x": 95.73336626093186, + "y": -59.10041730364373, + "z": 0.0 + }, + { + "x": 97.04842615778028, + "y": -59.3924109703997, + "z": 0.0 + }, + { + "x": 98.23211531382547, + "y": -59.48624809731275, + "z": 0.0 + }, + { + "x": 99.30051746549375, + "y": -59.498916680044445, + "z": 0.0 + }, + { + "x": 100.34521494363746, + "y": -59.49878938074643, + "z": 0.0 + }, + { + "x": 101.38991242178116, + "y": -59.498662081448416, + "z": 0.0 + } + ] + }, + { + "id": 237, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 101.38975224562901, + "y": -55.49866207127013, + "z": 0.0 + }, + { + "x": 100.35451945543977, + "y": -55.49878821726955, + "z": 0.0 + }, + { + "x": 99.3468932688754, + "y": -55.48506343129918, + "z": 0.0 + }, + { + "x": 98.42662430100265, + "y": -55.417625466811955, + "z": 0.0 + }, + { + "x": 97.6485517457146, + "y": -55.25379666365033, + "z": 0.0 + }, + { + "x": 96.83662282215542, + "y": -55.00957602877695, + "z": 0.0 + }, + { + "x": 96.04978126895155, + "y": -54.690974948978656, + "z": 0.0 + }, + { + "x": 95.34292935792287, + "y": -54.300343147111725, + "z": 0.0 + }, + { + "x": 94.69551164695628, + "y": -53.83370293027281, + "z": 0.0 + }, + { + "x": 94.0722995794701, + "y": -53.28615869571014, + "z": 0.0 + }, + { + "x": 93.53147317384932, + "y": -52.68638943767184, + "z": 0.0 + }, + { + "x": 93.11206255307954, + "y": -52.05384596541708, + "z": 0.0 + }, + { + "x": 92.81868923420566, + "y": -51.39541274371947, + "z": 0.0 + }, + { + "x": 92.57536532669909, + "y": -50.6445173026241, + "z": 0.0 + }, + { + "x": 92.42453828934885, + "y": -49.869001139017534, + "z": 0.0 + }, + { + "x": 92.37078360217731, + "y": -49.081449119815105, + "z": 0.0 + }, + { + "x": 92.37733179938255, + "y": -48.218720127865645, + "z": 0.0 + }, + { + "x": 92.37717550149249, + "y": -47.185274954994725, + "z": 0.0 + }, + { + "x": 92.37701813297217, + "y": -46.15004216908085, + "z": 0.0 + } + ] + }, + { + "id": 240, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 338.77358612560033, + "y": -209.16116984879852, + "z": 0.0 + }, + { + "x": 338.77421008887006, + "y": -208.12813694877926, + "z": 0.0 + }, + { + "x": 338.7748340521398, + "y": -207.09510404876008, + "z": 0.0 + }, + { + "x": 338.7754580154094, + "y": -206.0620711487407, + "z": 0.0 + }, + { + "x": 338.77608197867914, + "y": -205.0290382487214, + "z": 0.0 + }, + { + "x": 338.69324281461707, + "y": -203.84852588242197, + "z": 0.0 + }, + { + "x": 338.4560333486288, + "y": -202.5937711387159, + "z": 0.0 + }, + { + "x": 338.04777525570614, + "y": -201.36112786701733, + "z": 0.0 + }, + { + "x": 337.47674806992393, + "y": -200.19350299029531, + "z": 0.0 + }, + { + "x": 336.7491768192449, + "y": -199.10957978959715, + "z": 0.0 + }, + { + "x": 335.80614769553483, + "y": -198.10892696995305, + "z": 0.0 + }, + { + "x": 334.8162987013774, + "y": -197.30407433766342, + "z": 0.0 + }, + { + "x": 333.7649898013082, + "y": -196.62897077714314, + "z": 0.0 + }, + { + "x": 332.6538532577283, + "y": -196.07256717159595, + "z": 0.0 + }, + { + "x": 331.4882291636196, + "y": -195.63627292305696, + "z": 0.0 + }, + { + "x": 330.21446207409156, + "y": -195.34317675727266, + "z": 0.0 + }, + { + "x": 328.97164850065326, + "y": -195.20398179351594, + "z": 0.0 + }, + { + "x": 327.8028929609527, + "y": -195.16038550288124, + "z": 0.0 + }, + { + "x": 326.7035191941376, + "y": -195.15919559105376, + "z": 0.0 + }, + { + "x": 325.67048610908853, + "y": -195.15911164734354, + "z": 0.0 + } + ] + }, + { + "id": 243, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.6698379252599, + "y": -199.15911160787866, + "z": 0.0 + }, + { + "x": 326.698705458449, + "y": -199.1591952130984, + "z": 0.0 + }, + { + "x": 327.64217907066535, + "y": -199.15744801084946, + "z": 0.0 + }, + { + "x": 328.52144543613406, + "y": -199.18957761215478, + "z": 0.0 + }, + { + "x": 329.33788028665595, + "y": -199.27490103789137, + "z": 0.0 + }, + { + "x": 330.07872304962353, + "y": -199.42141425818107, + "z": 0.0 + }, + { + "x": 330.8432506839614, + "y": -199.69421323637448, + "z": 0.0 + }, + { + "x": 331.58171654626835, + "y": -200.05387914235382, + "z": 0.0 + }, + { + "x": 332.27416847227875, + "y": -200.48357346066885, + "z": 0.0 + }, + { + "x": 332.89058912936, + "y": -200.95693908574123, + "z": 0.0 + }, + { + "x": 333.400252169316, + "y": -201.44391373597452, + "z": 0.0 + }, + { + "x": 333.85486512684065, + "y": -202.06898774610787, + "z": 0.0 + }, + { + "x": 334.22487174474423, + "y": -202.74504561156255, + "z": 0.0 + }, + { + "x": 334.5053961897313, + "y": -203.46220442450982, + "z": 0.0 + }, + { + "x": 334.6904965133175, + "y": -204.1895319344917, + "z": 0.0 + }, + { + "x": 334.7707155407038, + "y": -205.05396810570983, + "z": 0.0 + }, + { + "x": 334.7754511969514, + "y": -206.07215175838857, + "z": 0.0 + }, + { + "x": 334.77482974972054, + "y": -207.101019107294, + "z": 0.0 + }, + { + "x": 334.7742083024897, + "y": -208.12988645619942, + "z": 0.0 + }, + { + "x": 334.7735868552588, + "y": -209.15875380510485, + "z": 0.0 + } + ] + }, + { + "id": 246, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 334.78778715206863, + "y": -185.6487580936724, + "z": 0.0 + }, + { + "x": 334.787155504427, + "y": -186.69451323135144, + "z": 0.0 + }, + { + "x": 334.78754032623203, + "y": -187.6777088195608, + "z": 0.0 + }, + { + "x": 334.7615276547244, + "y": -188.60365903590986, + "z": 0.0 + }, + { + "x": 334.7144096790263, + "y": -189.3547372712996, + "z": 0.0 + }, + { + "x": 334.5374160576254, + "y": -190.1438427004075, + "z": 0.0 + }, + { + "x": 334.25838016768733, + "y": -190.92490920055405, + "z": 0.0 + }, + { + "x": 333.897785897096, + "y": -191.67086593067626, + "z": 0.0 + }, + { + "x": 333.5024894926457, + "y": -192.32274605647348, + "z": 0.0 + }, + { + "x": 332.9903625762737, + "y": -192.93797550733024, + "z": 0.0 + }, + { + "x": 332.3794707414414, + "y": -193.50480830036958, + "z": 0.0 + }, + { + "x": 331.7127141752909, + "y": -194.00395343470421, + "z": 0.0 + }, + { + "x": 331.05090017930854, + "y": -194.40768723334773, + "z": 0.0 + }, + { + "x": 330.3217752004306, + "y": -194.72386373113207, + "z": 0.0 + }, + { + "x": 329.51933956980224, + "y": -194.9515978352368, + "z": 0.0 + }, + { + "x": 328.67413547068077, + "y": -195.09519055948655, + "z": 0.0 + }, + { + "x": 327.76202119740066, + "y": -195.15928160435453, + "z": 0.0 + }, + { + "x": 326.7162658724131, + "y": -195.15919662684195, + "z": 0.0 + }, + { + "x": 325.67051054742564, + "y": -195.1591116493294, + "z": 0.0 + } + ] + }, + { + "id": 249, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.6698379252599, + "y": -199.15911160787866, + "z": 0.0 + }, + { + "x": 326.71138163818864, + "y": -199.1591962431579, + "z": 0.0 + }, + { + "x": 327.8492730069305, + "y": -199.15696665098056, + "z": 0.0 + }, + { + "x": 329.0903995103214, + "y": -199.08696153947074, + "z": 0.0 + }, + { + "x": 330.35957533320914, + "y": -198.88056682846835, + "z": 0.0 + }, + { + "x": 331.5936119652358, + "y": -198.5191337594488, + "z": 0.0 + }, + { + "x": 332.7739635436144, + "y": -198.00803518202366, + "z": 0.0 + }, + { + "x": 333.8828403175662, + "y": -197.35480324247453, + "z": 0.0 + }, + { + "x": 334.91750112386575, + "y": -196.5553271582158, + "z": 0.0 + }, + { + "x": 335.82219654976586, + "y": -195.64340922047694, + "z": 0.0 + }, + { + "x": 336.58969986776356, + "y": -194.65980949230965, + "z": 0.0 + }, + { + "x": 337.2504434774229, + "y": -193.60412357405087, + "z": 0.0 + }, + { + "x": 337.79922846031434, + "y": -192.48667964832532, + "z": 0.0 + }, + { + "x": 338.23048861397376, + "y": -191.31898851495265, + "z": 0.0 + }, + { + "x": 338.53979013659995, + "y": -190.11303929208032, + "z": 0.0 + }, + { + "x": 338.72349839333293, + "y": -188.8878609136412, + "z": 0.0 + }, + { + "x": 338.78652799858696, + "y": -187.7346192289334, + "z": 0.0 + }, + { + "x": 338.78715710236884, + "y": -186.69307570255887, + "z": 0.0 + }, + { + "x": 338.7877862061507, + "y": -185.65153217618433, + "z": 0.0 + } + ] + }, + { + "id": 252, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 334.78778715206863, + "y": -185.64875809367237, + "z": 0.0 + }, + { + "x": 334.7871697478595, + "y": -186.6709318202565, + "z": 0.0 + }, + { + "x": 334.7865523436503, + "y": -187.6931055468404, + "z": 0.0 + }, + { + "x": 334.7859349394412, + "y": -188.71527927342453, + "z": 0.0 + }, + { + "x": 334.78531753523214, + "y": -189.73745300000843, + "z": 0.0 + }, + { + "x": 334.784700131023, + "y": -190.75962672659244, + "z": 0.0 + }, + { + "x": 334.78408272681384, + "y": -191.78180045317663, + "z": 0.0 + }, + { + "x": 334.7834653226047, + "y": -192.80397417976064, + "z": 0.0 + }, + { + "x": 334.78284791839565, + "y": -193.82614790634466, + "z": 0.0 + }, + { + "x": 334.7822305141865, + "y": -194.84832163292856, + "z": 0.0 + }, + { + "x": 334.78161310997734, + "y": -195.8704953595127, + "z": 0.0 + }, + { + "x": 334.7809957057683, + "y": -196.8926690860966, + "z": 0.0 + }, + { + "x": 334.78037830155915, + "y": -197.91484281268072, + "z": 0.0 + }, + { + "x": 334.77976089735, + "y": -198.93701653926462, + "z": 0.0 + }, + { + "x": 334.77914349314085, + "y": -199.95919026584875, + "z": 0.0 + }, + { + "x": 334.7785260889318, + "y": -200.98136399243265, + "z": 0.0 + }, + { + "x": 334.77790868472266, + "y": -202.00353771901678, + "z": 0.0 + }, + { + "x": 334.7772912805135, + "y": -203.0257114456008, + "z": 0.0 + }, + { + "x": 334.77667387630447, + "y": -204.0478851721847, + "z": 0.0 + }, + { + "x": 334.7760564720953, + "y": -205.07005889876882, + "z": 0.0 + }, + { + "x": 334.77543906788617, + "y": -206.09223262535272, + "z": 0.0 + }, + { + "x": 334.774821663677, + "y": -207.11440635193674, + "z": 0.0 + }, + { + "x": 334.77420425946787, + "y": -208.13658007852086, + "z": 0.0 + }, + { + "x": 334.7735868552588, + "y": -209.15875380510488, + "z": 0.0 + } + ] + }, + { + "id": 253, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 340.77358576077114, + "y": -209.16237787064532, + "z": 0.0 + }, + { + "x": 340.77420316498024, + "y": -208.1402041440613, + "z": 0.0 + }, + { + "x": 340.7748205691894, + "y": -207.1180304174775, + "z": 0.0 + }, + { + "x": 340.77543797339854, + "y": -206.0958566908935, + "z": 0.0 + }, + { + "x": 340.77605537760763, + "y": -205.07368296430926, + "z": 0.0 + }, + { + "x": 340.7766727818168, + "y": -204.05150923772547, + "z": 0.0 + }, + { + "x": 340.7772901860259, + "y": -203.02933551114123, + "z": 0.0 + }, + { + "x": 340.777907590235, + "y": -202.00716178455718, + "z": 0.0 + }, + { + "x": 340.7785249944441, + "y": -200.9849880579734, + "z": 0.0 + }, + { + "x": 340.7791423986532, + "y": -199.96281433138915, + "z": 0.0 + }, + { + "x": 340.7797598028624, + "y": -198.94064060480537, + "z": 0.0 + }, + { + "x": 340.78037720707147, + "y": -197.91846687822112, + "z": 0.0 + }, + { + "x": 340.7809946112806, + "y": -196.89629315163734, + "z": 0.0 + }, + { + "x": 340.7816120154897, + "y": -195.8741194250531, + "z": 0.0 + }, + { + "x": 340.78222941969887, + "y": -194.8519456984693, + "z": 0.0 + }, + { + "x": 340.78284682390796, + "y": -193.82977197188507, + "z": 0.0 + }, + { + "x": 340.78346422811705, + "y": -192.80759824530105, + "z": 0.0 + }, + { + "x": 340.78408163232615, + "y": -191.78542451871704, + "z": 0.0 + }, + { + "x": 340.7846990365353, + "y": -190.76325079213322, + "z": 0.0 + }, + { + "x": 340.78531644074445, + "y": -189.7410770655492, + "z": 0.0 + }, + { + "x": 340.78593384495355, + "y": -188.71890333896496, + "z": 0.0 + }, + { + "x": 340.7865512491627, + "y": -187.69672961238118, + "z": 0.0 + }, + { + "x": 340.7871686533718, + "y": -186.67455588579693, + "z": 0.0 + }, + { + "x": 340.78778605758094, + "y": -185.65238215921315, + "z": 0.0 + } + ] + }, + { + "id": 255, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 338.77358612560033, + "y": -209.16116984879852, + "z": 0.0 + }, + { + "x": 338.7742035298095, + "y": -208.1389961222145, + "z": 0.0 + }, + { + "x": 338.77482093401863, + "y": -207.1168223956306, + "z": 0.0 + }, + { + "x": 338.7754383382278, + "y": -206.0946486690466, + "z": 0.0 + }, + { + "x": 338.7760557424368, + "y": -205.07247494246246, + "z": 0.0 + }, + { + "x": 338.776673146646, + "y": -204.05030121587856, + "z": 0.0 + }, + { + "x": 338.7772905508551, + "y": -203.02812748929443, + "z": 0.0 + }, + { + "x": 338.77790795506417, + "y": -202.00595376271036, + "z": 0.0 + }, + { + "x": 338.7785253592733, + "y": -200.98378003612646, + "z": 0.0 + }, + { + "x": 338.77914276348247, + "y": -199.96160630954233, + "z": 0.0 + }, + { + "x": 338.7797601676916, + "y": -198.93943258295843, + "z": 0.0 + }, + { + "x": 338.78037757190066, + "y": -197.9172588563743, + "z": 0.0 + }, + { + "x": 338.7809949761098, + "y": -196.8950851297904, + "z": 0.0 + }, + { + "x": 338.78161238031896, + "y": -195.87291140320627, + "z": 0.0 + }, + { + "x": 338.7822297845281, + "y": -194.85073767662237, + "z": 0.0 + }, + { + "x": 338.78284718873715, + "y": -193.82856395003824, + "z": 0.0 + }, + { + "x": 338.7834645929463, + "y": -192.80639022345423, + "z": 0.0 + }, + { + "x": 338.78408199715534, + "y": -191.78421649687021, + "z": 0.0 + }, + { + "x": 338.7846994013645, + "y": -190.7620427702863, + "z": 0.0 + }, + { + "x": 338.78531680557364, + "y": -189.7398690437023, + "z": 0.0 + }, + { + "x": 338.7859342097828, + "y": -188.71769531711817, + "z": 0.0 + }, + { + "x": 338.78655161399195, + "y": -187.69552159053427, + "z": 0.0 + }, + { + "x": 338.787169018201, + "y": -186.67334786395014, + "z": 0.0 + }, + { + "x": 338.78778642241014, + "y": -185.65117413736624, + "z": 0.0 + } + ] + }, + { + "id": 258, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.1602379954887, + "y": -59.47139504390145, + "z": 0.0 + }, + { + "x": 326.19698562451595, + "y": -59.47126871331473, + "z": 0.0 + }, + { + "x": 327.2337332535433, + "y": -59.471142382727976, + "z": 0.0 + }, + { + "x": 328.1307756152667, + "y": -59.466147760085974, + "z": 0.0 + }, + { + "x": 328.95765628647047, + "y": -59.51302416468887, + "z": 0.0 + }, + { + "x": 329.76671371919963, + "y": -59.643665082959686, + "z": 0.0 + }, + { + "x": 330.5566609642443, + "y": -59.860369230187196, + "z": 0.0 + }, + { + "x": 331.29314170067073, + "y": -60.146422142017485, + "z": 0.0 + }, + { + "x": 331.9768652134147, + "y": -60.51140009081671, + "z": 0.0 + }, + { + "x": 332.63035777743755, + "y": -60.98553706174534, + "z": 0.0 + }, + { + "x": 333.21354991847267, + "y": -61.51730905876411, + "z": 0.0 + }, + { + "x": 333.72272706335207, + "y": -62.1093268069832, + "z": 0.0 + }, + { + "x": 334.1393827093261, + "y": -62.73036296148267, + "z": 0.0 + }, + { + "x": 334.4598578619131, + "y": -63.39449632595675, + "z": 0.0 + }, + { + "x": 334.6829992249576, + "y": -64.14494231539462, + "z": 0.0 + }, + { + "x": 334.8114809369437, + "y": -64.98371014715602, + "z": 0.0 + }, + { + "x": 334.86010552665084, + "y": -65.91853702404615, + "z": 0.0 + }, + { + "x": 334.8594793197534, + "y": -66.95528447165245, + "z": 0.0 + }, + { + "x": 334.8588531128561, + "y": -67.99203191925852, + "z": 0.0 + }, + { + "x": 334.85822690595865, + "y": -69.02877936686474, + "z": 0.0 + } + ] + }, + { + "id": 261, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 338.85822617630015, + "y": -69.03119541055852, + "z": 0.0 + }, + { + "x": 338.85888005386664, + "y": -67.9486364339345, + "z": 0.0 + }, + { + "x": 338.859533931433, + "y": -66.86607745731037, + "z": 0.0 + }, + { + "x": 338.8453984688475, + "y": -65.75709899297308, + "z": 0.0 + }, + { + "x": 338.74794995835043, + "y": -64.5367784122154, + "z": 0.0 + }, + { + "x": 338.4478942489203, + "y": -63.1866427882245, + "z": 0.0 + }, + { + "x": 337.99539461249424, + "y": -61.93906013241491, + "z": 0.0 + }, + { + "x": 337.3918416838258, + "y": -60.757355585741436, + "z": 0.0 + }, + { + "x": 336.64510581466607, + "y": -59.65772951311925, + "z": 0.0 + }, + { + "x": 335.7099172537774, + "y": -58.63869350658027, + "z": 0.0 + }, + { + "x": 334.67415102685993, + "y": -57.77989147387602, + "z": 0.0 + }, + { + "x": 333.5955595287653, + "y": -57.070160318935095, + "z": 0.0 + }, + { + "x": 332.451682977315, + "y": -56.47803873653796, + "z": 0.0 + }, + { + "x": 331.24690110232734, + "y": -56.00756770704959, + "z": 0.0 + }, + { + "x": 329.9146552998319, + "y": -55.688996711487064, + "z": 0.0 + }, + { + "x": 328.6363731316137, + "y": -55.52987162210784, + "z": 0.0 + }, + { + "x": 327.4090981995594, + "y": -55.47289540543303, + "z": 0.0 + }, + { + "x": 326.2423097504109, + "y": -55.47126316074751, + "z": 0.0 + }, + { + "x": 325.15975058434924, + "y": -55.47139507359766, + "z": 0.0 + } + ] + }, + { + "id": 264, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 334.87188359293737, + "y": -46.41878349125916, + "z": 0.0 + }, + { + "x": 334.8712628344383, + "y": -47.446510576513944, + "z": 0.0 + }, + { + "x": 334.87064207593926, + "y": -48.47423766176885, + "z": 0.0 + }, + { + "x": 334.8700213174402, + "y": -49.501964747023536, + "z": 0.0 + }, + { + "x": 334.86940055894115, + "y": -50.529691832278345, + "z": 0.0 + }, + { + "x": 334.8687798004421, + "y": -51.55741891753325, + "z": 0.0 + }, + { + "x": 334.86815904194316, + "y": -52.58514600278794, + "z": 0.0 + }, + { + "x": 334.8675382834441, + "y": -53.612873088042846, + "z": 0.0 + }, + { + "x": 334.86691752494505, + "y": -54.64060017329754, + "z": 0.0 + }, + { + "x": 334.866296766446, + "y": -55.66832725855234, + "z": 0.0 + }, + { + "x": 334.86567600794694, + "y": -56.69605434380725, + "z": 0.0 + }, + { + "x": 334.865055249448, + "y": -57.72378142906193, + "z": 0.0 + }, + { + "x": 334.86443449094895, + "y": -58.75150851431674, + "z": 0.0 + }, + { + "x": 334.8638137324499, + "y": -59.77923559957164, + "z": 0.0 + }, + { + "x": 334.86319297395085, + "y": -60.80696268482633, + "z": 0.0 + }, + { + "x": 334.8625722154518, + "y": -61.83468977008113, + "z": 0.0 + }, + { + "x": 334.86195145695274, + "y": -62.862416855336036, + "z": 0.0 + }, + { + "x": 334.8613306984538, + "y": -63.89014394059084, + "z": 0.0 + }, + { + "x": 334.86070993995475, + "y": -64.91787102584553, + "z": 0.0 + }, + { + "x": 334.8600891814557, + "y": -65.94559811110031, + "z": 0.0 + }, + { + "x": 334.85946842295664, + "y": -66.97332519635523, + "z": 0.0 + }, + { + "x": 334.8588476644577, + "y": -68.00105228160993, + "z": 0.0 + }, + { + "x": 334.85822690595865, + "y": -69.02877936686471, + "z": 0.0 + } + ] + }, + { + "id": 265, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 340.85822581147096, + "y": -69.03240343240542, + "z": 0.0 + }, + { + "x": 340.85884656997, + "y": -68.00467634715062, + "z": 0.0 + }, + { + "x": 340.859467328469, + "y": -66.9769492618956, + "z": 0.0 + }, + { + "x": 340.86008808696806, + "y": -65.94922217664102, + "z": 0.0 + }, + { + "x": 340.8607088454671, + "y": -64.92149509138622, + "z": 0.0 + }, + { + "x": 340.8613296039661, + "y": -63.8937680061312, + "z": 0.0 + }, + { + "x": 340.8619503624651, + "y": -62.866040920876394, + "z": 0.0 + }, + { + "x": 340.86257112096416, + "y": -61.83831383562182, + "z": 0.0 + }, + { + "x": 340.8631918794632, + "y": -60.810586750367015, + "z": 0.0 + }, + { + "x": 340.8638126379622, + "y": -59.782859665112, + "z": 0.0 + }, + { + "x": 340.86443339646127, + "y": -58.755132579857424, + "z": 0.0 + }, + { + "x": 340.8650541549603, + "y": -57.72740549460262, + "z": 0.0 + }, + { + "x": 340.8656749134593, + "y": -56.699678409347605, + "z": 0.0 + }, + { + "x": 340.86629567195837, + "y": -55.67195132409302, + "z": 0.0 + }, + { + "x": 340.8669164304574, + "y": -54.64422423883823, + "z": 0.0 + }, + { + "x": 340.8675371889564, + "y": -53.616497153583204, + "z": 0.0 + }, + { + "x": 340.8681579474555, + "y": -52.58877006832863, + "z": 0.0 + }, + { + "x": 340.86877870595447, + "y": -51.561042983073605, + "z": 0.0 + }, + { + "x": 340.8693994644535, + "y": -50.53331589781903, + "z": 0.0 + }, + { + "x": 340.8700202229526, + "y": -49.50558881256423, + "z": 0.0 + }, + { + "x": 340.8706409814516, + "y": -48.47786172730921, + "z": 0.0 + }, + { + "x": 340.8712617399506, + "y": -47.45013464205463, + "z": 0.0 + }, + { + "x": 340.8718824984497, + "y": -46.42240755679985, + "z": 0.0 + } + ] + }, + { + "id": 267, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 338.85822617630015, + "y": -69.03119541055852, + "z": 0.0 + }, + { + "x": 338.8588469347992, + "y": -68.00346832530371, + "z": 0.0 + }, + { + "x": 338.85946769329826, + "y": -66.97574124004882, + "z": 0.0 + }, + { + "x": 338.8600884517973, + "y": -65.94801415479412, + "z": 0.0 + }, + { + "x": 338.86070921029636, + "y": -64.92028706953931, + "z": 0.0 + }, + { + "x": 338.8613299687953, + "y": -63.89255998428441, + "z": 0.0 + }, + { + "x": 338.86195072729436, + "y": -62.86483289902961, + "z": 0.0 + }, + { + "x": 338.8625714857934, + "y": -61.837105813774926, + "z": 0.0 + }, + { + "x": 338.86319224429246, + "y": -60.809378728520116, + "z": 0.0 + }, + { + "x": 338.8638130027914, + "y": -59.781651643265214, + "z": 0.0 + }, + { + "x": 338.86443376129046, + "y": -58.753924558010524, + "z": 0.0 + }, + { + "x": 338.8650545197895, + "y": -57.72619747275573, + "z": 0.0 + }, + { + "x": 338.86567527828856, + "y": -56.69847038750082, + "z": 0.0 + }, + { + "x": 338.8662960367876, + "y": -55.67074330224612, + "z": 0.0 + }, + { + "x": 338.86691679528667, + "y": -54.64301621699133, + "z": 0.0 + }, + { + "x": 338.8675375537856, + "y": -53.61528913173642, + "z": 0.0 + }, + { + "x": 338.86815831228466, + "y": -52.587562046481736, + "z": 0.0 + }, + { + "x": 338.8687790707837, + "y": -51.55983496122682, + "z": 0.0 + }, + { + "x": 338.86939982928277, + "y": -50.53210787597213, + "z": 0.0 + }, + { + "x": 338.8700205877818, + "y": -49.504380790717335, + "z": 0.0 + }, + { + "x": 338.87064134628076, + "y": -48.476653705462425, + "z": 0.0 + }, + { + "x": 338.8712621047798, + "y": -47.44892662020773, + "z": 0.0 + }, + { + "x": 338.87188286327887, + "y": -46.42119953495295, + "z": 0.0 + } + ] + }, + { + "id": 270, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.1602379954888, + "y": -59.47139504390147, + "z": 0.0 + }, + { + "x": 326.2277182989171, + "y": -59.470929141072, + "z": 0.0 + }, + { + "x": 327.35842293823544, + "y": -59.44753903629696, + "z": 0.0 + }, + { + "x": 328.6249307256167, + "y": -59.34585779940172, + "z": 0.0 + }, + { + "x": 329.83283393607644, + "y": -59.10445994848552, + "z": 0.0 + }, + { + "x": 330.99854190970746, + "y": -58.7476302319203, + "z": 0.0 + }, + { + "x": 332.12450630869796, + "y": -58.282204730606395, + "z": 0.0 + }, + { + "x": 333.2016302091149, + "y": -57.71199354431562, + "z": 0.0 + }, + { + "x": 334.2573023836869, + "y": -57.01204403553369, + "z": 0.0 + }, + { + "x": 335.20689490297315, + "y": -56.209077266950956, + "z": 0.0 + }, + { + "x": 336.0601484015708, + "y": -55.316518481772064, + "z": 0.0 + }, + { + "x": 336.81763920173995, + "y": -54.34038408681393, + "z": 0.0 + }, + { + "x": 337.4701625516368, + "y": -53.29086134605254, + "z": 0.0 + }, + { + "x": 338.02303709250344, + "y": -52.14534488442073, + "z": 0.0 + }, + { + "x": 338.43226232151005, + "y": -50.94637169459995, + "z": 0.0 + }, + { + "x": 338.69371665328697, + "y": -49.73742888246052, + "z": 0.0 + }, + { + "x": 338.8269504095423, + "y": -48.563284388624226, + "z": 0.0 + }, + { + "x": 338.87125999734656, + "y": -47.45241568426286, + "z": 0.0 + }, + { + "x": 338.87188263035193, + "y": -46.42158516849574, + "z": 0.0 + } + ] + }, + { + "id": 273, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 334.87188359293725, + "y": -46.41878349125915, + "z": 0.0 + }, + { + "x": 334.8712500900183, + "y": -47.46781103382229, + "z": 0.0 + }, + { + "x": 334.87465533163515, + "y": -48.3867486297635, + "z": 0.0 + }, + { + "x": 334.8340411563869, + "y": -49.20269489318105, + "z": 0.0 + }, + { + "x": 334.6984352919744, + "y": -50.00884118128332, + "z": 0.0 + }, + { + "x": 334.4706425605684, + "y": -50.79323570818916, + "z": 0.0 + }, + { + "x": 334.1537904682107, + "y": -51.545608539108564, + "z": 0.0 + }, + { + "x": 333.75211379318347, + "y": -52.25610409194188, + "z": 0.0 + }, + { + "x": 333.27060793851547, + "y": -52.9157049023742, + "z": 0.0 + }, + { + "x": 332.71479896932226, + "y": -53.51645171938627, + "z": 0.0 + }, + { + "x": 332.0924357454257, + "y": -54.05035381817845, + "z": 0.0 + }, + { + "x": 331.427675970019, + "y": -54.50254431697783, + "z": 0.0 + }, + { + "x": 330.7094081648772, + "y": -54.87085310925545, + "z": 0.0 + }, + { + "x": 329.9383881173603, + "y": -55.15215650825121, + "z": 0.0 + }, + { + "x": 329.14101179884665, + "y": -55.343337898478175, + "z": 0.0 + }, + { + "x": 328.25269461726884, + "y": -55.442782093772266, + "z": 0.0 + }, + { + "x": 327.2591991124581, + "y": -55.47113924994592, + "z": 0.0 + }, + { + "x": 326.2094748484037, + "y": -55.471267161771806, + "z": 0.0 + }, + { + "x": 325.15975058434924, + "y": -55.47139507359766, + "z": 0.0 + } + ] + }, + { + "id": 276, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 92.4016714980064, + "y": -208.32969356999655, + "z": 0.0 + }, + { + "x": 92.40151480877489, + "y": -207.29892941643521, + "z": 0.0 + }, + { + "x": 92.4013581195434, + "y": -206.26816526287388, + "z": 0.0 + }, + { + "x": 92.4348956724687, + "y": -205.30636743927084, + "z": 0.0 + }, + { + "x": 92.52818843367211, + "y": -204.4130756059148, + "z": 0.0 + }, + { + "x": 92.72123588524576, + "y": -203.67070398173175, + "z": 0.0 + }, + { + "x": 93.00974965835567, + "y": -202.95958489921435, + "z": 0.0 + }, + { + "x": 93.38865416626015, + "y": -202.2434998249028, + "z": 0.0 + }, + { + "x": 93.84361125052354, + "y": -201.57227382694185, + "z": 0.0 + }, + { + "x": 94.3679482439317, + "y": -200.96386620483992, + "z": 0.0 + }, + { + "x": 94.92835006058691, + "y": -200.49959300260977, + "z": 0.0 + }, + { + "x": 95.59256725930115, + "y": -200.05094130665384, + "z": 0.0 + }, + { + "x": 96.30313513512215, + "y": -199.6804342777397, + "z": 0.0 + }, + { + "x": 97.05276059073066, + "y": -199.39214154117593, + "z": 0.0 + }, + { + "x": 97.78075795641391, + "y": -199.23561854958365, + "z": 0.0 + }, + { + "x": 98.54816831250857, + "y": -199.1678728105677, + "z": 0.0 + }, + { + "x": 99.4342641119304, + "y": -199.1392723209954, + "z": 0.0 + }, + { + "x": 100.38873984010004, + "y": -199.1408053875916, + "z": 0.0 + }, + { + "x": 101.41950400216771, + "y": -199.14088914693036, + "z": 0.0 + } + ] + }, + { + "id": 279, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 101.4201637034698, + "y": -195.14088918733114, + "z": 0.0 + }, + { + "x": 100.34443380692284, + "y": -195.14080177410108, + "z": 0.0 + }, + { + "x": 99.22213065499349, + "y": -195.16674073057283, + "z": 0.0 + }, + { + "x": 98.00848018727567, + "y": -195.27836301508296, + "z": 0.0 + }, + { + "x": 96.7360855044522, + "y": -195.53387222132216, + "z": 0.0 + }, + { + "x": 95.49935446175567, + "y": -195.9299935677057, + "z": 0.0 + }, + { + "x": 94.30099645201025, + "y": -196.47952520287916, + "z": 0.0 + }, + { + "x": 93.18455033163266, + "y": -197.1596159343103, + "z": 0.0 + }, + { + "x": 92.15917603136714, + "y": -197.95480405569515, + "z": 0.0 + }, + { + "x": 91.22713561220709, + "y": -198.86627341871213, + "z": 0.0 + }, + { + "x": 90.40428222001984, + "y": -199.88960224606478, + "z": 0.0 + }, + { + "x": 89.70987654025186, + "y": -201.00743384361795, + "z": 0.0 + }, + { + "x": 89.15614980628833, + "y": -202.20137215494867, + "z": 0.0 + }, + { + "x": 88.7512504331463, + "y": -203.45401329200402, + "z": 0.0 + }, + { + "x": 88.50121720547153, + "y": -204.74710415228492, + "z": 0.0 + }, + { + "x": 88.40530287705167, + "y": -206.05240752625747, + "z": 0.0 + }, + { + "x": 88.40150796490579, + "y": -207.25421174575615, + "z": 0.0 + }, + { + "x": 88.40167148949946, + "y": -208.3299416334258, + "z": 0.0 + } + ] + }, + { + "id": 280, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 86.39832728819378, + "y": -186.330605900311, + "z": 0.0 + }, + { + "x": 86.39848653958121, + "y": -187.37822493582607, + "z": 0.0 + }, + { + "x": 86.39864579096867, + "y": -188.42584397134087, + "z": 0.0 + }, + { + "x": 86.3988050423561, + "y": -189.47346300685584, + "z": 0.0 + }, + { + "x": 86.39896429374355, + "y": -190.52108204237072, + "z": 0.0 + }, + { + "x": 86.39912354513098, + "y": -191.56870107788566, + "z": 0.0 + }, + { + "x": 86.3992827965184, + "y": -192.61632011340058, + "z": 0.0 + }, + { + "x": 86.39944204790584, + "y": -193.66393914891557, + "z": 0.0 + }, + { + "x": 86.39960129929328, + "y": -194.71155818443046, + "z": 0.0 + }, + { + "x": 86.39976055068071, + "y": -195.75917721994537, + "z": 0.0 + }, + { + "x": 86.39991980206814, + "y": -196.80679625546037, + "z": 0.0 + }, + { + "x": 86.40007905345558, + "y": -197.85441529097523, + "z": 0.0 + }, + { + "x": 86.40023830484301, + "y": -198.90203432649022, + "z": 0.0 + }, + { + "x": 86.40039755623046, + "y": -199.94965336200508, + "z": 0.0 + }, + { + "x": 86.40055680761789, + "y": -200.99727239752002, + "z": 0.0 + }, + { + "x": 86.40071605900532, + "y": -202.04489143303496, + "z": 0.0 + }, + { + "x": 86.40087531039275, + "y": -203.09251046854993, + "z": 0.0 + }, + { + "x": 86.4010345617802, + "y": -204.14012950406482, + "z": 0.0 + }, + { + "x": 86.40119381316762, + "y": -205.18774853957976, + "z": 0.0 + }, + { + "x": 86.40135306455505, + "y": -206.23536757509473, + "z": 0.0 + }, + { + "x": 86.4015123159425, + "y": -207.28298661060958, + "z": 0.0 + }, + { + "x": 86.40167156732993, + "y": -208.33060564612452, + "z": 0.0 + } + ] + }, + { + "id": 282, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 88.39832726508592, + "y": -186.330301874935, + "z": 0.0 + }, + { + "x": 88.39848651647335, + "y": -187.37792091045003, + "z": 0.0 + }, + { + "x": 88.39864576786081, + "y": -188.42553994596489, + "z": 0.0 + }, + { + "x": 88.39880501924824, + "y": -189.4731589814798, + "z": 0.0 + }, + { + "x": 88.39896427063569, + "y": -190.5207780169947, + "z": 0.0 + }, + { + "x": 88.39912352202312, + "y": -191.56839705250968, + "z": 0.0 + }, + { + "x": 88.39928277341055, + "y": -192.6160160880246, + "z": 0.0 + }, + { + "x": 88.39944202479798, + "y": -193.66363512353956, + "z": 0.0 + }, + { + "x": 88.39960127618542, + "y": -194.71125415905448, + "z": 0.0 + }, + { + "x": 88.39976052757285, + "y": -195.7588731945694, + "z": 0.0 + }, + { + "x": 88.39991977896028, + "y": -196.80649223008436, + "z": 0.0 + }, + { + "x": 88.40007903034773, + "y": -197.85411126559922, + "z": 0.0 + }, + { + "x": 88.40023828173516, + "y": -198.90173030111418, + "z": 0.0 + }, + { + "x": 88.4003975331226, + "y": -199.9493493366291, + "z": 0.0 + }, + { + "x": 88.40055678451003, + "y": -200.996968372144, + "z": 0.0 + }, + { + "x": 88.40071603589746, + "y": -202.04458740765898, + "z": 0.0 + }, + { + "x": 88.40087528728489, + "y": -203.0922064431739, + "z": 0.0 + }, + { + "x": 88.40103453867233, + "y": -204.1398254786888, + "z": 0.0 + }, + { + "x": 88.40119379005976, + "y": -205.18744451420378, + "z": 0.0 + }, + { + "x": 88.4013530414472, + "y": -206.2350635497187, + "z": 0.0 + }, + { + "x": 88.40151229283464, + "y": -207.2826825852336, + "z": 0.0 + }, + { + "x": 88.40167154422207, + "y": -208.33030162074851, + "z": 0.0 + } + ] + }, + { + "id": 285, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 92.40167149800635, + "y": -208.32969356999655, + "z": 0.0 + }, + { + "x": 92.40151224661892, + "y": -207.28207453448158, + "z": 0.0 + }, + { + "x": 92.40135299523148, + "y": -206.23445549896667, + "z": 0.0 + }, + { + "x": 92.40119374384405, + "y": -205.18683646345175, + "z": 0.0 + }, + { + "x": 92.40103449245662, + "y": -204.13921742793684, + "z": 0.0 + }, + { + "x": 92.40087524106917, + "y": -203.09159839242187, + "z": 0.0 + }, + { + "x": 92.40071598968174, + "y": -202.04397935690696, + "z": 0.0 + }, + { + "x": 92.40055673829431, + "y": -200.99636032139205, + "z": 0.0 + }, + { + "x": 92.40039748690688, + "y": -199.94874128587708, + "z": 0.0 + }, + { + "x": 92.40023823551944, + "y": -198.90112225036216, + "z": 0.0 + }, + { + "x": 92.40007898413201, + "y": -197.85350321484725, + "z": 0.0 + }, + { + "x": 92.39991973274456, + "y": -196.80588417933228, + "z": 0.0 + }, + { + "x": 92.39976048135713, + "y": -195.75826514381737, + "z": 0.0 + }, + { + "x": 92.3996012299697, + "y": -194.71064610830246, + "z": 0.0 + }, + { + "x": 92.39944197858226, + "y": -193.6630270727875, + "z": 0.0 + }, + { + "x": 92.39928272719483, + "y": -192.61540803727257, + "z": 0.0 + }, + { + "x": 92.3991234758074, + "y": -191.56778900175766, + "z": 0.0 + }, + { + "x": 92.39896422441997, + "y": -190.52016996624275, + "z": 0.0 + }, + { + "x": 92.39880497303253, + "y": -189.47255093072778, + "z": 0.0 + }, + { + "x": 92.3986457216451, + "y": -188.42493189521286, + "z": 0.0 + }, + { + "x": 92.39848647025764, + "y": -187.3773128596979, + "z": 0.0 + }, + { + "x": 92.39832721887021, + "y": -186.32969382418304, + "z": 0.0 + } + ] + }, + { + "id": 288, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 101.42016370346977, + "y": -195.14088918733114, + "z": 0.0 + }, + { + "x": 100.3390649845846, + "y": -195.1408013378335, + "z": 0.0 + }, + { + "x": 99.25796626569947, + "y": -195.14071348833582, + "z": 0.0 + }, + { + "x": 98.28458553074684, + "y": -195.0862693380189, + "z": 0.0 + }, + { + "x": 97.40383131032577, + "y": -194.94725467952273, + "z": 0.0 + }, + { + "x": 96.57117246015427, + "y": -194.71855142809554, + "z": 0.0 + }, + { + "x": 95.76729748780213, + "y": -194.40123909394055, + "z": 0.0 + }, + { + "x": 95.00103637582578, + "y": -193.99850278004064, + "z": 0.0 + }, + { + "x": 94.34149960300874, + "y": -193.52119580541665, + "z": 0.0 + }, + { + "x": 93.73697547677894, + "y": -192.95750232040297, + "z": 0.0 + }, + { + "x": 93.25279717064232, + "y": -192.34030109965005, + "z": 0.0 + }, + { + "x": 92.87293777889991, + "y": -191.6641748771362, + "z": 0.0 + }, + { + "x": 92.59918080829013, + "y": -190.93805588245885, + "z": 0.0 + }, + { + "x": 92.43778694671191, + "y": -190.1777214558072, + "z": 0.0 + }, + { + "x": 92.39097979703983, + "y": -189.39669912723474, + "z": 0.0 + }, + { + "x": 92.398655949702, + "y": -188.49221612587775, + "z": 0.0 + }, + { + "x": 92.3984916089792, + "y": -187.4111174159142, + "z": 0.0 + }, + { + "x": 92.39832726825641, + "y": -186.3300187059507, + "z": 0.0 + } + ] + }, + { + "id": 291, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 88.39832726508598, + "y": -186.33030187493506, + "z": 0.0 + }, + { + "x": 88.3984916284713, + "y": -187.41154966795028, + "z": 0.0 + }, + { + "x": 88.3997952677014, + "y": -188.55999082671315, + "z": 0.0 + }, + { + "x": 88.44947052786367, + "y": -189.81148110381363, + "z": 0.0 + }, + { + "x": 88.62649926441631, + "y": -191.13890401186998, + "z": 0.0 + }, + { + "x": 88.98204913025093, + "y": -192.4501989944092, + "z": 0.0 + }, + { + "x": 89.52455006209007, + "y": -193.71280814792257, + "z": 0.0 + }, + { + "x": 90.22524077583694, + "y": -194.85626879619775, + "z": 0.0 + }, + { + "x": 91.06876625472273, + "y": -195.89837434016766, + "z": 0.0 + }, + { + "x": 92.04228546886993, + "y": -196.8217242502015, + "z": 0.0 + }, + { + "x": 93.12956285485541, + "y": -197.60902540519552, + "z": 0.0 + }, + { + "x": 94.31193266701067, + "y": -198.2459903012798, + "z": 0.0 + }, + { + "x": 95.57847859315382, + "y": -198.72371333585062, + "z": 0.0 + }, + { + "x": 96.9321412796205, + "y": -199.02686395609504, + "z": 0.0 + }, + { + "x": 98.14627840384554, + "y": -199.12410570010613, + "z": 0.0 + }, + { + "x": 99.25702742289741, + "y": -199.14071342525216, + "z": 0.0 + }, + { + "x": 100.33827522483548, + "y": -199.14080128686422, + "z": 0.0 + }, + { + "x": 101.41952302677362, + "y": -199.1408891484763, + "z": 0.0 + } + ] + }, + { + "id": 294, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 334.8270901428559, + "y": -120.57876996339137, + "z": 0.0 + }, + { + "x": 334.826438409234, + "y": -121.65777942783936, + "z": 0.0 + }, + { + "x": 334.82911918092043, + "y": -122.6225829958806, + "z": 0.0 + }, + { + "x": 334.78744991664456, + "y": -123.50619030723817, + "z": 0.0 + }, + { + "x": 334.67608453095875, + "y": -124.323014465026, + "z": 0.0 + }, + { + "x": 334.48218923292706, + "y": -125.07716990733435, + "z": 0.0 + }, + { + "x": 334.17478222813236, + "y": -125.79893448616556, + "z": 0.0 + }, + { + "x": 333.736351798824, + "y": -126.49931703182511, + "z": 0.0 + }, + { + "x": 333.2075836156737, + "y": -127.14427060363033, + "z": 0.0 + }, + { + "x": 332.5869206240877, + "y": -127.73394318759833, + "z": 0.0 + }, + { + "x": 331.951783150246, + "y": -128.22595479867536, + "z": 0.0 + }, + { + "x": 331.19135709749276, + "y": -128.65090699743394, + "z": 0.0 + }, + { + "x": 330.3850127040796, + "y": -128.99600822103105, + "z": 0.0 + }, + { + "x": 329.5488060070645, + "y": -129.25864203600875, + "z": 0.0 + }, + { + "x": 328.7330851925337, + "y": -129.43304937339707, + "z": 0.0 + }, + { + "x": 327.7768843418315, + "y": -129.50432910452471, + "z": 0.0 + }, + { + "x": 326.72022650283077, + "y": -129.51556751521045, + "z": 0.0 + }, + { + "x": 325.64121694925416, + "y": -129.5150854205275, + "z": 0.0 + } + ] + }, + { + "id": 297, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.63907988605513, + "y": -133.51508486495032, + "z": 0.0 + }, + { + "x": 326.72271965974255, + "y": -133.5155690283865, + "z": 0.0 + }, + { + "x": 327.88515173096323, + "y": -133.51453576338582, + "z": 0.0 + }, + { + "x": 329.12984339921354, + "y": -133.45934839617428, + "z": 0.0 + }, + { + "x": 330.44595125527894, + "y": -133.28444611390069, + "z": 0.0 + }, + { + "x": 331.8029942989284, + "y": -132.91945053130473, + "z": 0.0 + }, + { + "x": 333.0210008030467, + "y": -132.3794292227165, + "z": 0.0 + }, + { + "x": 334.15841440892063, + "y": -131.6948662890082, + "z": 0.0 + }, + { + "x": 335.19981972688277, + "y": -130.8782083731809, + "z": 0.0 + }, + { + "x": 336.1295437018704, + "y": -129.9468692721997, + "z": 0.0 + }, + { + "x": 336.9739198883692, + "y": -128.86302591188698, + "z": 0.0 + }, + { + "x": 337.63193009535365, + "y": -127.715469424601, + "z": 0.0 + }, + { + "x": 338.14372121746567, + "y": -126.5108268803566, + "z": 0.0 + }, + { + "x": 338.5150341584568, + "y": -125.2568558340516, + "z": 0.0 + }, + { + "x": 338.741154142397, + "y": -123.97452122052148, + "z": 0.0 + }, + { + "x": 338.8257801477764, + "y": -122.74880439198486, + "z": 0.0 + }, + { + "x": 338.82643467810203, + "y": -121.66516470780864, + "z": 0.0 + }, + { + "x": 338.82708920842776, + "y": -120.58152502363232, + "z": 0.0 + } + ] + }, + { + "id": 298, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 340.8131424361464, + "y": -143.67238981697838, + "z": 0.0 + }, + { + "x": 340.81377637306554, + "y": -142.62284455388536, + "z": 0.0 + }, + { + "x": 340.81441030998474, + "y": -141.57329929079253, + "z": 0.0 + }, + { + "x": 340.8150442469039, + "y": -140.5237540276993, + "z": 0.0 + }, + { + "x": 340.8156781838231, + "y": -139.4742087646065, + "z": 0.0 + }, + { + "x": 340.8163121207423, + "y": -138.42466350151346, + "z": 0.0 + }, + { + "x": 340.8169460576614, + "y": -137.37511823842024, + "z": 0.0 + }, + { + "x": 340.8175799945806, + "y": -136.32557297532742, + "z": 0.0 + }, + { + "x": 340.81821393149977, + "y": -135.2760277122342, + "z": 0.0 + }, + { + "x": 340.81884786841897, + "y": -134.22648244914137, + "z": 0.0 + }, + { + "x": 340.81948180533817, + "y": -133.17693718604835, + "z": 0.0 + }, + { + "x": 340.8201157422573, + "y": -132.12739192295513, + "z": 0.0 + }, + { + "x": 340.8207496791765, + "y": -131.07784665986227, + "z": 0.0 + }, + { + "x": 340.82138361609566, + "y": -130.02830139676905, + "z": 0.0 + }, + { + "x": 340.82201755301486, + "y": -128.97875613367623, + "z": 0.0 + }, + { + "x": 340.82265148993406, + "y": -127.92921087058322, + "z": 0.0 + }, + { + "x": 340.8232854268532, + "y": -126.87966560748997, + "z": 0.0 + }, + { + "x": 340.8239193637724, + "y": -125.83012034439716, + "z": 0.0 + }, + { + "x": 340.8245533006916, + "y": -124.78057508130414, + "z": 0.0 + }, + { + "x": 340.82518723761075, + "y": -123.7310298182109, + "z": 0.0 + }, + { + "x": 340.82582117452995, + "y": -122.68148455511809, + "z": 0.0 + }, + { + "x": 340.8264551114491, + "y": -121.63193929202485, + "z": 0.0 + }, + { + "x": 340.8270890483683, + "y": -120.58239402893204, + "z": 0.0 + } + ] + }, + { + "id": 300, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 338.8131428009756, + "y": -143.6711817951316, + "z": 0.0 + }, + { + "x": 338.8137767378947, + "y": -142.62163653203856, + "z": 0.0 + }, + { + "x": 338.814410674814, + "y": -141.57209126894566, + "z": 0.0 + }, + { + "x": 338.81504461173313, + "y": -140.52254600585252, + "z": 0.0 + }, + { + "x": 338.8156785486523, + "y": -139.4730007427596, + "z": 0.0 + }, + { + "x": 338.81631248557153, + "y": -138.4234554796666, + "z": 0.0 + }, + { + "x": 338.8169464224907, + "y": -137.37391021657345, + "z": 0.0 + }, + { + "x": 338.8175803594098, + "y": -136.32436495348054, + "z": 0.0 + }, + { + "x": 338.81821429632896, + "y": -135.2748196903874, + "z": 0.0 + }, + { + "x": 338.8188482332482, + "y": -134.2252744272945, + "z": 0.0 + }, + { + "x": 338.81948217016736, + "y": -133.17572916420147, + "z": 0.0 + }, + { + "x": 338.8201161070865, + "y": -132.12618390110833, + "z": 0.0 + }, + { + "x": 338.82075004400576, + "y": -131.07663863801537, + "z": 0.0 + }, + { + "x": 338.8213839809249, + "y": -130.02709337492226, + "z": 0.0 + }, + { + "x": 338.82201791784405, + "y": -128.97754811182932, + "z": 0.0 + }, + { + "x": 338.8226518547633, + "y": -127.92800284873633, + "z": 0.0 + }, + { + "x": 338.82328579168245, + "y": -126.87845758564319, + "z": 0.0 + }, + { + "x": 338.8239197286016, + "y": -125.82891232255027, + "z": 0.0 + }, + { + "x": 338.82455366552085, + "y": -124.77936705945724, + "z": 0.0 + }, + { + "x": 338.82518760244, + "y": -123.72982179636412, + "z": 0.0 + }, + { + "x": 338.82582153935914, + "y": -122.6802765332712, + "z": 0.0 + }, + { + "x": 338.8264554762783, + "y": -121.63073127017807, + "z": 0.0 + }, + { + "x": 338.82708941319754, + "y": -120.58118600708515, + "z": 0.0 + } + ] + }, + { + "id": 303, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 334.8270901428559, + "y": -120.57876996339137, + "z": 0.0 + }, + { + "x": 334.8264562059368, + "y": -121.62831522648449, + "z": 0.0 + }, + { + "x": 334.82582226901764, + "y": -122.67786048957741, + "z": 0.0 + }, + { + "x": 334.8251883320984, + "y": -123.72740575267053, + "z": 0.0 + }, + { + "x": 334.82455439517923, + "y": -124.77695101576346, + "z": 0.0 + }, + { + "x": 334.8239204582601, + "y": -125.82649627885648, + "z": 0.0 + }, + { + "x": 334.82328652134083, + "y": -126.8760415419496, + "z": 0.0 + }, + { + "x": 334.8226525844217, + "y": -127.92558680504254, + "z": 0.0 + }, + { + "x": 334.82201864750255, + "y": -128.97513206813557, + "z": 0.0 + }, + { + "x": 334.8213847105833, + "y": -130.02467733122867, + "z": 0.0 + }, + { + "x": 334.82075077366414, + "y": -131.0742225943216, + "z": 0.0 + }, + { + "x": 334.820116836745, + "y": -132.12376785741475, + "z": 0.0 + }, + { + "x": 334.81948289982586, + "y": -133.17331312050766, + "z": 0.0 + }, + { + "x": 334.8188489629066, + "y": -134.22285838360068, + "z": 0.0 + }, + { + "x": 334.81821502598746, + "y": -135.27240364669382, + "z": 0.0 + }, + { + "x": 334.8175810890683, + "y": -136.32194890978673, + "z": 0.0 + }, + { + "x": 334.81694715214906, + "y": -137.37149417287986, + "z": 0.0 + }, + { + "x": 334.8163132152299, + "y": -138.42103943597277, + "z": 0.0 + }, + { + "x": 334.81567927831077, + "y": -139.4705846990658, + "z": 0.0 + }, + { + "x": 334.8150453413915, + "y": -140.52012996215893, + "z": 0.0 + }, + { + "x": 334.81441140447237, + "y": -141.56967522525184, + "z": 0.0 + }, + { + "x": 334.8137774675532, + "y": -142.61922048834498, + "z": 0.0 + }, + { + "x": 334.8131435306341, + "y": -143.668765751438, + "z": 0.0 + } + ] + }, + { + "id": 306, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 325.63907988605513, + "y": -133.51508486495032, + "z": 0.0 + }, + { + "x": 326.67019718616996, + "y": -133.5155455616756, + "z": 0.0 + }, + { + "x": 327.6267617532583, + "y": -133.51458291459252, + "z": 0.0 + }, + { + "x": 328.52292898248186, + "y": -133.543939973342, + "z": 0.0 + }, + { + "x": 329.2742202450984, + "y": -133.6035686906993, + "z": 0.0 + }, + { + "x": 330.0201302280161, + "y": -133.770079203602, + "z": 0.0 + }, + { + "x": 330.77655635636665, + "y": -134.05646514360325, + "z": 0.0 + }, + { + "x": 331.49554132796845, + "y": -134.42382055127538, + "z": 0.0 + }, + { + "x": 332.1406372704785, + "y": -134.84261994710033, + "z": 0.0 + }, + { + "x": 332.71762879810797, + "y": -135.33178515700604, + "z": 0.0 + }, + { + "x": 333.2591096594325, + "y": -135.95221620441072, + "z": 0.0 + }, + { + "x": 333.733370070378, + "y": -136.6249454962728, + "z": 0.0 + }, + { + "x": 334.1250015663861, + "y": -137.3152949237132, + "z": 0.0 + }, + { + "x": 334.4237299295962, + "y": -138.01139148784793, + "z": 0.0 + }, + { + "x": 334.63255558517926, + "y": -138.80940768845167, + "z": 0.0 + }, + { + "x": 334.7599229345734, + "y": -139.6608399232524, + "z": 0.0 + }, + { + "x": 334.81501194915836, + "y": -140.57541410661145, + "z": 0.0 + }, + { + "x": 334.8143891429836, + "y": -141.60653132155363, + "z": 0.0 + }, + { + "x": 334.81376633680884, + "y": -142.63764853649582, + "z": 0.0 + }, + { + "x": 334.8131435306341, + "y": -143.66876575143795, + "z": 0.0 + } + ] + }, + { + "id": 309, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 338.8131428009756, + "y": -143.6711817951316, + "z": 0.0 + }, + { + "x": 338.8137965285674, + "y": -142.58887111618375, + "z": 0.0 + }, + { + "x": 338.8144502561594, + "y": -141.50656043723603, + "z": 0.0 + }, + { + "x": 338.80452378079116, + "y": -140.40517317962764, + "z": 0.0 + }, + { + "x": 338.7221956474102, + "y": -139.2014638193349, + "z": 0.0 + }, + { + "x": 338.4870991066125, + "y": -137.90405253847825, + "z": 0.0 + }, + { + "x": 338.0897824986565, + "y": -136.63336212248896, + "z": 0.0 + }, + { + "x": 337.55332253795063, + "y": -135.43436195830742, + "z": 0.0 + }, + { + "x": 336.88172244657096, + "y": -134.30613350150293, + "z": 0.0 + }, + { + "x": 336.08408380664827, + "y": -133.26372464196993, + "z": 0.0 + }, + { + "x": 335.16573655510433, + "y": -132.31945660580425, + "z": 0.0 + }, + { + "x": 334.13272510353136, + "y": -131.48915637822523, + "z": 0.0 + }, + { + "x": 333.0025310364399, + "y": -130.7917272269492, + "z": 0.0 + }, + { + "x": 331.794475882789, + "y": -130.2398661749147, + "z": 0.0 + }, + { + "x": 330.527098532855, + "y": -129.84208429620077, + "z": 0.0 + }, + { + "x": 329.21984492042554, + "y": -129.60456021730624, + "z": 0.0 + }, + { + "x": 327.9164407754452, + "y": -129.51916243893834, + "z": 0.0 + }, + { + "x": 326.72353082855994, + "y": -129.5155689915624, + "z": 0.0 + }, + { + "x": 325.6412200602107, + "y": -129.51508542191746, + "z": 0.0 + } + ] + }, + { + "id": 312, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 101.42088944063468, + "y": -129.4149051882574, + "z": 0.0 + }, + { + "x": 100.36794814680857, + "y": -129.41443474070897, + "z": 0.0 + }, + { + "x": 99.31500685298246, + "y": -129.41396429316055, + "z": 0.0 + }, + { + "x": 98.30383981392947, + "y": -129.3924442708536, + "z": 0.0 + }, + { + "x": 97.38637308458796, + "y": -129.30831693031158, + "z": 0.0 + }, + { + "x": 96.70134847805133, + "y": -129.09939945587251, + "z": 0.0 + }, + { + "x": 95.97200630061965, + "y": -128.7864127775635, + "z": 0.0 + }, + { + "x": 95.28913333276736, + "y": -128.38290542597278, + "z": 0.0 + }, + { + "x": 94.66256411964747, + "y": -127.89454957337901, + "z": 0.0 + }, + { + "x": 94.11758375964698, + "y": -127.33284893767612, + "z": 0.0 + }, + { + "x": 93.6843654291251, + "y": -126.71718361991702, + "z": 0.0 + }, + { + "x": 93.25681560147831, + "y": -125.9858391418419, + "z": 0.0 + }, + { + "x": 92.90470702382066, + "y": -125.21397935800047, + "z": 0.0 + }, + { + "x": 92.63198694553196, + "y": -124.40914583329769, + "z": 0.0 + }, + { + "x": 92.47881422598947, + "y": -123.6229887138957, + "z": 0.0 + }, + { + "x": 92.41383599195208, + "y": -122.8063733641458, + "z": 0.0 + }, + { + "x": 92.38746542147446, + "y": -121.88066414921204, + "z": 0.0 + }, + { + "x": 92.38838000711462, + "y": -120.8929742241692, + "z": 0.0 + }, + { + "x": 92.38821994666225, + "y": -119.84003283741217, + "z": 0.0 + } + ] + }, + { + "id": 315, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 88.38821994146043, + "y": -119.84030264315575, + "z": 0.0 + }, + { + "x": 88.38837809887212, + "y": -120.8807250706138, + "z": 0.0 + }, + { + "x": 88.39108030715192, + "y": -122.02168901593632, + "z": 0.0 + }, + { + "x": 88.46172661639932, + "y": -123.24696762096069, + "z": 0.0 + }, + { + "x": 88.65163376427458, + "y": -124.47952527394865, + "z": 0.0 + }, + { + "x": 88.96882473851097, + "y": -125.68535880665443, + "z": 0.0 + }, + { + "x": 89.40991646639421, + "y": -126.85168614146029, + "z": 0.0 + }, + { + "x": 89.97029178657252, + "y": -127.96611544907387, + "z": 0.0 + }, + { + "x": 90.65011037520333, + "y": -129.02431893537982, + "z": 0.0 + }, + { + "x": 91.46501813655146, + "y": -130.0258988673246, + "z": 0.0 + }, + { + "x": 92.39252006977256, + "y": -130.91241263730257, + "z": 0.0 + }, + { + "x": 93.42051250911672, + "y": -131.67941488778277, + "z": 0.0 + }, + { + "x": 94.53360561789397, + "y": -132.3151872514357, + "z": 0.0 + }, + { + "x": 95.71546101136482, + "y": -132.8105823365878, + "z": 0.0 + }, + { + "x": 96.94879613644846, + "y": -133.15842236729776, + "z": 0.0 + }, + { + "x": 98.18776931068606, + "y": -133.3522153716725, + "z": 0.0 + }, + { + "x": 99.33790052318741, + "y": -133.41397492115766, + "z": 0.0 + }, + { + "x": 100.37832285881944, + "y": -133.41443977531426, + "z": 0.0 + }, + { + "x": 101.41874519445152, + "y": -133.4149046294709, + "z": 0.0 + } + ] + }, + { + "id": 318, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 101.42088944063467, + "y": -129.4149051882574, + "z": 0.0 + }, + { + "x": 100.34918903743696, + "y": -129.41442635925688, + "z": 0.0 + }, + { + "x": 99.27748863423932, + "y": -129.41394753025634, + "z": 0.0 + }, + { + "x": 98.2057882310415, + "y": -129.41346870125585, + "z": 0.0 + }, + { + "x": 96.9790928920085, + "y": -129.50438028664234, + "z": 0.0 + }, + { + "x": 95.72699472251898, + "y": -129.72334221739763, + "z": 0.0 + }, + { + "x": 94.47718775569217, + "y": -130.09316132412522, + "z": 0.0 + }, + { + "x": 93.20291881911453, + "y": -130.70787150482607, + "z": 0.0 + }, + { + "x": 92.09516742532853, + "y": -131.44996192328514, + "z": 0.0 + }, + { + "x": 91.10692769644493, + "y": -132.30271654696537, + "z": 0.0 + }, + { + "x": 90.21746230150107, + "y": -133.29915320805418, + "z": 0.0 + }, + { + "x": 89.45902662178946, + "y": -134.54870352378, + "z": 0.0 + }, + { + "x": 88.94031665824139, + "y": -135.76772659417503, + "z": 0.0 + }, + { + "x": 88.58295337176378, + "y": -137.04449451862712, + "z": 0.0 + }, + { + "x": 88.41675272056585, + "y": -138.42152323901217, + "z": 0.0 + }, + { + "x": 88.3914370555155, + "y": -139.66810737551634, + "z": 0.0 + }, + { + "x": 88.39140126344014, + "y": -140.76830532949788, + "z": 0.0 + }, + { + "x": 88.39156417551544, + "y": -141.84000582728214, + "z": 0.0 + } + ] + }, + { + "id": 321, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 92.39156417438086, + "y": -141.83969433821727, + "z": 0.0 + }, + { + "x": 92.39140217513292, + "y": -140.7739987822551, + "z": 0.0 + }, + { + "x": 92.391240175885, + "y": -139.7083032262929, + "z": 0.0 + }, + { + "x": 92.41837629818835, + "y": -138.69631264740704, + "z": 0.0 + }, + { + "x": 92.52586734119478, + "y": -137.8119269363075, + "z": 0.0 + }, + { + "x": 92.74283833555268, + "y": -137.0624991874285, + "z": 0.0 + }, + { + "x": 93.06753376102517, + "y": -136.3852570186857, + "z": 0.0 + }, + { + "x": 93.495580281799, + "y": -135.75125720493622, + "z": 0.0 + }, + { + "x": 94.01667929190448, + "y": -135.17314606117776, + "z": 0.0 + }, + { + "x": 94.61882399787538, + "y": -134.66403625537419, + "z": 0.0 + }, + { + "x": 95.29395983371364, + "y": -134.22585973512975, + "z": 0.0 + }, + { + "x": 96.02427251934127, + "y": -133.87263924746935, + "z": 0.0 + }, + { + "x": 96.7940290496316, + "y": -133.6140008174741, + "z": 0.0 + }, + { + "x": 97.59150682567487, + "y": -133.45419602327453, + "z": 0.0 + }, + { + "x": 98.37060357830944, + "y": -133.4171244960692, + "z": 0.0 + }, + { + "x": 99.30449982593655, + "y": -133.4138869326253, + "z": 0.0 + }, + { + "x": 100.35309976405674, + "y": -133.41442850579415, + "z": 0.0 + }, + { + "x": 101.41879522596236, + "y": -133.41490465182466, + "z": 0.0 + } + ] + }, + { + "id": 324, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 92.39156417438082, + "y": -141.83969433821727, + "z": 0.0 + }, + { + "x": 92.39140492299339, + "y": -140.79207530270236, + "z": 0.0 + }, + { + "x": 92.39124567160594, + "y": -139.7444562671874, + "z": 0.0 + }, + { + "x": 92.39108642021851, + "y": -138.69683723167248, + "z": 0.0 + }, + { + "x": 92.39092716883108, + "y": -137.64921819615756, + "z": 0.0 + }, + { + "x": 92.39076791744364, + "y": -136.6015991606426, + "z": 0.0 + }, + { + "x": 92.39060866605621, + "y": -135.55398012512768, + "z": 0.0 + }, + { + "x": 92.39044941466878, + "y": -134.50636108961277, + "z": 0.0 + }, + { + "x": 92.39029016328135, + "y": -133.45874205409785, + "z": 0.0 + }, + { + "x": 92.3901309118939, + "y": -132.41112301858288, + "z": 0.0 + }, + { + "x": 92.38997166050648, + "y": -131.36350398306797, + "z": 0.0 + }, + { + "x": 92.38981240911905, + "y": -130.31588494755306, + "z": 0.0 + }, + { + "x": 92.3896531577316, + "y": -129.2682659120381, + "z": 0.0 + }, + { + "x": 92.38949390634417, + "y": -128.22064687652318, + "z": 0.0 + }, + { + "x": 92.38933465495673, + "y": -127.17302784100823, + "z": 0.0 + }, + { + "x": 92.3891754035693, + "y": -126.12540880549332, + "z": 0.0 + }, + { + "x": 92.38901615218187, + "y": -125.07778976997838, + "z": 0.0 + }, + { + "x": 92.38885690079442, + "y": -124.03017073446344, + "z": 0.0 + }, + { + "x": 92.38869764940699, + "y": -122.98255169894853, + "z": 0.0 + }, + { + "x": 92.38853839801956, + "y": -121.93493266343359, + "z": 0.0 + }, + { + "x": 92.38837914663212, + "y": -120.88731362791864, + "z": 0.0 + }, + { + "x": 92.38821989524469, + "y": -119.83969459240373, + "z": 0.0 + } + ] + }, + { + "id": 325, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 86.38821996456826, + "y": -119.84060666853175, + "z": 0.0 + }, + { + "x": 86.3883792159557, + "y": -120.88822570404673, + "z": 0.0 + }, + { + "x": 86.38853846734314, + "y": -121.9358447395616, + "z": 0.0 + }, + { + "x": 86.38869771873057, + "y": -122.98346377507654, + "z": 0.0 + }, + { + "x": 86.388856970118, + "y": -124.03108281059153, + "z": 0.0 + }, + { + "x": 86.38901622150544, + "y": -125.0787018461064, + "z": 0.0 + }, + { + "x": 86.38917547289287, + "y": -126.12632088162133, + "z": 0.0 + }, + { + "x": 86.3893347242803, + "y": -127.17393991713632, + "z": 0.0 + }, + { + "x": 86.38949397566775, + "y": -128.22155895265118, + "z": 0.0 + }, + { + "x": 86.38965322705518, + "y": -129.26917798816618, + "z": 0.0 + }, + { + "x": 86.38981247844262, + "y": -130.31679702368103, + "z": 0.0 + }, + { + "x": 86.38997172983005, + "y": -131.36441605919597, + "z": 0.0 + }, + { + "x": 86.39013098121748, + "y": -132.41203509471094, + "z": 0.0 + }, + { + "x": 86.39029023260493, + "y": -133.45965413022583, + "z": 0.0 + }, + { + "x": 86.39044948399236, + "y": -134.50727316574077, + "z": 0.0 + }, + { + "x": 86.39060873537979, + "y": -135.55489220125568, + "z": 0.0 + }, + { + "x": 86.39076798676722, + "y": -136.60251123677068, + "z": 0.0 + }, + { + "x": 86.39092723815466, + "y": -137.65013027228557, + "z": 0.0 + }, + { + "x": 86.39108648954209, + "y": -138.69774930780048, + "z": 0.0 + }, + { + "x": 86.39124574092952, + "y": -139.74536834331548, + "z": 0.0 + }, + { + "x": 86.39140499231696, + "y": -140.79298737883033, + "z": 0.0 + }, + { + "x": 86.3915642437044, + "y": -141.84060641434527, + "z": 0.0 + } + ] + }, + { + "id": 327, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 88.3882199414604, + "y": -119.84030264315575, + "z": 0.0 + }, + { + "x": 88.38837919284784, + "y": -120.8879216786707, + "z": 0.0 + }, + { + "x": 88.38853844423528, + "y": -121.9355407141856, + "z": 0.0 + }, + { + "x": 88.38869769562271, + "y": -122.98315974970055, + "z": 0.0 + }, + { + "x": 88.38885694701014, + "y": -124.03077878521549, + "z": 0.0 + }, + { + "x": 88.38901619839758, + "y": -125.0783978207304, + "z": 0.0 + }, + { + "x": 88.38917544978501, + "y": -126.12601685624531, + "z": 0.0 + }, + { + "x": 88.38933470117244, + "y": -127.17363589176028, + "z": 0.0 + }, + { + "x": 88.38949395255989, + "y": -128.2212549272752, + "z": 0.0 + }, + { + "x": 88.38965320394732, + "y": -129.26887396279017, + "z": 0.0 + }, + { + "x": 88.38981245533476, + "y": -130.31649299830502, + "z": 0.0 + }, + { + "x": 88.38997170672219, + "y": -131.36411203382, + "z": 0.0 + }, + { + "x": 88.39013095810962, + "y": -132.4117310693349, + "z": 0.0 + }, + { + "x": 88.39029020949707, + "y": -133.45935010484982, + "z": 0.0 + }, + { + "x": 88.3904494608845, + "y": -134.5069691403648, + "z": 0.0 + }, + { + "x": 88.39060871227193, + "y": -135.5545881758797, + "z": 0.0 + }, + { + "x": 88.39076796365936, + "y": -136.60220721139467, + "z": 0.0 + }, + { + "x": 88.3909272150468, + "y": -137.64982624690958, + "z": 0.0 + }, + { + "x": 88.39108646643423, + "y": -138.6974452824245, + "z": 0.0 + }, + { + "x": 88.39124571782166, + "y": -139.74506431793947, + "z": 0.0 + }, + { + "x": 88.3914049692091, + "y": -140.79268335345432, + "z": 0.0 + }, + { + "x": 88.39156422059654, + "y": -141.8403023889693, + "z": 0.0 + } + ] + }, + { + "id": 330, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 154.02380798404414, + "y": -46.19753632639322, + "z": 0.0 + }, + { + "x": 154.0225405266159, + "y": -47.24090674538898, + "z": 0.0 + }, + { + "x": 154.0212957833844, + "y": -48.27687009781563, + "z": 0.0 + }, + { + "x": 154.0224864762247, + "y": -49.17072627310411, + "z": 0.0 + }, + { + "x": 153.97584197898615, + "y": -49.95867202474612, + "z": 0.0 + }, + { + "x": 153.82494572714774, + "y": -50.74658892864789, + "z": 0.0 + }, + { + "x": 153.58120716526844, + "y": -51.50973756548072, + "z": 0.0 + }, + { + "x": 153.2478967703762, + "y": -52.238362120680605, + "z": 0.0 + }, + { + "x": 152.85518620641, + "y": -52.89185296315288, + "z": 0.0 + }, + { + "x": 152.36821934903156, + "y": -53.49002530084883, + "z": 0.0 + }, + { + "x": 151.77805426447105, + "y": -54.03404810038104, + "z": 0.0 + }, + { + "x": 151.12816900523492, + "y": -54.502702172032784, + "z": 0.0 + }, + { + "x": 150.42705192181336, + "y": -54.890159888561826, + "z": 0.0 + }, + { + "x": 149.70552810564578, + "y": -55.18594301814386, + "z": 0.0 + }, + { + "x": 148.97820888894648, + "y": -55.38229475154137, + "z": 0.0 + }, + { + "x": 148.07093106567913, + "y": -55.468392753747764, + "z": 0.0 + }, + { + "x": 147.0768176160945, + "y": -55.49309497508044, + "z": 0.0 + }, + { + "x": 146.033446435009, + "y": -55.493222112765466, + "z": 0.0 + }, + { + "x": 144.99007525392352, + "y": -55.49334925045048, + "z": 0.0 + } + ] + }, + { + "id": 333, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 144.9902393330799, + "y": -59.49334926015318, + "z": 0.0 + }, + { + "x": 146.03540288443622, + "y": -59.49322190406285, + "z": 0.0 + }, + { + "x": 147.14476546935714, + "y": -59.492056076550405, + "z": 0.0 + }, + { + "x": 148.33262517418535, + "y": -59.44855439963858, + "z": 0.0 + }, + { + "x": 149.60538379079756, + "y": -59.30093427784442, + "z": 0.0 + }, + { + "x": 150.90060319706703, + "y": -58.985014243942075, + "z": 0.0 + }, + { + "x": 152.08417688840183, + "y": -58.51452779035827, + "z": 0.0 + }, + { + "x": 153.2043480453745, + "y": -57.91271930306415, + "z": 0.0 + }, + { + "x": 154.25115479129303, + "y": -57.18432584118074, + "z": 0.0 + }, + { + "x": 155.2151905323367, + "y": -56.32888544962101, + "z": 0.0 + }, + { + "x": 156.10325086827027, + "y": -55.30748534345081, + "z": 0.0 + }, + { + "x": 156.80994358117522, + "y": -54.18961306282728, + "z": 0.0 + }, + { + "x": 157.34809131646162, + "y": -53.00526040834794, + "z": 0.0 + }, + { + "x": 157.72881984867638, + "y": -51.762961636059096, + "z": 0.0 + }, + { + "x": 157.94460164983178, + "y": -50.51353312774852, + "z": 0.0 + }, + { + "x": 158.01999573792733, + "y": -49.3382052613273, + "z": 0.0 + }, + { + "x": 158.02126537267566, + "y": -48.29304247336981, + "z": 0.0 + }, + { + "x": 158.02253500742398, + "y": -47.24787968541243, + "z": 0.0 + }, + { + "x": 158.02380464217237, + "y": -46.20271689745499, + "z": 0.0 + } + ] + }, + { + "id": 336, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 154.02380798404414, + "y": -46.19753632639322, + "z": 0.0 + }, + { + "x": 154.02254778720277, + "y": -47.234929833323704, + "z": 0.0 + }, + { + "x": 154.0220914396506, + "y": -48.33150366522665, + "z": 0.0 + }, + { + "x": 154.05846020639342, + "y": -49.48693261271582, + "z": 0.0 + }, + { + "x": 154.20277863371672, + "y": -50.83323725619208, + "z": 0.0 + }, + { + "x": 154.5289316112454, + "y": -52.066952903777064, + "z": 0.0 + }, + { + "x": 154.99269289011525, + "y": -53.23838843678435, + "z": 0.0 + }, + { + "x": 155.585298044496, + "y": -54.34977085110656, + "z": 0.0 + }, + { + "x": 156.35177765287185, + "y": -55.44682750656724, + "z": 0.0 + }, + { + "x": 157.22845126186928, + "y": -56.37736680088315, + "z": 0.0 + }, + { + "x": 158.17629805628042, + "y": -57.17180132816905, + "z": 0.0 + }, + { + "x": 159.19562702626834, + "y": -57.86450820303658, + "z": 0.0 + }, + { + "x": 160.34457511087447, + "y": -58.480341225935305, + "z": 0.0 + }, + { + "x": 161.52777689166018, + "y": -58.92780889150592, + "z": 0.0 + }, + { + "x": 162.72257395798567, + "y": -59.232723132560764, + "z": 0.0 + }, + { + "x": 163.9265285225684, + "y": -59.41699686668909, + "z": 0.0 + }, + { + "x": 165.09545063910528, + "y": -59.49089938414677, + "z": 0.0 + }, + { + "x": 166.1328449037599, + "y": -59.49077297476566, + "z": 0.0 + }, + { + "x": 167.1702391684145, + "y": -59.49064656538455, + "z": 0.0 + } + ] + }, + { + "id": 339, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 167.16975175727498, + "y": -55.49064659508076, + "z": 0.0 + }, + { + "x": 166.1275959090633, + "y": -55.49077358467409, + "z": 0.0 + }, + { + "x": 165.08544006085165, + "y": -55.49090057426743, + "z": 0.0 + }, + { + "x": 164.15696033917465, + "y": -55.436032284142954, + "z": 0.0 + }, + { + "x": 163.29745779390208, + "y": -55.306797258467256, + "z": 0.0 + }, + { + "x": 162.4896909874122, + "y": -55.0948741218035, + "z": 0.0 + }, + { + "x": 161.7535005053105, + "y": -54.794716920603875, + "z": 0.0 + }, + { + "x": 161.0666842268726, + "y": -54.40656115534773, + "z": 0.0 + }, + { + "x": 160.38320540908438, + "y": -53.92896674701984, + "z": 0.0 + }, + { + "x": 159.7578042552214, + "y": -53.384689518722695, + "z": 0.0 + }, + { + "x": 159.21527538386513, + "y": -52.78400531379128, + "z": 0.0 + }, + { + "x": 158.83996895929573, + "y": -52.17304058119422, + "z": 0.0 + }, + { + "x": 158.49249840672923, + "y": -51.45319407003326, + "z": 0.0 + }, + { + "x": 158.2337868647591, + "y": -50.697068790528874, + "z": 0.0 + }, + { + "x": 158.06719322456945, + "y": -49.91369373265339, + "z": 0.0 + }, + { + "x": 158.0261760820918, + "y": -49.161618091827535, + "z": 0.0 + }, + { + "x": 158.02114821720056, + "y": -48.262173506744624, + "z": 0.0 + }, + { + "x": 158.02253863907634, + "y": -47.24489011075576, + "z": 0.0 + }, + { + "x": 158.02380462015304, + "y": -46.20273502374609, + "z": 0.0 + } + ] + }, + { + "id": 342, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 167.16975175727498, + "y": -55.49064659508076, + "z": 0.0 + }, + { + "x": 166.11356128892572, + "y": -55.490775294831636, + "z": 0.0 + }, + { + "x": 165.0573708205764, + "y": -55.490903994582524, + "z": 0.0 + }, + { + "x": 164.00118035222715, + "y": -55.49103269433341, + "z": 0.0 + }, + { + "x": 162.9449898838779, + "y": -55.4911613940843, + "z": 0.0 + }, + { + "x": 161.88879941552864, + "y": -55.49129009383519, + "z": 0.0 + }, + { + "x": 160.83260894717938, + "y": -55.49141879358608, + "z": 0.0 + }, + { + "x": 159.77641847883012, + "y": -55.49154749333697, + "z": 0.0 + }, + { + "x": 158.72022801048087, + "y": -55.491676193087855, + "z": 0.0 + }, + { + "x": 157.66403754213155, + "y": -55.49180489283874, + "z": 0.0 + }, + { + "x": 156.60784707378232, + "y": -55.49193359258962, + "z": 0.0 + }, + { + "x": 155.55165660543304, + "y": -55.492062292340506, + "z": 0.0 + }, + { + "x": 154.49546613708378, + "y": -55.492190992091395, + "z": 0.0 + }, + { + "x": 153.43927566873452, + "y": -55.49231969184228, + "z": 0.0 + }, + { + "x": 152.38308520038527, + "y": -55.49244839159317, + "z": 0.0 + }, + { + "x": 151.326894732036, + "y": -55.49257709134406, + "z": 0.0 + }, + { + "x": 150.2707042636867, + "y": -55.49270579109495, + "z": 0.0 + }, + { + "x": 149.21451379533744, + "y": -55.49283449084584, + "z": 0.0 + }, + { + "x": 148.15832332698818, + "y": -55.492963190596726, + "z": 0.0 + }, + { + "x": 147.10213285863895, + "y": -55.4930918903476, + "z": 0.0 + }, + { + "x": 146.04594239028967, + "y": -55.49322059009849, + "z": 0.0 + }, + { + "x": 144.9897519219404, + "y": -55.49334928984938, + "z": 0.0 + } + ] + }, + { + "id": 343, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 144.99048303864967, + "y": -61.493349245305076, + "z": 0.0 + }, + { + "x": 146.04667350699893, + "y": -61.49322054555419, + "z": 0.0 + }, + { + "x": 147.10286397534819, + "y": -61.4930918458033, + "z": 0.0 + }, + { + "x": 148.15905444369747, + "y": -61.49296314605242, + "z": 0.0 + }, + { + "x": 149.21524491204673, + "y": -61.49283444630153, + "z": 0.0 + }, + { + "x": 150.27143538039599, + "y": -61.49270574655064, + "z": 0.0 + }, + { + "x": 151.32762584874524, + "y": -61.49257704679975, + "z": 0.0 + }, + { + "x": 152.38381631709453, + "y": -61.49244834704887, + "z": 0.0 + }, + { + "x": 153.44000678544379, + "y": -61.49231964729798, + "z": 0.0 + }, + { + "x": 154.49619725379307, + "y": -61.492190947547094, + "z": 0.0 + }, + { + "x": 155.55238772214233, + "y": -61.492062247796206, + "z": 0.0 + }, + { + "x": 156.60857819049156, + "y": -61.49193354804532, + "z": 0.0 + }, + { + "x": 157.66476865884084, + "y": -61.491804848294436, + "z": 0.0 + }, + { + "x": 158.72095912719013, + "y": -61.49167614854355, + "z": 0.0 + }, + { + "x": 159.77714959553938, + "y": -61.49154744879266, + "z": 0.0 + }, + { + "x": 160.8333400638886, + "y": -61.49141874904177, + "z": 0.0 + }, + { + "x": 161.88953053223793, + "y": -61.49129004929089, + "z": 0.0 + }, + { + "x": 162.94572100058718, + "y": -61.49116134954, + "z": 0.0 + }, + { + "x": 164.00191146893644, + "y": -61.49103264978911, + "z": 0.0 + }, + { + "x": 165.0581019372857, + "y": -61.49090395003822, + "z": 0.0 + }, + { + "x": 166.11429240563496, + "y": -61.490775250287335, + "z": 0.0 + }, + { + "x": 167.1704828739842, + "y": -61.490646550536454, + "z": 0.0 + } + ] + }, + { + "id": 345, + "map_element_id": 2, + "type": "lane", + "geometry": [ + { + "x": 144.9902393330799, + "y": -59.49334926015318, + "z": 0.0 + }, + { + "x": 146.04642980142916, + "y": -59.49322056040229, + "z": 0.0 + }, + { + "x": 147.10262026977844, + "y": -59.493091860651404, + "z": 0.0 + }, + { + "x": 148.15881073812773, + "y": -59.492963160900516, + "z": 0.0 + }, + { + "x": 149.21500120647698, + "y": -59.49283446114963, + "z": 0.0 + }, + { + "x": 150.27119167482624, + "y": -59.49270576139874, + "z": 0.0 + }, + { + "x": 151.3273821431755, + "y": -59.49257706164785, + "z": 0.0 + }, + { + "x": 152.38357261152476, + "y": -59.492448361896976, + "z": 0.0 + }, + { + "x": 153.439763079874, + "y": -59.49231966214609, + "z": 0.0 + }, + { + "x": 154.49595354822333, + "y": -59.4921909623952, + "z": 0.0 + }, + { + "x": 155.55214401657258, + "y": -59.49206226264431, + "z": 0.0 + }, + { + "x": 156.6083344849218, + "y": -59.49193356289342, + "z": 0.0 + }, + { + "x": 157.6645249532711, + "y": -59.491804863142534, + "z": 0.0 + }, + { + "x": 158.72071542162035, + "y": -59.491676163391645, + "z": 0.0 + }, + { + "x": 159.7769058899696, + "y": -59.49154746364076, + "z": 0.0 + }, + { + "x": 160.83309635831887, + "y": -59.49141876388987, + "z": 0.0 + }, + { + "x": 161.88928682666818, + "y": -59.491290064138994, + "z": 0.0 + }, + { + "x": 162.94547729501744, + "y": -59.491161364388105, + "z": 0.0 + }, + { + "x": 164.0016677633667, + "y": -59.49103266463722, + "z": 0.0 + }, + { + "x": 165.05785823171595, + "y": -59.49090396488633, + "z": 0.0 + }, + { + "x": 166.1140487000652, + "y": -59.49077526513544, + "z": 0.0 + }, + { + "x": 167.17023916841447, + "y": -59.49064656538455, + "z": 0.0 + } + ] + }, + { + "id": 130, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 325.6278797108732, + "y": -3.988677721665928, + "z": 0.0 + }, + { + "x": 326.6645461982845, + "y": -3.989228436985744, + "z": 0.0 + }, + { + "x": 327.7012126856958, + "y": -3.9897791523055597, + "z": 0.0 + }, + { + "x": 328.7378791731071, + "y": -3.9903298676253756, + "z": 0.0 + }, + { + "x": 329.5221086572586, + "y": -4.047669202376462, + "z": 0.0 + }, + { + "x": 330.1072270974078, + "y": -4.173581082904699, + "z": 0.0 + }, + { + "x": 330.6144262143476, + "y": -4.360288299602975, + "z": 0.0 + }, + { + "x": 331.0954172342736, + "y": -4.608571370574099, + "z": 0.0 + }, + { + "x": 331.54334222118945, + "y": -4.915257127838937, + "z": 0.0 + }, + { + "x": 331.843444119078, + "y": -5.226392769639217, + "z": 0.0 + }, + { + "x": 332.1744536934619, + "y": -5.632692116040604, + "z": 0.0 + }, + { + "x": 332.45058407826144, + "y": -6.077457497319008, + "z": 0.0 + }, + { + "x": 332.66638742822687, + "y": -6.552465214205474, + "z": 0.0 + }, + { + "x": 332.81977427548895, + "y": -7.051954724123156, + "z": 0.0 + }, + { + "x": 332.9081272804868, + "y": -7.568500980156154, + "z": 0.0 + }, + { + "x": 332.895030754424, + "y": -7.996637987132772, + "z": 0.0 + }, + { + "x": 332.89493219600683, + "y": -8.76330403472345, + "z": 0.0 + }, + { + "x": 332.8940312132095, + "y": -9.750603823797125, + "z": 0.0 + }, + { + "x": 332.89340505523876, + "y": -10.787270268385383, + "z": 0.0 + } + ] + }, + { + "id": 145, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 340.89340340765136, + "y": -10.792414056232396, + "z": 0.0 + }, + { + "x": 340.89403578359634, + "y": -9.745453140274215, + "z": 0.0 + }, + { + "x": 340.89466815954137, + "y": -8.698492224316256, + "z": 0.0 + }, + { + "x": 340.89530053548634, + "y": -7.651531308357863, + "z": 0.0 + }, + { + "x": 340.9521407676781, + "y": -6.852378699784743, + "z": 0.0 + }, + { + "x": 341.06688111734144, + "y": -6.135182389188954, + "z": 0.0 + }, + { + "x": 341.22823435714616, + "y": -5.902494853710985, + "z": 0.0 + }, + { + "x": 341.46602833031625, + "y": -5.569414699066449, + "z": 0.0 + }, + { + "x": 341.7994848809484, + "y": -5.165549665951211, + "z": 0.0 + }, + { + "x": 342.13051965040574, + "y": -4.903219459030506, + "z": 0.0 + }, + { + "x": 342.4962616320244, + "y": -4.698227530630974, + "z": 0.0 + }, + { + "x": 343.01185668684076, + "y": -4.43994024407544, + "z": 0.0 + }, + { + "x": 343.5712427807595, + "y": -4.230705239368477, + "z": 0.0 + }, + { + "x": 344.1507044170504, + "y": -4.085364578513123, + "z": 0.0 + }, + { + "x": 344.743421203216, + "y": -4.005725125338712, + "z": 0.0 + }, + { + "x": 345.34990134625497, + "y": -3.9905056740214206, + "z": 0.0 + }, + { + "x": 346.13395460346004, + "y": -3.9995713019347696, + "z": 0.0 + }, + { + "x": 347.1809155626665, + "y": -4.000127486056169, + "z": 0.0 + }, + { + "x": 348.227876521873, + "y": -4.0006836701775725, + "z": 0.0 + } + ] + }, + { + "id": 157, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 160.06653921314967, + "y": -11.024850911531969, + "z": 0.0 + }, + { + "x": 160.0678134667562, + "y": -9.975885881460881, + "z": 0.0 + }, + { + "x": 160.06908772036275, + "y": -8.926920851389792, + "z": 0.0 + }, + { + "x": 160.07036197396928, + "y": -7.877955821318704, + "z": 0.0 + }, + { + "x": 160.1246918567833, + "y": -7.060305047376277, + "z": 0.0 + }, + { + "x": 160.2374873644286, + "y": -6.342829622261114, + "z": 0.0 + }, + { + "x": 160.41028615430943, + "y": -5.865624377840656, + "z": 0.0 + }, + { + "x": 160.62898947587635, + "y": -5.516198652845463, + "z": 0.0 + }, + { + "x": 160.9587560838947, + "y": -5.0263174378290145, + "z": 0.0 + }, + { + "x": 161.34037650307783, + "y": -4.58232228373524, + "z": 0.0 + }, + { + "x": 161.6532871645665, + "y": -4.377425268002961, + "z": 0.0 + }, + { + "x": 162.012325453008, + "y": -4.210009421664965, + "z": 0.0 + }, + { + "x": 162.4819073479187, + "y": -4.032043747178901, + "z": 0.0 + }, + { + "x": 162.97457927269812, + "y": -3.9185762591816546, + "z": 0.0 + }, + { + "x": 163.2561113559408, + "y": -3.9648852550583116, + "z": 0.0 + }, + { + "x": 164.00033558629985, + "y": -3.954801759477505, + "z": 0.0 + }, + { + "x": 164.93268600146294, + "y": -3.956601518087601, + "z": 0.0 + }, + { + "x": 165.98165179952323, + "y": -3.956713473436086, + "z": 0.0 + }, + { + "x": 167.03061759758353, + "y": -3.9568254287845774, + "z": 0.0 + }, + { + "x": 168.07958339564385, + "y": -3.956937384133062, + "z": 0.0 + } + ] + }, + { + "id": 160, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 144.95958352573157, + "y": -3.9544698035434926, + "z": 0.0 + }, + { + "x": 146.0212169873974, + "y": -3.954583110902402, + "z": 0.0 + }, + { + "x": 147.0828504490632, + "y": -3.954696418261311, + "z": 0.0 + }, + { + "x": 148.144483910729, + "y": -3.954809725620221, + "z": 0.0 + }, + { + "x": 149.05967964890726, + "y": -3.990641340582388, + "z": 0.0 + }, + { + "x": 149.83780177823488, + "y": -4.082760914533853, + "z": 0.0 + }, + { + "x": 150.1743168945339, + "y": -4.242647825577707, + "z": 0.0 + }, + { + "x": 150.61969315594254, + "y": -4.4830122559322945, + "z": 0.0 + }, + { + "x": 151.07615455507627, + "y": -4.797092817882984, + "z": 0.0 + }, + { + "x": 151.48742320962174, + "y": -5.166058802470898, + "z": 0.0 + }, + { + "x": 151.67611237008094, + "y": -5.475440162631369, + "z": 0.0 + }, + { + "x": 151.84574867678245, + "y": -5.848483006759167, + "z": 0.0 + }, + { + "x": 152.00442107081673, + "y": -6.310109105308325, + "z": 0.0 + }, + { + "x": 152.09632190626255, + "y": -6.791790352034089, + "z": 0.0 + }, + { + "x": 152.07837964471057, + "y": -7.181400923116529, + "z": 0.0 + }, + { + "x": 152.07070286095353, + "y": -7.883406095020281, + "z": 0.0 + }, + { + "x": 152.0691243996725, + "y": -8.891867371922766, + "z": 0.0 + }, + { + "x": 152.06783475775103, + "y": -9.953500056324756, + "z": 0.0 + }, + { + "x": 152.06654511582957, + "y": -11.015132740726854, + "z": 0.0 + } + ] + }, + { + "id": 175, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 86.42210766601971, + "y": -317.12405432540857, + "z": 0.0 + }, + { + "x": 86.40322153115828, + "y": -317.8749514922378, + "z": 0.0 + }, + { + "x": 86.3292625154455, + "y": -318.58491186848573, + "z": 0.0 + }, + { + "x": 86.18953213327386, + "y": -319.2846940672616, + "z": 0.0 + }, + { + "x": 85.98523313042162, + "y": -319.9683863526217, + "z": 0.0 + }, + { + "x": 85.71807956869432, + "y": -320.6302044599884, + "z": 0.0 + }, + { + "x": 85.39028468437556, + "y": -321.2645335106671, + "z": 0.0 + }, + { + "x": 85.01656276535591, + "y": -321.85141823949874, + "z": 0.0 + }, + { + "x": 84.61328386764781, + "y": -322.3733874363649, + "z": 0.0 + }, + { + "x": 84.14776694319312, + "y": -322.855932640633, + "z": 0.0 + }, + { + "x": 83.63582517526206, + "y": -323.28636997869825, + "z": 0.0 + }, + { + "x": 83.08208237236526, + "y": -323.6607081495259, + "z": 0.0 + }, + { + "x": 82.49250331518978, + "y": -323.9750097865338, + "z": 0.0 + }, + { + "x": 81.87341023048599, + "y": -324.22594956684435, + "z": 0.0 + }, + { + "x": 81.23142281271754, + "y": -324.41084517913515, + "z": 0.0 + }, + { + "x": 80.53314857363705, + "y": -324.5294262581491, + "z": 0.0 + }, + { + "x": 79.44718379231384, + "y": -324.5819492549276, + "z": 0.0 + } + ] + }, + { + "id": 178, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 101.8061452205714, + "y": -324.5933877050256, + "z": 0.0 + }, + { + "x": 100.76420901034751, + "y": -324.544843879481, + "z": 0.0 + }, + { + "x": 100.05547286081084, + "y": -324.4402442473347, + "z": 0.0 + }, + { + "x": 99.40097425397511, + "y": -324.2766062823703, + "z": 0.0 + }, + { + "x": 98.76392649992916, + "y": -324.05345432697123, + "z": 0.0 + }, + { + "x": 98.14938349604752, + "y": -323.77243681296414, + "z": 0.0 + }, + { + "x": 97.61695804856943, + "y": -323.4496290183012, + "z": 0.0 + }, + { + "x": 97.09931695655445, + "y": -323.0644970568544, + "z": 0.0 + }, + { + "x": 96.59466314544346, + "y": -322.6165467084913, + "z": 0.0 + }, + { + "x": 96.13171624236867, + "y": -322.1232796739841, + "z": 0.0 + }, + { + "x": 95.71288930249867, + "y": -321.58761950526895, + "z": 0.0 + }, + { + "x": 95.34255411729966, + "y": -321.0145041533784, + "z": 0.0 + }, + { + "x": 95.04377845391564, + "y": -320.42949063438977, + "z": 0.0 + }, + { + "x": 94.82285770290609, + "y": -319.84438630967213, + "z": 0.0 + }, + { + "x": 94.63316860976981, + "y": -319.18946806306946, + "z": 0.0 + }, + { + "x": 94.50330750802169, + "y": -318.5204043978035, + "z": 0.0 + }, + { + "x": 94.43423405405653, + "y": -317.8422626237095, + "z": 0.0 + }, + { + "x": 94.41410567044805, + "y": -317.1186932324719, + "z": 0.0 + } + ] + }, + { + "id": 193, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 94.37171129421938, + "y": -11.239391821784363, + "z": 0.0 + }, + { + "x": 94.37155111803641, + "y": -10.185689112991424, + "z": 0.0 + }, + { + "x": 94.37139094185343, + "y": -9.131986404198488, + "z": 0.0 + }, + { + "x": 94.39012123383223, + "y": -8.153369150514646, + "z": 0.0 + }, + { + "x": 94.46022890273653, + "y": -7.337998068902732, + "z": 0.0 + }, + { + "x": 94.6072688252939, + "y": -6.9230812441710645, + "z": 0.0 + }, + { + "x": 94.83259463557908, + "y": -6.385304482763309, + "z": 0.0 + }, + { + "x": 95.11913777981543, + "y": -5.877941833921707, + "z": 0.0 + }, + { + "x": 95.46350212363555, + "y": -5.407065852095712, + "z": 0.0 + }, + { + "x": 95.86171945887978, + "y": -4.978761611453896, + "z": 0.0 + }, + { + "x": 96.22923305880748, + "y": -4.719862677775668, + "z": 0.0 + }, + { + "x": 96.70185990677085, + "y": -4.441451745629632, + "z": 0.0 + }, + { + "x": 97.22041617308734, + "y": -4.211505752369636, + "z": 0.0 + }, + { + "x": 97.76345113210014, + "y": -4.0457846580773555, + "z": 0.0 + }, + { + "x": 98.32410668616481, + "y": -3.9466924676147257, + "z": 0.0 + }, + { + "x": 98.79512439302592, + "y": -3.95205280415974, + "z": 0.0 + }, + { + "x": 99.58080669915239, + "y": -3.9508205713340376, + "z": 0.0 + }, + { + "x": 100.5839090094622, + "y": -3.9508137140995263, + "z": 0.0 + }, + { + "x": 101.63761167446887, + "y": -3.9504703020497662, + "z": 0.0 + }, + { + "x": 102.69131433947555, + "y": -3.950126890000005, + "z": 0.0 + } + ] + }, + { + "id": 196, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 79.38131557415628, + "y": -3.9577238475875323, + "z": 0.0 + }, + { + "x": 80.43950680616342, + "y": -3.9573789726696917, + "z": 0.0 + }, + { + "x": 81.49769803817055, + "y": -3.957034097751851, + "z": 0.0 + }, + { + "x": 82.54733788811372, + "y": -3.958919061057222, + "z": 0.0 + }, + { + "x": 83.25546999072677, + "y": -4.0367179671995865, + "z": 0.0 + }, + { + "x": 83.85626624649599, + "y": -4.181507034273803, + "z": 0.0 + }, + { + "x": 84.45707638728011, + "y": -4.39224457294905, + "z": 0.0 + }, + { + "x": 84.89020730165043, + "y": -4.641475916963456, + "z": 0.0 + }, + { + "x": 85.27499915893839, + "y": -4.945073788381097, + "z": 0.0 + }, + { + "x": 85.72199976105516, + "y": -5.3529289744430795, + "z": 0.0 + }, + { + "x": 86.08734206940625, + "y": -5.789075209259341, + "z": 0.0 + }, + { + "x": 86.12224575164548, + "y": -6.021688634033307, + "z": 0.0 + }, + { + "x": 86.28329841826393, + "y": -6.499402208514818, + "z": 0.0 + }, + { + "x": 86.38562053758875, + "y": -7.009892905183665, + "z": 0.0 + }, + { + "x": 86.38134700142467, + "y": -7.4383508230156385, + "z": 0.0 + }, + { + "x": 86.37153594890037, + "y": -8.114997986374872, + "z": 0.0 + }, + { + "x": 86.37138966964652, + "y": -9.124225371328526, + "z": 0.0 + }, + { + "x": 86.37155052814866, + "y": -10.182416647308463, + "z": 0.0 + }, + { + "x": 86.3717113866508, + "y": -11.2406079232884, + "z": 0.0 + } + ] + }, + { + "id": 202, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 347.7299857691685, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 346.65641965126474, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 345.6051845218596, + "y": -324.60410859498836, + "z": 0.0 + }, + { + "x": 344.7850166539401, + "y": -324.540098970213, + "z": 0.0 + }, + { + "x": 344.25909294341756, + "y": -324.39700813462906, + "z": 0.0 + }, + { + "x": 343.71191033205946, + "y": -324.1828372395416, + "z": 0.0 + }, + { + "x": 343.19528786244814, + "y": -323.904106512928, + "z": 0.0 + }, + { + "x": 342.7166149375832, + "y": -323.5649536309744, + "z": 0.0 + }, + { + "x": 342.28274894064253, + "y": -323.17033164995433, + "z": 0.0 + }, + { + "x": 341.8913001189622, + "y": -322.7206360617598, + "z": 0.0 + }, + { + "x": 341.5369668432233, + "y": -322.2125067112267, + "z": 0.0 + }, + { + "x": 341.2324938951551, + "y": -321.65769348921674, + "z": 0.0 + }, + { + "x": 340.99061304977715, + "y": -321.07212369910155, + "z": 0.0 + }, + { + "x": 340.83080310229485, + "y": -320.48807252445783, + "z": 0.0 + }, + { + "x": 340.74178785032285, + "y": -319.89215389539834, + "z": 0.0 + }, + { + "x": 340.71272597311315, + "y": -319.2600014064103, + "z": 0.0 + }, + { + "x": 340.70687562977463, + "y": -318.4515480594214, + "z": 0.0 + }, + { + "x": 340.70817719947337, + "y": -317.45271969952285, + "z": 0.0 + } + ] + }, + { + "id": 217, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 332.7081788771901, + "y": -317.4475260295794, + "z": 0.0 + }, + { + "x": 332.7075245816217, + "y": -318.5307770498437, + "z": 0.0 + }, + { + "x": 332.7149193734867, + "y": -319.3628031526399, + "z": 0.0 + }, + { + "x": 332.69090557791753, + "y": -320.049931684257, + "z": 0.0 + }, + { + "x": 332.6128631715627, + "y": -320.679999573273, + "z": 0.0 + }, + { + "x": 332.4651120128465, + "y": -321.2974806177943, + "z": 0.0 + }, + { + "x": 332.31111388697144, + "y": -321.78577852098607, + "z": 0.0 + }, + { + "x": 332.0291584429973, + "y": -322.3238751397163, + "z": 0.0 + }, + { + "x": 331.67371169882904, + "y": -322.8360704972532, + "z": 0.0 + }, + { + "x": 331.276763504097, + "y": -323.2917244669964, + "z": 0.0 + }, + { + "x": 330.83781253302345, + "y": -323.6909312682483, + "z": 0.0 + }, + { + "x": 330.48216088504284, + "y": -323.9757259923004, + "z": 0.0 + }, + { + "x": 329.96569825792506, + "y": -324.23364793609016, + "z": 0.0 + }, + { + "x": 329.40367289306323, + "y": -324.42640954825083, + "z": 0.0 + }, + { + "x": 328.7325685885115, + "y": -324.5533841445278, + "z": 0.0 + }, + { + "x": 327.8864882032299, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 326.8032369853645, + "y": -324.6099853515625, + "z": 0.0 + }, + { + "x": 325.71998576749917, + "y": -324.6099853515625, + "z": 0.0 + } + ] + }, + { + "id": 226, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 94.38036233629381, + "y": -68.14939116425025, + "z": 0.0 + }, + { + "x": 94.380205608378, + "y": -67.1183725299237, + "z": 0.0 + }, + { + "x": 94.38004888046221, + "y": -66.08735389559722, + "z": 0.0 + }, + { + "x": 94.3798921525464, + "y": -65.0563352612706, + "z": 0.0 + }, + { + "x": 94.41540859131102, + "y": -64.17671650467226, + "z": 0.0 + }, + { + "x": 94.50599020801253, + "y": -63.43406355283531, + "z": 0.0 + }, + { + "x": 94.65004354411337, + "y": -63.28886531615959, + "z": 0.0 + }, + { + "x": 94.89412789099731, + "y": -62.88319975924353, + "z": 0.0 + }, + { + "x": 95.19296693797658, + "y": -62.51318763201182, + "z": 0.0 + }, + { + "x": 95.50496933112525, + "y": -62.25534955729171, + "z": 0.0 + }, + { + "x": 95.79800974776776, + "y": -62.11894221635172, + "z": 0.0 + }, + { + "x": 96.32100408123506, + "y": -61.84314210418763, + "z": 0.0 + }, + { + "x": 96.87868341854731, + "y": -61.62060831764035, + "z": 0.0 + }, + { + "x": 97.29632721050396, + "y": -61.55600143297452, + "z": 0.0 + }, + { + "x": 97.80242386355842, + "y": -61.52230377982157, + "z": 0.0 + }, + { + "x": 98.5261196610379, + "y": -61.49245168271566, + "z": 0.0 + }, + { + "x": 99.3281588135278, + "y": -61.498913326717286, + "z": 0.0 + }, + { + "x": 100.3591774521123, + "y": -61.498787694223985, + "z": 0.0 + }, + { + "x": 101.39019609069686, + "y": -61.49866206173068, + "z": 0.0 + } + ] + }, + { + "id": 235, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 101.38950854005927, + "y": -53.49866208611823, + "z": 0.0 + }, + { + "x": 100.35427574987001, + "y": -53.49878823211765, + "z": 0.0 + }, + { + "x": 99.37376770017384, + "y": -53.48524399821469, + "z": 0.0 + }, + { + "x": 98.56594764529008, + "y": -53.42248411699823, + "z": 0.0 + }, + { + "x": 98.02529054486976, + "y": -53.28960016706168, + "z": 0.0 + }, + { + "x": 97.39333152686908, + "y": -53.08861912710111, + "z": 0.0 + }, + { + "x": 96.78166837055359, + "y": -52.82970085027407, + "z": 0.0 + }, + { + "x": 96.28198883142825, + "y": -52.534509829604154, + "z": 0.0 + }, + { + "x": 95.8363635631698, + "y": -52.191004873637944, + "z": 0.0 + }, + { + "x": 95.37363437662033, + "y": -51.767432997723176, + "z": 0.0 + }, + { + "x": 94.99551614629756, + "y": -51.32382634745366, + "z": 0.0 + }, + { + "x": 94.75043184234941, + "y": -50.90678621458571, + "z": 0.0 + }, + { + "x": 94.61657447268031, + "y": -50.51927995168681, + "z": 0.0 + }, + { + "x": 94.46613425141832, + "y": -49.99260252804384, + "z": 0.0 + }, + { + "x": 94.38030857826998, + "y": -49.45071585721417, + "z": 0.0 + }, + { + "x": 94.36315168668953, + "y": -48.906894212072416, + "z": 0.0 + }, + { + "x": 94.37733070564443, + "y": -48.21662848944666, + "z": 0.0 + }, + { + "x": 94.37717547838463, + "y": -47.18497092961871, + "z": 0.0 + }, + { + "x": 94.37701810986431, + "y": -46.14973814370483, + "z": 0.0 + } + ] + }, + { + "id": 241, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 325.6696754063413, + "y": -201.15911160127555, + "z": 0.0 + }, + { + "x": 326.69854293953034, + "y": -201.1591952064953, + "z": 0.0 + }, + { + "x": 327.55662263077403, + "y": -201.1556171967777, + "z": 0.0 + }, + { + "x": 328.2878604030311, + "y": -201.17589028449774, + "z": 0.0 + }, + { + "x": 328.9011683532972, + "y": -201.22663941361236, + "z": 0.0 + }, + { + "x": 329.3792074949348, + "y": -201.2950945907748, + "z": 0.0 + }, + { + "x": 329.94437832953804, + "y": -201.48083812438352, + "z": 0.0 + }, + { + "x": 330.50391400106264, + "y": -201.73861700728952, + "z": 0.0 + }, + { + "x": 331.024340149681, + "y": -202.0449603967076, + "z": 0.0 + }, + { + "x": 331.4555572397345, + "y": -202.35002324535176, + "z": 0.0 + }, + { + "x": 331.7582337858688, + "y": -202.58574368321777, + "z": 0.0 + }, + { + "x": 332.0804677406411, + "y": -202.99176286272518, + "z": 0.0 + }, + { + "x": 332.347243162328, + "y": -203.43389313205873, + "z": 0.0 + }, + { + "x": 332.55520982858246, + "y": -203.9057956290992, + "z": 0.0 + }, + { + "x": 332.69773103323286, + "y": -204.35948999220938, + "z": 0.0 + }, + { + "x": 332.77073692392213, + "y": -205.06321647940158, + "z": 0.0 + }, + { + "x": 332.7754515617806, + "y": -206.07094373654172, + "z": 0.0 + }, + { + "x": 332.77483011454973, + "y": -207.09981108544716, + "z": 0.0 + }, + { + "x": 332.7742086673189, + "y": -208.12867843435257, + "z": 0.0 + }, + { + "x": 332.773587220088, + "y": -209.157545783258, + "z": 0.0 + } + ] + }, + { + "id": 244, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 332.7877875168978, + "y": -185.64755007182552, + "z": 0.0 + }, + { + "x": 332.7871558692562, + "y": -186.69330520950456, + "z": 0.0 + }, + { + "x": 332.78855716050793, + "y": -187.6139412482442, + "z": 0.0 + }, + { + "x": 332.769849486949, + "y": -188.42140076858865, + "z": 0.0 + }, + { + "x": 332.77083182214864, + "y": -188.88303279362856, + "z": 0.0 + }, + { + "x": 332.66348831483367, + "y": -189.4449902018104, + "z": 0.0 + }, + { + "x": 332.46997372679783, + "y": -190.02958668760976, + "z": 0.0 + }, + { + "x": 332.2154937201096, + "y": -190.5892499954893, + "z": 0.0 + }, + { + "x": 331.98978605376124, + "y": -191.01441570599346, + "z": 0.0 + }, + { + "x": 331.64962893870444, + "y": -191.45391576692543, + "z": 0.0 + }, + { + "x": 331.20220308693445, + "y": -191.88800872415374, + "z": 0.0 + }, + { + "x": 330.7115349826413, + "y": -192.27258396974145, + "z": 0.0 + }, + { + "x": 330.2919359880639, + "y": -192.5572890717597, + "z": 0.0 + }, + { + "x": 329.8012178989161, + "y": -192.79279664378373, + "z": 0.0 + }, + { + "x": 329.2041630135967, + "y": -192.97658802806663, + "z": 0.0 + }, + { + "x": 328.54331794047005, + "y": -193.09947345183087, + "z": 0.0 + }, + { + "x": 327.7621837163193, + "y": -193.15928161095763, + "z": 0.0 + }, + { + "x": 326.7164283913317, + "y": -193.15919663344505, + "z": 0.0 + }, + { + "x": 325.67067306634425, + "y": -193.1591116559325, + "z": 0.0 + } + ] + }, + { + "id": 256, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 325.1604817010584, + "y": -61.471395029053355, + "z": 0.0 + }, + { + "x": 326.19722933008575, + "y": -61.47126869846662, + "z": 0.0 + }, + { + "x": 327.233976959113, + "y": -61.47114236787987, + "z": 0.0 + }, + { + "x": 327.99131405353273, + "y": -61.46127945318263, + "z": 0.0 + }, + { + "x": 328.6109717729404, + "y": -61.482747456950605, + "z": 0.0 + }, + { + "x": 329.2103753540747, + "y": -61.5647292733214, + "z": 0.0 + }, + { + "x": 329.79705055025045, + "y": -61.71050220350344, + "z": 0.0 + }, + { + "x": 330.3123387974076, + "y": -61.889415448071965, + "z": 0.0 + }, + { + "x": 330.77626372745664, + "y": -62.11094879964533, + "z": 0.0 + }, + { + "x": 331.25491038381944, + "y": -62.43748212523404, + "z": 0.0 + }, + { + "x": 331.670805195674, + "y": -62.7900771917235, + "z": 0.0 + }, + { + "x": 332.03159138732866, + "y": -63.17706278805754, + "z": 0.0 + }, + { + "x": 332.3123598399787, + "y": -63.543989064113035, + "z": 0.0 + }, + { + "x": 332.5315476756131, + "y": -63.92517497204276, + "z": 0.0 + }, + { + "x": 332.70310131549746, + "y": -64.42779257280169, + "z": 0.0 + }, + { + "x": 332.8139116311539, + "y": -65.08228432514662, + "z": 0.0 + }, + { + "x": 332.8601058914801, + "y": -65.91732900219925, + "z": 0.0 + }, + { + "x": 332.85947968458265, + "y": -66.95407644980567, + "z": 0.0 + }, + { + "x": 332.8588534776853, + "y": -67.99082389741164, + "z": 0.0 + }, + { + "x": 332.85822727078784, + "y": -69.02757134501785, + "z": 0.0 + } + ] + }, + { + "id": 271, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 332.8718839577665, + "y": -46.417575469412235, + "z": 0.0 + }, + { + "x": 332.8712509968554, + "y": -47.46590647417591, + "z": 0.0 + }, + { + "x": 332.87906109993855, + "y": -48.254069835605016, + "z": 0.0 + }, + { + "x": 332.8674708247359, + "y": -48.83855051155455, + "z": 0.0 + }, + { + "x": 332.78721881227335, + "y": -49.41956063034073, + "z": 0.0 + }, + { + "x": 332.6404482078824, + "y": -49.986768950414024, + "z": 0.0 + }, + { + "x": 332.42919462016573, + "y": -50.532805912282264, + "z": 0.0 + }, + { + "x": 332.15627773256864, + "y": -51.050572148092485, + "z": 0.0 + }, + { + "x": 331.82467710757146, + "y": -51.533936458630656, + "z": 0.0 + }, + { + "x": 331.4370083989903, + "y": -51.977864296335234, + "z": 0.0 + }, + { + "x": 330.99884451709175, + "y": -52.37582157742848, + "z": 0.0 + }, + { + "x": 330.54784008475104, + "y": -52.70646836786131, + "z": 0.0 + }, + { + "x": 330.05399673340213, + "y": -52.98129341041239, + "z": 0.0 + }, + { + "x": 329.503203182546, + "y": -53.20007708555586, + "z": 0.0 + }, + { + "x": 328.93171552914595, + "y": -53.35431927828143, + "z": 0.0 + }, + { + "x": 328.1971693258425, + "y": -53.443553006846, + "z": 0.0 + }, + { + "x": 327.25895540688833, + "y": -53.47113926479402, + "z": 0.0 + }, + { + "x": 326.209231142834, + "y": -53.471267176619904, + "z": 0.0 + }, + { + "x": 325.15950687877955, + "y": -53.47139508844576, + "z": 0.0 + } + ] + }, + { + "id": 274, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 94.40167147489854, + "y": -208.3293895446205, + "z": 0.0 + }, + { + "x": 94.40151478566703, + "y": -207.29862539105918, + "z": 0.0 + }, + { + "x": 94.40135809643554, + "y": -206.26786123749787, + "z": 0.0 + }, + { + "x": 94.43376229952128, + "y": -205.3736891092996, + "z": 0.0 + }, + { + "x": 94.51834203531422, + "y": -204.61128923276965, + "z": 0.0 + }, + { + "x": 94.66783350768677, + "y": -204.1297875213049, + "z": 0.0 + }, + { + "x": 94.87944244681093, + "y": -203.6696897342904, + "z": 0.0 + }, + { + "x": 95.16995944891461, + "y": -203.15286855648935, + "z": 0.0 + }, + { + "x": 95.51540707027908, + "y": -202.67004371951856, + "z": 0.0 + }, + { + "x": 95.90389606178833, + "y": -202.24482846065445, + "z": 0.0 + }, + { + "x": 96.2525027421791, + "y": -201.99846580436187, + "z": 0.0 + }, + { + "x": 96.73848706787206, + "y": -201.69010810485491, + "z": 0.0 + }, + { + "x": 97.25615282237987, + "y": -201.43877363286256, + "z": 0.0 + }, + { + "x": 97.80048676780363, + "y": -201.24710934793697, + "z": 0.0 + }, + { + "x": 98.25513109950654, + "y": -201.17854678323314, + "z": 0.0 + }, + { + "x": 98.76739644056705, + "y": -201.15582125755216, + "z": 0.0 + }, + { + "x": 99.51039002690968, + "y": -201.13782300713487, + "z": 0.0 + }, + { + "x": 100.38857732118137, + "y": -201.1408053809885, + "z": 0.0 + }, + { + "x": 101.4193414832491, + "y": -201.14088914032726, + "z": 0.0 + } + ] + }, + { + "id": 286, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 101.42032622238838, + "y": -193.14088919393424, + "z": 0.0 + }, + { + "x": 100.33922750350321, + "y": -193.1408013444366, + "z": 0.0 + }, + { + "x": 99.25812878461814, + "y": -193.14071349493892, + "z": 0.0 + }, + { + "x": 98.39054133013732, + "y": -193.08907796797558, + "z": 0.0 + }, + { + "x": 97.69618927189643, + "y": -192.96873836108958, + "z": 0.0 + }, + { + "x": 97.07486869043078, + "y": -192.78301788211778, + "z": 0.0 + }, + { + "x": 96.47651183719475, + "y": -192.5312083437614, + "z": 0.0 + }, + { + "x": 95.90761962214879, + "y": -192.21577823107452, + "z": 0.0 + }, + { + "x": 95.47809790869928, + "y": -191.87555176993956, + "z": 0.0 + }, + { + "x": 95.07232590934612, + "y": -191.46859694320713, + "z": 0.0 + }, + { + "x": 94.79183893066474, + "y": -191.06305779436045, + "z": 0.0 + }, + { + "x": 94.58695946635352, + "y": -190.6335781301305, + "z": 0.0 + }, + { + "x": 94.44899671077283, + "y": -190.1776736582307, + "z": 0.0 + }, + { + "x": 94.38112600071274, + "y": -189.70503411601993, + "z": 0.0 + }, + { + "x": 94.383139280547, + "y": -189.21977939325217, + "z": 0.0 + }, + { + "x": 94.39865592659415, + "y": -188.4919121005017, + "z": 0.0 + }, + { + "x": 94.39849158587134, + "y": -187.41081339053818, + "z": 0.0 + }, + { + "x": 94.39832724514855, + "y": -186.32971468057468, + "z": 0.0 + } + ] + }, + { + "id": 292, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 332.82709050768517, + "y": -120.57756194154449, + "z": 0.0 + }, + { + "x": 332.82643877406326, + "y": -121.6565714059926, + "z": 0.0 + }, + { + "x": 332.83245205105794, + "y": -122.50716907762718, + "z": 0.0 + }, + { + "x": 332.81132858665546, + "y": -123.19805967071827, + "z": 0.0 + }, + { + "x": 332.7542482002542, + "y": -123.76934929727207, + "z": 0.0 + }, + { + "x": 332.6646701817641, + "y": -124.24252956643309, + "z": 0.0 + }, + { + "x": 332.5001486679359, + "y": -124.70549841621741, + "z": 0.0 + }, + { + "x": 332.2121530385942, + "y": -125.20439690327898, + "z": 0.0 + }, + { + "x": 331.8507388515651, + "y": -125.67492643492409, + "z": 0.0 + }, + { + "x": 331.39999244756945, + "y": -126.12422224787402, + "z": 0.0 + }, + { + "x": 330.99793115335666, + "y": -126.46806789445478, + "z": 0.0 + }, + { + "x": 330.4254675243916, + "y": -126.80336453193688, + "z": 0.0 + }, + { + "x": 329.8075639202306, + "y": -127.08118371157036, + "z": 0.0 + }, + { + "x": 329.1656402917356, + "y": -127.29568914951442, + "z": 0.0 + }, + { + "x": 328.59192458915544, + "y": -127.43803717191713, + "z": 0.0 + }, + { + "x": 327.75584160763026, + "y": -127.50443980675412, + "z": 0.0 + }, + { + "x": 326.7211200901641, + "y": -127.51556771483503, + "z": 0.0 + }, + { + "x": 325.6421105365875, + "y": -127.51508562015208, + "z": 0.0 + } + ] + }, + { + "id": 304, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 325.6381862987218, + "y": -135.51508466532573, + "z": 0.0 + }, + { + "x": 326.6693035988366, + "y": -135.515545362051, + "z": 0.0 + }, + { + "x": 327.55131543289843, + "y": -135.5131593711596, + "z": 0.0 + }, + { + "x": 328.3141035849688, + "y": -135.5330080851354, + "z": 0.0 + }, + { + "x": 328.7928591328234, + "y": -135.54477745834626, + "z": 0.0 + }, + { + "x": 329.2838720270384, + "y": -135.62962857414666, + "z": 0.0 + }, + { + "x": 329.8398044272193, + "y": -135.82352366647075, + "z": 0.0 + }, + { + "x": 330.3697282088117, + "y": -136.07686163386663, + "z": 0.0 + }, + { + "x": 330.8094226454465, + "y": -136.3352242557169, + "z": 0.0 + }, + { + "x": 331.19388056147704, + "y": -136.62723539200704, + "z": 0.0 + }, + { + "x": 331.6098466658718, + "y": -137.08355681539902, + "z": 0.0 + }, + { + "x": 331.9767702484966, + "y": -137.58116569359478, + "z": 0.0 + }, + { + "x": 332.26804777178256, + "y": -138.05807524433806, + "z": 0.0 + }, + { + "x": 332.48255764058945, + "y": -138.49289968548555, + "z": 0.0 + }, + { + "x": 332.65222061387357, + "y": -139.0891815282288, + "z": 0.0 + }, + { + "x": 332.76312477510174, + "y": -139.7739642368658, + "z": 0.0 + }, + { + "x": 332.81501231398755, + "y": -140.57420608476463, + "z": 0.0 + }, + { + "x": 332.8143895078128, + "y": -141.6053232997068, + "z": 0.0 + }, + { + "x": 332.81376670163803, + "y": -142.63644051464897, + "z": 0.0 + }, + { + "x": 332.81314389546327, + "y": -143.66755772959112, + "z": 0.0 + } + ] + }, + { + "id": 310, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 101.42178302796803, + "y": -127.41490538788197, + "z": 0.0 + }, + { + "x": 100.36884173414194, + "y": -127.41443494033355, + "z": 0.0 + }, + { + "x": 99.31590044031583, + "y": -127.41396449278513, + "z": 0.0 + }, + { + "x": 98.34557054873348, + "y": -127.3928796818061, + "z": 0.0 + }, + { + "x": 97.55962058570432, + "y": -127.31583473381473, + "z": 0.0 + }, + { + "x": 97.20790067612784, + "y": -127.16461138721388, + "z": 0.0 + }, + { + "x": 96.7223537644397, + "y": -126.93250374971481, + "z": 0.0 + }, + { + "x": 96.27063494180855, + "y": -126.64030547433455, + "z": 0.0 + }, + { + "x": 95.85910137782332, + "y": -126.29195836230957, + "z": 0.0 + }, + { + "x": 95.51989604462473, + "y": -125.90683342043921, + "z": 0.0 + }, + { + "x": 95.28468889415034, + "y": -125.51761502775999, + "z": 0.0 + }, + { + "x": 94.97091192766963, + "y": -124.95536653932524, + "z": 0.0 + }, + { + "x": 94.71416588676566, + "y": -124.36200598792965, + "z": 0.0 + }, + { + "x": 94.51831459567889, + "y": -123.74448953392844, + "z": 0.0 + }, + { + "x": 94.4338890820918, + "y": -123.20146492211585, + "z": 0.0 + }, + { + "x": 94.40464030373457, + "y": -122.61480564194734, + "z": 0.0 + }, + { + "x": 94.38639075227408, + "y": -121.8151086621219, + "z": 0.0 + }, + { + "x": 94.38837998400676, + "y": -120.89267019879318, + "z": 0.0 + }, + { + "x": 94.38821992355439, + "y": -119.83972881203614, + "z": 0.0 + } + ] + }, + { + "id": 319, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 94.391564151273, + "y": -141.83939031284123, + "z": 0.0 + }, + { + "x": 94.39140215202507, + "y": -140.77369475687905, + "z": 0.0 + }, + { + "x": 94.39124015277714, + "y": -139.7079992009169, + "z": 0.0 + }, + { + "x": 94.41769376377435, + "y": -138.74855890854363, + "z": 0.0 + }, + { + "x": 94.51320921265764, + "y": -138.03658731539213, + "z": 0.0 + }, + { + "x": 94.67785056645131, + "y": -137.5681944180493, + "z": 0.0 + }, + { + "x": 94.89872548747795, + "y": -137.18945653433522, + "z": 0.0 + }, + { + "x": 95.1855065404848, + "y": -136.82090632507058, + "z": 0.0 + }, + { + "x": 95.53687355774571, + "y": -136.47276500306168, + "z": 0.0 + }, + { + "x": 95.94636994374555, + "y": -136.15990448540106, + "z": 0.0 + }, + { + "x": 96.41739399178752, + "y": -135.88051851943328, + "z": 0.0 + }, + { + "x": 96.93028384483344, + "y": -135.65565452448743, + "z": 0.0 + }, + { + "x": 97.46813231162776, + "y": -135.49697314657672, + "z": 0.0 + }, + { + "x": 98.02286346439605, + "y": -135.40712496469334, + "z": 0.0 + }, + { + "x": 98.51827011133815, + "y": -135.41166569519828, + "z": 0.0 + }, + { + "x": 99.32070176238868, + "y": -135.4138213058624, + "z": 0.0 + }, + { + "x": 100.35220617672339, + "y": -135.41442830616955, + "z": 0.0 + }, + { + "x": 101.41790163862902, + "y": -135.41490445220006, + "z": 0.0 + } + ] + }, + { + "id": 328, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 152.02380945971413, + "y": -46.195106783691955, + "z": 0.0 + }, + { + "x": 152.02254200228586, + "y": -47.23847720268771, + "z": 0.0 + }, + { + "x": 152.0213199732512, + "y": -48.26703348854526, + "z": 0.0 + }, + { + "x": 152.0288322655578, + "y": -49.01153177480047, + "z": 0.0 + }, + { + "x": 152.01859274755594, + "y": -49.54736259613325, + "z": 0.0 + }, + { + "x": 151.9309711128801, + "y": -50.10404697631353, + "z": 0.0 + }, + { + "x": 151.77769148461007, + "y": -50.64525437326739, + "z": 0.0 + }, + { + "x": 151.56081242716232, + "y": -51.164236234723724, + "z": 0.0 + }, + { + "x": 151.33509844602395, + "y": -51.59210944971475, + "z": 0.0 + }, + { + "x": 151.03922219866305, + "y": -51.995446238265515, + "z": 0.0 + }, + { + "x": 150.63750602870874, + "y": -52.39113917962509, + "z": 0.0 + }, + { + "x": 150.1923699306697, + "y": -52.735138851514144, + "z": 0.0 + }, + { + "x": 149.70952634494085, + "y": -53.023302356093474, + "z": 0.0 + }, + { + "x": 149.23875404894363, + "y": -53.24117517081868, + "z": 0.0 + }, + { + "x": 148.79867298597753, + "y": -53.39036933638519, + "z": 0.0 + }, + { + "x": 148.0224206112521, + "y": -53.468981156349344, + "z": 0.0 + }, + { + "x": 147.07657391052473, + "y": -53.493094989928544, + "z": 0.0 + }, + { + "x": 146.03320272943924, + "y": -53.49322212761356, + "z": 0.0 + }, + { + "x": 144.98983154835375, + "y": -53.49334926529858, + "z": 0.0 + } + ] + }, + { + "id": 337, + "map_element_id": 15, + "type": "road_edge", + "geometry": [ + { + "x": 167.1695080517052, + "y": -53.490646609928866, + "z": 0.0 + }, + { + "x": 166.12735220349356, + "y": -53.49077359952219, + "z": 0.0 + }, + { + "x": 165.08519635528188, + "y": -53.490900589115526, + "z": 0.0 + }, + { + "x": 164.26826123122513, + "y": -53.43913165781505, + "z": 0.0 + }, + { + "x": 163.57831205067666, + "y": -53.32661522480176, + "z": 0.0 + }, + { + "x": 162.97263741222574, + "y": -53.15405915103483, + "z": 0.0 + }, + { + "x": 162.47269917418078, + "y": -52.928503300812395, + "z": 0.0 + }, + { + "x": 162.01532313836688, + "y": -52.645855553721226, + "z": 0.0 + }, + { + "x": 161.50784418968078, + "y": -52.27512648472766, + "z": 0.0 + }, + { + "x": 161.0504105618973, + "y": -51.85852801483733, + "z": 0.0 + }, + { + "x": 160.67677545057913, + "y": -51.41871503147218, + "z": 0.0 + }, + { + "x": 160.50406612361127, + "y": -51.063635052220704, + "z": 0.0 + }, + { + "x": 160.27764479185996, + "y": -50.55138900037866, + "z": 0.0 + }, + { + "x": 160.11411017382582, + "y": -50.015611342568725, + "z": 0.0 + }, + { + "x": 160.0156401774726, + "y": -49.46252361870256, + "z": 0.0 + }, + { + "x": 160.01938909966404, + "y": -48.996991646258856, + "z": 0.0 + }, + { + "x": 160.02102230073152, + "y": -48.239731358425196, + "z": 0.0 + }, + { + "x": 160.02253716340635, + "y": -47.247319653457076, + "z": 0.0 + }, + { + "x": 160.02380314448305, + "y": -46.20516456644735, + "z": 0.0 + } + ] + } + ], + "tl_states": {}, + "metadata": { + "sdc_track_index": 0, + "tracks_to_predict": [], + "objects_of_interest": [] + } +} diff --git a/data_utils/carla/process_carla_roads.py b/data_utils/carla/process_carla_roads.py new file mode 100644 index 0000000000..2b39924887 --- /dev/null +++ b/data_utils/carla/process_carla_roads.py @@ -0,0 +1,338 @@ +import sys +import os +import pyxodr +import json +import numpy as np +from lxml import etree +from pyxodr.road_objects.road import Road +from pyxodr.road_objects.lane import Lane, ConnectionPosition, LaneOrientation, TrafficOrientation +from pyxodr.road_objects.junction import Junction +from pyxodr.road_objects.lane_section import LaneSection +from pyxodr.road_objects.network import RoadNetwork +from shapely.geometry import Polygon +from enum import IntEnum +import random +import string + + +class MapType(IntEnum): + LANE_UNDEFINED = 0 + LANE_FREEWAY = 1 + LANE_SURFACE_STREET = 2 + LANE_BIKE_LANE = 3 + # Original definition skips 4 + ROAD_LINE_UNKNOWN = 5 + ROAD_LINE_BROKEN_SINGLE_WHITE = 6 + ROAD_LINE_SOLID_SINGLE_WHITE = 7 + ROAD_LINE_SOLID_DOUBLE_WHITE = 8 + ROAD_LINE_BROKEN_SINGLE_YELLOW = 9 + ROAD_LINE_BROKEN_DOUBLE_YELLOW = 10 + ROAD_LINE_SOLID_SINGLE_YELLOW = 11 + ROAD_LINE_SOLID_DOUBLE_YELLOW = 12 + ROAD_LINE_PASSING_DOUBLE_YELLOW = 13 + ROAD_EDGE_UNKNOWN = 14 + ROAD_EDGE_BOUNDARY = 15 + ROAD_EDGE_MEDIAN = 16 + STOP_SIGN = 17 + CROSSWALK = 18 + SPEED_BUMP = 19 + DRIVEWAY = 20 # New womd datatype in v1.2.0: Driveway entrances + UNKNOWN = -1 + NUM_TYPES = 21 + + +def save_lane_section_to_json(xodr_json, id, road_edges, road_lines, lanes, sidewalks=[]): + roads = xodr_json.get("roads", []) + for road_edge in road_edges: + # edge_polygon = Polygon(road_edge) + edge_data = { + "id": id, + "map_element_id": int(MapType.ROAD_EDGE_BOUNDARY), + "type": "road_edge", + "geometry": [{"x": float(pt[0]), "y": float(pt[1]), "z": 0.0} for pt in road_edge], + } + roads.append(edge_data) + id += 1 + for road_line in road_lines: + line_data = { + "id": id, + "map_element_id": int(MapType.ROAD_LINE_BROKEN_SINGLE_WHITE), + "type": "road_line", + "geometry": [{"x": float(pt[0]), "y": float(pt[1]), "z": 0.0} for pt in road_line], + } + roads.append(line_data) + id += 1 + for lane in lanes: + lane_data = { + "id": id, + "map_element_id": int(MapType.LANE_SURFACE_STREET), + "type": "lane", + "geometry": [{"x": float(pt[0]), "y": float(pt[1]), "z": 0.0} for pt in lane], + } + roads.append(lane_data) + id += 1 + # for sidewalk in sidewalks: + # sidewalk_data = { + # "id": id, + # "map_element_id": int(MapType.LANE_BIKE_LANE), + # "type": "sidewalk", + # "geometry": [{"x": float(pt[0]), "y": float(pt[1]), "z": 0.0} for pt in sidewalk] + # } + # roads.append(sidewalk_data) + # id += 1 + xodr_json["roads"] = roads + return id + + +def get_lane_data(lane, type="BOUNDARY", check_dir=True): + if type == "BOUNDARY": + points = lane.boundary_line + # print(f'Number of boundary pts: {len(points)}') + elif type == "CENTERLINE": + points = lane.centre_line + # print(f'Number of centerline pts: {len(points)}') + else: + raise ValueError(f"Unknown lane data type: {type}") + + if not check_dir: + return points + + # Check traffic direction + travel_dir = None + vector_lane = lane.lane_xml.find(".//userData/vectorLane") + if vector_lane is not None: + travel_dir = vector_lane.get("travelDir") + + if travel_dir == "backward": + # Reverse points for backward travel + points = points[::-1] + + return points + + +def sum_pts(road_elts): + road_geometries = [len(elt) for elt in road_elts] + return sum(road_geometries) + + +def create_empty_json(town_name): + def random_string(length=8): + return "".join(random.choices(string.ascii_letters + string.digits, k=length)) + + json_data = { + "name": town_name, + "scenario_id": random_string(12), + "objects": [], + "roads": [], + "tl_states": {}, + "metadata": {"sdc_track_index": 0, "tracks_to_predict": [], "objects_of_interest": []}, + } + return json_data + + +def generate_carla_road( + town_name, source_dir, carla_map_dir, resolution, dest_dir, max_samples, print_number_of_sample_truncations +): + src_file_path = os.path.join(source_dir, f"{town_name}.json") + dst_file_path = os.path.join(dest_dir, f"{town_name}.json") + if not os.path.isfile(src_file_path): + print(f"Warning: {src_file_path} does not exist, creating empty file.") + empty_json = create_empty_json(town_name) + with open(src_file_path, "w") as f: + json.dump(empty_json, f, indent=2) + + with open(src_file_path, "r") as f: + xodr_json = json.load(f) + xodr_json["roads"] = [] + + with open(dst_file_path, "w") as f: + json.dump(xodr_json, f, indent=2) + + odr_file = os.path.join(carla_map_dir, town_name + ".xodr") + + road_network = RoadNetwork(xodr_file_path=odr_file, resolution=resolution, max_samples=max_samples) + roads = road_network.get_roads() + print(f"Number of roads in the network: {len(roads)}") + # print(f"Type: {type(roads[0])}\nRoads: {roads}") + print(f"Number of lanes in the network: {sum([sum([len(ls.lanes) for ls in r.lane_sections]) for r in roads])}") + print( + f"Road 0 lane 1 boundary_pts: {len(roads[0].lane_sections[0].lanes[1].boundary_line)}" + ) # Sanity check to see if resolution is working + + # Go only till last "driving" lane("parking" NTD) + # "median" lane means a road edge(add after all of them appear) + # Add "sidewalk" lane as well + + id = 0 + roads_json_cnt = [[], [], []] + print(f"Network has {len(roads)} roads.") + for road_obj in roads: + # print(f"Road ID: {road_obj.id}") + lane_sections = road_obj.lane_sections + # print(f"Lane Sections: {lane_sections}") + for lane_section in lane_sections: + # print(f"Lane Section ID: {lane_section.lane_section_ordinal}") + # print(f"Number of Left Lanes: {len(lane_section.left_lanes)}") + # print(f"Number of Right Lanes: {len(lane_section.right_lanes)}") + road_edges = [] + road_lines = [] + lanes = [] + # sidwalks = [] + + left_immediate_driveable = False + right_immediate_driveable = False + + # Left Lanes + add_lane_data = False + add_edge_data = False + previous_lane = None + for i, left_lane in enumerate(lane_section.left_lanes): + if left_lane.type == "driving" or left_lane.type == "parking": + if i == 0: + left_immediate_driveable = True + + if add_lane_data: + road_line_data = get_lane_data(previous_lane, "BOUNDARY") + road_line_data = road_line_data + road_lines.append(road_line_data) + lanes.append(get_lane_data(previous_lane, "CENTERLINE")) + # Add outer edge as road edge + elif add_edge_data: + road_edges.append(get_lane_data(previous_lane, "BOUNDARY")) + add_lane_data = True + add_edge_data = False + else: + # Add inner lane as road edge + if add_lane_data and i != 0: + lanes.append(get_lane_data(previous_lane, "CENTERLINE")) + road_edges.append(get_lane_data(previous_lane, "BOUNDARY")) + add_edge_data = True + add_lane_data = False + previous_lane = left_lane + + if add_lane_data: + lanes.append(get_lane_data(previous_lane, "CENTERLINE")) + road_edges.append(get_lane_data(previous_lane, "BOUNDARY")) + # elif add_edge_data: + # if previous_lane.type == 'sidewalk': + # sidwalks.append(get_lane_data(previous_lane, "BOUNDARY")) + + # print("LEFT STATS") + # print(f"Number of Road edges: {len(road_edges)}") + # print(f"Road lines: {len(road_lines)}") + # print(f"Lanes: {len(lanes)}") + # print(f"Sidewalks: {len(sidwalks)}") + + # Right Lanes + add_lane_data = False + add_edge_data = False + previous_lane = None + for i, right_lane in enumerate(lane_section.right_lanes): + if right_lane.type == "driving" or right_lane.type == "parking": + if i == 0: + right_immediate_driveable = True + + if add_lane_data: + road_line_data = get_lane_data(previous_lane, "BOUNDARY") + road_line_data = road_line_data + road_lines.append(road_line_data) + lanes.append(get_lane_data(previous_lane, "CENTERLINE")) + # Add outer edge as road edge + elif add_edge_data: + road_edges.append(get_lane_data(previous_lane, "BOUNDARY")) + add_lane_data = True + add_edge_data = False + else: + # Add inner lane as road edge + if add_lane_data and i != 0: + lanes.append(get_lane_data(previous_lane, "CENTERLINE")) + road_edges.append(get_lane_data(previous_lane, "BOUNDARY")) + add_edge_data = True + add_lane_data = False + previous_lane = right_lane + + if add_lane_data: + lanes.append(get_lane_data(previous_lane, "CENTERLINE")) + road_edges.append(get_lane_data(previous_lane, "BOUNDARY")) + # elif add_edge_data: + # if previous_lane.type == 'sidewalk': + # sidwalks.append(get_lane_data(previous_lane, "BOUNDARY")) + + # print(f"Number of Road edges in {road_obj.id}: {len(road_edges)}") + # print(f"Road lines in {road_obj.id}: {len(road_lines)}") + # print(f"Lanes in {road_obj.id}: {len(lanes)}") + # print(f"Sidewalks in {road_obj.id}: {len(sidwalks)}") + + # If atleast one side has no immediate driveable lane add center as road edge + if not left_immediate_driveable or not right_immediate_driveable: + road_edges.append(lane_section.lane_section_reference_line) + else: + road_line_data = get_lane_data(previous_lane, "BOUNDARY") + road_lines.append(road_line_data) + + if len(road_lines) == 0 and len(lanes) == 0: + road_edges = [] + id = save_lane_section_to_json(xodr_json, id, road_edges, road_lines, lanes) + roads_json_cnt[0].append(len(road_edges)) + roads_json_cnt[1].append(len(road_lines)) + roads_json_cnt[2].append(len(lanes)) + # if len(lanes) == 0 and len(road_lines) != 0: + # print(f"Road: {road_obj.id}, Lane Section: {lane_section.lane_section_ordinal}") + # print(f"Road edges: {len(road_edges)}, Road lines: {len(road_lines)}, Lanes: {len(lanes)}") + # break + # break + print(f"Total roads JSON count: {sum(roads_json_cnt[0]) + sum(roads_json_cnt[1]) + sum(roads_json_cnt[2])}") + + # Save to file + with open(dst_file_path, "w") as f: + json.dump(xodr_json, f, indent=2) + + # Print logs + if print_number_of_sample_truncations: + road_network.print_logs_max_samples_hit() + + +def generate_carla_roads( + town_names, source_dir, carla_map_dir, resolution, dest_dir, max_samples, print_number_of_sample_truncations +): + if type(resolution) == float: + resolution = [resolution] * len(town_names) + elif type(resolution) != list: + raise ValueError("Resolution must be a float or a list type") + elif len(resolution) != len(town_names): + raise ValueError("Resolution must be of the same length as town_names.") + for i, town in enumerate(town_names): + print(f"Processing town: {town}") + generate_carla_road( + town, + source_dir, + carla_map_dir, + resolution[i], + dest_dir, + max_samples, + print_number_of_sample_truncations=print_number_of_sample_truncations, + ) + + +if __name__ == "__main__": + town_names = ["Town01", "Town02", "Town03", "Town04", "Town05", "Town06", "Town07", "Town10HD"] + source_dir = "data_utils/carla" + dest_dir = "data_utils/carla" + carla_map_dir = "/scratch/pm3881/Carla-0.10.0-Linux-Shipping/CarlaUnreal/Content/Carla/Maps/OpenDrive" + resolution = 1.0 # [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5] # Meters + max_samples = int(1e5) # Max points to sample per reference line + print_number_of_sample_truncations = True # Enable to see the number of data points lost + generate_carla_roads( + town_names, source_dir, carla_map_dir, resolution, dest_dir, max_samples, print_number_of_sample_truncations + ) + # resolution = 1.0 + # town_name = 'town06' + # generate_carla_road( + # town_name, + # source_dir, + # carla_map_dir, + # resolution, + # dest_dir, + # max_samples, + # print_number_of_sample_truncations + # ) diff --git a/data_utils/carla/process_carla_xodr.py b/data_utils/carla/process_carla_xodr.py new file mode 100644 index 0000000000..0c11b8c1b4 --- /dev/null +++ b/data_utils/carla/process_carla_xodr.py @@ -0,0 +1,897 @@ +import sys +import os +import json +import numpy as np +import random +from lxml import etree +import pyxodr +from pyxodr.road_objects.road import Road +from pyxodr.road_objects.lane import Lane, ConnectionPosition, LaneOrientation, TrafficOrientation +from pyxodr.road_objects.junction import Junction +from pyxodr.road_objects.lane_section import LaneSection +from pyxodr.road_objects.network import RoadNetwork +from shapely.geometry import Polygon +from enum import IntEnum + + +class MapType(IntEnum): + LANE_UNDEFINED = 0 + LANE_FREEWAY = 1 + LANE_SURFACE_STREET = 2 + LANE_BIKE_LANE = 3 + # Original definition skips 4 + ROAD_LINE_UNKNOWN = 5 + ROAD_LINE_BROKEN_SINGLE_WHITE = 6 + ROAD_LINE_SOLID_SINGLE_WHITE = 7 + ROAD_LINE_SOLID_DOUBLE_WHITE = 8 + ROAD_LINE_BROKEN_SINGLE_YELLOW = 9 + ROAD_LINE_BROKEN_DOUBLE_YELLOW = 10 + ROAD_LINE_SOLID_SINGLE_YELLOW = 11 + ROAD_LINE_SOLID_DOUBLE_YELLOW = 12 + ROAD_LINE_PASSING_DOUBLE_YELLOW = 13 + ROAD_EDGE_UNKNOWN = 14 + ROAD_EDGE_BOUNDARY = 15 + ROAD_EDGE_MEDIAN = 16 + STOP_SIGN = 17 + CROSSWALK = 18 + SPEED_BUMP = 19 + DRIVEWAY = 20 # New womd datatype in v1.2.0: Driveway entrances + UNKNOWN = -1 + NUM_TYPES = 21 + + +def save_lane_section_to_json(xodr_json, id, road_edges, road_lines, lanes, sidewalks=[]): + roads = xodr_json.get("roads", []) + for road_edge in road_edges: + # edge_polygon = Polygon(road_edge) + edge_data = { + "id": id, + "map_element_id": int(MapType.ROAD_EDGE_BOUNDARY), + "type": "road_edge", + "geometry": [{"x": float(pt[0]), "y": float(pt[1]), "z": 0.0} for pt in road_edge], + } + roads.append(edge_data) + id += 1 + for road_line in road_lines: + line_data = { + "id": id, + "map_element_id": int(MapType.ROAD_LINE_BROKEN_SINGLE_WHITE), + "type": "road_line", + "geometry": [{"x": float(pt[0]), "y": float(pt[1]), "z": 0.0} for pt in road_line], + } + roads.append(line_data) + id += 1 + for lane in lanes: + lane_data = { + "id": id, + "map_element_id": int(MapType.LANE_SURFACE_STREET), + "type": "lane", + "geometry": [{"x": float(pt[0]), "y": float(pt[1]), "z": 0.0} for pt in lane], + } + roads.append(lane_data) + id += 1 + # for sidewalk in sidewalks: + # sidewalk_data = { + # "id": id, + # "map_element_id": int(MapType.LANE_BIKE_LANE), + # "type": "sidewalk", + # "geometry": [{"x": float(pt[0]), "y": float(pt[1]), "z": 0.0} for pt in sidewalk] + # } + # roads.append(sidewalk_data) + # id += 1 + xodr_json["roads"] = roads + return id + + +def get_lane_data(lane, type="BOUNDARY", check_dir=True): + if type == "BOUNDARY": + points = lane.boundary_line + elif type == "CENTERLINE": + points = lane.centre_line + else: + raise ValueError(f"Unknown lane data type: {type}") + + if not check_dir: + return points + + # Check traffic direction + travel_dir = None + vector_lane = lane.lane_xml.find(".//userData/vectorLane") + if vector_lane is not None: + travel_dir = vector_lane.get("travelDir") + + if travel_dir == "backward": + # Reverse points for backward travel + points = points[::-1] + + return points + + +class RoadLinkObject: + def __init__(self, road_id, pred_lane_section_ids, succ_lane_section_ids): + self.road_id = road_id + self.pred_lane_section_ids = pred_lane_section_ids + self.succ_lane_section_ids = succ_lane_section_ids + self.lane_links_map = {} # map from (lane_id, lane_section_index) to LaneLinkObject + self.predecessor_roads = [] + self.successor_roads = [] + + +class LaneLinkObject: + def __init__(self, lane_id, lane_section_index, road_id, lane, lane_centerpoints, forward_dir, is_junction): + self.lane_id = lane_id + self.lane_section_index = lane_section_index + self.road_id = road_id + self.lane = lane + self.lane_centerpoints = lane_centerpoints + self.forward_dir = forward_dir + self.predecessor_lanes = [] + self.successor_lanes = [] + self.outgoing_edges = [] + self.incoming_edges = [] + self.is_sampled = False + self.is_junction = is_junction + + +def get_junction(road_network, junction_id): + for junction in road_network.get_junctions(): + if junction.id == junction_id: + return junction + return None + + +def get_road(road_network, road_id): + for road in road_network.get_roads(): + if road.id == road_id: + return road + return None + + +def is_forward_dir(lane): + # Check traffic direction + travel_dir = None + vector_lane = lane.lane_xml.find(".//userData/vectorLane") + if vector_lane is not None: + travel_dir = vector_lane.get("travelDir") + + if travel_dir == "forward": + return True + return False + + +def create_lane_link_elements(road_network, roads, road_link_map): + roads_json_cnt = [[], [], []] + print(f"Network has {len(roads)} roads.") + for road_obj in roads: + # print(f"Road ID: {road_obj.id}") + lane_sections = road_obj.lane_sections + + is_road_junction = False if road_obj.road_xml.attrib["junction"] == "-1" else True + pred_lane_section_ids = {} + for predecessor_xml in road_obj.road_xml.find("link").findall("predecessor"): + if predecessor_xml.attrib["elementType"] == "road": + pred_road_id = predecessor_xml.attrib["elementId"] + if predecessor_xml.attrib["contactPoint"] == "start": + pred_lane_section_ids[pred_road_id] = 0 + else: + pred_road = get_road(road_network, pred_road_id) + pred_lane_section_ids[pred_road_id] = len(pred_road.lane_sections) - 1 + + succ_lane_section_ids = {} + for successor_xml in road_obj.road_xml.find("link").findall("successor"): + if successor_xml.attrib["elementType"] == "road": + succ_road_id = successor_xml.attrib["elementId"] + if successor_xml.attrib["contactPoint"] == "start": + succ_lane_section_ids[succ_road_id] = 0 + else: + succ_road = get_road(road_network, succ_road_id) + succ_lane_section_ids[succ_road_id] = len(succ_road.lane_sections) - 1 + + road_link_object = RoadLinkObject( + road_id=road_obj.id, + pred_lane_section_ids=pred_lane_section_ids, + succ_lane_section_ids=succ_lane_section_ids, + ) + + for lane_section in lane_sections: + # print(f"Lane Section ID: {lane_section.lane_section_ordinal}") + # print(f"Number of Left Lanes: {len(lane_section.left_lanes)}") + # print(f"Number of Right Lanes: {len(lane_section.right_lanes)}") + road_edges = [] + road_lines = [] + lanes = [] + # sidwalks = [] + + left_immediate_driveable = False + right_immediate_driveable = False + + # Left Lanes + add_lane_data = False + add_edge_data = False + previous_lane = None + for i, left_lane in enumerate(lane_section.left_lanes): + if left_lane.type == "driving": # We only deal with driving lanes + if i == 0: + left_immediate_driveable = True + + if add_lane_data: + road_line_data = get_lane_data(previous_lane, "BOUNDARY") + road_line_data = road_line_data[::40] + road_lines.append(road_line_data) + waypoints = get_lane_data(previous_lane, "CENTERLINE") + lanes.append(waypoints) + road_link_object.lane_links_map[(str(previous_lane.id), lane_section.lane_section_ordinal)] = ( + LaneLinkObject( + lane_id=previous_lane.id, + lane_section_index=lane_section.lane_section_ordinal, + road_id=road_obj.id, + lane=previous_lane, + lane_centerpoints=waypoints, + forward_dir=is_forward_dir(previous_lane), + is_junction=is_road_junction, + ) + ) + # Add outer edge as road edge + elif add_edge_data: + road_edges.append(get_lane_data(previous_lane, "BOUNDARY")) + add_lane_data = True + add_edge_data = False + else: + # Add inner lane as road edge + if add_lane_data and i != 0: + waypoints = get_lane_data(previous_lane, "CENTERLINE") + lanes.append(waypoints) + road_link_object.lane_links_map[(str(previous_lane.id), lane_section.lane_section_ordinal)] = ( + LaneLinkObject( + lane_id=previous_lane.id, + lane_section_index=lane_section.lane_section_ordinal, + road_id=road_obj.id, + lane=previous_lane, + lane_centerpoints=waypoints, + forward_dir=is_forward_dir(previous_lane), + is_junction=is_road_junction, + ) + ) + road_edges.append(get_lane_data(previous_lane, "BOUNDARY")) + add_edge_data = True + add_lane_data = False + previous_lane = left_lane + + if add_lane_data: + waypoints = get_lane_data(previous_lane, "CENTERLINE") + lanes.append(waypoints) + road_link_object.lane_links_map[(str(previous_lane.id), lane_section.lane_section_ordinal)] = ( + LaneLinkObject( + lane_id=previous_lane.id, + lane_section_index=lane_section.lane_section_ordinal, + road_id=road_obj.id, + lane=previous_lane, + lane_centerpoints=waypoints, + forward_dir=is_forward_dir(previous_lane), + is_junction=is_road_junction, + ) + ) + road_edges.append(get_lane_data(previous_lane, "BOUNDARY")) + # elif add_edge_data: + # if previous_lane.type == 'sidewalk': + # sidwalks.append(get_lane_data(previous_lane, "BOUNDARY")) + + # print("LEFT STATS") + # print(f"Number of Road edges: {len(road_edges)}") + # print(f"Road lines: {len(road_lines)}") + # print(f"Lanes: {len(lanes)}") + # print(f"Sidewalks: {len(sidwalks)}") + + # Right Lanes + add_lane_data = False + add_edge_data = False + previous_lane = None + for i, right_lane in enumerate(lane_section.right_lanes): + if right_lane.type == "driving": + if i == 0: + right_immediate_driveable = True + + if add_lane_data: + road_line_data = get_lane_data(previous_lane, "BOUNDARY") + road_line_data = road_line_data[::40] + road_lines.append(road_line_data) + waypoints = get_lane_data(previous_lane, "CENTERLINE") + lanes.append(waypoints) + road_link_object.lane_links_map[(str(previous_lane.id), lane_section.lane_section_ordinal)] = ( + LaneLinkObject( + lane_id=previous_lane.id, + lane_section_index=lane_section.lane_section_ordinal, + road_id=road_obj.id, + lane=previous_lane, + lane_centerpoints=waypoints, + forward_dir=is_forward_dir(previous_lane), + is_junction=is_road_junction, + ) + ) + # Add outer edge as road edge + elif add_edge_data: + road_edges.append(get_lane_data(previous_lane, "BOUNDARY")) + add_lane_data = True + add_edge_data = False + else: + # Add inner lane as road edge + if add_lane_data and i != 0: + waypoints = get_lane_data(previous_lane, "CENTERLINE") + lanes.append(waypoints) + road_link_object.lane_links_map[(str(previous_lane.id), lane_section.lane_section_ordinal)] = ( + LaneLinkObject( + lane_id=previous_lane.id, + lane_section_index=lane_section.lane_section_ordinal, + road_id=road_obj.id, + lane=previous_lane, + lane_centerpoints=waypoints, + forward_dir=is_forward_dir(previous_lane), + is_junction=is_road_junction, + ) + ) + road_edges.append(get_lane_data(previous_lane, "BOUNDARY")) + add_edge_data = True + add_lane_data = False + previous_lane = right_lane + + if add_lane_data: + waypoints = get_lane_data(previous_lane, "CENTERLINE") + lanes.append(waypoints) + road_link_object.lane_links_map[(str(previous_lane.id), lane_section.lane_section_ordinal)] = ( + LaneLinkObject( + lane_id=previous_lane.id, + lane_section_index=lane_section.lane_section_ordinal, + road_id=road_obj.id, + lane=previous_lane, + lane_centerpoints=waypoints, + forward_dir=is_forward_dir(previous_lane), + is_junction=is_road_junction, + ) + ) + road_edges.append(get_lane_data(previous_lane, "BOUNDARY")) + # elif add_edge_data: + # if previous_lane.type == 'sidewalk': + # sidwalks.append(get_lane_data(previous_lane, "BOUNDARY")) + + road_link_map[road_obj.id] = road_link_object + + roads_json_cnt[0].append(len(road_edges)) + roads_json_cnt[1].append(len(road_lines)) + roads_json_cnt[2].append(len(lanes)) + # if len(lanes) == 0 and len(road_lines) != 0: + # print(f"Road: {road_obj.id}, Lane Section: {lane_section.lane_section_ordinal}") + # print(f"Road edges: {len(road_edges)}, Road lines: {len(road_lines)}, Lanes: {len(lanes)}") + # break + # break + print(f"Total roads JSON count: {sum(roads_json_cnt[0]) + sum(roads_json_cnt[1]) + sum(roads_json_cnt[2])}") + # print(f"Road edges count: {roads_json_cnt[0]}") + # print(f"Road lines count: {roads_json_cnt[1]}") + print(f"Lanes count: {sum(roads_json_cnt[2])}") + total_lane_links = sum(len(obj.lane_links_map) for obj in road_link_map.values()) + assert sum(roads_json_cnt[2]) == total_lane_links + + +def create_successor_predecessor_elements(road_network, roads, road_link_map): + stopping_points = 0 + + for road_obj in roads: + # print(f"Road ID: {road_obj.id}") + road_link_object = road_link_map[road_obj.id] + lane_sections = road_obj.lane_sections + # print(f"Lane Sections: {lane_sections}") + + for lane_link_obj in road_link_object.lane_links_map.values(): + lane_link_obj.predecessor_lanes = [] + lane_link_obj.successor_lanes = [] + + lane = lane_link_obj.lane + + link_xml = lane.lane_xml.find("link") + + successor_is_junction = True + if link_xml is not None and link_xml.findall("successor") != []: + successor_is_junction = False + # if link_xml.findall("successor") == []: + # print(f"Successor for road: {road_obj.id}, lane_section: {lane_link_obj.lane_section_index}, lane: {lane_link_obj.lane.id}: {link_xml.findall('successor')}") + # Process Successor Links + for successor in link_xml.findall("successor"): + successor_id = successor.get("id") + + if lane_link_obj.lane_section_index + 1 < len(lane_sections): + # Lane link in next lane section + lane_link_obj.successor_lanes.append( + road_link_object.lane_links_map[(successor_id, lane_link_obj.lane_section_index + 1)] + ) + else: + # Lane link in successor roads + for road_succ in road_obj.road_xml.find("link").findall("successor"): + if road_succ.attrib["elementType"] == "road": + succ_road_id = road_succ.attrib["elementId"] + succ_road = road_link_map[succ_road_id] + succ_lane_section_index = road_link_object.succ_lane_section_ids[succ_road_id] + # if (lane_link_obj.lane_id, succ_lane_section_index) not in succ_road.lane_links_map: + # print(f"Key:{(successor_id, succ_lane_section_index)} not found in lane_links_map - road_id: {succ_road_id}, lane_section_index: {succ_lane_section_index}, lane_id: {successor_id}") + lane_link_obj.successor_lanes.append( + succ_road.lane_links_map[(successor_id, succ_lane_section_index)] + ) + else: + # Junction case + successor_is_junction = True + elif successor_is_junction: + # if road_obj.id == "0" and str(lane.id) == "-1": + # print(f"Road: {road_obj.id}, lane: {lane.id}, successor is a junction") + # break + # Handle junction case + for successor in road_obj.road_xml.find("link").findall("successor"): + if successor.attrib["elementType"] == "junction": + junction_id = successor.attrib["elementId"] + # print(f"Road: {road_obj.id}, lane: {lane.id}, successor is a junction: {junction_id}") + junction = get_junction(road_network, junction_id) + # print(f"Retrieved Junction: {junction.id} from road_network") + connected_lanes = junction.get_lane_junction_lanes(str(lane.id), road_id=road_obj.id) + if len(connected_lanes) == 0 and lane_link_obj.forward_dir: + stopping_points += 1 + print( + f"Non junction road: {road_obj.id}, lane_section: {lane_link_obj.lane_section_index}, lane: {lane_link_obj.lane.id} has no junction or road links, it is an ending lane" + ) + for conn_lane in connected_lanes: + succ_road_obj = get_road(road_network, conn_lane["road_id"]) + succ_road = road_link_map[conn_lane["road_id"]] + succ_lane_section_index = conn_lane["lane_section_index"] + if succ_lane_section_index == -1: + succ_lane_section_index = len(succ_road_obj.lane_sections) - 1 + succ_lane_id = conn_lane["lane_id"] + lane_link_obj.successor_lanes.append( + succ_road.lane_links_map[(str(succ_lane_id), succ_lane_section_index)] + ) + else: + if lane_link_obj.forward_dir: + # Stopping point + stopping_points += 1 + print( + f"Non junction road: {road_obj.id}, lane_section: {lane_link_obj.lane_section_index}, lane: {lane_link_obj.lane.id} has no junction or road links, it is an ending lane" + ) + + predecessor_is_junction = True + if link_xml is not None and link_xml.findall("predecessor") != []: + predecessor_is_junction = False + # Process Predecessor Links + for predecessor in link_xml.findall("predecessor"): + predecessor_id = predecessor.get("id") + + if lane_link_obj.lane_section_index - 1 >= 0: + # Lane link in previous lane section + lane_link_obj.predecessor_lanes.append( + road_link_object.lane_links_map[(predecessor_id, lane_link_obj.lane_section_index - 1)] + ) + else: + # Lane link in predecessor roads + for road_pred in road_obj.road_xml.find("link").findall("predecessor"): + if road_pred.attrib["elementType"] == "road": + pred_id = road_pred.attrib["elementId"] + pred_road = road_link_map[pred_id] + pred_lane_section_index = road_link_object.pred_lane_section_ids[pred_id] + # print(f"Curr lane: {lane_link_obj.lane.id}, section: {lane_link_obj.lane_section_index}, road: {road_obj.id}; Pred lane: {predecessor_id}, section: {road_link_object.pred_lane_section_ids[pred_id]}, road: {pred_id}") + lane_link_obj.predecessor_lanes.append( + pred_road.lane_links_map[(predecessor_id, pred_lane_section_index)] + ) + else: + # Junction case + predecessor_is_junction = True + elif predecessor_is_junction: + # Handle junction case + for predecessor in road_obj.road_xml.find("link").findall("predecessor"): + if predecessor.attrib["elementType"] == "junction": + junction_id = predecessor.attrib["elementId"] + junction = get_junction(road_network, junction_id) + connected_lanes = junction.get_lane_junction_lanes(lane_id=str(lane.id), road_id=road_obj.id) + if len(connected_lanes) == 0 and not lane_link_obj.forward_dir: + stopping_points += 1 + print( + f"Non junction road: {road_obj.id}, lane_section: {lane_link_obj.lane_section_index}, lane: {lane_link_obj.lane.id} has no junction or road links, it is a starting lane" + ) + for conn_lane in connected_lanes: + pred_road_obj = get_road(road_network, conn_lane["road_id"]) + pred_road = road_link_map[conn_lane["road_id"]] + pred_lane_section_index = conn_lane["lane_section_index"] + if pred_lane_section_index == -1: + pred_lane_section_index = len(pred_road_obj.lane_sections) - 1 + pred_lane_id = conn_lane["lane_id"] + lane_link_obj.predecessor_lanes.append( + pred_road.lane_links_map[(str(pred_lane_id), pred_lane_section_index)] + ) + else: + if not lane_link_obj.forward_dir: + # Stopping case + stopping_points += 1 + print( + f"Non junction road: {road_obj.id}, lane_section: {lane_link_obj.lane_section_index}, lane: {lane_link_obj.lane.id} has no junction or road links, it is a starting lane" + ) + + print(f"Road network has {stopping_points} stopping points (lanes with no predecessors or successors).") + + +def add_incoming_outgoing_edges(road_network, roads, road_link_map): + for road_obj in roads: + # print(f"Road ID: {road_obj.id}") + road_link_object = road_link_map[road_obj.id] + lane_sections = road_obj.lane_sections + # print(f"Lane Sections: {lane_sections}") + + for lane_link_obj in road_link_object.lane_links_map.values(): + lane = lane_link_obj.lane + link_xml = lane.lane_xml.find("link") + + if lane_link_obj.forward_dir: + # Forward direction, predecessor lanes are incoming edges, successor lanes are outgoing edges + lane_link_obj.incoming_edges = lane_link_obj.predecessor_lanes + lane_link_obj.outgoing_edges = lane_link_obj.successor_lanes + else: + # Backward direction, predecessor lanes are outgoing edges, successor lanes are incoming edges + lane_link_obj.outgoing_edges = lane_link_obj.predecessor_lanes + lane_link_obj.incoming_edges = lane_link_obj.successor_lanes + + +def test_linkage(road_link_map): + # Testing linkage + + start_road_id = "0" + road_link_object = road_link_map[start_road_id] + + lane_link_keys = list(road_link_object.lane_links_map.keys()) + random_lane_link_key = None + if random_lane_link_key is None: + random_lane_link_key = random.choice(lane_link_keys) + lane_link_obj = road_link_object.lane_links_map[random_lane_link_key] + + print(f"Starting at road id: {start_road_id}") + print(f"Lane link key: {random_lane_link_key}") + print(f"Lane id: {lane_link_obj.lane_id}, Lane section index: {lane_link_obj.lane_section_index}") + + # Traverse outgoing edges for 10 steps + current = lane_link_obj + for step in range(10): + print(f"\nStep {step}:") + print( + f" Road id: {current.road_id}, Lane id: {current.lane_id}, Lane section index: {current.lane_section_index}" + ) + if current.outgoing_edges: + current = random.choice(current.outgoing_edges) + else: + print(" No outgoing edges. Stopping traversal.") + print("Debugging") + print( + f"Outgoing Edges: {[(edge.road_id, str(edge.lane.id), edge.lane_section_index) for edge in current.outgoing_edges]}" + ) + print( + f"Incoming Edges: {[(edge.road_id, str(edge.lane.id), edge.lane_section_index) for edge in current.incoming_edges]}" + ) + print( + f"Successors: {[(edge.road_id, str(edge.lane.id), edge.lane_section_index) for edge in current.successor_lanes]}" + ) + print( + f"Predecessors: {[(edge.road_id, str(edge.lane.id), edge.lane_section_index) for edge in current.predecessor_lanes]}" + ) + break + + +def print_traj_stats(waypoints_list, num_timestamps, episode_length): + # Extract positions + positions = [wp["position"] for wp in waypoints_list if "position" in wp] + positions = np.array(positions) + + # Compute consecutive distances + if positions.shape[0] < 2: + print("Not enough waypoints to compute statistics.") + return + + diffs = positions[1:] - positions[:-1] + distances = np.linalg.norm(diffs, axis=1) + distance_traversed = np.sum(distances) + + # Compute max speed along trajectory + timestamp_dur = episode_length / num_timestamps + speeds = distances / timestamp_dur + max_speed_traj = np.max(speeds) + + print(f"Distance traversed: {distance_traversed} meters") + print(f"Max speed in trajectory: {max_speed_traj} m/s") + + +def check_geometry(point, all_geometries): + for pt in all_geometries: + dist = np.linalg.norm(np.array(pt) - np.array(point)) + if dist < 1e-9: # threshold, adjust as needed + return False + return True + + +def generate_traj_data( + road_link_map, + num_timestamps=90, + resolution=0.1, + episode_length=9, + max_speed=10, + random_sampling_variation=1, + resample=True, + all_geometries=[], +): + # Calculate average speed (70% of max_speed) + avg_speed = 0.7 * max_speed + avg_cons_pts_dist = resolution * (1 + np.sqrt(2)) / 2 + time_step_dur = episode_length / num_timestamps + sampling_length = int((avg_speed * time_step_dur) / avg_cons_pts_dist) + + # # Calculate junction speed (20% of max_speed) + # junction_speed = 0.2 * max_speed + + # Pick a random lane_link_key + while True: + road_link_keys = list(road_link_map.keys()) + start_key = random.choice(road_link_keys) + lane_link_keys = list(road_link_map[start_key].lane_links_map.keys()) + if lane_link_keys != []: + if resample: + start_lane_key = random.choice(lane_link_keys) + lane_link_obj = road_link_map[start_key].lane_links_map[start_lane_key] + if not lane_link_obj.is_sampled: + # print(f"Starting: RoadLink key: {start_key}\n LaneLink key: {start_lane_key}") + break + else: + start_lane_key = random.choice(lane_link_keys) + lane_link_obj = road_link_map[start_key].lane_links_map[start_lane_key] + + waypoints_list = [] + current_lane_link = lane_link_obj + current_lane_link.is_sampled = True + idx = random.randint(0, len(current_lane_link.lane_centerpoints) - 1) + # if check_geometry(current_lane_link.lane_centerpoints[idx], all_geometries) == False: + # print(f"Waypoint {current_lane_link.lane_centerpoints[idx]}, lane: {current_lane_link.lane_id}, Lane_Section: {current_lane_link.lane_section_index} Road: {current_lane_link.road_id} not in all_geometries") + waypoints_list.append( + { + "timestamp": 0, + "position": current_lane_link.lane_centerpoints[idx].tolist() + if hasattr(current_lane_link.lane_centerpoints[idx], "tolist") + else list(current_lane_link.lane_centerpoints[idx]), + "lane_id": current_lane_link.lane_id, + "lane_section_index": current_lane_link.lane_section_index, + "road_id": current_lane_link.road_id, + } + ) + change_lane = False + + for t in range(num_timestamps): + if change_lane: + # Pick a random outgoing edge + if current_lane_link.outgoing_edges: + if resample: + # Filter outgoing_edges with is_sampled == False + unsampled_edges = [ + edge for edge in current_lane_link.outgoing_edges if not getattr(edge, "is_sampled", False) + ] + if unsampled_edges != []: + current_lane_link = random.choice(unsampled_edges) + else: + current_lane_link = random.choice(current_lane_link.outgoing_edges) + current_lane_link.is_sampled = True + idx = 0 # Lane connection width is zero so reset at start + else: + current_lane_link = random.choice(current_lane_link.outgoing_edges) + else: + # No outgoing edge, stop trajectory + print("No outgoing edge, stopping trajectory") + while len(waypoints_list) < num_timestamps + 1: + waypoints_list.append( + { + "position": waypoint.tolist() if hasattr(waypoint, "tolist") else list(waypoint), + "velocity": {"x": 0.0, "y": 0.0}, + "heading": 0.0 if len(waypoints_list) == 0 else waypoints_list[-1]["heading"], + "lane_id": current_lane_link.lane_id, + "lane_section_index": current_lane_link.lane_section_index, + "road_id": current_lane_link.road_id, + "change_lane": change_lane, + } + ) + break + + # Randomize sampling length + curr_sampling_length = sampling_length + random.randint(-random_sampling_variation, random_sampling_variation) + next_idx = idx + curr_sampling_length + + if next_idx < len(current_lane_link.lane_centerpoints): + waypoint = current_lane_link.lane_centerpoints[next_idx] + idx = next_idx + change_lane = False + else: + waypoint = current_lane_link.lane_centerpoints[-1] + change_lane = True + + # Velocity and heading calculation + v_x = (waypoint[0] - waypoints_list[t - 1]["position"][0]) / time_step_dur + v_y = (waypoint[1] - waypoints_list[t - 1]["position"][1]) / time_step_dur + heading = np.arctan2(v_y, v_x) + + # if check_geometry(waypoint, all_geometries) == False: + # print(f"Waypoint {waypoint}, lane: {current_lane_link.lane_id}, Lane_Section: {current_lane_link.lane_section_index} Road: {current_lane_link.road_id} not in all_geometries") + + waypoints_list.append( + { + "position": waypoint.tolist() if hasattr(waypoint, "tolist") else list(waypoint), + "velocity": {"x": v_x, "y": v_y}, + "heading": heading, + "lane_id": current_lane_link.lane_id, + "lane_section_index": current_lane_link.lane_section_index, + "road_id": current_lane_link.road_id, + } + ) + + # Change first waypoint with average velocity and avg heading keeping everything else same + waypoints_list[0] = { + "position": waypoints_list[0]["position"], + "velocity": { + "x": np.mean([wp["velocity"]["x"] for wp in waypoints_list[1:]]), + "y": np.mean([wp["velocity"]["y"] for wp in waypoints_list[1:]]), + }, + "heading": np.mean([wp["heading"] for wp in waypoints_list[1:]]), + "lane_id": waypoints_list[0]["lane_id"], + "lane_section_index": waypoints_list[0]["lane_section_index"], + "road_id": waypoints_list[0]["road_id"], + } + + return waypoints_list + + +def save_object_to_json( + xodr_json, + road_link_map, + id, + resolution=0.1, + object_type="vehicle", + all_geometries=[], + start_with_zero_velocity=True, +): + traj_data = generate_traj_data(road_link_map=road_link_map, resolution=resolution, all_geometries=all_geometries) + + z = 1.0 + headings = [] + positions = [] + velocities = [] + for i, traj in enumerate(traj_data): + x = traj["position"][0] + y = traj["position"][1] + positions.append({"x": float(x), "y": float(y), "z": float(z)}) + v_x = 0.0 if start_with_zero_velocity and i == 0 else traj["velocity"]["x"] + v_y = 0.0 if start_with_zero_velocity and i == 0 else traj["velocity"]["y"] + velocities.append({"x": float(v_x), "y": float(v_y)}) + headings.append(float(traj["heading"])) + + object_data = { + "position": list(positions), + "width": 2.0, + "length": 4.5, + "height": 1.8, + "id": id, + "heading": list(headings), + "velocity": list(velocities), + "valid": [True] * len(positions), + "goalPosition": { + "x": float(positions[-1]["x"]), + "y": float(positions[-1]["y"]), + "z": float(positions[-1]["z"]), + }, + "type": object_type, + "mark_as_expert": False, + } + + objects = xodr_json.get("objects", []) + objects.append(object_data) + xodr_json["objects"] = objects + return id + 1 + + +def generate_data_each_map( + town_names, + carla_map_dir, + resolution, + input_json_base_path, + output_json_root_dir, + num_data_per_map, + num_objects, + make_only_first_agent_controllable, + start_with_zero_velocity=True, +): + os.makedirs(output_json_root_dir, exist_ok=True) + for town_name in town_names: + json_file = town_name + ".json" + odr_file = os.path.join(carla_map_dir, "T" + town_name[1:] + ".xodr") + input_json_path = os.path.join(input_json_base_path, json_file) + + for id in range(num_data_per_map): + output_json_path = os.path.join(output_json_root_dir, f"{town_name}_{id}.json") + + road_network = RoadNetwork(xodr_file_path=odr_file, resolution=resolution) + roads = road_network.get_roads() + print(f"Number of roads in the network: {len(roads)}") + + # Create a dictionary to map road_id to RoadLinkObject + road_link_map = {} + + # First create the lane link elements + create_lane_link_elements(road_network, roads, road_link_map) + + # Create successor predecessor elements + create_successor_predecessor_elements(road_network, roads, road_link_map) + + # Now add outgoing and incoming edges based on driving direction + add_incoming_outgoing_edges(road_network, roads, road_link_map) + + # Test linkage + test_linkage(road_link_map) + + with open(input_json_path, "r") as f: + xodr_json = json.load(f) + + roads = xodr_json["roads"] + all_geometries = [] + for road in roads: + geometry = [[pt["x"], pt["y"], pt["z"]] for pt in road["geometry"]] + all_geometries.extend(geometry) + + print(f"Total number of geometry points: {len(all_geometries)}") + # print(all_geometries[:100]) + + xodr_json["objects"] = [] + + for i in range(num_objects): + id = i + 1 + save_object_to_json( + xodr_json, + road_link_map, + id, + resolution=resolution, + all_geometries=all_geometries, + start_with_zero_velocity=start_with_zero_velocity, + ) + + # Make first agent only controllable + if make_only_first_agent_controllable: + for i, obj in enumerate(xodr_json.get("objects", [])): + if i == 0: + obj["mark_as_expert"] = False + else: + obj["mark_as_expert"] = True + + # Save to file + with open(output_json_path, "w") as f: + json.dump(xodr_json, f, indent=2) + + # Verify number of objects + with open(output_json_path, "r") as f: + xodr_json = json.load(f) + assert len(xodr_json.get("objects", [])) == num_objects + + print(f"Saved {num_objects} objects to {output_json_path}") + + +if __name__ == "__main__": + town_names = ["Town01", "Town02", "Town03", "Town04", "Town05", "Town06", "Town07", "Town10HD"] + # town_names = ['Town03'] + input_json_base_path = "data_utils/carla" + output_json_root_dir = "data/processed/carla_data" + carla_map_dir = "/scratch/pm3881/Carla-0.10.0-Linux-Shipping/CarlaUnreal/Content/Carla/Maps/OpenDrive" + resolution = 0.1 + num_data_per_map = 20 + num_objects = 32 + make_only_first_agent_controllable = False + start_with_zero_velocity = True + generate_data_each_map( + town_names, + carla_map_dir, + resolution, + input_json_base_path, + output_json_root_dir, + num_data_per_map, + num_objects=num_objects, + make_only_first_agent_controllable=make_only_first_agent_controllable, + start_with_zero_velocity=start_with_zero_velocity, + ) diff --git a/mlops/README.md b/mlops/README.md new file mode 100644 index 0000000000..cd46c1f367 --- /dev/null +++ b/mlops/README.md @@ -0,0 +1,131 @@ +# PufferDrive MLOps + +Tooling for running PufferDrive experiments on GCP Vertex AI. + +## Concepts + +- **Experiment**: A group of related training runs (e.g., "hyperparam_sweep", "baseline_comparison") +- **Run**: An individual training job within an experiment + +Output is organized hierarchically in the bucket: +``` +gs://bucket/experiments/// +``` + +## Quick Start + +```bash +# Launch a single run +python mlops/mlops.py launch my_experiment my_run --machine T4 + +# Launch multiple runs from config +python mlops/mlops.py launch-batch mlops/configs/experiments.yaml + +# Build base Docker image (only needed after dependency changes) +python mlops/mlops.py build-image +``` + +## Commands + +### `launch` - Run a single training job + +```bash +python mlops/mlops.py launch [options] + +Options: + --machine, -m Machine preset (see table below). Default: T4 + --dataset-path, -d GCS path to training dataset + --eval-dataset-path GCS path to eval dataset + --mode Run mode: train or sweep. Default: train + --project, -p GCP project (DRILAX, NOA, ...). Default: DRILAX + --verbose, -v Show Docker build/push output + +# Examples: +python mlops/mlops.py launch baseline run1 --machine T4 +python mlops/mlops.py launch hyperparam_sweep lr_1e-3 -m L4 + +# Hyperparameter sweep (uses [sweep.*] sections from drive.ini) +python mlops/mlops.py launch my_sweep run1 --project NOA --machine T4 --mode sweep --max-runs 5 --dataset-path /gcs/valeo-cp2879-driving-policy/datasets/womd/1000 +``` + +### `launch-batch` - Run multiple experiments/runs + +Define experiments in a YAML file: + +```yaml +experiments: + # Experiment with multiple runs + - name: hyperparam_sweep + machine: T4 + params: + env.num-agents: 1024 + runs: + - name: lr_1e-3 + params: + train.learning-rate: 0.001 + - name: lr_5e-4 + params: + train.learning-rate: 0.0005 + + # Single run experiment (no 'runs' field — experiment name used as run name) + - name: baseline_T4 + machine: T4 + params: + train.minibatch-size: 11648 +``` + +Then run: + +```bash +python mlops/mlops.py launch-batch mlops/configs/experiments.yaml +``` + +One Docker image is built per project, compiled for the union of all CUDA architectures +used by the runs in that project. Mixed machine types in the same batch are supported. + +### `train-test` - CI smoke test + +Launches the runs defined in `mlops/configs/smoke-tests.yaml`. Called automatically on PR merge. + +```bash +python mlops/mlops.py train-test +``` + +### `build-image` - Build base Docker image + +Only needed when Python dependencies change (torch, heavyball, etc.): + +```bash +python mlops/mlops.py build-image +``` + +## Machine Presets + +| Preset | Machine Type | GPU | Count | +|-------------|--------------------|----------------------|-------| +| T4 | n1-standard-16 | NVIDIA T4 | 1 | +| T4_2 | n1-standard-32 | NVIDIA T4 | 2 | +| T4_4 | n1-standard-32 | NVIDIA T4 | 4 | +| L4 | g2-standard-16 | NVIDIA L4 | 1 | +| L4_8 | g2-standard-96 | NVIDIA L4 | 8 | +| A100 | a2-highgpu-1g | NVIDIA A100 | 1 | +| A100_4 | a2-megagpu-16g | NVIDIA A100 | 4 | +| RTX6000 | g4-standard-48 | NVIDIA RTX Pro 6000 | 1 | +| RTX6000_2 | g4-standard-96 | NVIDIA RTX Pro 6000 | 2 | +| RTX6000_4 | g4-standard-192 | NVIDIA RTX Pro 6000 | 4 | +| RTX6000_8 | g4-standard-384 | NVIDIA RTX Pro 6000 | 8 | + +## File Structure + +``` +mlops/ +├── mlops.py # Main CLI +├── run_training.sh # Container entrypoint script +├── configs/ +│ ├── smoke-tests.yaml # CI smoke test runs +│ └── experiments.yaml # (user-created) batch experiment configs +├── dockerfile/ +│ ├── .dockerignore # Docker ignore file (copied to root during build) +│ ├── build.dockerfile # Base image with Python deps (rebuild on dep changes) +│ └── launch.dockerfile # Training image (rebuilds on code changes) +``` diff --git a/mlops/configs/experiments.yaml b/mlops/configs/experiments.yaml new file mode 100644 index 0000000000..de59bb837b --- /dev/null +++ b/mlops/configs/experiments.yaml @@ -0,0 +1,92 @@ +# PufferDrive Experiments Configuration +# ====================================== +# +# Define experiments and runs to execute on GCP Vertex AI. +# +# Structure: +# experiments: +# - name: experiment_name # Group name for related runs +# machine: T4 # Default machine for all runs (optional) +# dataset_path: gs://... # Default dataset for all runs (optional) +# params: {...} # Default params inherited by all runs (optional) +# param.key: value # Flat params also supported at experiment level +# runs: # List of individual runs +# - name: run_name # Unique name within the experiment +# machine: L4 # Override machine for this run (optional) +# params: {...} # Additional/override params (optional) +# +# If no 'runs' are specified, the experiment itself becomes a single run. +# +# Output structure in bucket: +# gs://bucket/experiments/// +# +# Usage: +# python mlops/mlops.py launch-batch mlops/experiments.yaml + + +experiments: + - name: gigaflow + machine: RTX6000_2 + params: + # Vec + vec.num-envs: 32 + # Env + env.num-agents: 4096 + # Train + train.minibatch-size: 262_144 + train.max-minibatch-size: 262_144 + train.total-timesteps: 300_000_000_000 + # Paper hparams + train.gamma: 0.99 + train.gae-lambda: 0.95 + train.learning-rate: 0.0005 + train.ent-coef: 0.01 + train.vf-coef: 0.5 + train.clip-coef: 0.2 + train.max-grad-norm: 0.5 + train.update-epochs: 1 + runs: + # # 1. Faithful paper replication: FF + large arch + paper hparams + # - name: ff_paper_arch + # params: + # rnn-name: None + # policy.input-size: 128 + # policy.backbone-hidden-size: 1024 + # policy.backbone-num-layers: 3 + # policy.encoder-gigaflow: True + + # # 2. LSTM + paper-sized arch + paper hparams + # # (split-network must be False: LSTM wrapper asserts this) + # - name: lstm_paper_arch + # params: + # policy.input-size: 128 + # policy.backbone-hidden-size: 1024 + # policy.backbone-num-layers: 2 + # policy.encoder-gigaflow: True + # policy.dropout: 0.2 + # rnn.input-size: 1024 # must match backbone-hidden-size + # rnn.hidden-size: 1024 + + # - name: l4_lstm_new_arch_input_128_24_env + # params: + # policy.input-size: 128 + # policy.encoder-gigaflow: True + # policy.dropout: 0.2 + + # - name: test_dockerfile + # params: + # rnn-name: Recurrent + # policy.encoder-gigaflow: True + # policy.dropout: 0.2 + + - name: test_dockerfile_ptx + params: + rnn-name: None + policy.encoder-gigaflow: True + policy.dropout: 0.2 + + # 4. LSTM + current (small) arch + paper hparams → cheapest LSTM comparison + # - name: lstm_small_arch + # params: + # policy.encoder-gigaflow: True + # rnn.hidden-size: 512 diff --git a/mlops/configs/smoke-tests.yaml b/mlops/configs/smoke-tests.yaml new file mode 100644 index 0000000000..fc09505a83 --- /dev/null +++ b/mlops/configs/smoke-tests.yaml @@ -0,0 +1,174 @@ +# PufferDrive Smoke Tests Configuration +# ====================================== +# +# Short training runs (~200M steps, ~60 min on T4) for CI convergence checks. +# Launched on every PR merge to develop via cmd_train_test. +# +# 4 runs covering the key training setups to verify reward trends upward. + +experiments: + - name: smoke_tests + machine: T4 + params: + vec.num-envs: 8 + train.total-timesteps: 500_000_000 + train.torch-deterministic: True + env.num-agents: 1024 + env.dt: 0.1 + env.reach-goal-behavior: 1 + env.max-lane-segment-observations: 32 + env.max-boundary-segment-observations: 12 + env.max-partner-observations: 4 + env.max-traffic-light-observations: 4 + env.max-stop-sign-observations: 1 + policy.input-size: 64 + policy.backbone-hidden-size: 256 + policy.backbone-num-layers: 1 + policy.actor-hidden-size: 256 + policy.actor-num-layers: 0 + policy.critic-hidden-size: 256 + policy.critic-num-layers: 0 + policy.split-network: False + policy.encoder-gigaflow: False + policy.dropout: 0.0 + rnn.input-size: 256 + rnn.hidden-size: 256 + + runs: + - name: smoke_gf_disc_jerk + dataset_path: "/gcs/valeo-cp2386-datasets/pufferdrive/v1.1/carla/" + params: + # Training parameters + train.minibatch-size: 4096 + train.max-minibatch-size: 4096 + train.bptt-horizon: 64 + # Environment parameters + env.simulation-mode: "gigaflow" + env.action-type: "discrete" + env.dynamics-model: "jerk" + env.reward-conditioning: True + env.reward-randomization: True + env.scenario-length: 128 + env.resample-frequency: 0 + env.num-maps: 1 + + # Observations + env.target-type: "static" + env.num-target-waypoints: 1 + env.min-waypoint-spacing: 2.0 + env.max-waypoint-spacing: 2.0 + + - name: smoke_replay_cont_classic + dataset_path: "/gcs/valeo-cp2386-datasets/pufferdrive/v1.1/womd/1000/" + params: + # Training parameters + train.minibatch-size: 5824 + train.max-minibatch-size: 5824 + train.bptt-horizon: 91 + # Environment parameters + env.simulation-mode: "replay" + env.action-type: "continuous" + env.dynamics-model: "classic" + env.reward-conditioning: False + env.reward-randomization: False + env.scenario-length: 91 + env.resample-frequency: 910 + env.num-maps: 1000 + + # Observations + env.target-type: "dynamic" + env.num-target-waypoints: 20 + env.min-waypoint-spacing: 2.0 + env.max-waypoint-spacing: 2.0 + + # Reward + env.reward-vehicle-collision: 1.0 + env.reward-offroad-collision: 1.0 + env.reward-traffic-light-violation: 1.0 + env.reward-ade: 0.0 + env.reward-goal: 0.0 + env.reward-progression: 0.2 + env.reward-under-speed: 0.05 + env.reward-comfort: 0.0 + env.reward-vel-align: 0.0 + env.reward-velocity: 0.0 + env.reward-lane-align: 0.0 + env.reward-lane-center: 1.0 + env.reward-timestep: 0.0 + + - name: smoke_replay_traj_jerk + dataset_path: "/gcs/valeo-cp2386-datasets/pufferdrive/v1.1/womd/1000/" + params: + # Training parameters + train.minibatch-size: 5824 + train.max-minibatch-size: 5824 + train.bptt-horizon: 91 + # Environment parameters + env.simulation-mode: "replay" + env.action-type: "trajectory_jerk" + env.dynamics-model: "jerk" + env.reward-conditioning: False + env.reward-randomization: False + env.trajectory-scaling-factors: [1.0, 1.0, 1.0, 1.0, 1.0, 1.0] + env.scenario-length: 91 + env.resample-frequency: 910 + env.num-maps: 1000 + + # Observations + env.target-type: "dynamic" + env.num-target-waypoints: 20 + env.min-waypoint-spacing: 2.0 + env.max-waypoint-spacing: 2.0 + + # Reward + env.reward-vehicle-collision: 1.0 + env.reward-offroad-collision: 1.0 + env.reward-traffic-light-violation: 1.0 + env.reward-ade: 0.0 + env.reward-goal: 0.0 + env.reward-progression: 0.2 + env.reward-under-speed: 0.05 + env.reward-comfort: 0.0 + env.reward-vel-align: 0.0 + env.reward-velocity: 0.0 + env.reward-lane-align: 0.0 + env.reward-lane-center: 1.0 + env.reward-timestep: 0.0 + + - name: smoke_replay_disc_jerk + dataset_path: "/gcs/valeo-cp2386-datasets/pufferdrive/v1.1/womd/1000/" + params: + # Training parameters + train.minibatch-size: 5824 + train.max-minibatch-size: 5824 + train.bptt-horizon: 91 + # Environment parameters + env.simulation-mode: "replay" + env.action-type: "discrete" + env.dynamics-model: "jerk" + env.reward-conditioning: False + env.reward-randomization: False + env.scenario-length: 91 + env.resample-frequency: 910 + env.num-maps: 1000 + + # Observations + env.target-type: "dynamic" + env.num-target-waypoints: 20 + env.min-waypoint-spacing: 2.0 + env.max-waypoint-spacing: 2.0 + + # Reward + env.reward-vehicle-collision: 1.0 + env.reward-offroad-collision: 1.0 + env.reward-traffic-light-violation: 1.0 + env.reward-ade: 0.0 + env.reward-goal: 0.0 + env.reward-progression: 0.2 + env.reward-under-speed: 0.05 + env.reward-comfort: 0.0 + env.reward-vel-align: 0.0 + env.reward-velocity: 0.0 + env.reward-lane-align: 0.0 + env.reward-lane-center: 1.0 + env.reward-timestep: 0.0 diff --git a/mlops/dockerfile/.dockerignore b/mlops/dockerfile/.dockerignore new file mode 100644 index 0000000000..ced3190b86 --- /dev/null +++ b/mlops/dockerfile/.dockerignore @@ -0,0 +1,83 @@ +# ============================================================================= +# Docker Ignore for PufferDrive +# ============================================================================= +# Excludes files not needed in the training container to speed up builds. +# This file is copied to the project root during docker build by mlops.py + +# Git +.git/ +.gitignore +.github/ + +# Python virtual environment +.venv/ +venv/ +env/ + +# Python cache and compiled files +**/__pycache__/ +*.pyc +*.pyo +*.pyd +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ + +# Build artifacts (will be rebuilt in container) +build/ +dist/ +*.egg-info/ +*.so +*.o +*.a + +# Pre-built binaries for other platforms (keep linux only) +*_macos*/ +*_webassembly*/ +build_web/ + +# Data files (downloaded at runtime) +pufferlib/resources/drive/**/*.bin +resources/ +data/ + +# IDE and editor configuration +.vscode/ +.idea/ +*.swp +*.swo + +# Documentation (exclude .md but keep pyproject.toml) +*.md +*.pdf +!mlops/sync/readme.md +LICENSE + +# Config files not needed in container +.pre-commit-config.yaml +ruff.toml + +# MLOps files not needed in container (keep run_training.sh and dockerfile/) +mlops/configs/ +mlops/__pycache__/ +mlops/sync/ + +# Experiment outputs and logs +experiments/ +benchmark/ +wandb/ +videos*/ +runs/ + +# Test files +tests/ + +# Example files +examples/ + +# Misc +*.gif +*.mp4 +*.png +*.jpg +config/ diff --git a/mlops/dockerfile/build.dockerfile b/mlops/dockerfile/build.dockerfile new file mode 100644 index 0000000000..93302ab668 --- /dev/null +++ b/mlops/dockerfile/build.dockerfile @@ -0,0 +1,86 @@ +# ============================================================================= +# PufferDrive Base Image +# ============================================================================= + +FROM nvcr.io/nvidia/cuda:12.8.1-cudnn-devel-ubuntu24.04 + +ENV TZ=Europe/Paris \ + DEBIAN_FRONTEND=noninteractive \ + PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + UV_COMPILE_BYTECODE=1 \ + UV_NO_DEV=1 \ + PATH="/usr/local/nvidia/bin:${PATH}" \ + LD_LIBRARY_PATH="/usr/local/nvidia/lib64:${LD_LIBRARY_PATH}" \ + NVIDIA_VISIBLE_DEVICES=all \ + NVIDIA_DRIVER_CAPABILITIES=compute,utility + +WORKDIR /pufferdrive + +# ============================================================================= +# System Dependencies +# ============================================================================= +RUN --mount=type=cache,target=/var/cache/apt \ + --mount=type=cache,target=/var/lib/apt/lists \ + apt-get update && \ + apt-get install -y --no-install-recommends \ + curl \ + build-essential \ + apt-transport-https \ + ca-certificates \ + gnupg && \ + # Google Cloud SDK + echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" \ + | tee /etc/apt/sources.list.d/google-cloud-sdk.list && \ + curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg \ + | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg && \ + apt-get update && \ + apt-get install -y --no-install-recommends google-cloud-cli && \ + rm -rf /tmp/* /var/tmp/* + +# ============================================================================= +# Install uv + Python + venv +# ============================================================================= +COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv + +ENV PATH="/root/.local/bin:$PATH" + +RUN uv venv --python 3.12 /pufferdrive/.venv + +# Activate venv for all subsequent commands +ENV VIRTUAL_ENV=/pufferdrive/.venv \ + PATH="/pufferdrive/.venv/bin:$PATH" + +# ============================================================================= +# Python Dependencies (heavy packages - cached separately) +# ============================================================================= +RUN --mount=type=cache,target=/root/.cache/uv \ + uv pip install torch --index-url https://download.pytorch.org/whl/cu128 + +RUN --mount=type=cache,target=/root/.cache/uv \ + uv pip install \ + psutil \ + rich \ + rich_argparse \ + pandas \ + tqdm \ + matplotlib \ + imageio \ + pyro-ppl \ + mediapy \ + heavyball \ + neptune \ + wandb \ + tensorboard + +# ============================================================================= +# PufferLib Installation +# ============================================================================= +COPY pyproject.toml setup.py setup.cfg ./ +COPY pufferlib ./pufferlib + +RUN --mount=type=cache,target=/root/.cache/uv \ + NO_TRAIN=1 NO_OCEAN=1 uv pip install -e . + +# Remove .so files in pufferlib/ +RUN find /pufferdrive/pufferlib -name "*.so" -delete diff --git a/mlops/dockerfile/launch.dockerfile b/mlops/dockerfile/launch.dockerfile new file mode 100644 index 0000000000..f2b2538e30 --- /dev/null +++ b/mlops/dockerfile/launch.dockerfile @@ -0,0 +1,33 @@ +# ============================================================================= +# PufferDrive Training Image +# ============================================================================= + +FROM europe-west4-docker.pkg.dev/valeo-cp2386-dev/build-images/pufferdrive_cuda12.8_py3.12:latest + +# ============================================================================= +# Build C Extensions (only C files to maximize cache hits) +# ============================================================================= +COPY pufferlib/ocean ./pufferlib/ocean +COPY pufferlib/extensions/ ./pufferlib/extensions/ + +ARG GPU_ARCH +ENV TORCH_CUDA_ARCH_LIST="${GPU_ARCH}" +RUN python setup.py build_ext --inplace --force + +# ============================================================================= +# Copy Source Code +# ============================================================================= +COPY --chmod=755 mlops/run_training.sh /pufferdrive/run_training.sh +COPY pufferlib/*.py ./pufferlib/ +COPY pufferlib/resources ./pufferlib/resources +COPY pufferlib/config ./pufferlib/config + +# ============================================================================= +# Copy Staged Model (For Finetuning) +# ============================================================================= +COPY mlops/staging_models/ /pufferdrive/preload_model/ + +# ============================================================================= +# Entrypoint +# ============================================================================= +ENTRYPOINT ["/pufferdrive/run_training.sh"] diff --git a/mlops/mlops.py b/mlops/mlops.py new file mode 100644 index 0000000000..c50687c24c --- /dev/null +++ b/mlops/mlops.py @@ -0,0 +1,719 @@ +#!/usr/bin/env python3 +""" +Unified MLOps CLI for PufferDrive training on GCP Vertex AI. + +Usage: + # Launch a single run within an experiment + python mlops/mlops.py launch my_experiment my_run --machine T4 + + # Launch multiple runs from config file + python mlops/mlops.py launch-batch mlops/configs/experiments.yaml + + # Build and push the base image + python mlops/mlops.py build-image + + # Sync data to/from GCS + python mlops/mlops.py sync-data gs://bucket/path local/path --download +""" + +import argparse +import os +import shutil +import subprocess +import sys +from contextlib import contextmanager +from dataclasses import dataclass, field +from datetime import datetime +from google.cloud import aiplatform +from google.cloud.aiplatform.compat.types import reservation_affinity_v1 as reservation_affinity +from pathlib import Path +import yaml + +# Suppress noisy Google Cloud logs +os.environ["GRPC_VERBOSITY"] = "ERROR" +import logging + +logging.getLogger("google.api_core").setLevel(logging.ERROR) +logging.getLogger("google.auth").setLevel(logging.ERROR) +logging.getLogger("google.cloud").setLevel(logging.ERROR) +logging.getLogger("grpc").setLevel(logging.ERROR) + + +# ============================================================================= +# Configuration +# ============================================================================= + + +@dataclass +class GCPConfig: + """GCP project configuration.""" + + project_id: str + staging_bucket: str + service_account: str + default_dataset_path: str + training_container_registry: str + use_reservation: bool = False + location: str = "europe-west4" + builder_image: str = "europe-west4-docker.pkg.dev/valeo-cp2386-dev/build-images/pufferdrive_cuda12.8_py3.12:latest" + tensorboard_resource: str | None = None + + +GCP_CONFIGS = { + "DRILAX": GCPConfig( + project_id="valeo-cp2386-dev", + staging_bucket="gs://valeo-cp2386-runs", + service_account="valeo-cp2386-dev@appspot.gserviceaccount.com", + default_dataset_path="/gcs/valeo-cp2386-datasets/pufferdrive/v1.0/womd/training/", + training_container_registry="europe-west4-docker.pkg.dev/valeo-cp2386-dev/training-images", + tensorboard_resource="projects/858441583698/locations/europe-west4/tensorboards/6648324600696406016", + ), + "NOA": GCPConfig( + project_id="valeo-cp2879-dev", + staging_bucket="gs://valeo-cp2879-driving-policy", + service_account="valeo-cp2879-dev-job@valeo-cp2879-dev.iam.gserviceaccount.com", + default_dataset_path="/gcs/valeo-cp2879-driving-policy/datasets/carla/", + training_container_registry="europe-west4-docker.pkg.dev/valeo-cp2879-dev/driving-policy/training-images", + use_reservation=False, + tensorboard_resource=None, + ), +} + + +def get_config(project): + if project not in GCP_CONFIGS: + raise ValueError(f"Unknown project: {project}. Available: {list(GCP_CONFIGS.keys())}") + return GCP_CONFIGS[project] + + +@dataclass +class MachineSpec: + """Machine type specification.""" + + machine_type: str + accelerator_type: str + accelerator_count: int + cuda_arch: str + boot_disk_type: str = "pd-ssd" + + +# Machine type presets +MACHINE_PRESETS: dict[str, MachineSpec] = { + "T4": MachineSpec("n1-standard-16", "NVIDIA_TESLA_T4", 1, "7.5"), + "T4_2": MachineSpec("n1-standard-32", "NVIDIA_TESLA_T4", 2, "7.5"), + "T4_4": MachineSpec("n1-standard-32", "NVIDIA_TESLA_T4", 4, "7.5"), + "T4_8": MachineSpec("n1-standard-64", "NVIDIA_TESLA_T4", 8, "7.5"), + "L4": MachineSpec("g2-standard-16", "NVIDIA_L4", 1, "8.9"), + "L4_2": MachineSpec("g2-standard-32", "NVIDIA_L4", 2, "8.9"), + "L4_4": MachineSpec("g2-standard-64", "NVIDIA_L4", 4, "8.9"), + "L4_8": MachineSpec("g2-standard-96", "NVIDIA_L4", 8, "8.9"), + "A100": MachineSpec("a2-highgpu-1g", "NVIDIA_A100", 1, "8.0"), + "A100_2": MachineSpec("a2-highgpu-2g", "NVIDIA_A100", 2, "8.0"), + "A100_4": MachineSpec("a2-megagpu-16g", "NVIDIA_A100", 4, "8.0"), + "A100_8": MachineSpec("a2-megagpu-16g", "NVIDIA_A100", 8, "8.0"), + "RTX6000": MachineSpec("g4-standard-48", "NVIDIA_RTX_PRO_6000", 1, "12.0", "hyperdisk-balanced"), + "RTX6000_2": MachineSpec("g4-standard-96", "NVIDIA_RTX_PRO_6000", 2, "12.0", "hyperdisk-balanced"), + "RTX6000_4": MachineSpec("g4-standard-192", "NVIDIA_RTX_PRO_6000", 4, "12.0", "hyperdisk-balanced"), + "RTX6000_8": MachineSpec("g4-standard-384", "NVIDIA_RTX_PRO_6000", 8, "12.0", "hyperdisk-balanced"), +} + + +@dataclass +class Run: + """Run configuration within an experiment.""" + + experiment: str + name: str + machine: str = "T4" + dataset_path: str = "" + eval_dataset_path: str = "" + project: str = "DRILAX" + params: dict = field(default_factory=dict) + extra_args: list[str] = field(default_factory=list) + + +# ============================================================================= +# Utility Functions +# ============================================================================= + + +def run_command(command: list[str], description: str, verbose: bool = False) -> bool: + """Run a shell command with nice output.""" + print(f"🔧 {description}") + print(f" $ {' '.join(command)}") + + try: + subprocess.run(command, check=True, capture_output=not verbose, text=True) + print(" ✅ Success") + return True + except subprocess.CalledProcessError as e: + print(" ❌ Failed") + if not verbose and e.stdout: + print(f" STDOUT: {e.stdout}") + if not verbose and e.stderr: + print(f" STDERR: {e.stderr}") + return False + + +@contextmanager +def setup_dockerignore(): + """Context manager to copy .dockerignore to root for build and clean up after.""" + dockerignore_src = "mlops/dockerfile/.dockerignore" + dockerignore_dst = ".dockerignore" + + if os.path.exists(dockerignore_src): + shutil.copy(dockerignore_src, dockerignore_dst) + + try: + yield + finally: + if os.path.exists(dockerignore_dst): + os.remove(dockerignore_dst) + + +@contextmanager +def stage_model_artifacts(extra_args: list[str]): + """ + Checks if --load-model-path is present. If so: + 1. Copies the model and config.yaml to mlops/staging_models/ + 2. Updates the arg path to point to the container location. + 3. Cleans up after the build. + """ + staging_dir = Path("mlops/staging_models") + + # 1. Clean start: Create staging dir (even if empty, to satisfy Docker COPY) + if staging_dir.exists(): + shutil.rmtree(staging_dir) + staging_dir.mkdir(parents=True) + (staging_dir / ".keep").touch() # Prevent Docker COPY failure on empty dir + + # Check for argument + model_arg_idx = -1 + if "--load-model-path" in extra_args: + print("🔍 Detected --load-model-path argument, preparing model artifacts...") + model_arg_idx = extra_args.index("--load-model-path") + + try: + # If model arg exists and has a value + if model_arg_idx != -1 and model_arg_idx + 1 < len(extra_args): + local_path_str = extra_args[model_arg_idx + 1] + local_pt = Path(local_path_str) + + if not local_pt.exists(): + print(f"❌ Error: Model file not found: {local_pt}") + sys.exit(1) + + # Copy .pt file + print(f"📦 Staging model for Docker build: {local_pt.name}") + shutil.copy(local_pt, staging_dir / local_pt.name) + + # Copy config.yaml (check parent dir) + local_config = local_pt.parent.parent / "config.yaml" + if local_config.exists(): + shutil.copy(local_config, staging_dir / "config.yaml") + print(f"📦 Staged config: {local_config.name}") + else: + print("❌ Error: Config file not found: config.yaml") + + # The file will be at /pufferdrive/preload_model/ + container_path = f"/pufferdrive/preload_model/{local_pt.name}" + extra_args[model_arg_idx + 1] = container_path + print(f"🔄 Remapped --load-model-path to container path: {container_path}") + + yield + + finally: + # Cleanup staging area after build/push is done + if staging_dir.exists(): + shutil.rmtree(staging_dir) + + +# ============================================================================= +# Vertex AI Job Submission +# ============================================================================= + + +def submit_vertex_job( + config: GCPConfig, + display_name: str, + container_uri: str, + machine: MachineSpec, + experiment_name: str, + run_name: str, + project: str, + dataset_path: str, + eval_dataset_path: str = "", + extra_args: list[str] | None = None, + mode: str = "train", +) -> None: + """Submit a training job to Vertex AI.""" + + experiment_name = experiment_name.replace("_", "-") + run_name = run_name.replace("_", "-") + if config.project_id == "valeo-cp2879-dev": + cloud_path = f"{config.staging_bucket}/runs/{experiment_name}/{run_name}" + else: + cloud_path = f"{config.staging_bucket}/{experiment_name}/{run_name}" + + aiplatform.init( + project=config.project_id, + location=config.location, + staging_bucket=config.staging_bucket, + # experiment=experiment_name, + # experiment_tensorboard=config.tensorboard_resource, + ) + + # # Explicitly register the run in the Vertex ML Metadata store + # try: + # # First, try to fetch it if it already exists (e.g., re-running a failed job) + # aiplatform.start_run(run=run_name, resume=True) + # except Exception: + # # If it throws a 404 (doesn't exist yet), create it fresh + # aiplatform.start_run(run=run_name) + # finally: + # # Always end the local session so the CustomJob can take over + # aiplatform.end_run() + + # Build container arguments + container_args = ["--mode", mode, "--accelerator-count", str(machine.accelerator_count)] + if not dataset_path: + dataset_path = config.default_dataset_path + job_extra_args = list(extra_args) if extra_args else [] + job_extra_args.extend(["--env.map-dir", dataset_path]) + + # Add eval dataset path if provided + if eval_dataset_path: + job_extra_args.extend(["--eval.map-dir", eval_dataset_path]) + + container_args.extend(job_extra_args) + + # Machine spec with optional reservation affinity + machine_spec = { + "machine_type": machine.machine_type, + "accelerator_type": machine.accelerator_type, + "accelerator_count": machine.accelerator_count, + } + if config.use_reservation: + machine_spec["reservation_affinity"] = reservation_affinity.ReservationAffinity( + reservation_affinity_type=reservation_affinity.ReservationAffinity.Type.ANY_RESERVATION + ) + + worker_pool_specs = [ + { + "machine_spec": machine_spec, + "replica_count": 1, + "disk_spec": { + "boot_disk_type": machine.boot_disk_type, + "boot_disk_size_gb": 100, + }, + "container_spec": { + "image_uri": container_uri, + "args": container_args, + "env": [ + { + "name": "TORCH_CUDA_ARCH_LIST", + "value": machine.cuda_arch, + }, + { + "name": "CLOUD", + "value": "1", + }, + { + "name": "CLOUD_PATH", + "value": cloud_path, + }, + ], + }, + } + ] + + if sha := os.environ.get("GITHUB_SHA"): + labels = {"commit_sha": sha} + else: + labels = {"username": os.getlogin()} + + # Create and submit job + job = aiplatform.CustomJob( + display_name=display_name, + worker_pool_specs=worker_pool_specs, + staging_bucket=config.staging_bucket, + base_output_dir=cloud_path, + labels=labels, + project=config.project_id, + location=config.location, + ) + + print(f"📤 Submitting job: {display_name}") + job.submit( + service_account=config.service_account, + enable_web_access=False, + scheduling_strategy="STANDARD", + tensorboard=config.tensorboard_resource, + disable_retries=True, + # experiment=experiment_name, + # experiment_run=run_name, + ) + print(" ✅ Job submitted successfully") + + +# ============================================================================= +# Docker Operations +# ============================================================================= + + +def build_and_push_image(config: GCPConfig, tag: str, verbose: bool = False, gpu_arch: str = "") -> str: + """Build and push the training Docker image.""" + if not gpu_arch.strip(): + print("❌ GPU_ARCH is empty. Set machine.cuda_arch explicitly for this build.") + sys.exit(1) + + if os.environ.get("GITHUB_SHA"): + username = "pr-test" + else: + username = os.getlogin() + container_uri = f"{config.training_container_registry}/{username}:{tag}" + + with setup_dockerignore(): + build_cmd = [ + "docker", + "build", + "--tag", + container_uri, + "--build-arg", + f"GPU_ARCH={gpu_arch}", + "--file", + "mlops/dockerfile/launch.dockerfile", + ".", + ] + if not run_command(build_cmd, "Building Docker image", verbose): + sys.exit(1) + + # Push image + push_cmd = ["docker", "push", container_uri] + if not run_command(push_cmd, "Pushing Docker image", verbose): + print("💡 Tip: Run `gcloud auth configure-docker europe-west4-docker.pkg.dev`") + sys.exit(1) + + return container_uri + + +def build_base_image(config: GCPConfig, verbose: bool = False) -> None: + """Build and push the base builder image.""" + + with setup_dockerignore(): + build_cmd = [ + "docker", + "build", + "--tag", + config.builder_image, + "--file", + "mlops/dockerfile/build.dockerfile", + ".", + ] + if not run_command(build_cmd, "Building base image", verbose): + sys.exit(1) + + push_cmd = ["docker", "push", config.builder_image] + if not run_command(push_cmd, "Pushing base image", verbose): + sys.exit(1) + + print(f"✅ Base image ready: {config.builder_image}") + + +# ============================================================================= +# Experiment Loading +# ============================================================================= + + +def load_runs_from_yaml(path: str, default_project: str = "DRILAX") -> list[Run]: + """Load runs from a YAML file.""" + with open(path) as f: + data = yaml.safe_load(f) + + runs = [] + for exp_data in data.get("experiments", []): + experiment_name = exp_data["name"] + experiment_machine = exp_data.get("machine", "T4") + experiment_dataset = exp_data.get("dataset_path", "") + experiment_eval_dataset = exp_data.get("eval_dataset_path", "") + experiment_project = exp_data.get("project", default_project) + experiment_params = exp_data.get("params", {}) + experiment_extra_args = exp_data.get("extra_args", []) + + # If runs are defined, create a Run for each + if "runs" in exp_data: + for run_data in exp_data["runs"]: + # Merge experiment-level params with run-level params (run takes precedence) + merged_params = {**experiment_params, **run_data.get("params", {})} + merged_extra_args = experiment_extra_args + run_data.get("extra_args", []) + runs.append( + Run( + experiment=experiment_name, + name=run_data["name"], + machine=run_data.get("machine", experiment_machine), + dataset_path=run_data.get("dataset_path", experiment_dataset), + eval_dataset_path=run_data.get("eval_dataset_path", experiment_eval_dataset), + project=run_data.get("project", experiment_project), + params=merged_params, + extra_args=merged_extra_args, + ) + ) + else: + # No runs defined, treat experiment as a single run with same name + runs.append( + Run( + experiment=experiment_name, + name=experiment_name, + machine=experiment_machine, + dataset_path=experiment_dataset, + eval_dataset_path=experiment_eval_dataset, + project=experiment_project, + params=experiment_params, + extra_args=experiment_extra_args, + ) + ) + + return runs + + +def params_to_args(params: dict) -> list[str]: + """Convert parameter dictionary to command-line arguments.""" + args = [] + for key, value in params.items(): + # Convert param.subparam to --param.subparam format + args.extend([f"--{key}", str(value)]) + return args + + +# ============================================================================= +# CLI Commands +# ============================================================================= + + +def cmd_launch(args) -> None: + """Launch a single run within an experiment.""" + config = get_config(args.project) + + # Validate machine type + if args.machine not in MACHINE_PRESETS: + print(f"❌ Unknown machine type: {args.machine}") + print(f" Available: {', '.join(MACHINE_PRESETS.keys())}") + sys.exit(1) + + machine = MACHINE_PRESETS[args.machine] + + with stage_model_artifacts(args.extra_args): + # Generate tag and build image + tag = datetime.now().strftime("%d%m%H%M%S") + container_uri = build_and_push_image(config, tag, args.verbose, machine.cuda_arch) + + submit_vertex_job( + config=config, + display_name=f"pufferdrive/{args.experiment_name}/{args.run_name}", + container_uri=container_uri, + machine=machine, + experiment_name=args.experiment_name, + run_name=args.run_name, + project=args.project, + dataset_path=args.dataset_path or "", + eval_dataset_path=args.eval_dataset_path or "", + extra_args=args.extra_args, + mode=args.mode, + ) + + print( + f"\n🎉 Run '{args.run_name}' in experiment '{args.experiment_name}' launched on {args.machine} ({args.project})" + ) + + +def cmd_launch_batch(args) -> None: + """Launch multiple runs from a YAML config file.""" + # Load runs with CLI project as default + runs = load_runs_from_yaml(args.config_file, default_project=args.project) + if not runs: + print("❌ No runs found in config file") + sys.exit(1) + + print(f"📋 Found {len(runs)} runs") + + # Validate all machine types and projects upfront + valid_runs = [] + for run in runs: + if run.machine not in MACHINE_PRESETS: + print(f"⚠️ Unknown machine type '{run.machine}' for '{run.experiment}/{run.name}', skipping...") + elif run.project not in GCP_CONFIGS: + print(f"⚠️ Unknown project '{run.project}' for '{run.experiment}/{run.name}', skipping...") + else: + valid_runs.append(run) + + if not valid_runs: + print("❌ No valid runs to launch") + sys.exit(1) + + # Group runs by project to build one image per project + runs_by_project = {} + for run in valid_runs: + runs_by_project.setdefault(run.project, []).append(run) + + # Build and push images for each project + tag = datetime.now().strftime("%d%m%H%M%S") + container_uris = {} + + with stage_model_artifacts([]): + for project in runs_by_project: + config = get_config(project) + gpu_arch = " ".join(sorted({MACHINE_PRESETS[run.machine].cuda_arch for run in runs_by_project[project]})) + print(f"\n📦 Building image for {project}...") + container_uris[project] = build_and_push_image(config, tag, args.verbose, gpu_arch) + + print(f"\n🚀 Submitting {len(valid_runs)} runs sequentially...") + + for i, run in enumerate(valid_runs, 1): + print(f"\n[{i}/{len(valid_runs)}] Processing: {run.experiment}/{run.name} ...") + try: + config = get_config(run.project) + machine = MACHINE_PRESETS[run.machine] + # Construct args specifically for this run + extra_args = params_to_args(run.params) + run.extra_args + display_name = f"pufferdrive/{run.experiment}/{run.name}" + + submit_vertex_job( + config=config, + display_name=display_name, + container_uri=container_uris[run.project], + machine=machine, + experiment_name=run.experiment, + run_name=run.name, + project=run.project, + dataset_path=run.dataset_path, + eval_dataset_path=run.eval_dataset_path, + extra_args=extra_args, + ) + except Exception as e: + print(f" ❌ {run.experiment}/{run.name} failed: {e}") + continue + + print(f"\n🎉 All {len(valid_runs)} runs submitted!") + + +def cmd_train_test(args) -> None: + """Launch a training test for CI.""" + config_file = "mlops/configs/smoke-tests.yaml" + print(f"🚀 Launching CI training test from {config_file}") + + # Load runs with CLI project as default + runs = load_runs_from_yaml(config_file) + + # Group runs by project to build one image per project + runs_by_project = {} + for run in runs: + runs_by_project.setdefault(run.project, []).append(run) + + tag = os.environ.get("GITHUB_SHA") or datetime.now().strftime("%d%m%H%M%S") + short_sha = ( + os.environ.get("GITHUB_SHA") or subprocess.check_output(["git", "rev-parse", "HEAD"]).decode().strip() + )[:6] + container_uris = {} + + with stage_model_artifacts([]): # No extra args needed here + for project in runs_by_project: + config = get_config(project) + gpu_arch = " ".join(sorted({MACHINE_PRESETS[run.machine].cuda_arch for run in runs_by_project[project]})) + print(f"\n📦 Building image for {project}...") + container_uris[project] = build_and_push_image(config, tag, args.verbose, gpu_arch) + + print(f"\n🚀 Submitting {len(runs)} CI test runs sequentially...") + + for i, run in enumerate(runs, 1): + run_name = f"{short_sha}-{run.name}" + print(f"\n[{i}/{len(runs)}] Processing: {run.experiment}/{run_name} ...") + config = get_config(run.project) + machine = MACHINE_PRESETS[run.machine] + extra_args = params_to_args(run.params) + run.extra_args + display_name = f"pufferdrive-ci/{run.experiment}/{run_name}" + submit_vertex_job( + config=config, + display_name=display_name, + container_uri=container_uris[run.project], + machine=machine, + experiment_name=run.experiment, + run_name=run_name, + project=run.project, + dataset_path=run.dataset_path, + eval_dataset_path=run.eval_dataset_path, + extra_args=extra_args, + ) + + print(f"\n🎉 All {len(runs)} CI test runs submitted!") + + +def cmd_build_image(args) -> None: + """Build and push the base builder image.""" + config = get_config(args.project) + build_base_image(config, args.verbose) + + +# ============================================================================= +# Main +# ============================================================================= + + +def main(): + common = argparse.ArgumentParser(add_help=False) + common.add_argument( + "--project", + "-p", + default="DRILAX", + choices=list(GCP_CONFIGS.keys()), + help="GCP project to use (default: DRILAX)", + ) + + parser = argparse.ArgumentParser( + description="PufferDrive MLOps CLI", + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + subparsers = parser.add_subparsers(dest="command", help="Available commands") + + # Launch single run + launch_parser = subparsers.add_parser("launch", parents=[common], help="Launch a single run within an experiment") + launch_parser.add_argument("experiment_name", help="Name for the experiment (groups related runs)") + launch_parser.add_argument("run_name", help="Name for this specific run") + launch_parser.add_argument( + "--machine", "-m", default="T4", choices=list(MACHINE_PRESETS.keys()), help="Machine type preset" + ) + launch_parser.add_argument("--dataset-path", "-d", help="GCS path to training dataset") + launch_parser.add_argument("--eval-dataset-path", help="GCS path to eval dataset") + launch_parser.add_argument("--verbose", "-v", action="store_true", help="Show verbose output") + launch_parser.add_argument("--mode", choices=["train", "sweep"], default="train", help="Run mode: train or sweep") + launch_parser.set_defaults(func=cmd_launch) + + # Launch batch runs + batch_parser = subparsers.add_parser("launch-batch", parents=[common], help="Launch multiple runs from config") + batch_parser.add_argument("config_file", help="YAML config file with experiments") + batch_parser.add_argument("--verbose", "-v", action="store_true", help="Show verbose output") + batch_parser.set_defaults(func=cmd_launch_batch) + + # Train test + train_test_parser = subparsers.add_parser("train-test", help="Launch a training test for CI") + train_test_parser.add_argument("--verbose", "-v", action="store_true", help="Show verbose output") + train_test_parser.set_defaults(func=cmd_train_test) + + # Build base image + build_parser = subparsers.add_parser("build-image", parents=[common], help="Build and push base Docker image") + build_parser.add_argument("--verbose", "-v", action="store_true", help="Show verbose output") + build_parser.set_defaults(func=cmd_build_image) + + args, extra_args = parser.parse_known_args() + + # Store extra args for passing to the container + args.extra_args = extra_args + + if not args.command: + parser.print_help() + sys.exit(1) + + args.func(args) + + +if __name__ == "__main__": + main() diff --git a/mlops/run_training.sh b/mlops/run_training.sh new file mode 100755 index 0000000000..36cd57fcbe --- /dev/null +++ b/mlops/run_training.sh @@ -0,0 +1,182 @@ +#!/bin/bash +# +# Container entrypoint for PufferDrive training on GCP. + +set -eo pipefail + +echo "🚀 Starting PufferDrive training..." + +# ============================================================================= +# Argument Parsing +# ============================================================================= + +ACCELERATOR_COUNT=1 +MODE="train" +TRAINING_ARGS=() + +while [[ $# -gt 0 ]]; do + case "$1" in + --accelerator-count) + ACCELERATOR_COUNT="$2" + shift 2 + ;; + --mode) + MODE="$2" + shift 2 + ;; + *) + TRAINING_ARGS+=("$1") + shift + ;; + esac +done + +if ! [[ "$ACCELERATOR_COUNT" =~ ^[0-9]+$ ]] || [[ "$ACCELERATOR_COUNT" -lt 1 ]]; then + echo "❌ Error: --accelerator-count must be an integer >= 1 (got '$ACCELERATOR_COUNT')" + exit 1 +fi + +# ============================================================================= +# GPU Preflight Checks (fail fast, no CPU fallback) +# ============================================================================= + +echo "🔎 Validating GPU environment..." + +if ! command -v nvidia-smi >/dev/null 2>&1; then + echo "❌ Error: nvidia-smi not found. NVIDIA driver is missing or not visible in container." + exit 1 +fi + +if ! nvidia-smi -L >/dev/null 2>&1; then + echo "❌ Error: nvidia-smi failed to query GPUs. Driver/runtime setup is invalid." + exit 1 +fi + +VISIBLE_GPUS=$(nvidia-smi --query-gpu=name --format=csv,noheader | sed '/^$/d' | wc -l | tr -d ' ') +if [[ "$VISIBLE_GPUS" -lt "$ACCELERATOR_COUNT" ]]; then + echo "❌ Error: requested ${ACCELERATOR_COUNT} GPU(s), but only ${VISIBLE_GPUS} visible via nvidia-smi." + exit 1 +fi + +if ! EXPECTED_GPUS="$ACCELERATOR_COUNT" python - <<'PY' +import os +import sys +import torch + +expected = int(os.environ["EXPECTED_GPUS"]) + +if torch.version.cuda is None: + print("❌ Error: installed PyTorch is not CUDA-enabled (torch.version.cuda is None).") + sys.exit(1) + +if not torch.cuda.is_available(): + print("❌ Error: torch.cuda.is_available() is False. CUDA runtime/driver unavailable.") + sys.exit(1) + +count = torch.cuda.device_count() +if count < expected: + print(f"❌ Error: PyTorch sees {count} CUDA device(s), but {expected} required.") + sys.exit(1) + +if expected > 1 and not torch.distributed.is_nccl_available(): + print("❌ Error: NCCL backend is unavailable for multi-GPU torchrun.") + sys.exit(1) + +if not torch.backends.cudnn.is_available(): + print("❌ Error: cuDNN is unavailable. CUDA stack is incomplete.") + sys.exit(1) + +print(f"✅ GPU preflight passed: torch CUDA={torch.version.cuda}, visible CUDA devices={count}.") +PY +then + exit 1 +fi + +# ============================================================================= +# Background Sync & Trap Setup +# ============================================================================= + +OUTPUT_DIR="/pufferdrive/training_output/" +mkdir -p "$OUTPUT_DIR" + +SYNC_PID="" +GCS_DEST="" + +if [[ -n "${CLOUD_PATH:-}" && "${NODE_RANK:-0}" == "0" ]]; then + GCS_DEST="${CLOUD_PATH}/" +fi + +do_sync() { + # Use 'timeout' to guarantee gcloud never hangs the container infinitely + if [[ "$MODE" == "sweep" ]]; then + timeout 120s gcloud storage rsync -r "$OUTPUT_DIR/" "$GCS_DEST" --quiet || true + else + local run_dir + run_dir=$(find "$OUTPUT_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | head -1) + if [[ -n "$run_dir" ]]; then + timeout 120s gcloud storage rsync -r "$run_dir/" "$GCS_DEST" --quiet || true + fi + fi +} + +cleanup() { + local exit_code=$? + # Clear traps instantly to prevent recursive loops + trap - EXIT INT TERM ERR + + echo "🛑 Script exiting (code: $exit_code). Forcing cleanup..." + + if [[ -n "$SYNC_PID" ]]; then + echo "🛑 Terminating background sync process (PID $SYNC_PID) and children..." + # pkill -P kills the child 'sleep' or 'gcloud' holding standard output open + pkill -TERM -P "$SYNC_PID" 2>/dev/null || true + kill -9 "$SYNC_PID" 2>/dev/null || true + fi + + if [[ -n "$GCS_DEST" ]]; then + echo "☁️ Final GCS sync → $GCS_DEST (Max 2 mins)" + do_sync + fi + + echo "👋 Container exit complete." + exit "$exit_code" +} + +# Catch normal exits, set -e errors, AND system interrupts from GCP +trap cleanup EXIT INT TERM ERR + +if [[ -n "$GCS_DEST" ]]; then + sync_loop() { + local sync_interval=90 + while true; do + sleep "$sync_interval" + do_sync + done + } + sync_loop & + SYNC_PID=$! + echo "☁️ Background GCS sync started (pid=$SYNC_PID) → $GCS_DEST" +fi + +# ============================================================================= +# Training +# ============================================================================= + +if [[ "$MODE" == "sweep" ]]; then + echo "Running hyperparameter sweep..." + python -m pufferlib.pufferl sweep puffer_drive \ + --tb \ + --train.data-dir "$OUTPUT_DIR" \ + "${TRAINING_ARGS[@]}" +else + torchrun \ + --standalone \ + --nproc-per-node="${ACCELERATOR_COUNT}" \ + --max-restarts=0 \ + -m pufferlib.pufferl train puffer_drive \ + --tb \ + --train.data-dir "$OUTPUT_DIR" \ + "${TRAINING_ARGS[@]}" +fi + +echo "✅ Training completed successfully!" diff --git a/notebooks/01_observations.ipynb b/notebooks/01_observations.ipynb new file mode 100644 index 0000000000..90e87364d6 --- /dev/null +++ b/notebooks/01_observations.ipynb @@ -0,0 +1,534 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 01 - Observation Pipeline Debug\n", + "Verify obs vector is correctly packed, normalized, interpretable." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from pufferlib.ocean.drive.drive import Drive\n", + "from pufferlib.ocean.drive import binding\n", + "import pufferlib.viz\n", + "\n", + "# --- Environment configuration ---\n", + "NUM_AGENTS = 64\n", + "SIMULATION_MODE = \"gigaflow\"\n", + "DYNAMICS_MODEL = \"jerk\"\n", + "ACTION_TYPE = \"discrete\"\n", + "DT = 0.1\n", + "SCENARIO_LENGTH = 512\n", + "RESAMPLE_FREQUENCY = 0\n", + "REWARD_CONDITIONING = True\n", + "REWARD_RANDOMIZATION = False\n", + "TARGET_TYPE = \"static\"\n", + "COLLISION_BEHAVIOR = 1\n", + "OFFROAD_BEHAVIOR = 1\n", + "SEED = 42\n", + "MAP_DIR = \"../pufferlib/resources/drive/binaries/carla\"\n", + "\n", + "# --- Observation dimensions (configurable) ---\n", + "MAX_PARTNERS = 16\n", + "MAX_LANES = 32\n", + "MAX_BOUNDS = 32\n", + "MAX_TRAFFIC = 10\n", + "MAX_STOP_SIGNS = 0\n", + "\n", + "# --- Derived from binding (compile-time) ---\n", + "EGO_DIM = binding.EGO_FEATURES_JERK\n", + "NUM_COEFS = binding.NUM_REWARD_COEFS\n", + "PARTNER_F = binding.PARTNER_FEATURES\n", + "ROAD_F = binding.ROAD_FEATURES\n", + "TRAFFIC_F = binding.TRAFFIC_LIGHT_FEATURES\n", + "STOP_SIGN_F = binding.STOP_SIGN_FEATURES\n", + "COEF_NAMES = [\n", + " \"goal_radius\",\n", + " \"collision\",\n", + " \"offroad\",\n", + " \"comfort\",\n", + " \"lane_align\",\n", + " \"lane_center\",\n", + " \"velocity\",\n", + " \"traffic_light\",\n", + " \"center_bias\",\n", + " \"vel_align\",\n", + " \"overspeed\",\n", + " \"timestep\",\n", + " \"reverse\",\n", + " \"throttle\",\n", + " \"steer\",\n", + " \"acc\",\n", + "]\n", + "\n", + "# --- Create environment ---\n", + "env = Drive(\n", + " num_agents=NUM_AGENTS,\n", + " num_maps=1,\n", + " min_agents_per_env=NUM_AGENTS,\n", + " max_agents_per_env=NUM_AGENTS,\n", + " simulation_mode=SIMULATION_MODE,\n", + " dynamics_model=DYNAMICS_MODEL,\n", + " action_type=ACTION_TYPE,\n", + " dt=DT,\n", + " scenario_length=SCENARIO_LENGTH,\n", + " resample_frequency=RESAMPLE_FREQUENCY,\n", + " reward_conditioning=REWARD_CONDITIONING,\n", + " reward_randomization=REWARD_RANDOMIZATION,\n", + " target_type=TARGET_TYPE,\n", + " map_dir=MAP_DIR,\n", + " collision_behavior=COLLISION_BEHAVIOR,\n", + " offroad_behavior=OFFROAD_BEHAVIOR,\n", + " max_lane_segment_observations=MAX_LANES,\n", + " max_boundary_segment_observations=MAX_BOUNDS,\n", + " max_partner_observations=MAX_PARTNERS,\n", + " max_traffic_light_observations=MAX_TRAFFIC,\n", + " max_stop_sign_observations=MAX_STOP_SIGNS,\n", + " seed=SEED,\n", + ")\n", + "obs, info = env.reset(seed=SEED)\n", + "\n", + "# --- Derived from env ---\n", + "MAX_TARGET = env.num_target_waypoints\n", + "TARGET_F = binding.STATIC_TARGET_FEATURES if TARGET_TYPE == \"static\" else binding.DYNAMIC_TARGET_FEATURES\n", + "TARGET_DIM = MAX_TARGET * TARGET_F\n", + "\n", + "print(f\"obs shape: {obs.shape}, dtype: {obs.dtype}\")\n", + "print(f\"EGO_DIM={EGO_DIM}, NUM_COEFS={NUM_COEFS}, MAX_PARTNERS={MAX_PARTNERS}, PARTNER_F={PARTNER_F}\")\n", + "print(f\"MAX_LANES={MAX_LANES}, MAX_BOUNDS={MAX_BOUNDS}, ROAD_F={ROAD_F}\")\n", + "print(f\"MAX_TRAFFIC={MAX_TRAFFIC}, TRAFFIC_F={TRAFFIC_F}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Raw obs inspection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Take first step so obs are populated\n", + "actions = np.zeros([env.num_agents, 1], dtype=np.int64)\n", + "\n", + "obs, rew, term, trunc, info = env.step(actions)\n", + "\n", + "print(f\"shape: {obs.shape}, dtype: {obs.dtype}\")\n", + "print(f\"min: {obs.min():.4f}, max: {obs.max():.4f}, mean: {obs.mean():.4f}, std: {obs.std():.4f}\")\n", + "print(f\"NaN: {np.isnan(obs).sum()}, Inf: {np.isinf(obs).sum()}\")\n", + "print(f\"% zeros: {(obs == 0).mean() * 100:.1f}%\")\n", + "print(f\"% outside [-1,1]: {((obs < -1) | (obs > 1)).mean() * 100:.2f}%\")\n", + "\n", + "fig, axes = plt.subplots(1, 2, figsize=(14, 4))\n", + "axes[0].hist(obs.flatten(), bins=100, edgecolor=\"black\", alpha=0.7)\n", + "axes[0].set_title(\"Full obs distribution\")\n", + "axes[0].set_xlabel(\"Value\")\n", + "# Per-agent: show obs[0] vs obs[1]\n", + "for i in range(min(4, obs.shape[0])):\n", + " axes[1].plot(obs[i], alpha=0.5, label=f\"agent {i}\")\n", + "axes[1].set_title(\"Obs vector by index (first 4 agents)\")\n", + "axes[1].legend()\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Unpack with pufferlib.viz.unpack_obs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ego, target, partners, lanes, boundaries, traffic, _ = pufferlib.viz.unpack_obs(\n", + " obs[:1],\n", + " dynamics_model=DYNAMICS_MODEL,\n", + " target_type=TARGET_TYPE,\n", + " reward_conditioning=REWARD_CONDITIONING,\n", + " num_target_waypoints=env.num_target_waypoints,\n", + " max_partners=MAX_PARTNERS,\n", + " max_lane_segments=MAX_LANES,\n", + " max_boundary_segments=MAX_BOUNDS,\n", + " max_traffic_lights=MAX_TRAFFIC,\n", + " max_stop_signs=MAX_STOP_SIGNS,\n", + ")\n", + "print(f\"ego: {ego.shape} = {ego}\")\n", + "print(f\"target: {target.shape}\")\n", + "print(f\"partners: {partners.shape}\")\n", + "print(f\"lanes: {lanes.shape}\")\n", + "print(f\"boundaries: {boundaries.shape}\")\n", + "print(f\"traffic: {traffic.shape}\")\n", + "\n", + "\n", + "labels = [\n", + " \"speed\",\n", + " \"width\",\n", + " \"length\",\n", + " \"steering\",\n", + " \"a_long\",\n", + " \"a_lat\",\n", + " \"lane_center_dist_01\",\n", + " \"lane_heading_cos\",\n", + " \"speed_limit\",\n", + "]\n", + "for name, val in zip(labels, ego):\n", + " print(f\" {name}: {val:.4f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Manual slice verification" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "o = obs[0] # first agent flat obs\n", + "idx = 0\n", + "\n", + "# Ego\n", + "ego_manual = o[idx : idx + EGO_DIM]\n", + "idx += EGO_DIM\n", + "assert np.allclose(ego_manual, ego), f\"ego mismatch: {ego_manual} vs {ego}\"\n", + "\n", + "# Reward conditioning coefs\n", + "coefs_manual = o[idx : idx + NUM_COEFS]\n", + "idx += NUM_COEFS\n", + "\n", + "# Target\n", + "target_manual = o[idx : idx + MAX_TARGET * TARGET_F].reshape(MAX_TARGET, TARGET_F)\n", + "idx += MAX_TARGET * TARGET_F\n", + "assert np.allclose(target_manual, target), \"target mismatch\"\n", + "\n", + "# Partners\n", + "partners_manual = o[idx : idx + MAX_PARTNERS * PARTNER_F].reshape(MAX_PARTNERS, PARTNER_F)\n", + "idx += MAX_PARTNERS * PARTNER_F\n", + "assert np.allclose(partners_manual, partners), \"partners mismatch\"\n", + "\n", + "# Lanes\n", + "lanes_manual = o[idx : idx + MAX_LANES * ROAD_F].reshape(MAX_LANES, ROAD_F)\n", + "idx += MAX_LANES * ROAD_F\n", + "assert np.allclose(lanes_manual, lanes), \"lanes mismatch\"\n", + "\n", + "# Boundaries\n", + "bounds_manual = o[idx : idx + MAX_BOUNDS * ROAD_F].reshape(MAX_BOUNDS, ROAD_F)\n", + "idx += MAX_BOUNDS * ROAD_F\n", + "assert np.allclose(bounds_manual, boundaries), \"boundaries mismatch\"\n", + "\n", + "# Traffic\n", + "traffic_manual = o[idx : idx + MAX_TRAFFIC * TRAFFIC_F].reshape(MAX_TRAFFIC, TRAFFIC_F)\n", + "idx += MAX_TRAFFIC * TRAFFIC_F\n", + "assert np.allclose(traffic_manual, traffic), \"traffic mismatch\"\n", + "\n", + "assert idx == obs.shape[1], f\"obs size mismatch: used {idx}, total {obs.shape[1]}\"\n", + "print(f\"All slices match. Total features used: {idx}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Reward conditioning coefficients" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "coefs = obs[0, EGO_DIM : EGO_DIM + NUM_COEFS]\n", + "fig, ax = plt.subplots(figsize=(12, 4))\n", + "bars = ax.bar(range(NUM_COEFS), coefs, tick_label=COEF_NAMES)\n", + "ax.set_ylabel(\"Normalized coef value\")\n", + "ax.set_title(\"Reward conditioning coefficients (agent 0)\")\n", + "plt.xticks(rotation=45, ha=\"right\")\n", + "for bar, val in zip(bars, coefs):\n", + " ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height(), f\"{val:.3f}\", ha=\"center\", va=\"bottom\", fontsize=8)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "# Compare across agents\n", + "all_coefs = obs[:, EGO_DIM : EGO_DIM + NUM_COEFS]\n", + "print(\"Coef stats across agents:\")\n", + "for i, name in enumerate(COEF_NAMES):\n", + " c = all_coefs[:, i]\n", + " print(f\" {name:15s}: mean={c.mean():.3f} std={c.std():.3f} min={c.min():.3f} max={c.max():.3f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Partner observations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "partner_labels = [\"rel_x\", \"rel_y\", \"width\", \"length\", \"heading_cos\", \"heading_sin\", \"speed\"]\n", + "active_mask = ~np.all(partners == 0, axis=1)\n", + "n_active = active_mask.sum()\n", + "print(f\"Active partners: {n_active}/{MAX_PARTNERS}\")\n", + "\n", + "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n", + "\n", + "# Heatmap\n", + "im = axes[0].imshow(partners, aspect=\"auto\", cmap=\"RdBu_r\", vmin=-1, vmax=1)\n", + "axes[0].set_xticks(range(PARTNER_F))\n", + "axes[0].set_xticklabels(partner_labels, rotation=45, ha=\"right\")\n", + "axes[0].set_ylabel(\"Partner index\")\n", + "axes[0].set_title(f\"Partner obs heatmap ({n_active} active)\")\n", + "plt.colorbar(im, ax=axes[0])\n", + "\n", + "# Scatter in ego frame\n", + "active_partners = partners[active_mask]\n", + "if len(active_partners) > 0:\n", + " axes[1].scatter(active_partners[:, 0], active_partners[:, 1], c=\"gray\", s=100, edgecolors=\"black\")\n", + " for i, p in enumerate(active_partners):\n", + " axes[1].annotate(str(i), (p[0], p[1]), fontsize=8, ha=\"center\", va=\"bottom\")\n", + "axes[1].scatter(0, 0, c=\"blue\", s=200, marker=\"s\", label=\"ego\", zorder=10)\n", + "axes[1].set_xlabel(\"rel_x\")\n", + "axes[1].set_ylabel(\"rel_y\")\n", + "axes[1].set_title(\"Partners in ego frame\")\n", + "axes[1].legend()\n", + "axes[1].set_aspect(\"equal\")\n", + "axes[1].grid(True, alpha=0.3)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Lane / boundary segments" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "road_labels = [\"rel_x\", \"rel_y\", \"length\", \"width\", \"dir_cos\", \"dir_sin\"]\n", + "\n", + "lane_active = ~np.all(lanes == 0, axis=1)\n", + "bound_active = ~np.all(boundaries == 0, axis=1)\n", + "print(f\"Active lanes: {lane_active.sum()}/{MAX_LANES}, boundaries: {bound_active.sum()}/{MAX_BOUNDS}\")\n", + "\n", + "fig, ax = plt.subplots(figsize=(10, 10))\n", + "\n", + "# Lanes\n", + "for seg in lanes[lane_active]:\n", + " x, y, length, width, dc, ds = seg\n", + " ax.plot([x - dc * length / 2, x + dc * length / 2], [y - ds * length / 2, y + ds * length / 2], c=\"lightgrey\", lw=1)\n", + " ax.scatter(x, y, c=\"lightgrey\", s=5)\n", + "\n", + "# Boundaries\n", + "for seg in boundaries[bound_active]:\n", + " x, y, length, width, dc, ds = seg\n", + " ax.plot([x - dc * length / 2, x + dc * length / 2], [y - ds * length / 2, y + ds * length / 2], c=\"black\", lw=1)\n", + " ax.scatter(x, y, c=\"black\", s=5)\n", + "\n", + "ax.scatter(0, 0, c=\"blue\", s=200, marker=\"s\", label=\"ego\", zorder=10)\n", + "ax.set_aspect(\"equal\")\n", + "ax.set_title(\"Lane + boundary segments in ego frame\")\n", + "ax.legend()\n", + "ax.grid(True, alpha=0.3)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Ego-centric view (pufferlib.viz)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "img = pufferlib.viz.plot_observation(\n", + " obs[:1],\n", + " dynamics_model=DYNAMICS_MODEL,\n", + " target_type=TARGET_TYPE,\n", + " reward_conditioning=True,\n", + " num_target_waypoints=env.num_target_waypoints,\n", + " max_partners=MAX_PARTNERS,\n", + " max_lane_segments=MAX_LANES,\n", + " max_boundary_segments=MAX_BOUNDS,\n", + " max_traffic_lights=MAX_TRAFFIC,\n", + " max_stop_signs=MAX_STOP_SIGNS,\n", + ")\n", + "fig, ax = plt.subplots(figsize=(10, 10))\n", + "ax.imshow(img)\n", + "ax.axis(\"off\")\n", + "ax.set_title(\"Ego-centric observation (agent 0)\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Bird's eye view (simulator state)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "scenarios = env.get_state()\n", + "# get_state returns a list of scenario dicts (one per sub-env) or a single dict\n", + "if isinstance(scenarios, list):\n", + " scenario = scenarios[0]\n", + "else:\n", + " scenario = scenarios\n", + "\n", + "img = pufferlib.viz.plot_simulator_state(scenario, timestep=0)\n", + "fig, ax = plt.subplots(figsize=(12, 12))\n", + "ax.imshow(img)\n", + "ax.axis(\"off\")\n", + "ax.set_title(\"Bird's eye view\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Multi-step: ego features over time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "N_STEPS = 20\n", + "ego_labels = [\"goal_x\", \"goal_y\", \"speed\", \"width\", \"length\", \"steering\", \"a_long\", \"a_lat\"]\n", + "ego_history = np.zeros((N_STEPS, EGO_DIM))\n", + "\n", + "for t in range(N_STEPS):\n", + " actions = np.zeros([env.num_agents, 1], dtype=np.int64)\n", + " obs_t, _, _, _, _ = env.step(actions)\n", + " ego_history[t] = obs_t[0, :EGO_DIM]\n", + "\n", + "fig, axes = plt.subplots(2, 2, figsize=(14, 8))\n", + "# Speed\n", + "axes[0, 0].plot(ego_history[:, 0])\n", + "axes[0, 0].set_title(\"speed\")\n", + "axes[0, 0].set_xlabel(\"step\")\n", + "# Steering\n", + "axes[0, 1].plot(ego_history[:, 3])\n", + "axes[0, 1].set_title(\"steering\")\n", + "axes[0, 1].set_xlabel(\"step\")\n", + "# a_long\n", + "axes[1, 0].plot(ego_history[:, 4])\n", + "axes[1, 0].set_title(\"a_long\")\n", + "axes[1, 0].set_xlabel(\"step\")\n", + "# a_lat\n", + "axes[1, 1].plot(ego_history[:, 5])\n", + "axes[1, 1].set_title(\"a_lat\")\n", + "axes[1, 1].set_xlabel(\"step\")\n", + "plt.suptitle(\"Agent 0 ego features over 20 steps (no-op action)\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cross-agent distributions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Current obs across all agents\n", + "speeds = obs[:, 2] if EGO_DIM >= 3 else obs[:, 0]\n", + "goal_dists = np.sqrt(obs[:, 0] ** 2 + obs[:, 1] ** 2) # goal_x, goal_y\n", + "\n", + "# Count active partners per agent\n", + "partner_start = EGO_DIM + NUM_COEFS + TARGET_DIM\n", + "partner_end = partner_start + MAX_PARTNERS * PARTNER_F\n", + "all_partners = obs[:, partner_start:partner_end].reshape(-1, MAX_PARTNERS, PARTNER_F)\n", + "partner_counts = (~np.all(all_partners == 0, axis=2)).sum(axis=1)\n", + "\n", + "fig, axes = plt.subplots(1, 3, figsize=(15, 4))\n", + "axes[0].hist(speeds, bins=20, edgecolor=\"black\", alpha=0.7)\n", + "axes[0].set_title(f\"Speed distribution (N={len(speeds)})\")\n", + "axes[0].set_xlabel(\"speed\")\n", + "\n", + "axes[1].hist(goal_dists, bins=20, edgecolor=\"black\", alpha=0.7, color=\"orange\")\n", + "axes[1].set_title(\"Goal distance (L2 of goal_x, goal_y)\")\n", + "axes[1].set_xlabel(\"distance\")\n", + "\n", + "axes[2].hist(partner_counts, bins=range(MAX_PARTNERS + 2), edgecolor=\"black\", alpha=0.7, color=\"green\")\n", + "axes[2].set_title(\"Active partners per agent\")\n", + "axes[2].set_xlabel(\"count\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/02_rewards.ipynb b/notebooks/02_rewards.ipynb new file mode 100644 index 0000000000..ae1326e124 --- /dev/null +++ b/notebooks/02_rewards.ipynb @@ -0,0 +1,405 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 02 - Reward Signals Debug\n", + "Understand reward magnitudes, components, and correlation with agent behavior." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from pufferlib.ocean.drive.drive import Drive\n", + "from pufferlib.ocean.drive import binding\n", + "import pufferlib.viz\n", + "\n", + "# --- Environment configuration ---\n", + "NUM_AGENTS = 64\n", + "SIMULATION_MODE = \"gigaflow\"\n", + "DYNAMICS_MODEL = \"jerk\"\n", + "ACTION_TYPE = \"discrete\"\n", + "DT = 0.1\n", + "SCENARIO_LENGTH = 512\n", + "RESAMPLE_FREQUENCY = 0\n", + "REWARD_CONDITIONING = True\n", + "REWARD_RANDOMIZATION = False\n", + "TARGET_TYPE = \"static\"\n", + "COLLISION_BEHAVIOR = 1\n", + "OFFROAD_BEHAVIOR = 1\n", + "SEED = 42\n", + "MAP_DIR = \"../pufferlib/resources/drive/binaries/carla\"\n", + "\n", + "# --- Observation dimensions (configurable) ---\n", + "MAX_PARTNERS = 16\n", + "MAX_LANES = 32\n", + "MAX_BOUNDS = 32\n", + "MAX_TRAFFIC = 10\n", + "MAX_STOP_SIGNS = 0\n", + "\n", + "# --- Derived from binding (compile-time) ---\n", + "EGO_DIM = binding.EGO_FEATURES_JERK\n", + "NUM_COEFS = binding.NUM_REWARD_COEFS\n", + "PARTNER_F = binding.PARTNER_FEATURES\n", + "ROAD_F = binding.ROAD_FEATURES\n", + "TRAFFIC_F = binding.TRAFFIC_LIGHT_FEATURES\n", + "STOP_SIGN_F = binding.STOP_SIGN_FEATURES\n", + "COEF_NAMES = [\n", + " \"goal_radius\",\n", + " \"collision\",\n", + " \"offroad\",\n", + " \"comfort\",\n", + " \"lane_align\",\n", + " \"lane_center\",\n", + " \"velocity\",\n", + " \"traffic_light\",\n", + " \"center_bias\",\n", + " \"vel_align\",\n", + " \"overspeed\",\n", + " \"timestep\",\n", + " \"reverse\",\n", + " \"throttle\",\n", + " \"steer\",\n", + " \"acc\",\n", + "]\n", + "\n", + "# --- Create environment ---\n", + "env = Drive(\n", + " num_agents=NUM_AGENTS,\n", + " num_maps=1,\n", + " min_agents_per_env=NUM_AGENTS,\n", + " max_agents_per_env=NUM_AGENTS,\n", + " simulation_mode=SIMULATION_MODE,\n", + " dynamics_model=DYNAMICS_MODEL,\n", + " action_type=ACTION_TYPE,\n", + " dt=DT,\n", + " scenario_length=SCENARIO_LENGTH,\n", + " resample_frequency=RESAMPLE_FREQUENCY,\n", + " reward_conditioning=REWARD_CONDITIONING,\n", + " reward_randomization=REWARD_RANDOMIZATION,\n", + " target_type=TARGET_TYPE,\n", + " map_dir=MAP_DIR,\n", + " collision_behavior=COLLISION_BEHAVIOR,\n", + " offroad_behavior=OFFROAD_BEHAVIOR,\n", + " max_lane_segment_observations=MAX_LANES,\n", + " max_boundary_segment_observations=MAX_BOUNDS,\n", + " max_partner_observations=MAX_PARTNERS,\n", + " max_traffic_light_observations=MAX_TRAFFIC,\n", + " max_stop_sign_observations=MAX_STOP_SIGNS,\n", + " seed=SEED,\n", + ")\n", + "obs, info = env.reset(seed=SEED)\n", + "\n", + "# --- Derived from env ---\n", + "MAX_TARGET = env.num_target_waypoints\n", + "TARGET_F = binding.STATIC_TARGET_FEATURES if TARGET_TYPE == \"static\" else binding.DYNAMIC_TARGET_FEATURES\n", + "TARGET_DIM = MAX_TARGET * TARGET_F\n", + "N_ACTIONS = 12\n", + "N = env.num_agents\n", + "ACT_SHAPE = (N, len(env.single_action_space.nvec))\n", + "\n", + "print(f\"env ready: {N} agents, obs={obs.shape}, act_shape={ACT_SHAPE}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Single step: no-op reward distribution" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "actions = np.zeros(ACT_SHAPE, dtype=np.int64)\n", + "obs, rew, term, trunc, info = env.step(actions)\n", + "\n", + "print(f\"reward shape: {rew.shape}\")\n", + "print(f\"min: {rew.min():.6f}, max: {rew.max():.6f}, mean: {rew.mean():.6f}, std: {rew.std():.6f}\")\n", + "print(f\"NaN: {np.isnan(rew).sum()}, all zero: {(rew == 0).all()}\")\n", + "print(f\"terminals: {term.sum()}, truncations: {trunc.sum()}\")\n", + "\n", + "fig, ax = plt.subplots(figsize=(8, 4))\n", + "ax.bar(range(len(rew)), rew, color=[\"red\" if r < 0 else \"green\" for r in rew])\n", + "ax.set_xlabel(\"Agent index\")\n", + "ax.set_ylabel(\"Reward\")\n", + "ax.set_title(\"Single step reward (no-op action)\")\n", + "ax.axhline(0, color=\"black\", lw=0.5)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 100-step rollout: reward heatmap and cumulative returns" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "N_STEPS = 100\n", + "rewards_history = np.zeros((N_STEPS, N))\n", + "terms_history = np.zeros((N_STEPS, N))\n", + "\n", + "for t in range(N_STEPS):\n", + " actions = np.random.randint(0, N_ACTIONS, size=ACT_SHAPE)\n", + " obs, rew, term, trunc, info = env.step(actions)\n", + " rewards_history[t] = rew\n", + " terms_history[t] = term\n", + "\n", + "fig, axes = plt.subplots(1, 3, figsize=(18, 5))\n", + "\n", + "axes[0].plot(rewards_history.mean(axis=1))\n", + "axes[0].set_xlabel(\"Step\")\n", + "axes[0].set_ylabel(\"Mean reward\")\n", + "axes[0].set_title(\"Mean reward per step\")\n", + "\n", + "im = axes[1].imshow(rewards_history.T, aspect=\"auto\", cmap=\"RdYlGn\", interpolation=\"nearest\")\n", + "axes[1].set_xlabel(\"Step\")\n", + "axes[1].set_ylabel(\"Agent\")\n", + "axes[1].set_title(\"Reward heatmap (steps x agents)\")\n", + "plt.colorbar(im, ax=axes[1])\n", + "\n", + "cum_returns = rewards_history.cumsum(axis=0)\n", + "for i in range(min(8, N)):\n", + " axes[2].plot(cum_returns[:, i], alpha=0.6, label=f\"agent {i}\")\n", + "axes[2].set_xlabel(\"Step\")\n", + "axes[2].set_ylabel(\"Cumulative return\")\n", + "axes[2].set_title(\"Cumulative returns\")\n", + "axes[2].legend(fontsize=7)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(f\"Total reward stats: mean={rewards_history.mean():.5f}, std={rewards_history.std():.5f}\")\n", + "print(f\"Per-episode return (100 steps): mean={cum_returns[-1].mean():.3f}, std={cum_returns[-1].std():.3f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Reward coefficient inspection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "all_coefs = obs[:, EGO_DIM : EGO_DIM + NUM_COEFS]\n", + "print(f\"Reward coefs shape: {all_coefs.shape}\")\n", + "print()\n", + "print(f\"{'Coef':>15s} | {'mean':>8s} {'std':>8s} {'min':>8s} {'max':>8s}\")\n", + "print(\"-\" * 55)\n", + "for i, name in enumerate(COEF_NAMES):\n", + " c = all_coefs[:, i]\n", + " print(f\"{name:>15s} | {c.mean():8.4f} {c.std():8.4f} {c.min():8.4f} {c.max():8.4f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Terminal analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "N_STEPS = 200\n", + "term_steps, trunc_steps = [], []\n", + "term_rewards, trunc_rewards = [], []\n", + "\n", + "for t in range(N_STEPS):\n", + " actions = np.random.randint(0, N_ACTIONS, size=ACT_SHAPE)\n", + " obs, rew, term, trunc, info = env.step(actions)\n", + " for i in range(N):\n", + " if term[i]:\n", + " term_steps.append(t)\n", + " term_rewards.append(rew[i])\n", + " if trunc[i]:\n", + " trunc_steps.append(t)\n", + " trunc_rewards.append(rew[i])\n", + "\n", + "print(f\"Terminals: {len(term_steps)}, Truncations: {len(trunc_steps)}\")\n", + "if term_rewards:\n", + " tr = np.array(term_rewards)\n", + " print(f\"Terminal reward: mean={tr.mean():.4f}, std={tr.std():.4f}\")\n", + " n_positive = (tr > 0).sum()\n", + " n_negative = (tr < 0).sum()\n", + " n_zero = (tr == 0).sum()\n", + " print(f\" positive: {n_positive}, negative: {n_negative}, zero: {n_zero}\")\n", + "\n", + "fig, ax = plt.subplots(figsize=(10, 4))\n", + "if term_steps:\n", + " ax.scatter(term_steps, term_rewards, c=\"red\", s=20, alpha=0.5, label=f\"terminal ({len(term_steps)})\")\n", + "if trunc_steps:\n", + " ax.scatter(trunc_steps, trunc_rewards, c=\"blue\", s=20, alpha=0.5, label=f\"truncation ({len(trunc_steps)})\")\n", + "ax.axhline(0, color=\"black\", lw=0.5)\n", + "ax.set_xlabel(\"Step\")\n", + "ax.set_ylabel(\"Reward at terminal/truncation\")\n", + "ax.set_title(\"Terminal events over 200 steps\")\n", + "ax.legend()\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Goal detection: high reward events" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "N_STEPS = 512\n", + "goal_events = []\n", + "\n", + "for t in range(N_STEPS):\n", + " prev_obs = obs.copy()\n", + " actions = np.random.randint(0, N_ACTIONS, size=ACT_SHAPE)\n", + " obs, rew, term, trunc, info = env.step(actions)\n", + " for i in range(N):\n", + " if rew[i] >= 0.5:\n", + " goal_dist = np.sqrt(prev_obs[i, 0] ** 2 + prev_obs[i, 1] ** 2)\n", + " goal_events.append((t, i, rew[i], goal_dist))\n", + "\n", + "print(f\"Goal-like events (reward >= 0.5): {len(goal_events)}\")\n", + "if goal_events:\n", + " events = np.array(goal_events)\n", + " print(f\"Reward range: [{events[:, 2].min():.3f}, {events[:, 2].max():.3f}]\")\n", + " print(f\"Goal distance at event: mean={events[:, 3].mean():.3f}, std={events[:, 3].std():.3f}\")\n", + "\n", + " fig, axes = plt.subplots(1, 2, figsize=(12, 4))\n", + " axes[0].hist(events[:, 2], bins=20, edgecolor=\"black\", alpha=0.7, color=\"gold\")\n", + " axes[0].set_title(\"Reward magnitude at goal events\")\n", + " axes[0].set_xlabel(\"Reward\")\n", + " axes[1].scatter(events[:, 3], events[:, 2], alpha=0.5)\n", + " axes[1].set_xlabel(\"Goal distance before event\")\n", + " axes[1].set_ylabel(\"Reward\")\n", + " axes[1].set_title(\"Goal distance vs reward\")\n", + " plt.tight_layout()\n", + " plt.show()\n", + "else:\n", + " print(\"No goal events detected in 512 steps with random actions\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Reward scale for PPO" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "all_rewards = rewards_history.flatten()\n", + "episodic_returns = rewards_history.sum(axis=0)\n", + "\n", + "fig, axes = plt.subplots(1, 2, figsize=(12, 4))\n", + "axes[0].hist(all_rewards[all_rewards != 0], bins=50, edgecolor=\"black\", alpha=0.7)\n", + "axes[0].set_title(f\"Per-step reward distribution (non-zero, N={(all_rewards != 0).sum()})\")\n", + "axes[0].set_xlabel(\"Reward\")\n", + "\n", + "axes[1].hist(episodic_returns, bins=20, edgecolor=\"black\", alpha=0.7, color=\"purple\")\n", + "axes[1].set_title(f\"Episodic return (100 steps): mean={episodic_returns.mean():.3f}\")\n", + "axes[1].set_xlabel(\"Return\")\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(f\"Reward magnitude range: [{all_rewards.min():.5f}, {all_rewards.max():.5f}]\")\n", + "print(f\"Mean episodic return: {episodic_returns.mean():.4f} +/- {episodic_returns.std():.4f}\")\n", + "if abs(episodic_returns.mean()) > 10:\n", + " print(\"WARNING: large episodic returns, consider scaling\")\n", + "if episodic_returns.std() < 1e-6:\n", + " print(\"WARNING: near-zero return variance\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Action-reward correlation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "STEPS_PER_ACTION = 20\n", + "action_rewards = {}\n", + "\n", + "for a in range(N_ACTIONS):\n", + " rews = []\n", + " for _ in range(STEPS_PER_ACTION):\n", + " actions = np.full(ACT_SHAPE, a, dtype=np.int64)\n", + " obs, rew, term, trunc, info = env.step(actions)\n", + " rews.append(rew.mean())\n", + " action_rewards[a] = np.mean(rews)\n", + "\n", + "fig, ax = plt.subplots(figsize=(10, 5))\n", + "actions_list = sorted(action_rewards.keys())\n", + "means = [action_rewards[a] for a in actions_list]\n", + "colors = [\"green\" if m > 0 else \"red\" for m in means]\n", + "labels = [f\"{a // 3}L,{a % 3}R\" for a in actions_list]\n", + "ax.bar(range(len(actions_list)), means, tick_label=labels, color=colors, edgecolor=\"black\")\n", + "ax.set_xlabel(\"Action (longitudinal, lateral)\")\n", + "ax.set_ylabel(\"Mean reward\")\n", + "ax.set_title(f\"Mean reward per action over {STEPS_PER_ACTION} steps\")\n", + "ax.axhline(0, color=\"black\", lw=0.5)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/03_metrics.ipynb b/notebooks/03_metrics.ipynb new file mode 100644 index 0000000000..01fb4b9b10 --- /dev/null +++ b/notebooks/03_metrics.ipynb @@ -0,0 +1,400 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 03 - Episode Metrics & Logging Debug\n", + "Verify vec_log returns correct metrics, aggregation is sane, episode boundaries handled." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from pufferlib.ocean.drive.drive import Drive\n", + "from pufferlib.ocean.drive import binding\n", + "import pufferlib.viz\n", + "\n", + "# --- Environment configuration ---\n", + "NUM_AGENTS = 64\n", + "SIMULATION_MODE = \"gigaflow\"\n", + "DYNAMICS_MODEL = \"jerk\"\n", + "ACTION_TYPE = \"discrete\"\n", + "DT = 0.1\n", + "SCENARIO_LENGTH = 512\n", + "RESAMPLE_FREQUENCY = 0\n", + "REWARD_CONDITIONING = True\n", + "REWARD_RANDOMIZATION = False\n", + "TARGET_TYPE = \"static\"\n", + "COLLISION_BEHAVIOR = 1\n", + "OFFROAD_BEHAVIOR = 1\n", + "SEED = 42\n", + "MAP_DIR = \"../pufferlib/resources/drive/binaries/carla\"\n", + "\n", + "# --- Observation dimensions (configurable) ---\n", + "MAX_PARTNERS = 16\n", + "MAX_LANES = 32\n", + "MAX_BOUNDS = 32\n", + "MAX_TRAFFIC = 10\n", + "MAX_STOP_SIGNS = 0\n", + "\n", + "# --- Derived from binding (compile-time) ---\n", + "EGO_DIM = binding.EGO_FEATURES_JERK\n", + "NUM_COEFS = binding.NUM_REWARD_COEFS\n", + "PARTNER_F = binding.PARTNER_FEATURES\n", + "ROAD_F = binding.ROAD_FEATURES\n", + "TRAFFIC_F = binding.TRAFFIC_LIGHT_FEATURES\n", + "STOP_SIGN_F = binding.STOP_SIGN_FEATURES\n", + "COEF_NAMES = [\n", + " \"goal_radius\",\n", + " \"collision\",\n", + " \"offroad\",\n", + " \"comfort\",\n", + " \"lane_align\",\n", + " \"lane_center\",\n", + " \"velocity\",\n", + " \"traffic_light\",\n", + " \"center_bias\",\n", + " \"vel_align\",\n", + " \"overspeed\",\n", + " \"timestep\",\n", + " \"reverse\",\n", + " \"throttle\",\n", + " \"steer\",\n", + " \"acc\",\n", + "]\n", + "\n", + "# --- Create environment ---\n", + "env = Drive(\n", + " num_agents=NUM_AGENTS,\n", + " num_maps=1,\n", + " min_agents_per_env=NUM_AGENTS,\n", + " max_agents_per_env=NUM_AGENTS,\n", + " simulation_mode=SIMULATION_MODE,\n", + " dynamics_model=DYNAMICS_MODEL,\n", + " action_type=ACTION_TYPE,\n", + " dt=DT,\n", + " scenario_length=SCENARIO_LENGTH,\n", + " resample_frequency=RESAMPLE_FREQUENCY,\n", + " reward_conditioning=REWARD_CONDITIONING,\n", + " reward_randomization=REWARD_RANDOMIZATION,\n", + " target_type=TARGET_TYPE,\n", + " map_dir=MAP_DIR,\n", + " collision_behavior=COLLISION_BEHAVIOR,\n", + " offroad_behavior=OFFROAD_BEHAVIOR,\n", + " max_lane_segment_observations=MAX_LANES,\n", + " max_boundary_segment_observations=MAX_BOUNDS,\n", + " max_partner_observations=MAX_PARTNERS,\n", + " max_traffic_light_observations=MAX_TRAFFIC,\n", + " seed=SEED,\n", + ")\n", + "obs, info = env.reset(seed=SEED)\n", + "\n", + "# --- Derived from env ---\n", + "MAX_TARGET = env.num_target_waypoints\n", + "TARGET_F = binding.STATIC_TARGET_FEATURES if TARGET_TYPE == \"static\" else binding.DYNAMIC_TARGET_FEATURES\n", + "TARGET_DIM = MAX_TARGET * TARGET_F\n", + "N_ACTIONS = 12\n", + "N = env.num_agents\n", + "ACT_SHAPE = (N, len(env.single_action_space.nvec))\n", + "\n", + "print(f\"env ready: {N} agents, act_shape={ACT_SHAPE}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Single vec_log call" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for _ in range(10):\n", + " actions = np.random.randint(0, N_ACTIONS, size=ACT_SHAPE)\n", + " obs, rew, term, trunc, info = env.step(actions)\n", + "\n", + "log = binding.vec_log(env.c_envs, N)\n", + "print(f\"vec_log type: {type(log)}\")\n", + "if log:\n", + " print(f\"Keys: {sorted(log.keys())}\")\n", + " for k, v in sorted(log.items()):\n", + " print(f\" {k}: {v}\")\n", + "else:\n", + " print(\"vec_log returned empty/None\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 512-step collection: all info dicts" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "N_STEPS = 512\n", + "all_logs = []\n", + "all_rewards = np.zeros((N_STEPS, N))\n", + "all_terms = np.zeros((N_STEPS, N))\n", + "all_truncs = np.zeros((N_STEPS, N))\n", + "\n", + "for t in range(N_STEPS):\n", + " actions = np.random.randint(0, N_ACTIONS, size=ACT_SHAPE)\n", + " obs, rew, term, trunc, info = env.step(actions)\n", + " all_rewards[t] = rew\n", + " all_terms[t] = term\n", + " all_truncs[t] = trunc\n", + " if info:\n", + " for log_entry in info:\n", + " log_entry[\"_step\"] = t\n", + " all_logs.append(log_entry)\n", + "\n", + "print(f\"Collected {len(all_logs)} log entries over {N_STEPS} steps\")\n", + "if all_logs:\n", + " keys = set()\n", + " for log in all_logs:\n", + " keys.update(log.keys())\n", + " keys.discard(\"_step\")\n", + " print(f\"\\n{'Metric':>25s} | {'count':>5s} {'mean':>10s} {'std':>10s} {'min':>10s} {'max':>10s}\")\n", + " print(\"-\" * 75)\n", + " for k in sorted(keys):\n", + " vals = [log[k] for log in all_logs if k in log and isinstance(log[k], (int, float))]\n", + " if vals:\n", + " v = np.array(vals)\n", + " print(f\"{k:>25s} | {len(v):5d} {v.mean():10.4f} {v.std():10.4f} {v.min():10.4f} {v.max():10.4f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Metric definitions reference\n", + "\n", + "| Metric | Description |\n", + "|--------|-------------|\n", + "| score | Goals reached cleanly (no collision/offroad) |\n", + "| collision_rate | Fraction of agents that collided |\n", + "| offroad_rate | Fraction of agents that went off-road |\n", + "| completion_rate | Fraction that reached goal (even with collision/offroad) |\n", + "| lane_heading_aligned_rate | Fraction of steps with cos(theta) >= 0.5 (within ~60 deg of lane heading) |\n", + "| lane_center_rate | Lane centering metric average (same as reward term) |\n", + "| avg_collisions_per_agent | Average collision events per agent per episode |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Terminal / truncation timeline" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "term_per_step = all_terms.sum(axis=1)\n", + "trunc_per_step = all_truncs.sum(axis=1)\n", + "\n", + "fig, ax = plt.subplots(figsize=(14, 4))\n", + "ax.plot(term_per_step, label=\"terminals\", alpha=0.7, color=\"red\")\n", + "ax.plot(trunc_per_step, label=\"truncations\", alpha=0.7, color=\"blue\")\n", + "ax.set_xlabel(\"Step\")\n", + "ax.set_ylabel(\"Count\")\n", + "ax.set_title(\"Terminal/truncation events per step\")\n", + "ax.legend()\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(f\"Total terminals: {all_terms.sum():.0f}, truncations: {all_truncs.sum():.0f}\")\n", + "print(f\"Terminals per step: mean={term_per_step.mean():.2f}, max={term_per_step.max():.0f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Agent lifecycle trajectories" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "TRACK_STEPS = 100\n", + "TRACK_AGENTS = min(5, N)\n", + "xy_history = np.zeros((TRACK_STEPS, TRACK_AGENTS, 2))\n", + "\n", + "for t in range(TRACK_STEPS):\n", + " actions = np.random.randint(0, N_ACTIONS, size=ACT_SHAPE)\n", + " env.step(actions)\n", + " states = env.get_global_agent_state()\n", + " for i in range(TRACK_AGENTS):\n", + " xy_history[t, i, 0] = states[\"x\"][i]\n", + " xy_history[t, i, 1] = states[\"y\"][i]\n", + "\n", + "fig, ax = plt.subplots(figsize=(10, 10))\n", + "for i in range(TRACK_AGENTS):\n", + " ax.plot(xy_history[:, i, 0], xy_history[:, i, 1], \"-o\", markersize=2, alpha=0.7, label=f\"agent {i}\")\n", + " ax.scatter(xy_history[0, i, 0], xy_history[0, i, 1], s=100, marker=\"s\", zorder=10)\n", + " ax.scatter(xy_history[-1, i, 0], xy_history[-1, i, 1], s=100, marker=\"*\", zorder=10)\n", + "ax.set_xlabel(\"x\")\n", + "ax.set_ylabel(\"y\")\n", + "ax.set_title(f\"{TRACK_AGENTS} agent trajectories over {TRACK_STEPS} steps\")\n", + "ax.legend()\n", + "ax.set_aspect(\"equal\")\n", + "ax.grid(True, alpha=0.3)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Consistency checks" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "if all_logs:\n", + " passed = 0\n", + " failed = 0\n", + " for log in all_logs:\n", + " if \"score\" in log and \"completion_rate\" in log:\n", + " if log[\"score\"] > log[\"completion_rate\"] + 1e-6:\n", + " print(\n", + " f\"FAIL: score ({log['score']:.4f}) > completion_rate ({log['completion_rate']:.4f}) at step {log['_step']}\"\n", + " )\n", + " failed += 1\n", + " else:\n", + " passed += 1\n", + " for rate_key in [\"collision_rate\", \"offroad_rate\", \"completion_rate\", \"score\"]:\n", + " if rate_key in log:\n", + " v = log[rate_key]\n", + " if v < -1e-6 or v > 1.0 + 1e-6:\n", + " print(f\"FAIL: {rate_key} = {v:.4f} outside [0,1] at step {log['_step']}\")\n", + " failed += 1\n", + " else:\n", + " passed += 1\n", + " print(f\"\\nConsistency checks: {passed} passed, {failed} failed\")\n", + "else:\n", + " print(\"No logs to check\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Gigaflow agent dynamics" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "episode_lengths = []\n", + "agent_step_count = np.zeros(N)\n", + "active_counts = []\n", + "\n", + "for t in range(N_STEPS):\n", + " active = (~np.all(all_rewards[: t + 1] == 0, axis=0) if t > 0 else np.ones(N, dtype=bool)).sum()\n", + " active_counts.append(active)\n", + " for i in range(N):\n", + " agent_step_count[i] += 1\n", + " if all_terms[t, i] or all_truncs[t, i]:\n", + " episode_lengths.append(agent_step_count[i])\n", + " agent_step_count[i] = 0\n", + "\n", + "fig, axes = plt.subplots(1, 2, figsize=(14, 4))\n", + "axes[0].plot(active_counts)\n", + "axes[0].set_xlabel(\"Step\")\n", + "axes[0].set_ylabel(\"Active agents\")\n", + "axes[0].set_title(\"Active agent count over time\")\n", + "\n", + "if episode_lengths:\n", + " axes[1].hist(episode_lengths, bins=30, edgecolor=\"black\", alpha=0.7)\n", + " axes[1].set_xlabel(\"Episode length (steps)\")\n", + " axes[1].set_title(f\"Episode length distribution (N={len(episode_lengths)})\")\n", + " print(f\"Episode lengths: mean={np.mean(episode_lengths):.1f}, median={np.median(episode_lengths):.1f}\")\n", + "else:\n", + " print(\"No episodes completed\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Score vs cumulative reward" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "if all_logs and \"score\" in all_logs[0]:\n", + " scores = [log[\"score\"] for log in all_logs if \"score\" in log]\n", + " log_steps = [log[\"_step\"] for log in all_logs if \"score\" in log]\n", + " cum_rew_at_log = [all_rewards[: t + 1].sum() / N for t in log_steps]\n", + "\n", + " fig, ax = plt.subplots(figsize=(8, 6))\n", + " ax.scatter(cum_rew_at_log, scores, alpha=0.5)\n", + " ax.set_xlabel(\"Avg cumulative reward up to step\")\n", + " ax.set_ylabel(\"Score\")\n", + " ax.set_title(\"Score vs cumulative reward\")\n", + " ax.grid(True, alpha=0.3)\n", + " plt.tight_layout()\n", + " plt.show()\n", + "else:\n", + " print(\"No score data available\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/04_training.ipynb b/notebooks/04_training.ipynb new file mode 100644 index 0000000000..c27363c941 --- /dev/null +++ b/notebooks/04_training.ipynb @@ -0,0 +1,625 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 04 - RL Training Loop Debug\n", + "End-to-end data flow from env -> policy -> loss. Debug encoding, sampling, advantages, gradients." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import torch\n", + "import torch.nn.functional as F\n", + "from pufferlib.ocean.drive.drive import Drive\n", + "from pufferlib.ocean.drive import binding\n", + "from pufferlib.ocean.torch import Drive as DrivePolicy\n", + "\n", + "# --- Environment configuration ---\n", + "NUM_AGENTS = 64\n", + "SIMULATION_MODE = \"gigaflow\"\n", + "DYNAMICS_MODEL = \"jerk\"\n", + "ACTION_TYPE = \"discrete\"\n", + "DT = 0.1\n", + "SCENARIO_LENGTH = 512\n", + "RESAMPLE_FREQUENCY = 0\n", + "REWARD_CONDITIONING = True\n", + "REWARD_RANDOMIZATION = False\n", + "TARGET_TYPE = \"static\"\n", + "COLLISION_BEHAVIOR = 1\n", + "OFFROAD_BEHAVIOR = 1\n", + "SEED = 42\n", + "MAP_DIR = \"../pufferlib/resources/drive/binaries/carla\"\n", + "\n", + "# --- Observation dimensions (configurable) ---\n", + "MAX_PARTNERS = 16\n", + "MAX_LANES = 32\n", + "MAX_BOUNDS = 32\n", + "MAX_TRAFFIC = 10\n", + "MAX_STOP_SIGNS = 0\n", + "\n", + "# --- Derived from binding (compile-time) ---\n", + "EGO_DIM = binding.EGO_FEATURES_JERK\n", + "NUM_COEFS = binding.NUM_REWARD_COEFS\n", + "PARTNER_F = binding.PARTNER_FEATURES\n", + "ROAD_F = binding.ROAD_FEATURES\n", + "TRAFFIC_F = binding.TRAFFIC_LIGHT_FEATURES\n", + "STOP_SIGN_F = binding.STOP_SIGN_FEATURES\n", + "\n", + "# --- Create environment ---\n", + "env = Drive(\n", + " num_agents=NUM_AGENTS,\n", + " num_maps=1,\n", + " min_agents_per_env=NUM_AGENTS,\n", + " max_agents_per_env=NUM_AGENTS,\n", + " simulation_mode=SIMULATION_MODE,\n", + " dynamics_model=DYNAMICS_MODEL,\n", + " action_type=ACTION_TYPE,\n", + " dt=DT,\n", + " scenario_length=SCENARIO_LENGTH,\n", + " resample_frequency=RESAMPLE_FREQUENCY,\n", + " reward_conditioning=REWARD_CONDITIONING,\n", + " reward_randomization=REWARD_RANDOMIZATION,\n", + " target_type=TARGET_TYPE,\n", + " map_dir=MAP_DIR,\n", + " collision_behavior=COLLISION_BEHAVIOR,\n", + " offroad_behavior=OFFROAD_BEHAVIOR,\n", + " max_lane_segment_observations=MAX_LANES,\n", + " max_boundary_segment_observations=MAX_BOUNDS,\n", + " max_partner_observations=MAX_PARTNERS,\n", + " max_traffic_light_observations=MAX_TRAFFIC,\n", + " max_stop_sign_observations=MAX_STOP_SIGNS,\n", + " seed=SEED,\n", + ")\n", + "obs, info = env.reset(seed=SEED)\n", + "\n", + "# --- Derived from env ---\n", + "MAX_TARGET = env.num_target_waypoints\n", + "TARGET_F = binding.STATIC_TARGET_FEATURES if TARGET_TYPE == \"static\" else binding.DYNAMIC_TARGET_FEATURES\n", + "TARGET_DIM = MAX_TARGET * TARGET_F\n", + "N_ACTIONS = 12\n", + "N = env.num_agents\n", + "ACT_SHAPE = (N, len(env.single_action_space.nvec))\n", + "\n", + "# --- Policy ---\n", + "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", + "policy = DrivePolicy(\n", + " env,\n", + " input_size=64,\n", + " backbone_hidden_size=128,\n", + " backbone_num_layers=1,\n", + " actor_hidden_size=128,\n", + " actor_num_layers=0,\n", + " critic_hidden_size=128,\n", + " critic_num_layers=0,\n", + " encoder_gigaflow=True,\n", + " dropout=0.0,\n", + " split_network=False,\n", + ").to(device)\n", + "print(f\"Policy on {device}, params: {sum(p.numel() for p in policy.parameters()):,}\")\n", + "print(f\"Action dim: {policy.atn_dim}, act_shape: {ACT_SHAPE}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Optional: load checkpoint" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# CHECKPOINT_PATH = '/home/o-vcharrau/Workspace/PufferDrive-Valeo/runs/big_test_7/models/model_puffer_drive_000520.pt'\n", + "# state_dict = torch.load(CHECKPOINT_PATH, map_location=device)\n", + "# state_dict = {k.replace(\"module.\", \"\"): v for k, v in state_dict.items()}\n", + "# print('Checkpoint loaded')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Encode observations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "actions = np.zeros(ACT_SHAPE, dtype=np.int64)\n", + "obs, rew, term, trunc, info = env.step(actions)\n", + "\n", + "obs_tensor = torch.FloatTensor(obs).to(device)\n", + "with torch.no_grad():\n", + " hidden = policy.encode_observations(obs_tensor)\n", + "\n", + "print(f\"Hidden shape: {hidden.shape}\")\n", + "print(f\"Hidden stats: min={hidden.min():.4f}, max={hidden.max():.4f}, mean={hidden.mean():.4f}\")\n", + "print(f\"NaN in hidden: {torch.isnan(hidden).sum().item()}\")\n", + "print(f\"Dead neurons (always 0): {(hidden.abs().sum(dim=0) == 0).sum().item()}/{hidden.shape[1]}\")\n", + "print(f\"% near-zero (<1e-6): {(hidden.abs() < 1e-6).float().mean().item() * 100:.1f}%\")\n", + "\n", + "fig, ax = plt.subplots(figsize=(10, 4))\n", + "ax.hist(hidden.cpu().numpy().flatten(), bins=50, edgecolor=\"black\", alpha=0.7)\n", + "ax.set_title(\"Hidden activation distribution\")\n", + "ax.set_xlabel(\"Activation value\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Action sampling" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with torch.no_grad():\n", + " action_logits, value = policy.decode_actions(hidden)\n", + "\n", + "for i, logit in enumerate(action_logits):\n", + " print(f\"Action head {i}: shape={logit.shape}\")\n", + " probs = F.softmax(logit, dim=-1)\n", + " entropy = -(probs * probs.log()).sum(dim=-1).mean()\n", + " max_entropy = np.log(logit.shape[-1])\n", + " print(f\" Entropy: {entropy:.4f} / {max_entropy:.4f} (max) = {entropy / max_entropy:.2%}\")\n", + " print(f\" Logit range: [{logit.min():.3f}, {logit.max():.3f}]\")\n", + "\n", + "print(f\"\\nValue: mean={value.mean():.4f}, std={value.std():.4f}\")\n", + "\n", + "fig, axes = plt.subplots(1, 2, figsize=(14, 4))\n", + "probs = F.softmax(action_logits[0], dim=-1)\n", + "mean_probs = probs.mean(dim=0).cpu().numpy()\n", + "axes[0].bar(range(len(mean_probs)), mean_probs, edgecolor=\"black\", alpha=0.7)\n", + "axes[0].axhline(1.0 / len(mean_probs), color=\"red\", ls=\"--\", label=\"uniform\")\n", + "axes[0].set_xlabel(\"Action\")\n", + "axes[0].set_ylabel(\"Probability\")\n", + "axes[0].set_title(\"Mean action probabilities\")\n", + "axes[0].legend()\n", + "\n", + "axes[1].hist(value.cpu().numpy().flatten(), bins=20, edgecolor=\"black\", alpha=0.7, color=\"purple\")\n", + "axes[1].set_title(\"Value predictions\")\n", + "axes[1].set_xlabel(\"Value\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Manual encode trace: check each encoder for NaN" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = obs_tensor\n", + "backbone = policy.actor_backbone\n", + "slide_idx = EGO_DIM\n", + "\n", + "ego_obs = x[:, :slide_idx]\n", + "print(\n", + " f\"ego_obs: shape={ego_obs.shape}, NaN={torch.isnan(ego_obs).sum().item()}, range=[{ego_obs.min():.3f}, {ego_obs.max():.3f}]\"\n", + ")\n", + "\n", + "cond_dim = backbone.conditioning_dim\n", + "if cond_dim > 0:\n", + " cond_obs = x[:, slide_idx : slide_idx + cond_dim]\n", + " slide_idx += cond_dim\n", + " print(f\"cond_obs: shape={cond_obs.shape}, NaN={torch.isnan(cond_obs).sum().item()}\")\n", + "\n", + "partner_dim = MAX_PARTNERS * PARTNER_F\n", + "lane_dim = MAX_LANES * ROAD_F\n", + "boundary_dim = MAX_BOUNDS * ROAD_F\n", + "\n", + "partner_obs = x[:, slide_idx : slide_idx + partner_dim]\n", + "slide_idx += partner_dim\n", + "lane_obs = x[:, slide_idx : slide_idx + lane_dim]\n", + "slide_idx += lane_dim\n", + "boundary_obs = x[:, slide_idx : slide_idx + boundary_dim]\n", + "slide_idx += boundary_dim\n", + "\n", + "with torch.no_grad():\n", + " ego_enc = backbone.ego_encoder(ego_obs)\n", + " partner_enc, _ = backbone.partner_encoder(partner_obs.view(-1, MAX_PARTNERS, PARTNER_F)).max(dim=1)\n", + " lane_enc, _ = backbone.lane_encoder(lane_obs.view(-1, MAX_LANES, ROAD_F)).max(dim=1)\n", + " bound_enc, _ = backbone.boundary_encoder(boundary_obs.view(-1, MAX_BOUNDS, ROAD_F)).max(dim=1)\n", + "\n", + "for name, enc in [(\"ego\", ego_enc), (\"partner\", partner_enc), (\"lane\", lane_enc), (\"boundary\", bound_enc)]:\n", + " print(\n", + " f\"{name:>10s}_enc: NaN={torch.isnan(enc).sum().item()}, dead={((enc.abs().sum(dim=0) == 0).sum().item())}, range=[{enc.min():.3f}, {enc.max():.3f}]\"\n", + " )\n", + "\n", + "if cond_dim > 0:\n", + " with torch.no_grad():\n", + " cond_enc = backbone.conditioning_encoder(cond_obs)\n", + " print(\n", + " f\"{'cond':>10s}_enc: NaN={torch.isnan(cond_enc).sum().item()}, dead={((cond_enc.abs().sum(dim=0) == 0).sum().item())}, range=[{cond_enc.min():.3f}, {cond_enc.max():.3f}]\"\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Forward-backward: fake advantage, loss, grads" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "policy.train()\n", + "optimizer = torch.optim.Adam(policy.parameters(), lr=3e-4)\n", + "\n", + "action_logits_list, value = policy(obs_tensor)\n", + "\n", + "fake_actions = torch.randint(0, N_ACTIONS, (N,), device=device)\n", + "fake_advantages = torch.randn(N, device=device)\n", + "fake_returns = torch.randn(N, device=device)\n", + "fake_old_logprobs = torch.randn(N, device=device)\n", + "\n", + "logits = action_logits_list[0]\n", + "dist = torch.distributions.Categorical(logits=logits)\n", + "new_logprobs = dist.log_prob(fake_actions)\n", + "entropy = dist.entropy()\n", + "\n", + "ratio = torch.exp(new_logprobs - fake_old_logprobs)\n", + "clip_coef = 0.2\n", + "pg_loss1 = -fake_advantages * ratio\n", + "pg_loss2 = -fake_advantages * torch.clamp(ratio, 1 - clip_coef, 1 + clip_coef)\n", + "pg_loss = torch.max(pg_loss1, pg_loss2).mean()\n", + "v_loss = 0.5 * ((value.squeeze() - fake_returns) ** 2).mean()\n", + "entropy_loss = entropy.mean()\n", + "loss = pg_loss + 0.5 * v_loss - 0.01 * entropy_loss\n", + "\n", + "print(f\"pg_loss: {pg_loss.item():.4f}\")\n", + "print(f\"v_loss: {v_loss.item():.4f}\")\n", + "print(f\"entropy: {entropy_loss.item():.4f}\")\n", + "print(f\"total: {loss.item():.4f}\")\n", + "print(f\"ratio: mean={ratio.mean():.4f}, std={ratio.std():.4f}\")\n", + "\n", + "optimizer.zero_grad()\n", + "loss.backward()\n", + "total_grad_norm = torch.nn.utils.clip_grad_norm_(policy.parameters(), float(\"inf\"))\n", + "print(f\"\\nTotal grad norm: {total_grad_norm:.4f}\")\n", + "print(f\"NaN in loss: {torch.isnan(loss).item()}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Gradient flow: per-parameter analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(f\"{'Parameter':>45s} | {'shape':>20s} | {'grad_norm':>10s} {'grad_mean':>10s} {'grad_max':>10s} | flag\")\n", + "print(\"-\" * 120)\n", + "for name, param in policy.named_parameters():\n", + " if param.grad is not None:\n", + " g = param.grad\n", + " norm = g.norm().item()\n", + " mean = g.mean().item()\n", + " mx = g.abs().max().item()\n", + " flag = \"\"\n", + " if norm == 0:\n", + " flag = \"ZERO GRAD\"\n", + " elif norm > 100:\n", + " flag = \"EXPLODING\"\n", + " elif norm < 1e-7:\n", + " flag = \"VANISHING\"\n", + " print(f\"{name:>45s} | {str(list(param.shape)):>20s} | {norm:10.6f} {mean:10.6f} {mx:10.6f} | {flag}\")\n", + " else:\n", + " print(f\"{name:>45s} | {str(list(param.shape)):>20s} | NO GRAD\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Experience buffer simulation: 128-step rollout" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "HORIZON = 128\n", + "obs_dim = obs.shape[1]\n", + "\n", + "obs_buf = np.zeros((HORIZON, N, obs_dim), dtype=np.float32)\n", + "act_buf = np.zeros((HORIZON, N), dtype=np.int64)\n", + "rew_buf = np.zeros((HORIZON, N), dtype=np.float32)\n", + "val_buf = np.zeros((HORIZON, N), dtype=np.float32)\n", + "logp_buf = np.zeros((HORIZON, N), dtype=np.float32)\n", + "done_buf = np.zeros((HORIZON, N), dtype=np.float32)\n", + "\n", + "policy.eval()\n", + "for t in range(HORIZON):\n", + " obs_t = torch.FloatTensor(obs).to(device)\n", + " with torch.no_grad():\n", + " logits_list, val = policy(obs_t)\n", + " dist = torch.distributions.Categorical(logits=logits_list[0])\n", + " act = dist.sample()\n", + " logp = dist.log_prob(act)\n", + "\n", + " obs_buf[t] = obs\n", + " act_buf[t] = act.cpu().numpy()\n", + " val_buf[t] = val.squeeze().cpu().numpy()\n", + " logp_buf[t] = logp.cpu().numpy()\n", + "\n", + " # Reshape (N,) -> (N, 1) for env.step with MultiDiscrete\n", + " env_actions = act.cpu().numpy().reshape(ACT_SHAPE)\n", + " obs, rew, term, trunc, info = env.step(env_actions)\n", + " rew_buf[t] = rew\n", + " done_buf[t] = term | trunc\n", + "\n", + "print(f\"Buffer shapes: obs={obs_buf.shape}, act={act_buf.shape}, rew={rew_buf.shape}\")\n", + "print(f\"Reward stats: mean={rew_buf.mean():.5f}, std={rew_buf.std():.5f}\")\n", + "print(f\"Value stats: mean={val_buf.mean():.5f}, std={val_buf.std():.5f}\")\n", + "print(f\"Done count: {done_buf.sum():.0f}\")\n", + "print(f\"LogProb stats: mean={logp_buf.mean():.4f}, std={logp_buf.std():.4f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## GAE advantage computation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "gamma, lam = 0.98, 0.95\n", + "advantages = np.zeros_like(rew_buf)\n", + "\n", + "last_gae = np.zeros(N)\n", + "for t in reversed(range(HORIZON - 1)):\n", + " next_non_terminal = 1.0 - done_buf[t + 1]\n", + " delta = rew_buf[t + 1] + gamma * val_buf[t + 1] * next_non_terminal - val_buf[t]\n", + " last_gae = delta + gamma * lam * last_gae * next_non_terminal\n", + " advantages[t] = last_gae\n", + "\n", + "returns = advantages + val_buf\n", + "\n", + "print(f\"Advantages: mean={advantages.mean():.5f}, std={advantages.std():.5f}\")\n", + "print(f\"Returns: mean={returns.mean():.5f}, std={returns.std():.5f}\")\n", + "print(f\"Advantage vs Return corr: {np.corrcoef(advantages.flatten(), returns.flatten())[0, 1]:.4f}\")\n", + "\n", + "fig, axes = plt.subplots(1, 4, figsize=(18, 4))\n", + "axes[0].hist(advantages.flatten(), bins=50, edgecolor=\"black\", alpha=0.7)\n", + "axes[0].set_title(f\"Advantage distribution (std={advantages.std():.4f})\")\n", + "\n", + "axes[1].hist(returns.flatten(), bins=50, edgecolor=\"black\", alpha=0.7, color=\"orange\")\n", + "axes[1].set_title(\"Returns distribution\")\n", + "\n", + "axes[2].plot(advantages.mean(axis=1))\n", + "axes[2].set_xlabel(\"Step\")\n", + "axes[2].set_ylabel(\"Mean advantage\")\n", + "axes[2].set_title(\"Mean advantage over time\")\n", + "\n", + "axes[3].plot(done_buf.mean(axis=1), color=\"orange\")\n", + "axes[3].set_xlabel(\"Step\")\n", + "axes[3].set_ylabel(\"Mean done\")\n", + "axes[3].set_title(\"Mean done over time\")\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## PPO loss components" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "MB = 16\n", + "mb_obs = torch.FloatTensor(obs_buf[:MB].reshape(-1, obs_dim)).to(device)\n", + "mb_act = torch.LongTensor(act_buf[:MB].flatten()).to(device)\n", + "mb_old_logp = torch.FloatTensor(logp_buf[:MB].flatten()).to(device)\n", + "mb_adv = torch.FloatTensor(advantages[:MB].flatten()).to(device)\n", + "mb_ret = torch.FloatTensor(returns[:MB].flatten()).to(device)\n", + "mb_old_val = torch.FloatTensor(val_buf[:MB].flatten()).to(device)\n", + "\n", + "mb_adv = (mb_adv - mb_adv.mean()) / (mb_adv.std() + 1e-8)\n", + "\n", + "policy.train()\n", + "logits_list, newvalue = policy(mb_obs)\n", + "newvalue = newvalue.squeeze()\n", + "dist = torch.distributions.Categorical(logits=logits_list[0])\n", + "new_logp = dist.log_prob(mb_act)\n", + "entropy = dist.entropy()\n", + "\n", + "ratio = torch.exp(new_logp - mb_old_logp)\n", + "print(f\"Ratio: mean={ratio.mean():.4f}, std={ratio.std():.4f}, min={ratio.min():.4f}, max={ratio.max():.4f}\")\n", + "if ratio.mean() < 0.5 or ratio.mean() > 2.0:\n", + " print(\"WARNING: ratio far from 1.0, policy may have diverged\")\n", + "\n", + "clip_coef = 0.2\n", + "pg_loss1 = -mb_adv * ratio\n", + "pg_loss2 = -mb_adv * torch.clamp(ratio, 1 - clip_coef, 1 + clip_coef)\n", + "pg_loss = torch.max(pg_loss1, pg_loss2).mean()\n", + "\n", + "vf_clip = 0.2\n", + "v_clipped = mb_old_val + torch.clamp(newvalue - mb_old_val, -vf_clip, vf_clip)\n", + "v_loss_unclipped = (newvalue - mb_ret) ** 2\n", + "v_loss_clipped = (v_clipped - mb_ret) ** 2\n", + "v_loss = 0.5 * torch.max(v_loss_unclipped, v_loss_clipped).mean()\n", + "\n", + "entropy_loss = entropy.mean()\n", + "\n", + "print(f\"\\npg_loss: {pg_loss.item():.6f}\")\n", + "print(f\"v_loss: {v_loss.item():.6f}\")\n", + "print(f\"entropy: {entropy_loss.item():.6f} (max={np.log(N_ACTIONS):.4f})\")\n", + "print(f\"total: {(pg_loss + 0.5 * v_loss - 0.01 * entropy_loss).item():.6f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5-epoch sanity training" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "optimizer = torch.optim.Adam(policy.parameters(), lr=3e-4)\n", + "all_obs = torch.FloatTensor(obs_buf.reshape(-1, obs_dim)).to(device)\n", + "all_act = torch.LongTensor(act_buf.flatten()).to(device)\n", + "all_old_logp = torch.FloatTensor(logp_buf.flatten()).to(device)\n", + "all_adv = torch.FloatTensor(advantages.flatten()).to(device)\n", + "all_ret = torch.FloatTensor(returns.flatten()).to(device)\n", + "\n", + "all_adv = (all_adv - all_adv.mean()) / (all_adv.std() + 1e-8)\n", + "\n", + "N_EPOCHS = 5\n", + "history = {\"pg_loss\": [], \"v_loss\": [], \"entropy\": [], \"kl\": []}\n", + "\n", + "policy.train()\n", + "for epoch in range(N_EPOCHS):\n", + " logits_list, newval = policy(all_obs)\n", + " newval = newval.squeeze()\n", + " dist = torch.distributions.Categorical(logits=logits_list[0])\n", + " new_logp = dist.log_prob(all_act)\n", + " ent = dist.entropy().mean()\n", + "\n", + " ratio = torch.exp(new_logp - all_old_logp)\n", + " approx_kl = (all_old_logp - new_logp).mean()\n", + "\n", + " pg1 = -all_adv * ratio\n", + " pg2 = -all_adv * torch.clamp(ratio, 0.8, 1.2)\n", + " pg = torch.max(pg1, pg2).mean()\n", + " vl = 0.5 * ((newval - all_ret) ** 2).mean()\n", + " loss = pg + 0.5 * vl - 0.01 * ent\n", + "\n", + " optimizer.zero_grad()\n", + " loss.backward()\n", + " torch.nn.utils.clip_grad_norm_(policy.parameters(), 0.5)\n", + " optimizer.step()\n", + "\n", + " history[\"pg_loss\"].append(pg.item())\n", + " history[\"v_loss\"].append(vl.item())\n", + " history[\"entropy\"].append(ent.item())\n", + " history[\"kl\"].append(approx_kl.item())\n", + " print(f\"Epoch {epoch}: pg={pg.item():.5f}, v={vl.item():.5f}, ent={ent.item():.4f}, kl={approx_kl.item():.5f}\")\n", + "\n", + "fig, axes = plt.subplots(1, 4, figsize=(16, 3))\n", + "for i, (key, color) in enumerate(zip(history.keys(), [\"red\", \"blue\", \"green\", \"orange\"])):\n", + " axes[i].plot(history[key], \"-o\", color=color)\n", + " axes[i].set_title(key)\n", + " axes[i].set_xlabel(\"Epoch\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Value accuracy: predicted vs actual returns" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "policy.eval()\n", + "with torch.no_grad():\n", + " _, pred_values = policy(all_obs)\n", + "pred_values = pred_values.squeeze().cpu().numpy()\n", + "actual_returns = returns.flatten()\n", + "\n", + "var_actual = np.var(actual_returns)\n", + "explained_var = 1 - np.var(actual_returns - pred_values) / (var_actual + 1e-8) if var_actual > 1e-8 else 0.0\n", + "\n", + "fig, ax = plt.subplots(figsize=(7, 7))\n", + "ax.scatter(actual_returns, pred_values, alpha=0.3, s=10)\n", + "lims = [min(actual_returns.min(), pred_values.min()), max(actual_returns.max(), pred_values.max())]\n", + "ax.plot(lims, lims, \"r--\", label=\"perfect\")\n", + "ax.set_xlabel(\"Actual return\")\n", + "ax.set_ylabel(\"Predicted value\")\n", + "ax.set_title(f\"Value accuracy (explained var: {explained_var:.4f})\")\n", + "ax.legend()\n", + "ax.grid(True, alpha=0.3)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(f\"Explained variance: {explained_var:.4f}\")\n", + "print(f\"Value MSE: {np.mean((actual_returns - pred_values) ** 2):.6f}\")\n", + "if explained_var < 0:\n", + " print(\"WARNING: negative explained variance, value head worse than predicting mean\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/05_inference.ipynb b/notebooks/05_inference.ipynb new file mode 100644 index 0000000000..640835d0fe --- /dev/null +++ b/notebooks/05_inference.ipynb @@ -0,0 +1,1682 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "cell-0", + "metadata": {}, + "source": [ + "# 05 - Model Inference Debug\n", + "End-to-end inference pipeline: config loading, policy forward pass, rollouts (deterministic vs stochastic), observation/reward analysis, value accuracy, trajectories, LSTM state." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cell-1", + "metadata": {}, + "outputs": [], + "source": [ + "import os, ast, glob, yaml, configparser\n", + "from collections import defaultdict\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import torch\n", + "import torch.nn.functional as F\n", + "\n", + "while not os.path.exists(\"pufferlib\") and os.getcwd() != \"/\":\n", + " os.chdir(\"..\")\n", + "print(\"CWD:\", os.getcwd())\n", + "\n", + "# --- Config ---\n", + "CHECKPOINT_PATH = \"\"\n", + "ENV_NAME = \"puffer_drive\"\n", + "\n", + "# --- Observation dimensions (configurable) ---\n", + "MAX_PARTNERS = 16\n", + "MAX_LANES = 32\n", + "MAX_BOUNDS = 32\n", + "MAX_TRAFFIC = 10\n", + "MAX_STOP_SIGNS = 0\n", + "\n", + "\n", + "def load_notebook_config(checkpoint_path=None, env_name=\"puffer_drive\"):\n", + " \"\"\"Load config from INI defaults, optionally overlaying checkpoint's config.yaml.\"\"\"\n", + " default_ini = \"pufferlib/config/default.ini\"\n", + " env_ini = None\n", + " for path in glob.glob(\"pufferlib/config/**/*.ini\", recursive=True):\n", + " p = configparser.ConfigParser()\n", + " p.read([default_ini, path])\n", + " if p.has_option(\"base\", \"env_name\") and env_name in p[\"base\"][\"env_name\"]:\n", + " env_ini = path\n", + " break\n", + " assert env_ini, f\"No config for {env_name}\"\n", + "\n", + " def parse_val(v):\n", + " try:\n", + " return ast.literal_eval(v)\n", + " except:\n", + " return v\n", + "\n", + " args = defaultdict(dict)\n", + " for section in p.sections():\n", + " for key in p[section]:\n", + " val = parse_val(p[section][key])\n", + " if section == \"base\":\n", + " args[key] = val\n", + " else:\n", + " args[section][key] = val\n", + "\n", + " # Overlay checkpoint config.yaml if exists\n", + " if checkpoint_path:\n", + " exp_dir = os.path.dirname(os.path.dirname(checkpoint_path))\n", + " cfg_yaml = os.path.join(exp_dir, \"config.yaml\")\n", + " if os.path.exists(cfg_yaml):\n", + " print(f\"Loading config.yaml from {cfg_yaml}\")\n", + " with open(cfg_yaml) as f:\n", + " ycfg = yaml.safe_load(f)\n", + " for section in [\"env\", \"train\", \"policy\", \"rnn\"]:\n", + " if section in ycfg and isinstance(ycfg[section], dict):\n", + " for k, v in ycfg[section].items():\n", + " args[section][k] = v\n", + "\n", + " args[\"train\"][\"use_rnn\"] = args.get(\"rnn_name\") is not None\n", + " return dict(args)\n", + "\n", + "\n", + "config = load_notebook_config(CHECKPOINT_PATH, ENV_NAME)\n", + "\n", + "# --- Env ---\n", + "from pufferlib.ocean.drive.drive import Drive\n", + "from pufferlib.ocean.drive import binding\n", + "\n", + "# Override for notebook: fewer agents, single env\n", + "config[\"env\"][\"num_agents\"] = 64\n", + "config[\"env\"][\"num_maps\"] = 1\n", + "config[\"env\"][\"eval_mode\"] = 1\n", + "config[\"env\"][\"map_dir\"] = \"pufferlib/resources/drive/binaries/carla\"\n", + "config[\"env\"][\"max_lane_segment_observations\"] = MAX_LANES\n", + "config[\"env\"][\"max_boundary_segment_observations\"] = MAX_BOUNDS\n", + "config[\"env\"][\"max_partner_observations\"] = MAX_PARTNERS\n", + "config[\"env\"][\"max_traffic_light_observations\"] = MAX_TRAFFIC\n", + "config[\"env\"][\"max_stop_sign_observations\"] = MAX_STOP_SIGNS\n", + "config[\"eval\"][\"map_dir\"] = \"pufferlib/resources/drive/binaries/carla\"\n", + "\n", + "env = Drive(**config[\"env\"])\n", + "obs, info = env.reset(seed=42)\n", + "N = env.num_agents\n", + "\n", + "# --- Derived from binding ---\n", + "EGO_DIM = binding.EGO_FEATURES_JERK\n", + "NUM_COEFS = binding.NUM_REWARD_COEFS\n", + "PARTNER_F = binding.PARTNER_FEATURES\n", + "ROAD_F = binding.ROAD_FEATURES\n", + "TRAFFIC_F = binding.TRAFFIC_LIGHT_FEATURES\n", + "STOP_SIGN_F = binding.STOP_SIGN_FEATURES\n", + "\n", + "# --- Policy ---\n", + "from pufferlib.ocean.torch import Drive as DrivePolicy, Recurrent\n", + "import pufferlib.pytorch\n", + "\n", + "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", + "policy = DrivePolicy(env, **config[\"policy\"]).to(device)\n", + "use_rnn = config[\"train\"].get(\"use_rnn\", False)\n", + "if use_rnn:\n", + " policy = Recurrent(env, policy, **config[\"rnn\"]).to(device)\n", + "\n", + "# Load checkpoint weights if provided\n", + "if CHECKPOINT_PATH:\n", + " sd = torch.load(CHECKPOINT_PATH, map_location=device)\n", + " sd = {k.replace(\"module.\", \"\"): v for k, v in sd.items()}\n", + " policy.load_state_dict(sd)\n", + " print(f\"Loaded checkpoint: {CHECKPOINT_PATH}\")\n", + "\n", + "# LSTM state\n", + "hidden_size = policy.hidden_size\n", + "state = {}\n", + "if use_rnn:\n", + " state = {\n", + " \"lstm_h\": torch.zeros(N, hidden_size, device=device),\n", + " \"lstm_c\": torch.zeros(N, hidden_size, device=device),\n", + " }\n", + "\n", + "# Action shape\n", + "inner_policy = policy.policy if use_rnn else policy\n", + "is_continuous = inner_policy.is_continuous\n", + "ACT_SHAPE = (N, len(env.single_action_space.nvec)) if not is_continuous else (N, env.single_action_space.shape[0])\n", + "\n", + "print(f\"Policy on {device}, params: {sum(p.numel() for p in policy.parameters()):,}\")\n", + "print(f\"Obs shape: {obs.shape}, Action space: {env.single_action_space}\")\n", + "print(f\"Config: dynamics={config['env']['dynamics_model']}, action={config['env']['action_type']}\")\n", + "print(f\"Use RNN: {use_rnn}, hidden_size: {hidden_size}\")" + ] + }, + { + "cell_type": "markdown", + "id": "cell-2", + "metadata": {}, + "source": [ + "## Single-step policy output" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cell-3", + "metadata": {}, + "outputs": [], + "source": [ + "# Take one step to get fresh obs\n", + "actions = np.zeros(ACT_SHAPE, dtype=np.int64 if not is_continuous else np.float32)\n", + "obs, rew, term, trunc, info = env.step(actions)\n", + "\n", + "obs_tensor = torch.FloatTensor(obs).to(device)\n", + "policy.eval()\n", + "\n", + "with torch.no_grad():\n", + " if use_rnn:\n", + " logits_list, value = policy.forward_eval(obs_tensor, state)\n", + " else:\n", + " logits_list, value = policy(obs_tensor)\n", + "\n", + "# Sample actions\n", + "action, logprob, ent = pufferlib.pytorch.sample_logits(logits_list)\n", + "action_det, _, _ = pufferlib.pytorch.sample_logits(logits_list, deterministic=True)\n", + "\n", + "print(f\"Value: mean={value.mean():.4f}, std={value.std():.4f}, range=[{value.min():.4f}, {value.max():.4f}]\")\n", + "print(f\"Entropy: mean={ent.mean():.4f}, std={ent.std():.4f}\")\n", + "print(f\"LogProb: mean={logprob.mean():.4f}, std={logprob.std():.4f}\")\n", + "print(f\"Stochastic action sample: {action[0].cpu().numpy()}\")\n", + "print(f\"Deterministic action: {action_det[0].cpu().numpy()}\")\n", + "\n", + "# Plot\n", + "fig, axes = plt.subplots(1, 2, figsize=(14, 4))\n", + "\n", + "# Action probs (first head for multi-discrete, or full logits)\n", + "if isinstance(logits_list, list) or isinstance(logits_list, tuple):\n", + " probs = F.softmax(logits_list[0], dim=-1)\n", + "else:\n", + " probs = F.softmax(logits_list, dim=-1)\n", + "mean_probs = probs.mean(dim=0).cpu().numpy()\n", + "axes[0].bar(range(len(mean_probs)), mean_probs, edgecolor=\"black\", alpha=0.7)\n", + "axes[0].axhline(1.0 / len(mean_probs), color=\"red\", ls=\"--\", label=\"uniform\")\n", + "axes[0].set_xlabel(\"Action\")\n", + "axes[0].set_ylabel(\"Probability\")\n", + "axes[0].set_title(\"Mean action probabilities (across agents)\")\n", + "axes[0].legend()\n", + "\n", + "axes[1].hist(value.cpu().numpy().flatten(), bins=30, edgecolor=\"black\", alpha=0.7, color=\"purple\")\n", + "axes[1].set_title(\"Value predictions across agents\")\n", + "axes[1].set_xlabel(\"Value\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "cell-4", + "metadata": {}, + "source": [ + "## Full rollout: deterministic vs stochastic" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cell-5", + "metadata": {}, + "outputs": [], + "source": [ + "HORIZON = 256\n", + "TRACKED_AGENT = 0 # agent index to track in detail\n", + "obs_dim = obs.shape[1]\n", + "\n", + "dyn_model = config[\"env\"][\"dynamics_model\"]\n", + "tgt_type = config[\"env\"][\"target_type\"]\n", + "rew_cond = config[\"env\"].get(\"reward_conditioning\", False)\n", + "n_tgt_wp = config[\"env\"].get(\"num_target_waypoints\", 3)\n", + "\n", + "\n", + "def run_rollout(env, policy, deterministic=False, horizon=HORIZON):\n", + " obs, _ = env.reset(seed=42)\n", + " N = env.num_agents\n", + " st = {}\n", + " if use_rnn:\n", + " st = {\n", + " \"lstm_h\": torch.zeros(N, hidden_size, device=device),\n", + " \"lstm_c\": torch.zeros(N, hidden_size, device=device),\n", + " }\n", + "\n", + " buffers = {\n", + " \"obs\": np.zeros((horizon, N, obs_dim), dtype=np.float32),\n", + " \"actions\": np.zeros((horizon, N), dtype=np.int64),\n", + " \"rewards\": np.zeros((horizon, N), dtype=np.float32),\n", + " \"values\": np.zeros((horizon, N), dtype=np.float32),\n", + " \"logprobs\": np.zeros((horizon, N), dtype=np.float32),\n", + " \"entropy\": np.zeros((horizon, N), dtype=np.float32),\n", + " \"terminals\": np.zeros((horizon, N), dtype=np.float32),\n", + " \"truncations\": np.zeros((horizon, N), dtype=np.float32),\n", + " \"positions_x\": np.zeros((horizon, N), dtype=np.float32),\n", + " \"positions_y\": np.zeros((horizon, N), dtype=np.float32),\n", + " }\n", + " if use_rnn:\n", + " buffers[\"lstm_h_norm\"] = np.zeros((horizon, N), dtype=np.float32)\n", + "\n", + " policy.eval()\n", + " for t in range(horizon):\n", + " obs_t = torch.FloatTensor(obs).to(device)\n", + " with torch.no_grad():\n", + " if use_rnn:\n", + " logits_list, val = policy.forward_eval(obs_t, st)\n", + " else:\n", + " logits_list, val = policy(obs_t)\n", + " act, logp, entr = pufferlib.pytorch.sample_logits(logits_list, deterministic=deterministic)\n", + "\n", + " buffers[\"obs\"][t] = obs\n", + " buffers[\"actions\"][t] = act.cpu().numpy().reshape(N) if act.dim() > 1 else act.cpu().numpy()\n", + " buffers[\"values\"][t] = val.squeeze().cpu().numpy()\n", + " buffers[\"logprobs\"][t] = logp.cpu().numpy()\n", + " buffers[\"entropy\"][t] = entr.cpu().numpy()\n", + "\n", + " if use_rnn:\n", + " buffers[\"lstm_h_norm\"][t] = st[\"lstm_h\"].norm(dim=-1).cpu().numpy()\n", + "\n", + " # Get positions\n", + " gstate = env.get_global_agent_state()\n", + " buffers[\"positions_x\"][t] = gstate[\"x\"]\n", + " buffers[\"positions_y\"][t] = gstate[\"y\"]\n", + "\n", + " # Step env\n", + " env_actions = act.cpu().numpy().reshape(ACT_SHAPE)\n", + " obs, rew, term, trunc, info = env.step(env_actions)\n", + " buffers[\"rewards\"][t] = rew\n", + " buffers[\"terminals\"][t] = term\n", + " buffers[\"truncations\"][t] = trunc\n", + "\n", + " return buffers\n", + "\n", + "\n", + "print(\"Running stochastic rollout...\")\n", + "buf_stoch = run_rollout(env, policy, deterministic=False)\n", + "print(\"Running deterministic rollout...\")\n", + "buf_det = run_rollout(env, policy, deterministic=True)\n", + "\n", + "for name, buf in [(\"Stochastic\", buf_stoch), (\"Deterministic\", buf_det)]:\n", + " print(f\"\\n--- {name} ---\")\n", + " print(f\" Reward: mean={buf['rewards'].mean():.5f}, std={buf['rewards'].std():.5f}\")\n", + " print(f\" Value: mean={buf['values'].mean():.5f}, std={buf['values'].std():.5f}\")\n", + " print(f\" Entropy: mean={buf['entropy'].mean():.4f}\")\n", + " print(f\" Terminals: {buf['terminals'].sum():.0f}, Truncations: {buf['truncations'].sum():.0f}\")" + ] + }, + { + "cell_type": "markdown", + "id": "cell-6", + "metadata": {}, + "source": [ + "## Observation analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cell-7", + "metadata": {}, + "outputs": [], + "source": [ + "from pufferlib.viz import unpack_obs, plot_observation, plot_simulator_state\n", + "\n", + "# Ego-centric observation at t=50 for tracked agent\n", + "sample_t = min(50, HORIZON - 1)\n", + "sample_obs = buf_stoch[\"obs\"][sample_t : sample_t + 1, TRACKED_AGENT : TRACKED_AGENT + 1][0]\n", + "print(dyn_model, tgt_type, rew_cond, n_tgt_wp)\n", + "img = plot_observation(\n", + " sample_obs,\n", + " dynamics_model=dyn_model,\n", + " target_type=tgt_type,\n", + " reward_conditioning=rew_cond,\n", + " num_target_waypoints=n_tgt_wp,\n", + " max_stop_signs=MAX_STOP_SIGNS,\n", + ")\n", + "plt.figure(figsize=(10, 10))\n", + "plt.imshow(img)\n", + "plt.axis(\"off\")\n", + "plt.title(f\"Ego-centric obs | agent={TRACKED_AGENT}, t={sample_t}\")\n", + "plt.show()\n", + "\n", + "# BEV simulator state\n", + "scenarios = env.get_state()\n", + "if scenarios and len(scenarios) > 0:\n", + " img_bev = plot_simulator_state(scenarios[0], timestep=0)\n", + " plt.figure(figsize=(10, 10))\n", + " plt.imshow(img_bev)\n", + " plt.axis(\"off\")\n", + " plt.title(\"BEV Simulator State\")\n", + " plt.show()\n", + "\n", + "# Ego feature time series for tracked agent\n", + "ego_features_over_time = []\n", + "for t in range(HORIZON):\n", + " ego, *_ = unpack_obs(\n", + " buf_stoch[\"obs\"][t : t + 1, TRACKED_AGENT : TRACKED_AGENT + 1][0],\n", + " dynamics_model=dyn_model,\n", + " target_type=tgt_type,\n", + " reward_conditioning=rew_cond,\n", + " num_target_waypoints=n_tgt_wp,\n", + " max_stop_signs=MAX_STOP_SIGNS,\n", + " )\n", + " ego_features_over_time.append(ego)\n", + "ego_ts = np.array(ego_features_over_time)\n", + "\n", + "if dyn_model == \"jerk\":\n", + " labels = [\"speed\", \"width\", \"length\", \"steering\", \"a_long\", \"a_lat\", \"lcenter\", \"lalign\", \"speed_limit\"]\n", + " plot_idxs = [0, 3, 4, 5] # speed, steering, a_long, a_lat\n", + "else:\n", + " labels = [\"speed\", \"width\", \"length\", \"lcenter\", \"lalign\", \"speed_limit\"]\n", + " plot_idxs = [0, 3, 4, 5] # speed, lcenter, lalign, speed_limit\n", + "\n", + "fig, axes = plt.subplots(len(plot_idxs), 1, figsize=(14, 3 * len(plot_idxs)), sharex=True)\n", + "for i, idx in enumerate(plot_idxs):\n", + " axes[i].plot(ego_ts[:, idx])\n", + " print(ego_ts[10:, idx].argmin())\n", + " axes[i].set_ylabel(labels[idx])\n", + " axes[i].grid(True, alpha=0.3)\n", + "axes[-1].set_xlabel(\"Step\")\n", + "fig.suptitle(f\"Ego features over time | agent={TRACKED_AGENT}\", fontsize=14)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "czs3aiuhgyo", + "metadata": {}, + "source": [ + "## Observation layer breakdown\n", + "\n", + "Obs layout (all ego-centric, normalized):\n", + "- **Ego**: speed, width, length, [jerk: steering, a_long, a_lat], lane_center_dist, lane_angle, speed_limit\n", + "- **Conditioning** (if enabled): 16 reward coefs (goal_radius, collision, offroad, comfort, lane_align, lane_center, velocity, traffic_light, center_bias, vel_align, overspeed, timestep, reverse, throttle, steer, acc) + target waypoints\n", + "- **Target**: static=rel_x,rel_y per waypoint; dynamic=rel_x,rel_y,heading_cos,heading_sin per waypoint\n", + "- **Partners** (MAX_PARTNERS x 7): rel_x, rel_y, width, length, heading_cos, heading_sin, speed\n", + "- **Lanes** (MAX_LANES x 6): rel_x, rel_y, seg_length, seg_width, dir_cos, dir_sin\n", + "- **Boundaries** (MAX_BOUNDS x 6): same as lanes\n", + "- **Traffic** (MAX_TRAFFIC x 3): rel_x, rel_y, state_normalized" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ytjdjnb471l", + "metadata": {}, + "outputs": [], + "source": [ + "from pufferlib.viz import unpack_obs\n", + "\n", + "sample_t = min(50, HORIZON - 1)\n", + "sample_obs = buf_stoch[\"obs\"][sample_t : sample_t + 1, TRACKED_AGENT : TRACKED_AGENT + 1][0]\n", + "ego, target, partners, lanes, boundaries, traffic, stop_sign = unpack_obs(\n", + " sample_obs,\n", + " dynamics_model=dyn_model,\n", + " target_type=tgt_type,\n", + " reward_conditioning=rew_cond,\n", + " num_target_waypoints=n_tgt_wp,\n", + " max_stop_signs=MAX_STOP_SIGNS,\n", + ")\n", + "\n", + "# Also unpack conditioning manually (unpack_obs doesn't return it separately)\n", + "ego_dim = binding.EGO_FEATURES_JERK if dyn_model == \"jerk\" else binding.EGO_FEATURES_CLASSIC\n", + "cond_dim = binding.NUM_REWARD_COEFS if rew_cond else 0\n", + "cond_obs = sample_obs[0, ego_dim : ego_dim + cond_dim] if cond_dim > 0 else None\n", + "\n", + "\n", + "# --- Print all layer shapes + stats ---\n", + "def layer_stats(name, arr):\n", + " flat = arr.flatten() if hasattr(arr, \"flatten\") else np.array(arr).flatten()\n", + " if flat.size == 0:\n", + " print(f\"{name:>14s}: shape={str(list(arr.shape)):>16s} (empty)\")\n", + " return\n", + " nonzero = np.count_nonzero(flat)\n", + " print(\n", + " f\"{name:>14s}: shape={str(list(arr.shape)):>16s} \"\n", + " f\"nonzero={nonzero:>5d}/{flat.size:<5d} \"\n", + " f\"range=[{flat.min():.4f}, {flat.max():.4f}] \"\n", + " f\"mean={flat.mean():.4f} std={flat.std():.4f}\"\n", + " )\n", + "\n", + "\n", + "print(f\"--- Observation breakdown at t={sample_t}, agent={TRACKED_AGENT} ---\")\n", + "print(f\"Total obs dim: {sample_obs.shape[-1]}\")\n", + "print()\n", + "layer_stats(\"Ego\", ego)\n", + "if cond_obs is not None:\n", + " layer_stats(\"Conditioning\", cond_obs)\n", + "layer_stats(\"Target\", target)\n", + "layer_stats(\"Partners\", partners)\n", + "layer_stats(\"Lanes\", lanes)\n", + "layer_stats(\"Boundaries\", boundaries)\n", + "layer_stats(\"Traffic\", traffic)\n", + "layer_stats(\"StopSign\", stop_sign)\n", + "\n", + "# --- Ego features detail ---\n", + "if dyn_model == \"jerk\":\n", + " ego_labels = [\"speed\", \"width\", \"length\", \"steering\", \"a_long\", \"a_lat\", \"lane_center\", \"lane_align\", \"speed_limit\"]\n", + "else:\n", + " ego_labels = [\"speed\", \"width\", \"length\", \"lane_center\", \"lane_align\", \"speed_limit\"]\n", + "\n", + "print(f\"\\n--- Ego features ---\")\n", + "for i, (label, val) in enumerate(zip(ego_labels, ego)):\n", + " print(f\" [{i}] {label:>14s} = {val:.4f}\")\n", + "\n", + "# --- Conditioning detail ---\n", + "if cond_obs is not None:\n", + " cond_labels = [\n", + " \"goal_radius\",\n", + " \"collision\",\n", + " \"offroad\",\n", + " \"comfort\",\n", + " \"lane_align\",\n", + " \"lane_center\",\n", + " \"velocity\",\n", + " \"traffic_light\",\n", + " \"center_bias\",\n", + " \"vel_align\",\n", + " \"overspeed\",\n", + " \"timestep\",\n", + " \"reverse\",\n", + " \"throttle\",\n", + " \"steer\",\n", + " \"acc\",\n", + " ]\n", + " print(f\"\\n--- Conditioning (reward coefs, normalized) ---\")\n", + " for i, (label, val) in enumerate(zip(cond_labels, cond_obs)):\n", + " print(f\" [{i:>2d}] {label:>16s} = {val:.4f}\")\n", + "\n", + "# --- Target waypoints ---\n", + "tgt_feat = binding.STATIC_TARGET_FEATURES if tgt_type == \"static\" else binding.DYNAMIC_TARGET_FEATURES\n", + "if tgt_type == \"static\":\n", + " tgt_labels = [\"rel_x\", \"rel_y\"]\n", + "else:\n", + " tgt_labels = [\"rel_x\", \"rel_y\", \"heading_cos\", \"heading_sin\"]\n", + "\n", + "print(f\"\\n--- Target waypoints (n={n_tgt_wp}, type={tgt_type}) ---\")\n", + "for wp in range(target.shape[0]):\n", + " vals = \", \".join(f\"{tgt_labels[j]}={target[wp, j]:.4f}\" for j in range(tgt_feat))\n", + " active = \"ACTIVE\" if not np.allclose(target[wp], 0) else \"zeroed\"\n", + " print(f\" wp[{wp}]: {vals} ({active})\")\n", + "\n", + "# --- Partner summary ---\n", + "n_visible = np.sum(np.any(partners != 0, axis=1))\n", + "print(f\"\\n--- Partners: {n_visible}/{partners.shape[0]} visible ---\")\n", + "partner_labels = [\"rel_x\", \"rel_y\", \"width\", \"length\", \"heading_cos\", \"heading_sin\", \"speed\"]\n", + "for p in range(min(int(n_visible), 5)):\n", + " vals = \", \".join(f\"{partner_labels[j]}={partners[p, j]:.3f}\" for j in range(7))\n", + " print(f\" [{p}] {vals}\")\n", + "if n_visible > 5:\n", + " print(f\" ... ({n_visible - 5} more)\")\n", + "\n", + "# --- Lane/boundary occupancy ---\n", + "n_lanes = np.sum(np.any(lanes != 0, axis=1))\n", + "n_bounds = np.sum(np.any(boundaries != 0, axis=1))\n", + "print(f\"\\n--- Road: {n_lanes}/{lanes.shape[0]} lane segs, {n_bounds}/{boundaries.shape[0]} boundary segs ---\")\n", + "\n", + "# --- Traffic ---\n", + "n_traffic = np.sum(np.any(traffic != 0, axis=1))\n", + "print(f\"\\n--- Traffic lights: {n_traffic}/{traffic.shape[0]} visible ---\")\n", + "traffic_labels = [\"rel_x\", \"rel_y\", \"state_normalized\"]\n", + "for t in range(min(int(n_traffic), 5)):\n", + " vals = \", \".join(\n", + " f\"{traffic_labels[j]}={traffic[t, j]:.3f}\" for j in range(min(len(traffic_labels), traffic.shape[1]))\n", + " )\n", + " print(f\" [{t}] {vals}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "65bg95pn7dp", + "metadata": {}, + "outputs": [], + "source": [ + "# --- Layer-level stats across ALL agents at sample_t ---\n", + "all_obs = buf_stoch[\"obs\"][sample_t] # (N, obs_dim)\n", + "\n", + "ego_dim = binding.EGO_FEATURES_JERK if dyn_model == \"jerk\" else binding.EGO_FEATURES_CLASSIC\n", + "cond_dim = binding.NUM_REWARD_COEFS if rew_cond else 0\n", + "tgt_feat = binding.STATIC_TARGET_FEATURES if tgt_type == \"static\" else binding.DYNAMIC_TARGET_FEATURES\n", + "tgt_dim = n_tgt_wp * tgt_feat\n", + "partner_dim = MAX_PARTNERS * PARTNER_F\n", + "lane_dim = MAX_LANES * ROAD_F\n", + "boundary_dim = MAX_BOUNDS * ROAD_F\n", + "traffic_dim = MAX_TRAFFIC * TRAFFIC_F\n", + "\n", + "# Slice indices\n", + "idx = 0\n", + "slices = {}\n", + "slices[\"ego\"] = (idx, idx + ego_dim)\n", + "idx += ego_dim\n", + "if cond_dim > 0:\n", + " slices[\"conditioning\"] = (idx, idx + cond_dim)\n", + " idx += cond_dim\n", + "slices[\"target\"] = (idx, idx + tgt_dim)\n", + "idx += tgt_dim\n", + "slices[\"partners\"] = (idx, idx + partner_dim)\n", + "idx += partner_dim\n", + "slices[\"lanes\"] = (idx, idx + lane_dim)\n", + "idx += lane_dim\n", + "slices[\"boundaries\"] = (idx, idx + boundary_dim)\n", + "idx += boundary_dim\n", + "slices[\"traffic\"] = (idx, idx + traffic_dim)\n", + "idx += traffic_dim\n", + "\n", + "print(f\"Obs dim used: {idx} / {all_obs.shape[1]}\")\n", + "print(\n", + " f\"\\n{'Layer':>14s} | {'start':>5s}-{'end':>5s} | {'dim':>5s} | {'mean':>8s} | {'std':>8s} | {'min':>8s} | {'max':>8s} | {'%nonzero':>8s}\"\n", + ")\n", + "print(\"-\" * 95)\n", + "for name, (s, e) in slices.items():\n", + " chunk = all_obs[:, s:e]\n", + " nz_pct = 100 * np.count_nonzero(chunk) / chunk.size\n", + " print(\n", + " f\"{name:>14s} | {s:>5d}-{e:>5d} | {e - s:>5d} | {chunk.mean():>8.4f} | {chunk.std():>8.4f} | \"\n", + " f\"{chunk.min():>8.4f} | {chunk.max():>8.4f} | {nz_pct:>7.1f}%\"\n", + " )\n", + "\n", + "# --- Plots ---\n", + "n_layers = len(slices)\n", + "fig, axes = plt.subplots(2, (n_layers + 1) // 2, figsize=(5 * ((n_layers + 1) // 2), 8))\n", + "axes = axes.flatten()\n", + "\n", + "for i, (name, (s, e)) in enumerate(slices.items()):\n", + " chunk = all_obs[:, s:e].flatten()\n", + " # Filter out exact zeros for histogram readability on sparse layers\n", + " nonzero_vals = chunk[chunk != 0]\n", + " if len(nonzero_vals) > 0:\n", + " axes[i].hist(nonzero_vals, bins=50, edgecolor=\"black\", alpha=0.7)\n", + " axes[i].set_title(f\"{name} (nonzero only, {len(nonzero_vals)}/{len(chunk)})\")\n", + " else:\n", + " axes[i].hist(chunk, bins=50, edgecolor=\"black\", alpha=0.7)\n", + " axes[i].set_title(f\"{name} (all zeros)\")\n", + " axes[i].set_xlabel(\"Value\")\n", + "\n", + "# Hide unused axes\n", + "for j in range(i + 1, len(axes)):\n", + " axes[j].set_visible(False)\n", + "\n", + "fig.suptitle(f\"Observation distributions across {N} agents at t={sample_t}\", fontsize=14)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dfm7par7pmo", + "metadata": {}, + "outputs": [], + "source": [ + "# --- Per-feature detail for partners, lanes, boundaries over time (tracked agent) ---\n", + "\n", + "\n", + "def unpack_all_timesteps(bufs, agent_idx):\n", + " \"\"\"Unpack all obs layers across time for one agent.\"\"\"\n", + " H = bufs[\"obs\"].shape[0]\n", + " egos, targets, conds = [], [], []\n", + " n_partners, n_lanes, n_bounds, n_traffic, n_stop_signs = [], [], [], [], []\n", + "\n", + " for t in range(H):\n", + " ob = bufs[\"obs\"][t : t + 1, agent_idx : agent_idx + 1][0]\n", + " ego, tgt, part, lane, bnd, tfc, stop_sign = unpack_obs(\n", + " ob,\n", + " dynamics_model=dyn_model,\n", + " target_type=tgt_type,\n", + " reward_conditioning=rew_cond,\n", + " num_target_waypoints=n_tgt_wp,\n", + " max_stop_signs=MAX_STOP_SIGNS,\n", + " )\n", + " egos.append(ego)\n", + " targets.append(tgt)\n", + " n_partners.append(np.sum(np.any(part != 0, axis=1)))\n", + " n_lanes.append(np.sum(np.any(lane != 0, axis=1)))\n", + " n_bounds.append(np.sum(np.any(bnd != 0, axis=1)))\n", + " n_traffic.append(np.sum(np.any(tfc != 0, axis=1)))\n", + " n_stop_signs.append(np.sum(np.any(stop_sign != 0, axis=1)))\n", + "\n", + " if rew_cond:\n", + " ed = binding.EGO_FEATURES_JERK if dyn_model == \"jerk\" else binding.EGO_FEATURES_CLASSIC\n", + " conds.append(ob[0, ed : ed + binding.NUM_REWARD_COEFS])\n", + "\n", + " return {\n", + " \"ego\": np.array(egos),\n", + " \"target\": np.array(targets),\n", + " \"cond\": np.array(conds) if conds else None,\n", + " \"n_partners\": np.array(n_partners),\n", + " \"n_lanes\": np.array(n_lanes),\n", + " \"n_bounds\": np.array(n_bounds),\n", + " \"n_traffic\": np.array(n_traffic),\n", + " \"n_stop_signs\": np.array(n_stop_signs),\n", + " }\n", + "\n", + "\n", + "ts = unpack_all_timesteps(buf_stoch, TRACKED_AGENT)\n", + "\n", + "fig, axes = plt.subplots(2, 2, figsize=(16, 10))\n", + "\n", + "# Occupancy over time\n", + "axes[0, 0].plot(ts[\"n_partners\"], label=\"partners\", alpha=0.8)\n", + "axes[0, 0].plot(ts[\"n_lanes\"], label=\"lanes\", alpha=0.8)\n", + "axes[0, 0].plot(ts[\"n_bounds\"], label=\"boundaries\", alpha=0.8)\n", + "axes[0, 0].plot(ts[\"n_traffic\"], label=\"traffic\", alpha=0.8)\n", + "axes[0, 0].plot(ts[\"n_stop_signs\"], label=\"stop_signs\", alpha=0.8)\n", + "axes[0, 0].set_xlabel(\"Step\")\n", + "axes[0, 0].set_ylabel(\"Visible count\")\n", + "axes[0, 0].set_title(f\"Obs occupancy over time | agent={TRACKED_AGENT}\")\n", + "axes[0, 0].legend()\n", + "axes[0, 0].grid(True, alpha=0.3)\n", + "\n", + "# Target waypoint distances over time\n", + "tgt_x = ts[\"target\"][:, :, 0]\n", + "tgt_y = ts[\"target\"][:, :, 1]\n", + "tgt_dist = np.sqrt(tgt_x**2 + tgt_y**2)\n", + "for wp in range(n_tgt_wp):\n", + " axes[0, 1].plot(tgt_dist[:, wp], label=f\"wp[{wp}]\", alpha=0.8)\n", + "axes[0, 1].set_xlabel(\"Step\")\n", + "axes[0, 1].set_ylabel(\"Distance (normalized)\")\n", + "axes[0, 1].set_title(\"Target waypoint distance over time\")\n", + "axes[0, 1].legend()\n", + "axes[0, 1].grid(True, alpha=0.3)\n", + "\n", + "# Conditioning heatmap over time\n", + "if ts[\"cond\"] is not None:\n", + " cond_labels = [\n", + " \"goal_rad\",\n", + " \"coll\",\n", + " \"offrd\",\n", + " \"comf\",\n", + " \"l_align\",\n", + " \"l_ctr\",\n", + " \"vel\",\n", + " \"traf\",\n", + " \"c_bias\",\n", + " \"v_align\",\n", + " \"ovspd\",\n", + " \"tstep\",\n", + " \"rev\",\n", + " \"throt\",\n", + " \"steer\",\n", + " \"acc\",\n", + " ]\n", + " im = axes[1, 0].imshow(ts[\"cond\"].T, aspect=\"auto\", cmap=\"coolwarm\", interpolation=\"nearest\")\n", + " axes[1, 0].set_yticks(range(len(cond_labels)))\n", + " axes[1, 0].set_yticklabels(cond_labels, fontsize=8)\n", + " axes[1, 0].set_xlabel(\"Step\")\n", + " axes[1, 0].set_title(\"Conditioning coefs over time\")\n", + " plt.colorbar(im, ax=axes[1, 0])\n", + "else:\n", + " axes[1, 0].text(0.5, 0.5, \"No conditioning\", ha=\"center\", va=\"center\", transform=axes[1, 0].transAxes)\n", + " axes[1, 0].set_title(\"Conditioning (disabled)\")\n", + "\n", + "# Partner closest distance over time\n", + "partner_dists = []\n", + "for t in range(HORIZON):\n", + " ob = buf_stoch[\"obs\"][t : t + 1, TRACKED_AGENT : TRACKED_AGENT + 1][0]\n", + " _, _, part, _, _, _, _ = unpack_obs(\n", + " ob,\n", + " dynamics_model=dyn_model,\n", + " target_type=tgt_type,\n", + " reward_conditioning=rew_cond,\n", + " num_target_waypoints=n_tgt_wp,\n", + " max_stop_signs=MAX_STOP_SIGNS,\n", + " )\n", + " dists = np.sqrt(part[:, 0] ** 2 + part[:, 1] ** 2)\n", + " visible = np.any(part != 0, axis=1)\n", + " partner_dists.append(dists[visible].min() if visible.any() else np.nan)\n", + "\n", + "axes[1, 1].plot(partner_dists, alpha=0.8, color=\"red\")\n", + "axes[1, 1].set_xlabel(\"Step\")\n", + "axes[1, 1].set_ylabel(\"Min partner dist (normalized)\")\n", + "axes[1, 1].set_title(\"Closest partner distance over time\")\n", + "axes[1, 1].grid(True, alpha=0.3)\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "j1h4h99tnve", + "metadata": {}, + "outputs": [], + "source": [ + "# --- Spatial scatter: all observed entities in ego frame at sample_t ---\n", + "sample_obs = buf_stoch[\"obs\"][sample_t : sample_t + 1, TRACKED_AGENT : TRACKED_AGENT + 1][0]\n", + "ego, target, partners, lanes, boundaries, traffic, stop_sign = unpack_obs(\n", + " sample_obs,\n", + " dynamics_model=dyn_model,\n", + " target_type=tgt_type,\n", + " reward_conditioning=rew_cond,\n", + " num_target_waypoints=n_tgt_wp,\n", + " max_stop_signs=MAX_STOP_SIGNS,\n", + ")\n", + "\n", + "fig, ax = plt.subplots(figsize=(10, 10))\n", + "\n", + "# Ego vehicle at origin\n", + "from matplotlib.patches import Rectangle\n", + "\n", + "ax.add_patch(\n", + " Rectangle((-ego[2] / 2, -ego[1] / 2), ego[2], ego[1], facecolor=\"blue\", edgecolor=\"black\", alpha=0.7, zorder=10)\n", + ")\n", + "ax.annotate(\"EGO\", (0, 0), fontsize=9, ha=\"center\", va=\"center\", color=\"white\", fontweight=\"bold\", zorder=11)\n", + "\n", + "# Lane segments\n", + "for i in range(lanes.shape[0]):\n", + " if np.allclose(lanes[i], 0):\n", + " continue\n", + " rx, ry, length, _, dc, ds = lanes[i]\n", + " ax.plot(\n", + " [rx - dc * length / 2, rx + dc * length / 2],\n", + " [ry - ds * length / 2, ry + ds * length / 2],\n", + " color=\"lightgray\",\n", + " linewidth=1,\n", + " zorder=1,\n", + " )\n", + "ax.scatter(\n", + " lanes[np.any(lanes != 0, axis=1), 0],\n", + " lanes[np.any(lanes != 0, axis=1), 1],\n", + " s=5,\n", + " color=\"gray\",\n", + " alpha=0.5,\n", + " label=f\"lanes ({n_lanes})\",\n", + " zorder=2,\n", + ")\n", + "\n", + "# Boundary segments\n", + "for i in range(boundaries.shape[0]):\n", + " if np.allclose(boundaries[i], 0):\n", + " continue\n", + " rx, ry, length, _, dc, ds = boundaries[i]\n", + " ax.plot(\n", + " [rx - dc * length / 2, rx + dc * length / 2],\n", + " [ry - ds * length / 2, ry + ds * length / 2],\n", + " color=\"black\",\n", + " linewidth=1,\n", + " zorder=1,\n", + " )\n", + "bnd_mask = np.any(boundaries != 0, axis=1)\n", + "if bnd_mask.any():\n", + " ax.scatter(\n", + " boundaries[bnd_mask, 0],\n", + " boundaries[bnd_mask, 1],\n", + " s=8,\n", + " color=\"black\",\n", + " alpha=0.6,\n", + " label=f\"boundaries ({n_bounds})\",\n", + " zorder=2,\n", + " )\n", + "\n", + "# Partners\n", + "for i in range(partners.shape[0]):\n", + " if np.allclose(partners[i], 0):\n", + " continue\n", + " rx, ry, w, l, hc, hs, spd = partners[i]\n", + " heading = np.arctan2(hs, hc)\n", + " rect = Rectangle((-l / 2, -w / 2), l, w, facecolor=\"orange\", edgecolor=\"black\", alpha=0.6, zorder=9)\n", + " rect.set_transform(plt.matplotlib.transforms.Affine2D().rotate(heading).translate(rx, ry) + ax.transData)\n", + " ax.add_patch(rect)\n", + " ax.annotate(f\"{spd:.2f}\", (rx, ry), fontsize=7, ha=\"center\", color=\"darkred\", zorder=12)\n", + "part_mask = np.any(partners != 0, axis=1)\n", + "if part_mask.any():\n", + " ax.scatter(\n", + " partners[part_mask, 0],\n", + " partners[part_mask, 1],\n", + " s=40,\n", + " color=\"orange\",\n", + " edgecolors=\"black\",\n", + " label=f\"partners ({n_visible})\",\n", + " zorder=8,\n", + " )\n", + "\n", + "# Target waypoints\n", + "for wp in range(target.shape[0]):\n", + " if np.allclose(target[wp], 0):\n", + " continue\n", + " marker = \"*\" if wp == 0 else \"o\"\n", + " s = 200 if wp == 0 else 80\n", + " color = \"red\" if wp == 0 else \"salmon\"\n", + " ax.scatter(\n", + " target[wp, 0],\n", + " target[wp, 1],\n", + " color=color,\n", + " marker=marker,\n", + " s=s,\n", + " zorder=15,\n", + " label=f\"target wp[{wp}]\" if wp < 3 else None,\n", + " )\n", + "\n", + "# Traffic lights\n", + "for i in range(traffic.shape[0]):\n", + " if np.allclose(traffic[i], 0):\n", + " continue\n", + " state_colors = {0: \"red\", 1: \"yellow\", 2: \"green\"}\n", + " c = state_colors.get(int(round(traffic[i, 2] * 2)), \"gray\")\n", + " ax.scatter(\n", + " traffic[i, 0], traffic[i, 1], color=c, s=100, marker=\"s\", edgecolors=\"black\", zorder=15, label=f\"traffic ({c})\"\n", + " )\n", + "\n", + "ax.set_xlim(-1, 1)\n", + "ax.set_ylim(-1, 1)\n", + "ax.set_aspect(\"equal\")\n", + "ax.set_xlabel(\"X (ego frame, normalized)\")\n", + "ax.set_ylabel(\"Y (ego frame, normalized)\")\n", + "ax.set_title(f\"All observed entities | agent={TRACKED_AGENT}, t={sample_t}\")\n", + "ax.legend(loc=\"upper right\", fontsize=8)\n", + "ax.grid(True, alpha=0.3)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "gsyrbg02vc", + "metadata": {}, + "source": [ + "### Ego + conditioning distributions across all agents" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "wwisx2muaj", + "metadata": {}, + "outputs": [], + "source": [ + "# Ego feature distributions across all agents, pooled over full rollout\n", + "ego_dim = binding.EGO_FEATURES_JERK if dyn_model == \"jerk\" else binding.EGO_FEATURES_CLASSIC\n", + "all_ego = buf_stoch[\"obs\"][:, :, :ego_dim].reshape(-1, ego_dim) # (H*N, ego_dim)\n", + "\n", + "if dyn_model == \"jerk\":\n", + " ego_labels = [\"speed\", \"width\", \"length\", \"steering\", \"a_long\", \"a_lat\", \"lane_center\", \"lane_align\", \"speed_limit\"]\n", + "else:\n", + " ego_labels = [\"speed\", \"width\", \"length\", \"lane_center\", \"lane_align\", \"speed_limit\"]\n", + "\n", + "fig, axes = plt.subplots(2, len(ego_labels), figsize=(3.5 * len(ego_labels), 7))\n", + "\n", + "# Row 0: histograms\n", + "for i, label in enumerate(ego_labels):\n", + " vals = all_ego[:, i]\n", + " print(f\"{label}: mean={vals}\")\n", + " axes[0, i].hist(vals, bins=60, edgecolor=\"black\", alpha=0.7, color=\"steelblue\")\n", + " axes[0, i].set_title(label, fontsize=10)\n", + " axes[0, i].set_xlabel(\"\")\n", + " axes[0, i].tick_params(labelsize=7)\n", + " axes[0, i].axvline(vals.mean(), color=\"red\", ls=\"--\", lw=1)\n", + "\n", + "# Row 1: boxplots per-agent (distribution across timesteps for each agent)\n", + "ego_per_agent = buf_stoch[\"obs\"][:, :, :ego_dim] # (H, N, ego_dim)\n", + "for i, label in enumerate(ego_labels):\n", + " data = [ego_per_agent[:, a, i] for a in range(N)]\n", + " bp = axes[1, i].boxplot(\n", + " data,\n", + " showfliers=False,\n", + " patch_artist=True,\n", + " boxprops=dict(facecolor=\"steelblue\", alpha=0.5),\n", + " medianprops=dict(color=\"red\"),\n", + " )\n", + " axes[1, i].set_xlabel(\"Agent\")\n", + " axes[1, i].tick_params(labelsize=7)\n", + " axes[1, i].set_title(f\"{label} per agent\", fontsize=9)\n", + "\n", + "fig.suptitle(\"Ego features: full rollout distributions\", fontsize=13)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "# Conditioning distributions across all agents (if enabled)\n", + "if rew_cond:\n", + " cond_start = ego_dim\n", + " cond_end = cond_start + binding.NUM_REWARD_COEFS\n", + " all_cond = buf_stoch[\"obs\"][:, :, cond_start:cond_end].reshape(-1, binding.NUM_REWARD_COEFS)\n", + "\n", + " cond_labels = [\n", + " \"goal_rad\",\n", + " \"coll\",\n", + " \"offrd\",\n", + " \"comf\",\n", + " \"l_align\",\n", + " \"l_ctr\",\n", + " \"vel\",\n", + " \"traf\",\n", + " \"c_bias\",\n", + " \"v_align\",\n", + " \"ovspd\",\n", + " \"tstep\",\n", + " \"rev\",\n", + " \"throt\",\n", + " \"steer\",\n", + " \"acc\",\n", + " ]\n", + "\n", + " fig, ax = plt.subplots(figsize=(14, 5))\n", + " parts = ax.violinplot(\n", + " [all_cond[:, i] for i in range(binding.NUM_REWARD_COEFS)],\n", + " positions=range(binding.NUM_REWARD_COEFS),\n", + " showmeans=True,\n", + " showmedians=True,\n", + " )\n", + " ax.set_xticks(range(binding.NUM_REWARD_COEFS))\n", + " ax.set_xticklabels(cond_labels, rotation=45, ha=\"right\", fontsize=9)\n", + " ax.set_ylabel(\"Normalized value\")\n", + " ax.set_title(\"Conditioning coef distributions (all agents, full rollout)\")\n", + " ax.grid(True, alpha=0.3, axis=\"y\")\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "fu6dbejpxdu", + "metadata": {}, + "source": [ + "### Partner per-feature distributions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6g55putjnwo", + "metadata": {}, + "outputs": [], + "source": [ + "# Partner per-feature distributions (pooled over all agents + timesteps, visible only)\n", + "partner_labels = [\"rel_x\", \"rel_y\", \"width\", \"length\", \"heading_cos\", \"heading_sin\", \"speed\"]\n", + "max_partners = MAX_PARTNERS\n", + "pf = PARTNER_F\n", + "\n", + "# Compute slices\n", + "_ego_d = binding.EGO_FEATURES_JERK if dyn_model == \"jerk\" else binding.EGO_FEATURES_CLASSIC\n", + "_cond_d = binding.NUM_REWARD_COEFS if rew_cond else 0\n", + "_tgt_f = binding.STATIC_TARGET_FEATURES if tgt_type == \"static\" else binding.DYNAMIC_TARGET_FEATURES\n", + "_tgt_d = n_tgt_wp * _tgt_f\n", + "_p_start = _ego_d + _cond_d + _tgt_d\n", + "_p_end = _p_start + max_partners * pf\n", + "\n", + "all_partners = buf_stoch[\"obs\"][:, :, _p_start:_p_end].reshape(-1, max_partners, pf) # (H*N, 16, 7)\n", + "# Mask: partner is visible if any feature != 0\n", + "visible_mask = np.any(all_partners != 0, axis=2) # (H*N, 16)\n", + "visible_partners = all_partners[visible_mask] # (K, 7) — all visible partner observations\n", + "\n", + "print(\n", + " f\"Total partner obs: {all_partners.shape[0] * max_partners}, visible: {len(visible_partners)} \"\n", + " f\"({100 * len(visible_partners) / (all_partners.shape[0] * max_partners):.1f}%)\"\n", + ")\n", + "\n", + "fig, axes = plt.subplots(2, 4, figsize=(20, 8))\n", + "axes = axes.flatten()\n", + "\n", + "for i, label in enumerate(partner_labels):\n", + " vals = visible_partners[:, i]\n", + " axes[i].hist(vals, bins=80, edgecolor=\"black\", alpha=0.7, color=\"darkorange\")\n", + " axes[i].set_title(f\"{label} (n={len(vals)})\", fontsize=10)\n", + " axes[i].axvline(vals.mean(), color=\"red\", ls=\"--\", lw=1, label=f\"mean={vals.mean():.3f}\")\n", + " axes[i].legend(fontsize=7)\n", + " axes[i].tick_params(labelsize=7)\n", + "\n", + "# rel_x vs rel_y scatter in last panel\n", + "axes[7].scatter(visible_partners[:, 0], visible_partners[:, 1], s=1, alpha=0.15, color=\"darkorange\")\n", + "axes[7].set_xlabel(\"rel_x\")\n", + "axes[7].set_ylabel(\"rel_y\")\n", + "axes[7].set_title(\"Partner positions (ego frame)\")\n", + "axes[7].set_aspect(\"equal\")\n", + "axes[7].grid(True, alpha=0.3)\n", + "\n", + "fig.suptitle(\"Partner features: all visible, full rollout\", fontsize=13)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "# Partner count distribution across (timestep, agent)\n", + "partner_counts = visible_mask.sum(axis=1) # (H*N,)\n", + "fig, axes = plt.subplots(1, 2, figsize=(12, 4))\n", + "axes[0].hist(partner_counts, bins=range(max_partners + 2), edgecolor=\"black\", alpha=0.7, color=\"darkorange\")\n", + "axes[0].set_xlabel(\"Visible partners\")\n", + "axes[0].set_ylabel(\"Count\")\n", + "axes[0].set_title(\"Partner count distribution (per agent per step)\")\n", + "\n", + "# Partner distance distribution\n", + "dists = np.sqrt(visible_partners[:, 0] ** 2 + visible_partners[:, 1] ** 2)\n", + "axes[1].hist(dists, bins=80, edgecolor=\"black\", alpha=0.7, color=\"coral\")\n", + "axes[1].set_xlabel(\"Distance (normalized)\")\n", + "axes[1].set_ylabel(\"Count\")\n", + "axes[1].set_title(f\"Partner distance distribution (mean={dists.mean():.3f})\")\n", + "axes[1].axvline(dists.mean(), color=\"red\", ls=\"--\", lw=1)\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "5n8a8dwmna3", + "metadata": {}, + "source": [ + "### Road (lanes + boundaries) and target distributions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4xgikpryeg", + "metadata": {}, + "outputs": [], + "source": [ + "# Road per-feature distributions (lanes + boundaries)\n", + "road_labels = [\"rel_x\", \"rel_y\", \"seg_length\", \"seg_width\", \"dir_cos\", \"dir_sin\"]\n", + "rf = ROAD_F\n", + "max_lanes = MAX_LANES\n", + "max_bounds = MAX_BOUNDS\n", + "\n", + "_l_start = _p_end\n", + "_l_end = _l_start + max_lanes * rf\n", + "_b_start = _l_end\n", + "_b_end = _b_start + max_bounds * rf\n", + "\n", + "all_lanes = buf_stoch[\"obs\"][:, :, _l_start:_l_end].reshape(-1, max_lanes, rf)\n", + "all_bounds = buf_stoch[\"obs\"][:, :, _b_start:_b_end].reshape(-1, max_bounds, rf)\n", + "\n", + "vis_lanes = all_lanes[np.any(all_lanes != 0, axis=2)]\n", + "vis_bounds = all_bounds[np.any(all_bounds != 0, axis=2)]\n", + "\n", + "print(\n", + " f\"Lanes: {len(vis_lanes)} visible / {all_lanes.shape[0] * max_lanes} total \"\n", + " f\"({100 * len(vis_lanes) / (all_lanes.shape[0] * max_lanes):.1f}%)\"\n", + ")\n", + "print(\n", + " f\"Boundaries: {len(vis_bounds)} visible / {all_bounds.shape[0] * max_bounds} total \"\n", + " f\"({100 * len(vis_bounds) / (all_bounds.shape[0] * max_bounds):.1f}%)\"\n", + ")\n", + "\n", + "fig, axes = plt.subplots(2, 6, figsize=(24, 8))\n", + "for i, label in enumerate(road_labels):\n", + " # Lanes\n", + " axes[0, i].hist(vis_lanes[:, i], bins=80, edgecolor=\"black\", alpha=0.7, color=\"silver\")\n", + " axes[0, i].set_title(f\"lane {label}\", fontsize=9)\n", + " axes[0, i].axvline(vis_lanes[:, i].mean(), color=\"red\", ls=\"--\", lw=1)\n", + " axes[0, i].tick_params(labelsize=7)\n", + " # Boundaries\n", + " axes[1, i].hist(vis_bounds[:, i], bins=80, edgecolor=\"black\", alpha=0.7, color=\"dimgray\")\n", + " axes[1, i].set_title(f\"boundary {label}\", fontsize=9)\n", + " axes[1, i].axvline(vis_bounds[:, i].mean(), color=\"red\", ls=\"--\", lw=1)\n", + " axes[1, i].tick_params(labelsize=7)\n", + "\n", + "fig.suptitle(\"Road features: all visible, full rollout (top=lanes, bottom=boundaries)\", fontsize=13)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "# Spatial scatter: lane vs boundary positions (pooled)\n", + "fig, axes = plt.subplots(1, 3, figsize=(18, 5))\n", + "axes[0].scatter(vis_lanes[:, 0], vis_lanes[:, 1], s=0.5, alpha=0.05, color=\"gray\")\n", + "axes[0].set_xlabel(\"rel_x\")\n", + "axes[0].set_ylabel(\"rel_y\")\n", + "axes[0].set_title(f\"Lane segment positions (n={len(vis_lanes)})\")\n", + "axes[0].set_aspect(\"equal\")\n", + "axes[0].grid(True, alpha=0.3)\n", + "\n", + "axes[1].scatter(vis_bounds[:, 0], vis_bounds[:, 1], s=0.5, alpha=0.05, color=\"black\")\n", + "axes[1].set_xlabel(\"rel_x\")\n", + "axes[1].set_ylabel(\"rel_y\")\n", + "axes[1].set_title(f\"Boundary segment positions (n={len(vis_bounds)})\")\n", + "axes[1].set_aspect(\"equal\")\n", + "axes[1].grid(True, alpha=0.3)\n", + "\n", + "# Lane + boundary segment length comparison\n", + "axes[2].hist(vis_lanes[:, 2], bins=80, alpha=0.6, color=\"silver\", edgecolor=\"black\", label=\"lanes\")\n", + "axes[2].hist(vis_bounds[:, 2], bins=80, alpha=0.6, color=\"dimgray\", edgecolor=\"black\", label=\"boundaries\")\n", + "axes[2].set_xlabel(\"Segment length (normalized)\")\n", + "axes[2].set_ylabel(\"Count\")\n", + "axes[2].set_title(\"Segment length distribution\")\n", + "axes[2].legend()\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "# Target distributions across all agents, full rollout\n", + "_tgt_start = _ego_d + _cond_d\n", + "_tgt_end = _tgt_start + _tgt_d\n", + "all_target = buf_stoch[\"obs\"][:, :, _tgt_start:_tgt_end].reshape(-1, n_tgt_wp, _tgt_f)\n", + "\n", + "if tgt_type == \"static\":\n", + " tgt_flabels = [\"rel_x\", \"rel_y\"]\n", + "else:\n", + " tgt_flabels = [\"rel_x\", \"rel_y\", \"heading_cos\", \"heading_sin\"]\n", + "\n", + "fig, axes = plt.subplots(1, n_tgt_wp + 1, figsize=(5 * (n_tgt_wp + 1), 4))\n", + "\n", + "for wp in range(n_tgt_wp):\n", + " wp_data = all_target[:, wp, :]\n", + " active = np.any(wp_data != 0, axis=1)\n", + " wp_active = wp_data[active]\n", + " dist = np.sqrt(wp_active[:, 0] ** 2 + wp_active[:, 1] ** 2) if len(wp_active) > 0 else np.array([])\n", + " axes[wp].hist(dist, bins=60, edgecolor=\"black\", alpha=0.7, color=[\"red\", \"salmon\", \"lightsalmon\"][wp % 3])\n", + " axes[wp].set_title(f\"wp[{wp}] distance (n={len(wp_active)}/{len(wp_data)})\", fontsize=10)\n", + " axes[wp].set_xlabel(\"Distance (normalized)\")\n", + "\n", + "# All waypoints x-y scatter\n", + "for wp in range(n_tgt_wp):\n", + " wp_data = all_target[:, wp, :]\n", + " active = np.any(wp_data != 0, axis=1)\n", + " wp_active = wp_data[active]\n", + " if len(wp_active) > 0:\n", + " axes[n_tgt_wp].scatter(wp_active[:, 0], wp_active[:, 1], s=1, alpha=0.1, label=f\"wp[{wp}]\")\n", + "axes[n_tgt_wp].set_xlabel(\"rel_x\")\n", + "axes[n_tgt_wp].set_ylabel(\"rel_y\")\n", + "axes[n_tgt_wp].set_title(\"Target positions (ego frame)\")\n", + "axes[n_tgt_wp].set_aspect(\"equal\")\n", + "axes[n_tgt_wp].legend(fontsize=8)\n", + "axes[n_tgt_wp].grid(True, alpha=0.3)\n", + "\n", + "fig.suptitle(\"Target waypoint distributions (all agents, full rollout)\", fontsize=13)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "csj7ji1j6ed", + "metadata": {}, + "source": [ + "### Observation sparsity and layer occupancy heatmaps" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3xbi2pbsfyv", + "metadata": {}, + "outputs": [], + "source": [ + "# Sparsity heatmap: fraction of nonzero per layer, per agent, over time\n", + "layer_names = [\"partners\", \"lanes\", \"boundaries\"]\n", + "layer_slices = [\n", + " (_p_start, _p_end, MAX_PARTNERS, PARTNER_F),\n", + " (_l_start, _l_end, MAX_LANES, ROAD_F),\n", + " (_b_start, _b_end, MAX_BOUNDS, ROAD_F),\n", + "]\n", + "\n", + "fig, axes = plt.subplots(1, 3, figsize=(20, 5))\n", + "for ax, name, (s, e, n_obj, n_feat) in zip(axes, layer_names, layer_slices):\n", + " # (H, N) -> fraction of visible objects per (timestep, agent)\n", + " raw = buf_stoch[\"obs\"][:, :, s:e].reshape(HORIZON, N, n_obj, n_feat)\n", + " occupancy = np.any(raw != 0, axis=3).sum(axis=2) / n_obj # (H, N)\n", + " im = ax.imshow(occupancy.T, aspect=\"auto\", cmap=\"YlOrRd\", interpolation=\"nearest\", vmin=0, vmax=1)\n", + " ax.set_xlabel(\"Step\")\n", + " ax.set_ylabel(\"Agent\")\n", + " ax.set_title(f\"{name} occupancy (frac visible)\")\n", + " plt.colorbar(im, ax=ax)\n", + "\n", + "plt.suptitle(\"Per-layer occupancy heatmaps (fraction of max slots filled)\", fontsize=13)\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "# Per-layer mean occupancy over time\n", + "fig, axes = plt.subplots(1, 2, figsize=(16, 4))\n", + "\n", + "# Mean across agents\n", + "for name, (s, e, n_obj, n_feat) in zip(layer_names, layer_slices):\n", + " raw = buf_stoch[\"obs\"][:, :, s:e].reshape(HORIZON, N, n_obj, n_feat)\n", + " occ_mean = np.any(raw != 0, axis=3).sum(axis=2).mean(axis=1) # (H,)\n", + " axes[0].plot(occ_mean, label=name, alpha=0.8)\n", + "axes[0].set_xlabel(\"Step\")\n", + "axes[0].set_ylabel(\"Mean visible count\")\n", + "axes[0].set_title(\"Mean occupancy over time (across agents)\")\n", + "axes[0].legend()\n", + "axes[0].grid(True, alpha=0.3)\n", + "\n", + "# Mean across timesteps (per agent)\n", + "for name, (s, e, n_obj, n_feat) in zip(layer_names, layer_slices):\n", + " raw = buf_stoch[\"obs\"][:, :, s:e].reshape(HORIZON, N, n_obj, n_feat)\n", + " occ_per_agent = np.any(raw != 0, axis=3).sum(axis=2).mean(axis=0) # (N,)\n", + " axes[1].bar(range(N), occ_per_agent, alpha=0.5, label=name)\n", + "axes[1].set_xlabel(\"Agent\")\n", + "axes[1].set_ylabel(\"Mean visible count\")\n", + "axes[1].set_title(\"Mean occupancy per agent (across timesteps)\")\n", + "axes[1].legend()\n", + "axes[1].grid(True, alpha=0.3)\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "# Full obs sparsity: fraction of zero features per obs dimension, pooled\n", + "all_flat = buf_stoch[\"obs\"].reshape(-1, obs_dim) # (H*N, obs_dim)\n", + "zero_frac = (all_flat == 0).mean(axis=0) # (obs_dim,)\n", + "fig, ax = plt.subplots(figsize=(18, 3))\n", + "ax.bar(range(obs_dim), zero_frac, width=1.0, color=\"steelblue\", alpha=0.7)\n", + "# Annotate layer boundaries\n", + "prev_e = 0\n", + "for name, (s, e) in slices.items():\n", + " ax.axvline(s, color=\"red\", ls=\"--\", lw=0.5, alpha=0.7)\n", + " mid = (s + e) / 2\n", + " ax.text(mid, 1.02, name, ha=\"center\", va=\"bottom\", fontsize=7, rotation=0, color=\"red\")\n", + " prev_e = e\n", + "ax.set_xlim(0, obs_dim)\n", + "ax.set_ylim(0, 1.1)\n", + "ax.set_xlabel(\"Obs dimension index\")\n", + "ax.set_ylabel(\"Fraction zero\")\n", + "ax.set_title(\"Per-dimension sparsity (fraction zero across full rollout)\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "cell-8", + "metadata": {}, + "source": [ + "## Policy outputs over time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cell-9", + "metadata": {}, + "outputs": [], + "source": [ + "# Compute action probs over time for tracked agent (stochastic rollout)\n", + "n_actions = env.single_action_space.nvec[0] if not is_continuous else 1\n", + "action_probs_time = np.zeros((HORIZON, n_actions))\n", + "for t in range(HORIZON):\n", + " obs_t = torch.FloatTensor(buf_stoch[\"obs\"][t : t + 1, TRACKED_AGENT : TRACKED_AGENT + 1][0]).to(device)\n", + " with torch.no_grad():\n", + " if use_rnn:\n", + " # Can't replay RNN states here easily, use feedforward approximation\n", + " inner = policy.policy if hasattr(policy, \"policy\") else policy\n", + " h = inner.encode_observations(obs_t)\n", + " logits_list, _ = inner.decode_actions(h)\n", + " else:\n", + " logits_list, _ = policy(obs_t)\n", + " logits = logits_list[0] if isinstance(logits_list, (list, tuple)) else logits_list\n", + " action_probs_time[t] = F.softmax(logits, dim=-1).cpu().numpy().flatten()\n", + "\n", + "fig, axes = plt.subplots(2, 2, figsize=(16, 10))\n", + "\n", + "# Action distribution heatmap\n", + "im = axes[0, 0].imshow(action_probs_time.T, aspect=\"auto\", cmap=\"viridis\", interpolation=\"nearest\")\n", + "axes[0, 0].set_xlabel(\"Step\")\n", + "axes[0, 0].set_ylabel(\"Action ID\")\n", + "axes[0, 0].set_title(f\"Action prob heatmap | agent={TRACKED_AGENT}\")\n", + "plt.colorbar(im, ax=axes[0, 0])\n", + "\n", + "# Entropy over time\n", + "axes[0, 1].plot(buf_stoch[\"entropy\"][:, TRACKED_AGENT], label=\"stochastic\", alpha=0.8)\n", + "axes[0, 1].set_xlabel(\"Step\")\n", + "axes[0, 1].set_ylabel(\"Entropy\")\n", + "axes[0, 1].set_title(\"Entropy over time\")\n", + "axes[0, 1].grid(True, alpha=0.3)\n", + "\n", + "# Value over time\n", + "axes[1, 0].plot(buf_stoch[\"values\"][:, TRACKED_AGENT], label=\"stochastic\", alpha=0.8)\n", + "axes[1, 0].plot(buf_det[\"values\"][:, TRACKED_AGENT], label=\"deterministic\", alpha=0.8)\n", + "axes[1, 0].set_xlabel(\"Step\")\n", + "axes[1, 0].set_ylabel(\"Value\")\n", + "axes[1, 0].set_title(\"Value predictions over time\")\n", + "axes[1, 0].legend()\n", + "axes[1, 0].grid(True, alpha=0.3)\n", + "\n", + "# Actions over time: deterministic vs stochastic\n", + "axes[1, 1].step(range(HORIZON), buf_stoch[\"actions\"][:, TRACKED_AGENT], label=\"stochastic\", alpha=0.7)\n", + "axes[1, 1].step(range(HORIZON), buf_det[\"actions\"][:, TRACKED_AGENT], label=\"deterministic\", alpha=0.7)\n", + "axes[1, 1].set_xlabel(\"Step\")\n", + "axes[1, 1].set_ylabel(\"Action\")\n", + "axes[1, 1].set_title(\"Selected action over time\")\n", + "axes[1, 1].legend()\n", + "axes[1, 1].grid(True, alpha=0.3)\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "cell-10", + "metadata": {}, + "source": [ + "## Rewards and returns" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cell-11", + "metadata": {}, + "outputs": [], + "source": [ + "fig, axes = plt.subplots(2, 3, figsize=(18, 10))\n", + "\n", + "# Per-step mean reward\n", + "axes[0, 0].plot(buf_stoch[\"rewards\"].mean(axis=1), label=\"stochastic\", alpha=0.8)\n", + "axes[0, 0].plot(buf_det[\"rewards\"].mean(axis=1), label=\"deterministic\", alpha=0.8)\n", + "axes[0, 0].set_xlabel(\"Step\")\n", + "axes[0, 0].set_ylabel(\"Mean reward\")\n", + "axes[0, 0].set_title(\"Mean reward per step\")\n", + "axes[0, 0].legend()\n", + "axes[0, 0].grid(True, alpha=0.3)\n", + "\n", + "# Reward heatmap (stochastic)\n", + "im = axes[0, 1].imshow(buf_stoch[\"rewards\"].T, aspect=\"auto\", cmap=\"RdYlGn\", interpolation=\"nearest\")\n", + "axes[0, 1].set_xlabel(\"Step\")\n", + "axes[0, 1].set_ylabel(\"Agent\")\n", + "axes[0, 1].set_title(\"Reward heatmap (stochastic)\")\n", + "plt.colorbar(im, ax=axes[0, 1])\n", + "\n", + "# Cumulative return per agent\n", + "cum_ret_stoch = buf_stoch[\"rewards\"].sum(axis=0)\n", + "cum_ret_det = buf_det[\"rewards\"].sum(axis=0)\n", + "axes[0, 2].hist(cum_ret_stoch, bins=30, alpha=0.6, label=\"stochastic\", edgecolor=\"black\")\n", + "axes[0, 2].hist(cum_ret_det, bins=30, alpha=0.6, label=\"deterministic\", edgecolor=\"black\")\n", + "axes[0, 2].set_xlabel(\"Cumulative return\")\n", + "axes[0, 2].set_ylabel(\"Count\")\n", + "axes[0, 2].set_title(\"Return distribution across agents\")\n", + "axes[0, 2].legend()\n", + "\n", + "# Reward distribution histogram\n", + "axes[1, 0].hist(buf_stoch[\"rewards\"].flatten(), bins=50, alpha=0.7, edgecolor=\"black\")\n", + "axes[1, 0].set_xlabel(\"Reward\")\n", + "axes[1, 0].set_ylabel(\"Count\")\n", + "axes[1, 0].set_title(\"Per-step reward distribution (stochastic)\")\n", + "axes[1, 0].set_yscale(\"log\")\n", + "\n", + "# Terminal/truncation timeline\n", + "axes[1, 1].plot(buf_stoch[\"terminals\"].sum(axis=1), label=\"terminals\", alpha=0.8)\n", + "axes[1, 1].plot(buf_stoch[\"truncations\"].sum(axis=1), label=\"truncations\", alpha=0.8)\n", + "axes[1, 1].set_xlabel(\"Step\")\n", + "axes[1, 1].set_ylabel(\"Count\")\n", + "axes[1, 1].set_title(\"Terminals/Truncations per step (stochastic)\")\n", + "axes[1, 1].legend()\n", + "axes[1, 1].grid(True, alpha=0.3)\n", + "\n", + "# Tracked agent reward\n", + "axes[1, 2].plot(buf_stoch[\"rewards\"][:, TRACKED_AGENT], label=\"stochastic\", alpha=0.8)\n", + "axes[1, 2].plot(buf_det[\"rewards\"][:, TRACKED_AGENT], label=\"deterministic\", alpha=0.8)\n", + "axes[1, 2].set_xlabel(\"Step\")\n", + "axes[1, 2].set_ylabel(\"Reward\")\n", + "axes[1, 2].set_title(f\"Reward over time | agent={TRACKED_AGENT}\")\n", + "axes[1, 2].legend()\n", + "axes[1, 2].grid(True, alpha=0.3)\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "cell-12", + "metadata": {}, + "source": [ + "## Episode metrics" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cell-13", + "metadata": {}, + "outputs": [], + "source": [ + "# Collect episode-level metrics from the C logging\n", + "log_stoch = binding.vec_log(env.c_envs, N)\n", + "\n", + "# eval_mode=1 returns a list of per-env dicts; aggregate by averaging\n", + "if isinstance(log_stoch, list) and log_stoch:\n", + " all_keys = set(k for d in log_stoch for k in d if isinstance(d[k], (int, float)))\n", + " log_stoch = {k: np.mean([d[k] for d in log_stoch if k in d]) for k in all_keys}\n", + "\n", + "if log_stoch:\n", + " print(\"Episode metrics (after stochastic rollout):\")\n", + " for k, v in sorted(log_stoch.items()):\n", + " if isinstance(v, (int, float)):\n", + " print(f\" {k}: {v:.4f}\")\n", + "\n", + " # Bar chart of key metrics\n", + " keys = [\"score\", \"collision_rate\", \"offroad_rate\", \"completion_rate\", \"dnf_rate\"]\n", + " vals = [log_stoch.get(k, 0) for k in keys]\n", + " fig, ax = plt.subplots(figsize=(10, 4))\n", + " bars = ax.bar(keys, vals, edgecolor=\"black\", alpha=0.7, color=[\"green\", \"red\", \"orange\", \"blue\", \"gray\"])\n", + " ax.set_ylabel(\"Rate\")\n", + " ax.set_title(\"Episode Metrics\")\n", + " for bar, v in zip(bars, vals):\n", + " ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + 0.01, f\"{v:.3f}\", ha=\"center\", fontsize=10)\n", + " plt.tight_layout()\n", + " plt.show()\n", + "else:\n", + " print(\"No episode metrics available yet (not enough episodes completed)\")" + ] + }, + { + "cell_type": "markdown", + "id": "cell-14", + "metadata": {}, + "source": [ + "## Value predictions vs actual returns" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cell-15", + "metadata": {}, + "outputs": [], + "source": [ + "gamma = config[\"train\"].get(\"gamma\", 0.98)\n", + "lam = config[\"train\"].get(\"gae_lambda\", 0.95)\n", + "\n", + "\n", + "def compute_gae(rewards, values, terminals, truncations, gamma, lam):\n", + " H, N = rewards.shape\n", + " advantages = np.zeros_like(rewards)\n", + " last_gae = np.zeros(N)\n", + " for t in reversed(range(H - 1)):\n", + " done = np.maximum(terminals[t + 1], truncations[t + 1])\n", + " next_non_terminal = 1.0 - done\n", + " delta = rewards[t + 1] + gamma * values[t + 1] * next_non_terminal - values[t]\n", + " last_gae = delta + gamma * lam * last_gae * next_non_terminal\n", + " advantages[t] = last_gae\n", + " return advantages\n", + "\n", + "\n", + "adv_stoch = compute_gae(\n", + " buf_stoch[\"rewards\"], buf_stoch[\"values\"], buf_stoch[\"terminals\"], buf_stoch[\"truncations\"], gamma, lam\n", + ")\n", + "returns_stoch = adv_stoch + buf_stoch[\"values\"]\n", + "\n", + "pred_v = buf_stoch[\"values\"].flatten()\n", + "actual_r = returns_stoch.flatten()\n", + "\n", + "var_actual = np.var(actual_r)\n", + "explained_var = 1 - np.var(actual_r - pred_v) / (var_actual + 1e-8) if var_actual > 1e-8 else 0.0\n", + "\n", + "fig, axes = plt.subplots(1, 3, figsize=(18, 5))\n", + "\n", + "# Scatter: predicted vs actual\n", + "axes[0].scatter(actual_r, pred_v, alpha=0.2, s=5)\n", + "lims = [min(actual_r.min(), pred_v.min()), max(actual_r.max(), pred_v.max())]\n", + "axes[0].plot(lims, lims, \"r--\", label=\"perfect\")\n", + "axes[0].set_xlabel(\"Actual return\")\n", + "axes[0].set_ylabel(\"Predicted value\")\n", + "axes[0].set_title(f\"Value accuracy (EV: {explained_var:.4f})\")\n", + "axes[0].legend()\n", + "axes[0].grid(True, alpha=0.3)\n", + "\n", + "# Value error over time\n", + "value_error = np.abs(returns_stoch - buf_stoch[\"values\"]).mean(axis=1)\n", + "axes[1].plot(value_error)\n", + "axes[1].set_xlabel(\"Step\")\n", + "axes[1].set_ylabel(\"Mean |error|\")\n", + "axes[1].set_title(\"Value prediction error over time\")\n", + "axes[1].grid(True, alpha=0.3)\n", + "\n", + "# Advantage distribution\n", + "axes[2].hist(adv_stoch.flatten(), bins=50, edgecolor=\"black\", alpha=0.7)\n", + "axes[2].set_xlabel(\"Advantage\")\n", + "axes[2].set_ylabel(\"Count\")\n", + "axes[2].set_title(f\"Advantage distribution (std={adv_stoch.std():.4f})\")\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "print(f\"Explained variance: {explained_var:.4f}\")\n", + "print(f\"Value MSE: {np.mean((actual_r - pred_v) ** 2):.6f}\")" + ] + }, + { + "cell_type": "markdown", + "id": "cell-16", + "metadata": {}, + "source": [ + "## Agent trajectories" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cell-17", + "metadata": {}, + "outputs": [], + "source": [ + "N_TRAJ = min(16, N) # number of agents to plot\n", + "\n", + "fig, axes = plt.subplots(1, 2, figsize=(16, 7))\n", + "\n", + "for i in range(N_TRAJ):\n", + " color = plt.cm.tab20(i % 20)\n", + " # Stochastic\n", + " axes[0].plot(buf_stoch[\"positions_x\"][:, i], buf_stoch[\"positions_y\"][:, i], alpha=0.6, color=color, linewidth=1)\n", + " axes[0].scatter(\n", + " buf_stoch[\"positions_x\"][0, i], buf_stoch[\"positions_y\"][0, i], color=color, s=30, marker=\"o\", zorder=5\n", + " ) # start\n", + " # Deterministic\n", + " axes[1].plot(buf_det[\"positions_x\"][:, i], buf_det[\"positions_y\"][:, i], alpha=0.6, color=color, linewidth=1)\n", + " axes[1].scatter(buf_det[\"positions_x\"][0, i], buf_det[\"positions_y\"][0, i], color=color, s=30, marker=\"o\", zorder=5)\n", + "\n", + "axes[0].set_title(f\"Stochastic trajectories (N={N_TRAJ})\")\n", + "axes[1].set_title(f\"Deterministic trajectories (N={N_TRAJ})\")\n", + "for ax in axes:\n", + " ax.set_xlabel(\"X\")\n", + " ax.set_ylabel(\"Y\")\n", + " ax.set_aspect(\"equal\")\n", + " ax.grid(True, alpha=0.3)\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "# ADE vs ground truth if scenario_length is set\n", + "if config[\"env\"].get(\"scenario_length\"):\n", + " try:\n", + " gt = env.get_ground_truth_trajectories()\n", + " # gt['x'] shape: (N, 1, T), positions shape: (T, N)\n", + " gt_x = gt[\"x\"][:, 0, :].T # (T, N)\n", + " gt_y = gt[\"y\"][:, 0, :].T\n", + " gt_valid = gt[\"valid\"][:, 0, :].T\n", + " T_gt = gt_x.shape[0]\n", + " T_use = min(T_gt, HORIZON)\n", + "\n", + " disp = np.sqrt(\n", + " (buf_stoch[\"positions_x\"][:T_use] - gt_x[:T_use]) ** 2\n", + " + (buf_stoch[\"positions_y\"][:T_use] - gt_y[:T_use]) ** 2\n", + " )\n", + " valid_mask = gt_valid[:T_use] > 0\n", + " if valid_mask.sum() > 0:\n", + " ade = disp[valid_mask].mean()\n", + " print(f\"ADE (stochastic vs ground truth): {ade:.3f}m\")\n", + " ade_per_agent = np.array(\n", + " [disp[:, i][valid_mask[:, i]].mean() for i in range(N) if valid_mask[:, i].sum() > 0]\n", + " )\n", + " plt.figure(figsize=(8, 3))\n", + " plt.hist(ade_per_agent, bins=30, edgecolor=\"black\", alpha=0.7)\n", + " plt.xlabel(\"ADE (m)\")\n", + " plt.ylabel(\"Count\")\n", + " plt.title(f\"Per-agent ADE distribution (mean={ade:.3f}m)\")\n", + " plt.tight_layout()\n", + " plt.show()\n", + " else:\n", + " print(\"No valid ground truth timesteps to compute ADE\")\n", + " except Exception as e:\n", + " print(f\"Could not compute ADE: {e}\")" + ] + }, + { + "cell_type": "markdown", + "id": "cell-18", + "metadata": {}, + "source": [ + "## LSTM hidden state analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cell-19", + "metadata": {}, + "outputs": [], + "source": [ + "if use_rnn and \"lstm_h_norm\" in buf_stoch:\n", + " h_norm = buf_stoch[\"lstm_h_norm\"]\n", + "\n", + " fig, axes = plt.subplots(1, 3, figsize=(18, 5))\n", + "\n", + " # Hidden state norm over time\n", + " axes[0].plot(h_norm.mean(axis=1), label=\"mean\", color=\"blue\")\n", + " axes[0].fill_between(\n", + " range(HORIZON),\n", + " h_norm.mean(axis=1) - h_norm.std(axis=1),\n", + " h_norm.mean(axis=1) + h_norm.std(axis=1),\n", + " alpha=0.2,\n", + " color=\"blue\",\n", + " )\n", + " axes[0].set_xlabel(\"Step\")\n", + " axes[0].set_ylabel(\"||h||\")\n", + " axes[0].set_title(\"LSTM hidden state norm over time\")\n", + " axes[0].grid(True, alpha=0.3)\n", + "\n", + " # Histogram at different timesteps\n", + " for t, color in [(0, \"blue\"), (HORIZON // 4, \"green\"), (HORIZON // 2, \"orange\"), (HORIZON - 1, \"red\")]:\n", + " axes[1].hist(h_norm[t], bins=30, alpha=0.4, label=f\"t={t}\", color=color, edgecolor=\"black\")\n", + " axes[1].set_xlabel(\"||h||\")\n", + " axes[1].set_ylabel(\"Count\")\n", + " axes[1].set_title(\"Hidden norm distribution at different timesteps\")\n", + " axes[1].legend()\n", + "\n", + " # Correlation: hidden norm vs value\n", + " axes[2].scatter(h_norm.flatten(), buf_stoch[\"values\"].flatten(), alpha=0.1, s=3)\n", + " corr = np.corrcoef(h_norm.flatten(), buf_stoch[\"values\"].flatten())[0, 1]\n", + " axes[2].set_xlabel(\"||h||\")\n", + " axes[2].set_ylabel(\"Value\")\n", + " axes[2].set_title(f\"Hidden norm vs Value (corr={corr:.3f})\")\n", + " axes[2].grid(True, alpha=0.3)\n", + "\n", + " plt.tight_layout()\n", + " plt.show()\n", + "else:\n", + " print(\"No LSTM — skipping hidden state analysis\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/06_architecture.ipynb b/notebooks/06_architecture.ipynb new file mode 100644 index 0000000000..d1dda5c0ff --- /dev/null +++ b/notebooks/06_architecture.ipynb @@ -0,0 +1,912 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 06 - Neural Network Architecture\n", + "Visualize, analyze, and iterate on the DrivePolicy architecture. Covers model summary, per-encoder breakdown, forward pass shape tracing, weight distributions, and architecture comparison." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import torch\n", + "import torch.nn.functional as F\n", + "from torchinfo import summary\n", + "from pufferlib.ocean.drive.drive import Drive\n", + "from pufferlib.ocean.drive import binding\n", + "from pufferlib.ocean.torch import Drive as DrivePolicy, DriveBackbone, Recurrent\n", + "\n", + "# --- Environment configuration ---\n", + "NUM_AGENTS = 64\n", + "SIMULATION_MODE = \"gigaflow\"\n", + "DYNAMICS_MODEL = \"jerk\"\n", + "ACTION_TYPE = \"discrete\"\n", + "DT = 0.1\n", + "SCENARIO_LENGTH = 512\n", + "RESAMPLE_FREQUENCY = 0\n", + "REWARD_CONDITIONING = True\n", + "REWARD_RANDOMIZATION = False\n", + "TARGET_TYPE = \"static\"\n", + "COLLISION_BEHAVIOR = 1\n", + "OFFROAD_BEHAVIOR = 1\n", + "REACH_GOAL_BEHAVIOR = 1\n", + "SEED = 42\n", + "MAP_DIR = \"../pufferlib/resources/drive/binaries/carla\"\n", + "\n", + "# --- Observation dimensions ---\n", + "MAX_PARTNERS = 20\n", + "MAX_LANES = 100\n", + "MAX_BOUNDS = 50\n", + "MAX_TRAFFIC = 4\n", + "MAX_STOP_SIGNS = 0\n", + "\n", + "# --- Policy architecture ---\n", + "INPUT_SIZE = 64\n", + "BACKBONE_HIDDEN_SIZE = 1024\n", + "BACKBONE_NUM_LAYERS = 3\n", + "ACTOR_HIDDEN_SIZE = 128\n", + "ACTOR_NUM_LAYERS = 3\n", + "CRITIC_HIDDEN_SIZE = 64\n", + "CRITIC_NUM_LAYERS = 2\n", + "SPLIT_NETWORK = False\n", + "ENCODER_GIGAFLOW = True\n", + "DROPOUT = 0.0\n", + "\n", + "# --- Derived from binding ---\n", + "EGO_DIM = binding.EGO_FEATURES_JERK\n", + "NUM_COEFS = binding.NUM_REWARD_COEFS\n", + "PARTNER_F = binding.PARTNER_FEATURES\n", + "ROAD_F = binding.ROAD_FEATURES\n", + "TRAFFIC_F = binding.TRAFFIC_LIGHT_FEATURES\n", + "STOP_SIGN_F = binding.STOP_SIGN_FEATURES\n", + "\n", + "# --- Create environment ---\n", + "env = Drive(\n", + " num_agents=NUM_AGENTS,\n", + " num_maps=1,\n", + " min_agents_per_env=NUM_AGENTS,\n", + " max_agents_per_env=NUM_AGENTS,\n", + " simulation_mode=SIMULATION_MODE,\n", + " dynamics_model=DYNAMICS_MODEL,\n", + " action_type=ACTION_TYPE,\n", + " dt=DT,\n", + " scenario_length=SCENARIO_LENGTH,\n", + " resample_frequency=RESAMPLE_FREQUENCY,\n", + " reward_conditioning=REWARD_CONDITIONING,\n", + " reward_randomization=REWARD_RANDOMIZATION,\n", + " target_type=TARGET_TYPE,\n", + " map_dir=MAP_DIR,\n", + " collision_behavior=COLLISION_BEHAVIOR,\n", + " offroad_behavior=OFFROAD_BEHAVIOR,\n", + " reach_goal_behavior=REACH_GOAL_BEHAVIOR,\n", + " max_lane_segment_observations=MAX_LANES,\n", + " max_boundary_segment_observations=MAX_BOUNDS,\n", + " max_partner_observations=MAX_PARTNERS,\n", + " max_traffic_light_observations=MAX_TRAFFIC,\n", + " max_stop_sign_observations=MAX_STOP_SIGNS,\n", + " seed=SEED,\n", + ")\n", + "obs, info = env.reset(seed=SEED)\n", + "\n", + "MAX_TARGET = env.num_target_waypoints\n", + "TARGET_F = binding.STATIC_TARGET_FEATURES if TARGET_TYPE == \"static\" else binding.DYNAMIC_TARGET_FEATURES\n", + "TARGET_DIM = MAX_TARGET * TARGET_F\n", + "\n", + "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n", + "policy = DrivePolicy(\n", + " env,\n", + " input_size=INPUT_SIZE,\n", + " backbone_hidden_size=BACKBONE_HIDDEN_SIZE,\n", + " backbone_num_layers=BACKBONE_NUM_LAYERS,\n", + " actor_hidden_size=ACTOR_HIDDEN_SIZE,\n", + " actor_num_layers=ACTOR_NUM_LAYERS,\n", + " critic_hidden_size=CRITIC_HIDDEN_SIZE,\n", + " critic_num_layers=CRITIC_NUM_LAYERS,\n", + " split_network=SPLIT_NETWORK,\n", + " encoder_gigaflow=ENCODER_GIGAFLOW,\n", + " dropout=DROPOUT,\n", + ").to(device)\n", + "\n", + "print(f\"Device: {device}\")\n", + "print(f\"Obs dim: {obs.shape[1]}\")\n", + "print(f\"Action dim: {policy.atn_dim}\")\n", + "print(f\"Split network: {SPLIT_NETWORK}\")\n", + "print(f\"Backbone: {BACKBONE_HIDDEN_SIZE} x {BACKBONE_NUM_LAYERS}L\")\n", + "print(f\"Actor: {ACTOR_HIDDEN_SIZE} x {ACTOR_NUM_LAYERS}L\")\n", + "print(f\"Critic: {CRITIC_HIDDEN_SIZE} x {CRITIC_NUM_LAYERS}L\")\n", + "print(f\"Encoder gigaflow: {ENCODER_GIGAFLOW}, Dropout: {DROPOUT}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Model Summary (torchinfo)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "obs_tensor = torch.FloatTensor(obs).to(device)\n", + "summary(policy, input_data=obs_tensor, depth=4, col_names=[\"input_size\", \"output_size\", \"num_params\", \"mult_adds\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Architecture Diagram" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "backbone = policy.actor_backbone\n", + "cond_dim = backbone.conditioning_dim\n", + "\n", + "# Collect encoder info — encoder_gigaflow adds Tanh+Dropout between LN and second Linear\n", + "# ego, partner, conditioning use encoder_gigaflow; lane, boundary, traffic_ctrl use dropout\n", + "encoders = [\n", + " (\"ego\", EGO_DIM, 1, \"direct\", ENCODER_GIGAFLOW),\n", + " (\"conditioning\", cond_dim, 1, \"direct\", ENCODER_GIGAFLOW) if cond_dim > 0 else None,\n", + " (\"partner\", PARTNER_F, MAX_PARTNERS, \"max-pool\", ENCODER_GIGAFLOW),\n", + " (\"lane\", ROAD_F, MAX_LANES, \"max-pool\", ENCODER_GIGAFLOW),\n", + " (\"boundary\", ROAD_F, MAX_BOUNDS, \"max-pool\", ENCODER_GIGAFLOW),\n", + " (\"traffic_ctrl\", TRAFFIC_F + 3, MAX_TRAFFIC, \"max-pool (onehot)\", ENCODER_GIGAFLOW),\n", + "]\n", + "encoders = [e for e in encoders if e is not None]\n", + "\n", + "fig, ax = plt.subplots(figsize=(14, 8))\n", + "ax.set_xlim(0, 10)\n", + "ax.set_ylim(0, 10)\n", + "ax.axis(\"off\")\n", + "\n", + "n_enc = len(encoders)\n", + "y_positions = np.linspace(9, 1, n_enc)\n", + "colors = plt.cm.Set2(np.linspace(0, 1, n_enc))\n", + "\n", + "# Draw encoders\n", + "for i, ((name, in_f, n_obj, agg, gigaflow), y, c) in enumerate(zip(encoders, y_positions, colors)):\n", + " # Input box\n", + " label = f\"{name}\\n{n_obj}x{in_f}\" if n_obj > 1 else f\"{name}\\n{in_f}\"\n", + " ax.add_patch(plt.Rectangle((0.2, y - 0.3), 1.6, 0.6, facecolor=c, edgecolor=\"black\", lw=1.2, alpha=0.8))\n", + " ax.text(1.0, y, label, ha=\"center\", va=\"center\", fontsize=8, fontweight=\"bold\")\n", + "\n", + " # Encoder box — show gigaflow arch vs standard\n", + " ax.add_patch(plt.Rectangle((2.5, y - 0.25), 2.0, 0.5, facecolor=\"lightyellow\", edgecolor=\"black\", lw=1))\n", + " ax.text(3.5, y + 0.05, f\"Linear({in_f},{INPUT_SIZE})\", ha=\"center\", va=\"center\", fontsize=7)\n", + " if gigaflow:\n", + " ax.text(\n", + " 3.5,\n", + " y - 0.12,\n", + " f\"LN+Tanh+Drop+Linear({INPUT_SIZE},{INPUT_SIZE})\",\n", + " ha=\"center\",\n", + " va=\"center\",\n", + " fontsize=5.5,\n", + " color=\"darkgreen\",\n", + " )\n", + " else:\n", + " drop_str = f\"+Drop({DROPOUT})\" if DROPOUT > 0 and name not in (\"ego\", \"partner\", \"conditioning\") else \"\"\n", + " ax.text(\n", + " 3.5,\n", + " y - 0.12,\n", + " f\"LN{drop_str}+Linear({INPUT_SIZE},{INPUT_SIZE})\",\n", + " ha=\"center\",\n", + " va=\"center\",\n", + " fontsize=6,\n", + " color=\"gray\",\n", + " )\n", + "\n", + " # Aggregation\n", + " if n_obj > 1:\n", + " ax.text(5.0, y, agg, ha=\"center\", va=\"center\", fontsize=7, style=\"italic\", color=\"darkblue\")\n", + " arrow_start = 5.5\n", + " else:\n", + " arrow_start = 4.6\n", + "\n", + " # Arrows\n", + " ax.annotate(\"\", xy=(2.5, y), xytext=(1.8, y), arrowprops=dict(arrowstyle=\"->\", lw=1))\n", + " ax.annotate(\"\", xy=(6.0, 5.0), xytext=(arrow_start, y), arrowprops=dict(arrowstyle=\"->\", lw=0.8, color=\"gray\"))\n", + "\n", + "# Concat box\n", + "ax.add_patch(plt.Rectangle((5.8, 4.5), 1.4, 1.0, facecolor=\"lightsalmon\", edgecolor=\"black\", lw=1.5))\n", + "ax.text(6.5, 5.2, \"Concat\", ha=\"center\", va=\"center\", fontsize=9, fontweight=\"bold\")\n", + "ax.text(6.5, 4.85, f\"{n_enc}x{INPUT_SIZE}={n_enc * INPUT_SIZE}\", ha=\"center\", va=\"center\", fontsize=7)\n", + "\n", + "# Backbone\n", + "ax.add_patch(plt.Rectangle((7.5, 4.5), 1.3, 1.0, facecolor=\"lightblue\", edgecolor=\"black\", lw=1.5))\n", + "ax.text(8.15, 5.15, f\"Backbone ({BACKBONE_NUM_LAYERS}L)\", ha=\"center\", va=\"center\", fontsize=8, fontweight=\"bold\")\n", + "ax.text(8.15, 4.85, f\"GELU+Linear\\n({n_enc * INPUT_SIZE},{BACKBONE_HIDDEN_SIZE})\", ha=\"center\", va=\"center\", fontsize=6)\n", + "ax.annotate(\"\", xy=(7.5, 5.0), xytext=(7.2, 5.0), arrowprops=dict(arrowstyle=\"->\", lw=1.5))\n", + "\n", + "# Actor / Critic heads\n", + "ax.add_patch(plt.Rectangle((9.0, 5.7), 0.9, 0.6, facecolor=\"lightgreen\", edgecolor=\"black\", lw=1.2))\n", + "actor_label = f\"Actor ({ACTOR_NUM_LAYERS}L)\\n{BACKBONE_HIDDEN_SIZE}->{sum(policy.atn_dim)}\"\n", + "if ACTOR_NUM_LAYERS > 1:\n", + " actor_label = (\n", + " f\"Actor ({ACTOR_NUM_LAYERS}L)\\n{BACKBONE_HIDDEN_SIZE}->{ACTOR_HIDDEN_SIZE}->...->{sum(policy.atn_dim)}\"\n", + " )\n", + "ax.text(9.45, 6.0, actor_label, ha=\"center\", va=\"center\", fontsize=6, fontweight=\"bold\")\n", + "\n", + "ax.add_patch(plt.Rectangle((9.0, 3.7), 0.9, 0.6, facecolor=\"plum\", edgecolor=\"black\", lw=1.2))\n", + "critic_label = f\"Critic ({CRITIC_NUM_LAYERS}L)\\n{BACKBONE_HIDDEN_SIZE}->1\"\n", + "if CRITIC_NUM_LAYERS > 1:\n", + " critic_label = f\"Critic ({CRITIC_NUM_LAYERS}L)\\n{BACKBONE_HIDDEN_SIZE}->{CRITIC_HIDDEN_SIZE}->...->1\"\n", + "ax.text(9.45, 4.0, critic_label, ha=\"center\", va=\"center\", fontsize=6, fontweight=\"bold\")\n", + "\n", + "ax.annotate(\"\", xy=(9.0, 6.0), xytext=(8.8, 5.3), arrowprops=dict(arrowstyle=\"->\", lw=1.2))\n", + "ax.annotate(\"\", xy=(9.0, 4.0), xytext=(8.8, 4.7), arrowprops=dict(arrowstyle=\"->\", lw=1.2))\n", + "\n", + "split_label = \"SPLIT\" if SPLIT_NETWORK else \"SHARED\"\n", + "ax.text(8.9, 4.55, split_label, ha=\"center\", va=\"center\", fontsize=7, color=\"red\", fontweight=\"bold\")\n", + "\n", + "gigaflow_label = \"GIGAFLOW\" if ENCODER_GIGAFLOW else \"STANDARD\"\n", + "ax.text(\n", + " 5.0,\n", + " 0.3,\n", + " f\"Encoder mode: {gigaflow_label} | Dropout: {DROPOUT}\",\n", + " ha=\"center\",\n", + " va=\"center\",\n", + " fontsize=8,\n", + " color=\"darkgreen\",\n", + " fontweight=\"bold\",\n", + ")\n", + "\n", + "ax.set_title(\n", + " f\"DrivePolicy Architecture (input_size={INPUT_SIZE}, backbone={BACKBONE_HIDDEN_SIZE})\",\n", + " fontsize=12,\n", + " fontweight=\"bold\",\n", + ")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Per-Encoder Parameter Breakdown" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def count_params(module):\n", + " return sum(p.numel() for p in module.parameters())\n", + "\n", + "\n", + "backbone = policy.actor_backbone\n", + "components = {\n", + " \"ego_encoder\": backbone.ego_encoder,\n", + " \"lane_encoder\": backbone.lane_encoder,\n", + " \"boundary_encoder\": backbone.boundary_encoder,\n", + " \"partner_encoder\": backbone.partner_encoder,\n", + " \"traffic_ctrl_encoder\": backbone.traffic_light_encoder,\n", + "}\n", + "if backbone.conditioning_dim > 0:\n", + " components[\"conditioning_encoder\"] = backbone.conditioning_encoder\n", + "components[\"backbone_mlp\"] = backbone.backbone\n", + "components[\"actor_head\"] = policy.actor_head\n", + "components[\"critic_head\"] = policy.critic_head\n", + "\n", + "names, counts = zip(*[(k, count_params(v)) for k, v in components.items()])\n", + "total = sum(counts)\n", + "\n", + "print(f\"{'Component':>25s} | {'Params':>10s} | {'%':>6s}\")\n", + "print(\"-\" * 48)\n", + "for n, c in zip(names, counts):\n", + " print(f\"{n:>25s} | {c:>10,d} | {c / total:>5.1%}\")\n", + "print(\"-\" * 48)\n", + "print(f\"{'TOTAL':>25s} | {total:>10,d}\")\n", + "if SPLIT_NETWORK:\n", + " critic_bb = count_params(policy.critic_backbone)\n", + " print(f\"{'+ critic_backbone':>25s} | {critic_bb:>10,d}\")\n", + " print(f\"{'GRAND TOTAL':>25s} | {total + critic_bb:>10,d}\")\n", + "\n", + "fig, ax = plt.subplots(figsize=(8, 5))\n", + "colors = plt.cm.Set3(np.linspace(0, 1, len(names)))\n", + "bars = ax.barh(names, counts, color=colors, edgecolor=\"black\")\n", + "for bar, c in zip(bars, counts):\n", + " ax.text(bar.get_width() + total * 0.01, bar.get_y() + bar.get_height() / 2, f\"{c:,}\", va=\"center\", fontsize=8)\n", + "ax.set_xlabel(\"Parameters\")\n", + "ax.set_title(f\"Parameter Distribution ({total:,} total)\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Forward Pass Shape Trace" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = obs_tensor\n", + "backbone = policy.actor_backbone\n", + "\n", + "slide_idx = EGO_DIM\n", + "cond_dim = backbone.conditioning_dim\n", + "partner_dim = MAX_PARTNERS * PARTNER_F\n", + "lane_dim = MAX_LANES * ROAD_F\n", + "boundary_dim = MAX_BOUNDS * ROAD_F\n", + "traffic_dim = MAX_TRAFFIC * TRAFFIC_F\n", + "\n", + "# Slicing\n", + "ego_obs = x[:, :slide_idx]\n", + "slices = [(\"ego\", 0, slide_idx, ego_obs.shape)]\n", + "\n", + "if cond_dim > 0:\n", + " cond_obs = x[:, slide_idx : slide_idx + cond_dim]\n", + " slices.append((\"conditioning\", slide_idx, slide_idx + cond_dim, cond_obs.shape))\n", + " slide_idx += cond_dim\n", + "\n", + "partner_obs = x[:, slide_idx : slide_idx + partner_dim]\n", + "slices.append((\"partners\", slide_idx, slide_idx + partner_dim, partner_obs.shape))\n", + "slide_idx += partner_dim\n", + "\n", + "lane_obs = x[:, slide_idx : slide_idx + lane_dim]\n", + "slices.append((\"lanes\", slide_idx, slide_idx + lane_dim, lane_obs.shape))\n", + "slide_idx += lane_dim\n", + "\n", + "boundary_obs = x[:, slide_idx : slide_idx + boundary_dim]\n", + "slices.append((\"boundaries\", slide_idx, slide_idx + boundary_dim, boundary_obs.shape))\n", + "slide_idx += boundary_dim\n", + "\n", + "traffic_obs = x[:, slide_idx : slide_idx + traffic_dim]\n", + "slices.append((\"traffic_ctrl\", slide_idx, slide_idx + traffic_dim, traffic_obs.shape))\n", + "\n", + "print(f\"Obs buffer layout (total={x.shape[1]}):\")\n", + "print(f\"{'Name':>15s} | {'Start':>5s} | {'End':>5s} | {'Width':>5s} | Shape\")\n", + "print(\"-\" * 65)\n", + "for name, start, end, shape in slices:\n", + " print(f\"{name:>15s} | {start:>5d} | {end:>5d} | {end - start:>5d} | {shape}\")\n", + "\n", + "# Forward through encoders\n", + "print(\"\\nEncoder outputs:\")\n", + "with torch.no_grad():\n", + " ego_enc = backbone.ego_encoder(ego_obs)\n", + " print(f\" ego_encoder: {ego_obs.shape} -> {ego_enc.shape}\")\n", + "\n", + " if cond_dim > 0:\n", + " cond_enc = backbone.conditioning_encoder(cond_obs)\n", + " print(f\" cond_encoder: {cond_obs.shape} -> {cond_enc.shape}\")\n", + "\n", + " p_reshaped = partner_obs.view(-1, MAX_PARTNERS, PARTNER_F)\n", + " p_enc, _ = backbone.partner_encoder(p_reshaped).max(dim=1)\n", + " print(f\" partner_encoder: {partner_obs.shape} -> view {p_reshaped.shape} -> encode -> max-pool -> {p_enc.shape}\")\n", + "\n", + " l_reshaped = lane_obs.view(-1, MAX_LANES, ROAD_F)\n", + " l_enc, _ = backbone.lane_encoder(l_reshaped).max(dim=1)\n", + " print(f\" lane_encoder: {lane_obs.shape} -> view {l_reshaped.shape} -> encode -> max-pool -> {l_enc.shape}\")\n", + "\n", + " b_reshaped = boundary_obs.view(-1, MAX_BOUNDS, ROAD_F)\n", + " b_enc, _ = backbone.boundary_encoder(b_reshaped).max(dim=1)\n", + " print(f\" bound_encoder: {boundary_obs.shape} -> view {b_reshaped.shape} -> encode -> max-pool -> {b_enc.shape}\")\n", + "\n", + " t_reshaped = traffic_obs.view(-1, MAX_TRAFFIC, TRAFFIC_F)\n", + " t_cont = t_reshaped[:, :, : TRAFFIC_F - 1]\n", + " t_cat = t_reshaped[:, :, TRAFFIC_F - 1]\n", + " t_onehot = F.one_hot(t_cat.long(), num_classes=4)\n", + " t_input = torch.cat([t_cont, t_onehot], dim=2)\n", + " t_enc, _ = backbone.traffic_light_encoder(t_input).max(dim=1)\n", + " print(\n", + " f\" traffic_encoder: {traffic_obs.shape} -> view {t_reshaped.shape} -> onehot {t_input.shape} -> encode -> max-pool -> {t_enc.shape}\"\n", + " )\n", + "\n", + " # Concat + backbone\n", + " features = [ego_enc, l_enc, b_enc, p_enc, t_enc]\n", + " if cond_dim > 0:\n", + " features.append(cond_enc)\n", + " concat = torch.cat(features, dim=1)\n", + " hidden = backbone.backbone(concat)\n", + " print(f\"\\n concat: {concat.shape}\")\n", + " print(f\" backbone_mlp: {concat.shape} -> {hidden.shape}\")\n", + "\n", + " # Heads\n", + " actor_out = policy.actor_head(hidden)\n", + " critic_out = policy.critic_head(hidden)\n", + " print(f\" actor_head: {hidden.shape} -> {actor_out.shape} (split into {policy.atn_dim})\")\n", + " print(f\" critic_head: {hidden.shape} -> {critic_out.shape}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Weight Distributions by Layer" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "weight_data = [\n", + " (n, p.data.cpu().numpy().flatten()) for n, p in policy.named_parameters() if \"weight\" in n and p.dim() >= 2\n", + "]\n", + "\n", + "n_weights = len(weight_data)\n", + "cols = 4\n", + "rows = (n_weights + cols - 1) // cols\n", + "fig, axes = plt.subplots(rows, cols, figsize=(4 * cols, 3 * rows))\n", + "axes = axes.flatten()\n", + "\n", + "for i, (name, w) in enumerate(weight_data):\n", + " ax = axes[i]\n", + " ax.hist(w, bins=50, edgecolor=\"black\", alpha=0.7, density=True)\n", + " ax.set_title(name.replace(\"actor_backbone.\", \"\"), fontsize=7)\n", + " ax.axvline(0, color=\"red\", ls=\"--\", lw=0.5)\n", + " ax.text(0.95, 0.95, f\"std={w.std():.3f}\", transform=ax.transAxes, fontsize=6, ha=\"right\", va=\"top\")\n", + "\n", + "for j in range(i + 1, len(axes)):\n", + " axes[j].axis(\"off\")\n", + "\n", + "fig.suptitle(\"Weight Distributions (init)\", fontsize=12, fontweight=\"bold\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Activation Analysis (per encoder)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "policy.eval()\n", + "with torch.no_grad():\n", + " hidden = policy.actor_backbone(obs_tensor, EGO_DIM)\n", + " action_logits, value = policy.decode_actions(hidden)\n", + "\n", + "# Collect per-encoder activations\n", + "activations = {}\n", + "with torch.no_grad():\n", + " slide = EGO_DIM\n", + " activations[\"ego\"] = backbone.ego_encoder(obs_tensor[:, :EGO_DIM])\n", + "\n", + " if cond_dim > 0:\n", + " activations[\"conditioning\"] = backbone.conditioning_encoder(obs_tensor[:, slide : slide + cond_dim])\n", + " slide += cond_dim\n", + "\n", + " p_obs = obs_tensor[:, slide : slide + partner_dim].view(-1, MAX_PARTNERS, PARTNER_F)\n", + " activations[\"partner\"], _ = backbone.partner_encoder(p_obs).max(dim=1)\n", + " slide += partner_dim\n", + "\n", + " l_obs = obs_tensor[:, slide : slide + lane_dim].view(-1, MAX_LANES, ROAD_F)\n", + " activations[\"lane\"], _ = backbone.lane_encoder(l_obs).max(dim=1)\n", + " slide += lane_dim\n", + "\n", + " b_obs = obs_tensor[:, slide : slide + boundary_dim].view(-1, MAX_BOUNDS, ROAD_F)\n", + " activations[\"boundary\"], _ = backbone.boundary_encoder(b_obs).max(dim=1)\n", + " slide += boundary_dim\n", + "\n", + " t_obs = obs_tensor[:, slide : slide + traffic_dim].view(-1, MAX_TRAFFIC, TRAFFIC_F)\n", + " t_cont = t_obs[:, :, : TRAFFIC_F - 1]\n", + " t_cat = t_obs[:, :, TRAFFIC_F - 1]\n", + " t_onehot = F.one_hot(t_cat.long(), num_classes=4)\n", + " t_input = torch.cat([t_cont, t_onehot], dim=2)\n", + " activations[\"traffic_ctrl\"], _ = backbone.traffic_light_encoder(t_input).max(dim=1)\n", + "\n", + " activations[\"hidden\"] = hidden\n", + "\n", + "fig, axes = plt.subplots(2, 4, figsize=(16, 6))\n", + "axes = axes.flatten()\n", + "for i, (name, act) in enumerate(activations.items()):\n", + " if i >= len(axes):\n", + " break\n", + " vals = act.cpu().numpy().flatten()\n", + " ax = axes[i]\n", + " ax.hist(vals, bins=50, edgecolor=\"black\", alpha=0.7)\n", + " dead = (act.abs().sum(dim=0) == 0).sum().item()\n", + " ax.set_title(f\"{name} (dead={dead}/{act.shape[1]})\", fontsize=9)\n", + " ax.text(\n", + " 0.95,\n", + " 0.95,\n", + " f\"mean={vals.mean():.3f}\\nstd={vals.std():.3f}\",\n", + " transform=ax.transAxes,\n", + " fontsize=7,\n", + " ha=\"right\",\n", + " va=\"top\",\n", + " )\n", + "\n", + "for j in range(i + 1, len(axes)):\n", + " axes[j].axis(\"off\")\n", + "\n", + "fig.suptitle(\"Per-Encoder Activation Distributions\", fontsize=12, fontweight=\"bold\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Encoder Embedding Similarity (cosine)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Mean embedding per encoder (exclude hidden — different dim)\n", + "emb_names = [k for k in activations.keys() if k != \"hidden\"]\n", + "emb_means = torch.stack([activations[k].mean(dim=0) for k in emb_names])\n", + "emb_norm = F.normalize(emb_means, dim=1)\n", + "sim_matrix = (emb_norm @ emb_norm.T).cpu().numpy()\n", + "\n", + "fig, ax = plt.subplots(figsize=(7, 6))\n", + "im = ax.imshow(sim_matrix, cmap=\"RdBu_r\", vmin=-1, vmax=1)\n", + "ax.set_xticks(range(len(emb_names)))\n", + "ax.set_yticks(range(len(emb_names)))\n", + "ax.set_xticklabels(emb_names, rotation=45, ha=\"right\", fontsize=8)\n", + "ax.set_yticklabels(emb_names, fontsize=8)\n", + "for i in range(len(emb_names)):\n", + " for j in range(len(emb_names)):\n", + " ax.text(j, i, f\"{sim_matrix[i, j]:.2f}\", ha=\"center\", va=\"center\", fontsize=7)\n", + "fig.colorbar(im, ax=ax)\n", + "ax.set_title(\"Cosine Similarity Between Encoder Mean Embeddings\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Architecture Comparison\n", + "Compare different architecture configs side-by-side without training." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "configs = [\n", + " {\"name\": \"tiny\", \"input_size\": 32, \"backbone_hidden_size\": 64},\n", + " {\"name\": \"small\", \"input_size\": 64, \"backbone_hidden_size\": 128},\n", + " {\"name\": \"medium\", \"input_size\": 128, \"backbone_hidden_size\": 256, \"backbone_num_layers\": 2},\n", + " {\n", + " \"name\": \"large\",\n", + " \"input_size\": 128,\n", + " \"backbone_hidden_size\": 512,\n", + " \"backbone_num_layers\": 2,\n", + " \"actor_num_layers\": 2,\n", + " \"actor_hidden_size\": 256,\n", + " \"critic_num_layers\": 2,\n", + " \"critic_hidden_size\": 256,\n", + " },\n", + " {\n", + " \"name\": \"xlarge\",\n", + " \"input_size\": 256,\n", + " \"backbone_hidden_size\": 1024,\n", + " \"backbone_num_layers\": 3,\n", + " \"actor_num_layers\": 2,\n", + " \"actor_hidden_size\": 512,\n", + " \"critic_num_layers\": 2,\n", + " \"critic_hidden_size\": 512,\n", + " },\n", + " {\"name\": \"small+giga\", \"input_size\": 64, \"backbone_hidden_size\": 128, \"encoder_gigaflow\": True, \"dropout\": 0.1},\n", + " {\n", + " \"name\": \"medium+giga\",\n", + " \"input_size\": 128,\n", + " \"backbone_hidden_size\": 256,\n", + " \"backbone_num_layers\": 2,\n", + " \"encoder_gigaflow\": True,\n", + " \"dropout\": 0.1,\n", + " },\n", + "]\n", + "\n", + "POLICY_DEFAULTS = {\n", + " \"backbone_num_layers\": 1,\n", + " \"actor_hidden_size\": 128,\n", + " \"actor_num_layers\": 0,\n", + " \"critic_hidden_size\": 128,\n", + " \"critic_num_layers\": 0,\n", + " \"encoder_gigaflow\": False,\n", + " \"dropout\": 0.0,\n", + " \"split_network\": False,\n", + "}\n", + "\n", + "results = []\n", + "for cfg in configs:\n", + " name = cfg.pop(\"name\")\n", + " full_cfg = {**POLICY_DEFAULTS, **cfg}\n", + " p = DrivePolicy(env, **full_cfg).to(device)\n", + " n_params = sum(pp.numel() for pp in p.parameters())\n", + "\n", + " with torch.no_grad():\n", + " import time\n", + "\n", + " t0 = time.time()\n", + " for _ in range(100):\n", + " p(obs_tensor)\n", + " if device.type == \"cuda\":\n", + " torch.cuda.synchronize()\n", + " ms_per_fwd = (time.time() - t0) / 100 * 1000\n", + "\n", + " results.append({\"name\": name, \"params\": n_params, \"ms/fwd\": ms_per_fwd, **cfg})\n", + " cfg[\"name\"] = name # restore\n", + " del p\n", + "\n", + "print(\n", + " f\"{'Config':>12s} | {'input':>5s} | {'bb_h':>5s} | {'bb_L':>4s} | {'act_h':>5s} | {'act_L':>5s} | {'crt_h':>5s} | {'crt_L':>5s} | {'giga':>5s} | {'Params':>10s} | {'ms/fwd':>8s}\"\n", + ")\n", + "print(\"-\" * 105)\n", + "for r in results:\n", + " print(\n", + " f\"{r['name']:>12s} | {r['input_size']:>5d} | {r.get('backbone_hidden_size', 1024):>5d} | {r.get('backbone_num_layers', 1):>4d} | {r.get('actor_hidden_size', 1024):>5d} | {r.get('actor_num_layers', 1):>5d} | {r.get('critic_hidden_size', 1024):>5d} | {r.get('critic_num_layers', 1):>5d} | {str(r.get('encoder_gigaflow', False)):>5s} | {r['params']:>10,d} | {r['ms/fwd']:>7.2f}ms\"\n", + " )\n", + "\n", + "fig, axes = plt.subplots(1, 2, figsize=(14, 4))\n", + "names = [r[\"name\"] for r in results]\n", + "params = [r[\"params\"] for r in results]\n", + "times = [r[\"ms/fwd\"] for r in results]\n", + "\n", + "bar_colors = [\"coral\" if r.get(\"encoder_gigaflow\") else \"steelblue\" for r in results]\n", + "\n", + "axes[0].bar(names, params, color=bar_colors, edgecolor=\"black\")\n", + "axes[0].set_ylabel(\"Parameters\")\n", + "axes[0].set_title(\"Parameter Count (orange=gigaflow)\")\n", + "axes[0].tick_params(axis=\"x\", rotation=30)\n", + "for i, v in enumerate(params):\n", + " axes[0].text(i, v, f\"{v:,}\", ha=\"center\", va=\"bottom\", fontsize=7)\n", + "\n", + "axes[1].bar(names, times, color=bar_colors, edgecolor=\"black\")\n", + "axes[1].set_ylabel(\"ms / forward\")\n", + "axes[1].set_title(f\"Forward Pass Latency ({NUM_AGENTS} agents)\")\n", + "axes[1].tick_params(axis=\"x\", rotation=30)\n", + "for i, v in enumerate(times):\n", + " axes[1].text(i, v, f\"{v:.2f}\", ha=\"center\", va=\"bottom\", fontsize=7)\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Observation Buffer Utilization\n", + "How much of each observation slot is actually filled (non-zero)?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run a few steps to get diverse observations\n", + "actions = np.zeros((NUM_AGENTS, len(env.single_action_space.nvec)), dtype=np.int64)\n", + "all_obs = [obs]\n", + "for _ in range(20):\n", + " o, _, _, _, _ = env.step(actions)\n", + " all_obs.append(o)\n", + "stacked = np.concatenate(all_obs, axis=0)\n", + "\n", + "slide = EGO_DIM\n", + "segments = [(\"ego\", 0, EGO_DIM, 1, EGO_DIM)]\n", + "if cond_dim > 0:\n", + " segments.append((\"conditioning\", slide, slide + cond_dim, 1, cond_dim))\n", + " slide += cond_dim\n", + "segments.append((\"partners\", slide, slide + partner_dim, MAX_PARTNERS, PARTNER_F))\n", + "slide += partner_dim\n", + "segments.append((\"lanes\", slide, slide + lane_dim, MAX_LANES, ROAD_F))\n", + "slide += lane_dim\n", + "segments.append((\"boundaries\", slide, slide + boundary_dim, MAX_BOUNDS, ROAD_F))\n", + "slide += boundary_dim\n", + "segments.append((\"traffic\", slide, slide + traffic_dim, MAX_TRAFFIC, TRAFFIC_F))\n", + "\n", + "print(f\"{'Segment':>15s} | {'Slots':>5s} | {'Features':>8s} | {'Fill %':>7s} | {'Mean':>8s} | {'Std':>8s}\")\n", + "print(\"-\" * 65)\n", + "fill_rates = []\n", + "seg_names = []\n", + "for name, start, end, n_slots, n_feat in segments:\n", + " chunk = stacked[:, start:end]\n", + " if n_slots > 1:\n", + " reshaped = chunk.reshape(-1, n_slots, n_feat)\n", + " # A slot is \"filled\" if any feature is non-zero\n", + " filled = (np.abs(reshaped).sum(axis=2) > 1e-8).mean()\n", + " else:\n", + " filled = (np.abs(chunk) > 1e-8).mean()\n", + " fill_rates.append(filled * 100)\n", + " seg_names.append(name)\n", + " print(f\"{name:>15s} | {n_slots:>5d} | {n_feat:>8d} | {filled:>6.1%} | {chunk.mean():>8.4f} | {chunk.std():>8.4f}\")\n", + "\n", + "fig, ax = plt.subplots(figsize=(8, 4))\n", + "colors = [\"#2ecc71\" if f > 50 else \"#e74c3c\" if f < 10 else \"#f39c12\" for f in fill_rates]\n", + "ax.barh(seg_names, fill_rates, color=colors, edgecolor=\"black\")\n", + "ax.set_xlabel(\"Fill Rate (%)\")\n", + "ax.set_title(\"Observation Slot Utilization\")\n", + "ax.axvline(50, color=\"gray\", ls=\"--\", alpha=0.5)\n", + "for i, v in enumerate(fill_rates):\n", + " ax.text(v + 1, i, f\"{v:.1f}%\", va=\"center\", fontsize=8)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## LSTM Wrapper Architecture" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "base_policy = DrivePolicy(\n", + " env,\n", + " input_size=INPUT_SIZE,\n", + " backbone_hidden_size=BACKBONE_HIDDEN_SIZE,\n", + " backbone_num_layers=BACKBONE_NUM_LAYERS,\n", + " actor_hidden_size=ACTOR_HIDDEN_SIZE,\n", + " actor_num_layers=ACTOR_NUM_LAYERS,\n", + " critic_hidden_size=CRITIC_HIDDEN_SIZE,\n", + " critic_num_layers=CRITIC_NUM_LAYERS,\n", + " encoder_gigaflow=ENCODER_GIGAFLOW,\n", + " dropout=DROPOUT,\n", + " split_network=SPLIT_NETWORK,\n", + ").to(device)\n", + "# LSTM input_size must match backbone_hidden_size (backbone output dim)\n", + "lstm_policy = Recurrent(env, base_policy, input_size=BACKBONE_HIDDEN_SIZE, hidden_size=BACKBONE_HIDDEN_SIZE).to(device)\n", + "\n", + "base_params = sum(p.numel() for p in base_policy.parameters())\n", + "lstm_params = sum(p.numel() for p in lstm_policy.parameters())\n", + "lstm_only = lstm_params - base_params\n", + "\n", + "print(f\"Base policy params: {base_params:>10,d}\")\n", + "print(f\"LSTM wrapper params: {lstm_params:>10,d}\")\n", + "print(f\"LSTM overhead: {lstm_only:>10,d} (+{lstm_only / base_params:.1%})\")\n", + "print()\n", + "\n", + "# torchinfo can't handle LSTMWrapper (requires state dict), so manual breakdown\n", + "print(f\"{'Component':>25s} | {'Params':>10s}\")\n", + "print(\"-\" * 40)\n", + "for name, module in lstm_policy.named_children():\n", + " n = sum(p.numel() for p in module.parameters())\n", + " print(f\"{name:>25s} | {n:>10,d}\")\n", + "print()\n", + "\n", + "# Verify forward pass works with proper state\n", + "# forward_eval uses LSTMCell which expects 2D state (batch, hidden)\n", + "with torch.no_grad():\n", + " state = {\n", + " \"lstm_h\": torch.zeros(NUM_AGENTS, BACKBONE_HIDDEN_SIZE, device=device),\n", + " \"lstm_c\": torch.zeros(NUM_AGENTS, BACKBONE_HIDDEN_SIZE, device=device),\n", + " }\n", + " actions, value = lstm_policy.forward_eval(obs_tensor, state)\n", + " if isinstance(actions, (list, tuple)):\n", + " print(f\"Forward eval OK: actions={[a.shape for a in actions]}, value={value.shape}\")\n", + " else:\n", + " print(f\"Forward eval OK: actions={actions}, value={value.shape}\")\n", + "\n", + "del base_policy, lstm_policy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Effective Receptive Field\n", + "Which input features have the most influence on the hidden representation?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Jacobian-based sensitivity: d(hidden) / d(obs) magnitude\n", + "sample = obs_tensor[:1].clone().requires_grad_(True)\n", + "hidden = policy.actor_backbone(sample, EGO_DIM)\n", + "# Sum hidden to scalar for backward\n", + "hidden.sum().backward()\n", + "sensitivity = sample.grad.abs().squeeze().cpu().numpy()\n", + "\n", + "fig, axes = plt.subplots(2, 1, figsize=(14, 6), gridspec_kw={\"height_ratios\": [2, 1]})\n", + "\n", + "# Full sensitivity\n", + "axes[0].plot(sensitivity, lw=0.5, color=\"steelblue\")\n", + "axes[0].set_ylabel(\"|grad|\")\n", + "axes[0].set_title(\"Input Feature Sensitivity (|d hidden / d obs|)\")\n", + "\n", + "# Mark segments\n", + "seg_boundaries = [0, EGO_DIM]\n", + "seg_labels = [\"ego\"]\n", + "s = EGO_DIM\n", + "if cond_dim > 0:\n", + " s += cond_dim\n", + " seg_boundaries.append(s)\n", + " seg_labels.append(\"cond\")\n", + "for name, dim in [\n", + " (\"partners\", partner_dim),\n", + " (\"lanes\", lane_dim),\n", + " (\"boundaries\", boundary_dim),\n", + " (\"traffic\", traffic_dim),\n", + "]:\n", + " s += dim\n", + " seg_boundaries.append(s)\n", + " seg_labels.append(name)\n", + "\n", + "seg_colors = plt.cm.Set2(np.linspace(0, 1, len(seg_labels)))\n", + "for i, (label, c) in enumerate(zip(seg_labels, seg_colors)):\n", + " start, end = seg_boundaries[i], seg_boundaries[i + 1]\n", + " axes[0].axvspan(start, end, alpha=0.15, color=c)\n", + " axes[0].text((start + end) / 2, axes[0].get_ylim()[1] * 0.9, label, ha=\"center\", fontsize=7, color=\"black\")\n", + "\n", + "# Per-segment mean sensitivity\n", + "seg_means = []\n", + "for i in range(len(seg_labels)):\n", + " start, end = seg_boundaries[i], seg_boundaries[i + 1]\n", + " seg_means.append(sensitivity[start:end].mean())\n", + "\n", + "axes[1].bar(seg_labels, seg_means, color=seg_colors, edgecolor=\"black\")\n", + "axes[1].set_ylabel(\"Mean |grad|\")\n", + "axes[1].set_title(\"Mean Sensitivity per Observation Segment\")\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "policy.zero_grad()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/pufferlib/__init__.py b/pufferlib/__init__.py index 7fb2007e2b..95f71d92db 100644 --- a/pufferlib/__init__.py +++ b/pufferlib/__init__.py @@ -2,13 +2,6 @@ import os -path = __path__[0] -link_to = os.path.join(path, "resources") -try: - os.symlink(link_to, "resources") -except FileExistsError: - pass - # Silence noisy dependencies import warnings diff --git a/pufferlib/config/default.ini b/pufferlib/config/default.ini index 72ce8e0502..1b5dc26d64 100644 --- a/pufferlib/config/default.ini +++ b/pufferlib/config/default.ini @@ -22,10 +22,10 @@ name = pufferai project = ablations seed = 42 -torch_deterministic = True +torch_deterministic = False cpu_offload = False device = cuda -optimizer = muon +optimizer = adam anneal_lr = True precision = float32 total_timesteps = 10_000_000 @@ -49,7 +49,7 @@ minibatch_size = 8192 # Accumulate gradients above this size max_minibatch_size = 32768 -rollout_horizon = 64 +bptt_horizon = 64 compile = False compile_mode = max-autotune-no-cudagraphs compile_fullgraph = True @@ -60,6 +60,11 @@ vtrace_c_clip = 1.0 prio_alpha = 0.8 prio_beta0 = 0.2 +ppo_granularity = auto +adv_filter_ewma_beta = 0.25 +adv_filter_threshold_scale = 0.01 +symlog_rewards = False + [sweep] method = Protein metric = score @@ -81,7 +86,7 @@ downsample = 10 ; mean = 1e8 ; scale = time -; [sweep.train.rollout_horizon] +; [sweep.train.bptt_horizon] ; distribution = uniform_pow2 ; min = 16 ; max = 64 diff --git a/pufferlib/config/ocean/drive.ini b/pufferlib/config/ocean/drive.ini index e7224203d2..3b99087be4 100644 --- a/pufferlib/config/ocean/drive.ini +++ b/pufferlib/config/ocean/drive.ini @@ -2,179 +2,355 @@ package = ocean env_name = puffer_drive policy_name = Drive -; Set to None to disable recurrence. In case this the policy will only see -; the current observation (o_t). Set to "Recurrent" to provide the policy with -; memory through an LSTM. -rnn_name = Recurrent +;Options: Recurrent, None +rnn_name = None [vec] -num_workers = 16 -num_envs = 16 -batch_size = 4 -;backend = Serial +num_envs = 8 +num_workers = auto +batch_size = auto +; backend = Serial [policy] input_size = 64 -hidden_size = 256 +backbone_hidden_size = 512 +backbone_num_layers = 4 +actor_hidden_size = 512 +actor_num_layers = 0 +critic_hidden_size = 512 +critic_num_layers = 0 +; True for GF network, False for LSTM one +split_network = False +encoder_gigaflow = True +dropout = 0.0 [rnn] -input_size = 256 -hidden_size = 256 +input_size = 512 +hidden_size = 512 [env] +; Options: "gigaflow", "replay" +simulation_mode = "gigaflow" +; Reward conditioning +reward_conditioning = False +; Reward randomization +reward_randomization = False +; Total number of agents in the environment num_agents = 1024 -; Options: discrete, continuous -action_type = discrete -; Options: classic, jerk -dynamics_model = classic -reward_vehicle_collision = -0.5 -reward_offroad_collision = -0.5 +; GIGAFLOW-specific: minimum number of agents per environment +min_agents_per_env = 1 +; GIGAFLOW-specific: maximum number of agents per environment +max_agents_per_env = 80 +; Actions type - options: "discrete", "continuous" +action_type = "discrete" +; Dynamics model - options: "classic", "jerk" +dynamics_model = "jerk" +; Time delta between steps in seconds dt = 0.1 +; Optional nonzero launch speed for gigaflow random spawns +spawn_initial_speed = 0.0 +; Target representation - options: "static", "dynamic" +target_type = "static" +; Collision behavior - options: 0 - Ignore, 1 - Stop, 2 - Remove +collision_behavior = 1 +; Offroad behavior - options: 0 - Ignore, 1 - Stop, 2 - Remove +offroad_behavior = 1 +; Traffic light behavior - options: 0 - Ignore, 1 - Stop, 2 - Remove +traffic_light_behavior = 1 +; Reward coefficients reward_goal = 1.0 -reward_goal_post_respawn = 0.25 +reward_vehicle_collision = 3.0 +reward_offroad_collision = 3.0 +reward_comfort = 0.05 +reward_lane_align = 0.025 +reward_vel_align = 1.0 +reward_lane_center = 0.0038 +reward_center_bias = 0.0 +reward_velocity = 0.0025 +reward_reverse = 0.005 +reward_traffic_light_violation = 1.0 +reward_timestep = 0.000025 +reward_overspeed = 0.05 +reward_ade = 0.0 ; Meters around goal to be considered "reached" goal_radius = 2.0 -; Max target speed in m/s for the agent to maintain towards the goal -goal_speed = 100.0 -; What to do when the goal is reached. Options: 0:"respawn", 1:"generate_new_goals", 2:"stop" -goal_behavior = 0 -; Determines the target distance to the new goal in the case of goal_behavior = generate_new_goals. -; Large numbers will select a goal point further away from the agent's current position. -goal_target_distance = 30.0 -; Options: 0 - Ignore, 1 - Stop, 2 - Remove -collision_behavior = 0 -; Options: 0 - Ignore, 1 - Stop, 2 - Remove -offroad_behavior = 0 -; Number of steps before -episode_length = 91 -resample_frequency = 910 -termination_mode = 1 # 0 - terminate at episode_length, 1 - terminate after all agents have been reset -map_dir = "resources/drive/binaries/training" -num_maps = 10000 +; Number of target waypoints in the observation (including goal) +num_target_waypoints = 3 +; Waypoint spacing range in meters when building path +min_waypoint_spacing = 20.0 +max_waypoint_spacing = 60.0 +; Number of steps before reset +scenario_length = 1024 +; Frequency of resampling scenario (in steps), 0 to disable +resample_frequency = 102_400_000 +; End of episode - options: 0 - scenario_length, 1 - early reset when too many agents are removed +termination_mode = 1 +; Ratio of inactive agents (stopped/removed) that triggers early reset (used when termination_mode = 1) +inactive_agent_threshold = 0.4 +; Path to map used for training +map_dir = "pufferlib/resources/drive/binaries/carla" +; Number of maps to load from map_dir +num_maps = 8 ; Determines which step of the trajectory to initialize the agents at upon reset init_steps = 0 -; Options: "control_vehicles", "control_agents", "control_wosac", "control_sdc_only", "control_mixed_play" -control_mode = "control_agents" +; options: "control_vehicles", "control_agents", "control_tracks_to_predict", "control_sdc_only" +control_mode = "control_vehicles" ; Options: "created_all_valid", "create_only_controlled" init_mode = "create_all_valid" -; Sets the maximum number of controllable agents per scene, ONLY used if control_mode is "control_mixed_play" -max_controlled_agents = 32 -; Render mode options: -; 0:"window" = pop-up raylib window (original) -; 1:"headless" = off-screen; frames piped to ffmpeg (recommended for training) -render_mode = 1 +; Enable computation of evaluation-only metrics +compute_eval_metrics = True +; Use rear-axle coordinates for trajectory planning/control while keeping sim_x/sim_y at vehicle center +use_rear_axle = True +; Max number of observations +max_lane_segment_observations = 64 +max_boundary_segment_observations = 32 +max_partner_observations = 20 +max_traffic_light_observations = 4 +max_stop_sign_observations = 0 [train] -seed=42 -total_timesteps = 2_000_000_000 -; learning_rate = 0.02 -; gamma = 0.985 +total_timesteps = 10_000_000_000 anneal_lr = True -anneal_entropy = False -; Needs to be: num_agents * num_workers * rollout_horizon -batch_size = 524288 -minibatch_size = 32768 -max_minibatch_size = 32768 -; bptt_horizon equals rollout_horizon at the moment. -; If you want to turn off recurrence, set rnn_name = None in [base] -rollout_horizon = 32 +; Needs to be: num_agents * num_workers * BPTT horizon +batch_size = auto +minibatch_size = 65_536 +max_minibatch_size = 65_536 +bptt_horizon = 128 adam_beta1 = 0.9 adam_beta2 = 0.999 adam_eps = 1e-8 clip_coef = 0.2 -ent_coef = 0.005 +ent_coef = 0.01 gae_lambda = 0.95 -gamma = 0.98 -learning_rate = 0.003 -max_grad_norm = 1 +gamma = 0.99 +learning_rate = 0.0005 +max_grad_norm = 0.5 prio_alpha = 0.8499999999999999 prio_beta0 = 0.8499999999999999 update_epochs = 1 vf_clip_coef = 0.1999999999999999 -vf_coef = 2 +vf_coef = 0.5 vtrace_c_clip = 1 vtrace_rho_clip = 1 -checkpoint_interval = 1000 +ppo_granularity = auto +adv_filter_ewma_beta = 0.25 +adv_filter_threshold_scale = 0.01 +checkpoint_interval = 50 +log_interval = 10 +; Rendering options +render = False +render_interval = 1000 +; If True, show exactly what the agent sees in agent observation +obs_only = True +; Show grid lines +show_grid = False +; Draws lines from ego agent observed ORUs and road elements to show detection range +show_lasers = False +; Display human xy logs in the background +show_human_logs = True +; Options: List[str to path], str to path (e.g., "resources/drive/training/binaries/map_001.bin"), None +render_map = pufferlib/resources/drive/binaries/carla/opendrive__Town01.bin [eval] -; Eval frequency in epochs -eval_interval = 500 +; Set to True to enable periodic multi-scenario evaluation during training +multi_scenario_eval = False +; Frequency of evaluation during training (in epochs) +eval_interval = 25 +num_agents = 512 +; Batch size for eval_multi_scenarios (number of scenarios per batch) ; Path to dataset used for evaluation -map_dir = "resources/drive/binaries/training" -; Number of agents to evaluate -num_eval_agents = 64 -; If True, enable self-play evaluation (pair policy-controlled agent with a copy of itself) -self_play_eval = True -; If True, enable human replay evaluation (pair policy-controlled agent with human replays) -human_replay_eval = False -; Which env to render during eval. Options: "first" (by index), "worst_collision", "random" -render_select_mode = "first" -; If True, render random scenarios. Note: Doing this frequency will slow down the training. -render_human_replay_eval = False -render_self_play_eval = True -; Number of scenarios to process per batch -wosac_batch_size = 32 -; Target number of unique scenarios perform evaluation in -wosac_target_scenarios = 64 -; Total pool of scenarios to sample from -wosac_scenario_pool_size = 1000 -; Max batches, used as a timeout to prevent an infinite loop -wosac_max_batches = 100 +map_dir = "pufferlib/resources/drive/binaries/eval" +; Simulation mode for evaluation: "gigaflow" or "replay" +multi_scenario_simulation_mode = "replay" +; Total number of scenarios to evaluate +multi_scenario_num_scenarios = 250 backend = PufferEnv ; WOSAC (Waymo Open Sim Agents Challenge) evaluation settings ; If True, enables evaluation on realism metrics each time we save a checkpoint wosac_realism_eval = False -; Number of policy rollouts per scene -wosac_num_rollouts = 32 -; When to start the simulation -wosac_init_steps = 10 -; Control everything valid at init in the scene -wosac_control_mode = "control_wosac" -; Create everything in valid at init the scene -wosac_init_mode = "create_all_valid" -; Stop when reaching the goal -wosac_goal_behavior = 2 -; Can shrink goal radius for WOSAC evaluation -wosac_goal_radius = 2.0 +wosac_num_rollouts = 32 ; Number of policy rollouts per scene +wosac_init_steps = 10 ; When to start the simulation +wosac_num_agents = 256 ; Total number of WOSAC agents to evaluate +wosac_control_mode = "control_wosac" ; Control the tracks to predict +wosac_init_mode = "create_all_valid" ; Initialize from the tracks to predict +wosac_goal_radius = 2.0 ; Can shrink goal radius for WOSAC evaluation wosac_sanity_check = False -; Only return aggregate results across all scenes -wosac_aggregate_results = True -; Evaluation mode: "policy", "ground_truth" -wosac_eval_mode = "policy" - -[sweep.train.learning_rate] -distribution = log_normal -min = 0.001 -mean = 0.003 -max = 0.005 -scale = auto - -[sweep.train.ent_coef] -distribution = log_normal -min = 0.001 -mean = 0.005 -max = 0.03 -scale = auto - -[sweep.train.gamma] -distribution = log_normal -min = 0.97 -mean = 0.98 -max = 0.999 -scale = auto - -[sweep.train.gae_lambda] -distribution = log_normal -min = 0.95 -mean = 0.98 -max = 0.999 -scale = auto - -[controlled_exp.train.goal_speed] -values = [10, 20, 30, 3] +wosac_aggregate_results = True ; Only return aggregate results across all scenes +; If True, enable human replay evaluation (pair policy-controlled agent with human replays) +human_replay_eval = False +human_replay_control_mode = "control_sdc_only" ; Control only the self-driving car +human_replay_num_agents = 64 ; This equals the number of scenarios, since we control one agent in each -[controlled_exp.train.ent_coef] -values = [0.001, 0.005, 0.01] +; [sweep.train.learning_rate] +; distribution = log_normal +; min = 0.0001 +; mean = 0.001 +; max = 0.002 +; scale = auto + +; [sweep.train.ent_coef] +; distribution = log_normal +; min = 0.0005 +; mean = 0.01 +; max = 0.02 +; scale = auto + +; [sweep.train.vf_clip_coef] +; distribution = log_normal +; min = 0.1 +; mean = 0.2 +; max = 3 +; scale = auto + +; [sweep.env.inactive_agent_threshold] +; distribution = log_normal +; min = 0.1 +; mean = 0.4 +; max = 1.0 +; scale = auto + +; [sweep.train.gamma] +; distribution = logit_normal +; min = 0.90 +; mean = 0.99 +; max = 0.9999 +; scale = auto + +; [sweep.train.max_grad_norm] +; distribution = uniform +; min = 0.2 +; mean = 0.5 +; max = 2.0 +; scale = auto + +; [sweep.train.update_epochs] +; distribution = int_uniform +; min = 1 +; mean = 1 +; max = 6 +; scale = auto + +; [sweep.train.vf_coef] +; distribution = uniform +; min = 0.2 +; mean = 0.5 +; max = 3.0 +; scale = auto + +; [sweep.train.vtrace_rho_clip] +; distribution = uniform +; min = 0.0 +; max = 5.0 +; mean = 1.0 +; scale = auto + +; [sweep.train.vtrace_c_clip] +; distribution = uniform +; min = 0.0 +; max = 5.0 +; mean = 1.0 +; scale = auto + +; [sweep.train.clip_coef] +; distribution = uniform +; min = 0.01 +; max = 1.0 +; mean = 0.2 +; scale = auto -[controlled_exp.train.seed] -values = [42, 55, 1] +; [sweep.train.gae_lambda] +; distribution = logit_normal +; min = 0.8 +; mean = 0.95 +; max = 0.995 +; scale = auto + +; [sweep.policy.actor_num_layers] +; distribution = int_uniform +; min = 1 +; mean = 1 +; max = 2 +; scale = auto + +; [sweep.policy.critic_num_layers] +; distribution = int_uniform +; min = 1 +; mean = 1 +; max = 2 +; scale = auto + +; [sweep.env.reward_goal] +; distribution = uniform +; min = 0.0 +; mean = 0.5 +; max = 1.0 +; scale = auto + +; [sweep.env.reward_under_speed] +; distribution = uniform +; min = 0.0 +; mean = 0.05 +; max = 0.2 +; scale = auto + +; [sweep.env.reward_comfort] +; distribution = uniform +; min = 0.0 +; mean = 0.5 +; max = 1.0 +; scale = auto + +; [sweep.env.reward_lane_align] +; distribution = uniform +; min = 0.0 +; mean = 0.5 +; max = 1.0 +; scale = auto + +; [sweep.env.reward_lane_center] +; distribution = uniform +; min = 0.0 +; mean = 0.5 +; max = 1.0 +; scale = auto + +; [sweep.env.reward_velocity] +; distribution = uniform +; min = 0.0 +; mean = 0.5 +; max = 1.0 +; scale = auto + +; [sweep.train.adam_beta1] +; distribution = logit_normal +; min = 0.7 +; mean = 0.9 +; max = 0.999 +; scale = auto + +; [sweep.train.adam_beta2] +; distribution = logit_normal +; min = 0.99 +; mean = 0.999 +; max = 0.9999 +; scale = auto + +; [sweep.train.prio_alpha] +; distribution = logit_normal +; min = 0.7 +; mean = 0.85 +; max = 0.99 +; scale = auto + +; [sweep.train.prio_beta0] +; distribution = logit_normal +; min = 0.7 +; mean = 0.85 +; max = 0.99 +; scale = auto + +[controlled_exp.train.learning_rate] +values = [0.001, 0.003, 0.01] + +[controlled_exp.train.ent_coef] +values = [0.01, 0.005] diff --git a/pufferlib/ocean/benchmark/README.md b/pufferlib/ocean/benchmark/README.md new file mode 100644 index 0000000000..7bae42c2e8 --- /dev/null +++ b/pufferlib/ocean/benchmark/README.md @@ -0,0 +1,67 @@ +# Waymo Open Sim Agent Challenge (WOSAC) benchmark + +## Usage + +WOSAC evaluation with random policy +```bash +puffer eval puffer_drive --eval.wosac-realism-eval True +``` + +WOSAC evaluation with your checkpoint +```bash +puffer eval puffer_drive --eval.wosac-realism-eval True --load-model-path .pt +``` + +## Links + +- [Challenge and leaderboard](https://waymo.com/open/challenges/2025/sim-agents/) +- [Sim agent challenge tutorial](https://github.com/waymo-research/waymo-open-dataset/blob/master/tutorial/tutorial_sim_agents.ipynb) +- [Reference paper introducing WOSAC](https://arxiv.org/pdf/2305.12032) +- [Metrics entry point](https://github.com/waymo-research/waymo-open-dataset/blob/master/src/waymo_open_dataset/wdl_limited/sim_agents_metrics/metrics.py) +- [Log-likelihood estimators](https://github.com/waymo-research/waymo-open-dataset/blob/master/src/waymo_open_dataset/wdl_limited/sim_agents_metrics/estimators.py) +- Configurations [proto file](https://github.com/waymo-research/waymo-open-dataset/blob/99a4cb3ff07e2fe06c2ce73da001f850f628e45a/src/waymo_open_dataset/protos/sim_agents_metrics.proto#L51) [default sim agent challenge configs](https://github.com/waymo-research/waymo-open-dataset/blob/master/src/waymo_open_dataset/wdl_limited/sim_agents_metrics/challenge_2025_sim_agents_config.textproto) + + +## Implementation + +- For the sim agent challenge we compute the log likelihood with `aggregate_objects=False`, which means that we use [`_log_likelihood_estimate_timeseries_agent_level()`](https://github.com/waymo-research/waymo-open-dataset/blob/99a4cb3ff07e2fe06c2ce73da001f850f628e45a/src/waymo_open_dataset/wdl_limited/sim_agents_metrics/estimators.py#L17) +- As such, the interpretation is as follows: + +Steps [for every scene]: +1. Rollout policy in environment K times → (n_agents, n_rollouts, n_steps) +2. Obtain log data → (n_agents, 1, n_steps) +3. Obtain features from (x, y, z, heading tuples) +4. Compute log-likelihood metrics from features + - a. Flatten across time (assume independence) → (n_agents, n_rollouts * n_steps) + - b. Use the per-agent simulated features to construct a probability distribution + - c. Take the per-agent ground-truth values and find the bin that is closed for each + - d. Take log of the probability for each bin → (n_agents, n_steps) +5. Likelihood score is exp(sum(log_probs)/n_steps) → (n_agents, 1) \in [0, 1] + +## Notes + +- Currently, only kinematics realism score is implemented. Next steps would be to add the interactive realism score, and the map realism score: + + - Interactive realism score: requires grouping agents per scenario, and computing pairwise distances between agents over time. + - Map realism score: requires access to the map and computing offroad status. + + Those two scores might require heavy computations, so we will consider reimplementic all the metrics in torch. + +- About the time-independence assumption: + + 1. This is the assumption used in the official WOSAC evaluation, their argument is that it would give more flexibility to the sim agents models: + + > Given the time series nature of simulation data, two choices emerge for how to treat samples over multiple timesteps for a given object for a given run segment: to treat them as time-independent or time-dependent samples. In the latter case, users would be expected to not only reconstruct the general behaviors present in the logged data in one rollout, but also recreate those behaviors over the exact same time intervals. To allow more flexibility in agent behavior, we use the former formulation when computing NLLs, defining each component metric m as an average (in log-space) over the time-axis, masked by validity. + + 2. However this will lead to the score of a perfect logged oracle being inferior to 1.0, and makes it less interpretable. Here are the scores of a logged oracle using the time-independence assumption (setup: 1024 agents, 48 rollouts): + + ``` + Linear speed: 0.5640 + Linear acceleration: 0.4658 + Angular speed: 0.5543 + Angular acceleration: 0.6589 + Kinematics realism score: 0.5607 + ``` + These scores go to 1.0 if we use the time-dependent estimator, execpt for the smoothing factor that is used to avoid bins with 0 probability. + + Using the time-dependent estimator means generating n_steps histograms per agent, using num_rollouts samples per histogram, while time-independence means generating one histogram per agent using n_rollouts * n_steps samples. With the speed of PufferDrive, we might be able to increase n_rollouts to have more samples per histogram. diff --git a/pufferlib/ocean/benchmark/evaluator.py b/pufferlib/ocean/benchmark/evaluator.py index e1b61a731a..383384e623 100644 --- a/pufferlib/ocean/benchmark/evaluator.py +++ b/pufferlib/ocean/benchmark/evaluator.py @@ -1,17 +1,14 @@ """WOSAC evaluation class for PufferDrive.""" -import copy import torch import numpy as np import pandas as pd from typing import Dict import matplotlib.pyplot as plt -from tqdm import tqdm import configparser import os -import pufferlib -# WOSAC eval +import pufferlib from pufferlib.ocean.benchmark import metrics from pufferlib.ocean.benchmark import estimators @@ -39,106 +36,11 @@ def __init__(self, config: Dict): self.sim_steps = self.num_steps - self.init_steps self.num_rollouts = config.get("eval", {}).get("wosac_num_rollouts", 32) self.device = config.get("train", {}).get("device", "cuda") - self.eval_mode = config.get("eval", {}).get("wosac_eval_mode", "policy") wosac_metrics_path = os.path.join(os.path.dirname(__file__), "wosac.ini") self.metrics_config = configparser.ConfigParser() self.metrics_config.read(wosac_metrics_path) - def evaluate(self, args, vecenv, policy=None, drop_scene_duplicates=True): - """Run full WOSAC evaluation with batched iteration over target scenarios. - - Args: - args: Configuration dictionary - vecenv: Vectorized environment - policy: Policy to evaluate - drop_scene_duplicates: Whether to drop duplicate scenarios - - Returns: - DataFrame: Full results aggregated by scenario. - """ - num_target_maps = args["eval"]["wosac_target_scenarios"] - max_batches = args["eval"].get("wosac_max_batches", 100) - - unique_files_sampled = set() - combined_results = [] - - with tqdm(total=100, desc="Processing batches", unit="%", colour="cyan") as pbar: - batch_idx = 0 - while batch_idx < max_batches: - # Resample maps for each batch (except first) - if batch_idx > 0: - vecenv.driver_env.resample_maps() - - # Obtain ground truth trajectories - gt_trajectories = self.collect_ground_truth_trajectories(vecenv) - - # Collect simulated trajectories - if policy is not None and self.eval_mode == "policy": - simulated_trajectories = self.collect_simulated_trajectories(args, vecenv, policy) - elif self.eval_mode == "ground_truth": - # Create fake simulated trajectories by repeating ground truth - simulated_trajectories = gt_trajectories.copy() - for key in ["x", "y", "heading", "id"]: - simulated_trajectories[key] = np.repeat( - gt_trajectories[key], args["eval"]["wosac_num_rollouts"], axis=1 - ) - simulated_trajectories["id"] = simulated_trajectories["id"][..., np.newaxis] - else: - raise ValueError(f"Policy is None or unknown evaluation mode: {self.eval_mode}") - - # Compute metrics for this batch - agent_state = vecenv.driver_env.get_global_agent_state() - road_edge_polylines = vecenv.driver_env.get_road_edge_polylines() - batch_results = self.compute_metrics( - gt_trajectories, - simulated_trajectories, - agent_state, - road_edge_polylines, - aggregate_results=False, - ) - - # Optional: sanity check on first batch - if args["eval"].get("wosac_sanity_check", False) and batch_idx == 0: - self._quick_sanity_check(gt_trajectories, simulated_trajectories) - - # Track coverage - unique_files_sampled.update(str(s) for s in np.unique(gt_trajectories["scenario_id"])) - combined_results.append(batch_results) - - # Update progress - coverage = len(unique_files_sampled) / num_target_maps - pbar.n = int(coverage * 100) - pbar.set_postfix({"n": len(unique_files_sampled), "batch": batch_idx + 1}) - pbar.refresh() - - batch_idx += 1 - - # Stop if we've covered all target scenarios - if len(unique_files_sampled) >= num_target_maps: - break - - # Check if we didn't reach target coverage - if len(unique_files_sampled) < num_target_maps: - print( - f"\nWarning: Only covered {len(unique_files_sampled)}/{num_target_maps} scenarios after {batch_idx} batches" - ) - - # Combine batch results into single dataframe - df_combined = pd.concat(combined_results) - - # Optionally drop duplicate scenarios (keep first occurrence) - if drop_scene_duplicates: - initial_count = len(df_combined) - df_combined = df_combined[~df_combined.index.duplicated(keep="first")] - dropped = initial_count - len(df_combined) - if dropped > 0: - print(f"\nDropped {dropped} duplicate scenarios.") - - print(f"\nCollected {len(df_combined)} agent records from {batch_idx} batches") - - return df_combined - def _compute_metametric(self, metrics: pd.Series) -> float: metametric = 0.0 for field_name in _METRIC_FIELD_NAMES: @@ -146,7 +48,9 @@ def _compute_metametric(self, metrics: pd.Series) -> float: weight = self.metrics_config.getfloat(field_name, "metametric_weight") metric_score = metrics[likelihood_field_name] metametric += weight * metric_score - return metametric + + weight_sum = sum(self.metrics_config.getfloat(fn, "metametric_weight") for fn in _METRIC_FIELD_NAMES) + return metametric / weight_sum def _get_histogram_params(self, metric_name: str): return ( @@ -217,53 +121,6 @@ def collect_simulated_trajectories(self, args, puffer_env, policy): return trajectories - def collect_wosac_random_baseline(self, puffer_env): - """ - Random Baseline from Wosac 2023 paper - """ - driver = puffer_env.driver_env - num_agents = puffer_env.observation_space.shape[0] - - trajectories = { - "x": np.zeros((num_agents, self.num_rollouts, self.sim_steps), dtype=np.float32), - "y": np.zeros((num_agents, self.num_rollouts, self.sim_steps), dtype=np.float32), - "heading": np.zeros((num_agents, self.num_rollouts, self.sim_steps), dtype=np.float32), - "id": np.zeros((num_agents, self.num_rollouts, self.sim_steps), dtype=np.int32), - } - - for rollout_idx in range(self.num_rollouts): - obs, info = puffer_env.reset() - - # Do Initialization - agent_state = driver.get_global_agent_state() - trajectories["x"][:, rollout_idx, 0] = agent_state["x"] - trajectories["y"][:, rollout_idx, 0] = agent_state["y"] - trajectories["heading"][:, rollout_idx, 0] = agent_state["heading"] - trajectories["id"][:, rollout_idx, 0] = agent_state["id"] - - # Update using Gaussian: - samples = np.random.normal(loc=1, scale=0.1, size=(num_agents, self.sim_steps, 3)) - for time_idx in range(1, self.sim_steps): - dx, dy, d_heading = samples[:, time_idx, 0], samples[:, time_idx, 1], samples[:, time_idx, 2] - x, y, heading = ( - trajectories["x"][:, rollout_idx, time_idx - 1], - trajectories["y"][:, rollout_idx, time_idx - 1], - trajectories["heading"][:, rollout_idx, time_idx - 1], - ) - - cos_h = np.cos(heading) - sin_h = np.sin(heading) - - x += dx * cos_h - dy * sin_h - y += dx * sin_h + dy * cos_h - heading += d_heading - - trajectories["x"][:, rollout_idx, time_idx] = x - trajectories["y"][:, rollout_idx, time_idx] = y - trajectories["heading"][:, rollout_idx, time_idx] = heading - - return trajectories - def compute_metrics( self, ground_truth_trajectories: Dict, @@ -290,7 +147,7 @@ def compute_metrics( "Agent IDs don't match between simulated and ground truth trajectories" ) - eval_mask = ground_truth_trajectories["is_track_to_predict"][:, 0] + eval_mask = ground_truth_trajectories["id"][:, 0] >= 0 # Extract trajectories sim_x = simulated_trajectories["x"] @@ -302,11 +159,8 @@ def compute_metrics( ref_valid = ground_truth_trajectories["valid"] agent_length = agent_state["length"] agent_width = agent_state["width"] - is_vehicle = ground_truth_trajectories["is_vehicle"] scenario_ids = ground_truth_trajectories["scenario_id"] - last_scenario_id = str(scenario_ids[-1][0]) - # We evaluate the metrics only for the Tracks to Predict. eval_sim_x = sim_x[eval_mask] eval_sim_y = sim_y[eval_mask] @@ -318,7 +172,6 @@ def compute_metrics( eval_agent_length = agent_length[eval_mask] eval_agent_width = agent_width[eval_mask] eval_scenario_ids = scenario_ids[eval_mask] - eval_is_vehicle = is_vehicle[eval_mask] # Compute features # Kinematics-related features @@ -484,48 +337,60 @@ def compute_metrics( sanity_check=False, ) - speed_log_likelihood = metrics._reduce_average_with_validity( - linear_speed_log_likelihood, - speed_validity[:, 0, :], - axis=1, + speed_likelihood = np.exp( + metrics._reduce_average_with_validity( + linear_speed_log_likelihood, + speed_validity[:, 0, :], + axis=1, + ) ) - accel_log_likelihood = metrics._reduce_average_with_validity( - linear_accel_log_likelihood, - acceleration_validity[:, 0, :], - axis=1, + accel_likelihood = np.exp( + metrics._reduce_average_with_validity( + linear_accel_log_likelihood, + acceleration_validity[:, 0, :], + axis=1, + ) ) - angular_speed_log_likelihood = metrics._reduce_average_with_validity( - angular_speed_log_likelihood, - speed_validity[:, 0, :], - axis=1, + angular_speed_likelihood = np.exp( + metrics._reduce_average_with_validity( + angular_speed_log_likelihood, + speed_validity[:, 0, :], + axis=1, + ) ) - angular_accel_log_likelihood = metrics._reduce_average_with_validity( - angular_accel_log_likelihood, - acceleration_validity[:, 0, :], - axis=1, + angular_accel_likelihood = np.exp( + metrics._reduce_average_with_validity( + angular_accel_log_likelihood, + acceleration_validity[:, 0, :], + axis=1, + ) ) - distance_to_nearest_object_log_likelihood = metrics._reduce_average_with_validity( - distance_to_nearest_object_log_likelihood, - eval_ref_valid[:, 0, :], - axis=1, + distance_to_nearest_object_likelihood = np.exp( + metrics._reduce_average_with_validity( + distance_to_nearest_object_log_likelihood, + eval_ref_valid[:, 0, :], + axis=1, + ) ) - # TTC is computed only for vehicles - ttc_valid = eval_ref_valid & eval_is_vehicle[..., None] - time_to_collision_log_likelihood = metrics._reduce_average_with_validity( - time_to_collision_log_likelihood, - ttc_valid[:, 0, :], - axis=1, + time_to_collision_likelihood = np.exp( + metrics._reduce_average_with_validity( + time_to_collision_log_likelihood, + eval_ref_valid[:, 0, :], + axis=1, + ) ) - distance_to_road_edge_log_likelihood = metrics._reduce_average_with_validity( - distance_to_road_edge_log_likelihood, - eval_ref_valid[:, 0, :], - axis=1, + distance_to_road_edge_likelihood = np.exp( + metrics._reduce_average_with_validity( + distance_to_road_edge_log_likelihood, + eval_ref_valid[:, 0, :], + axis=1, + ) ) # Collision likelihood is computed by aggregating in time. For invalid objects @@ -535,8 +400,8 @@ def compute_metrics( sim_collision_indication = np.any(np.where(eval_ref_valid, sim_collision_per_step, False), axis=2) ref_collision_indication = np.any(np.where(eval_ref_valid, ref_collision_per_step, False), axis=2) - sim_num_collisions = np.mean(sim_collision_indication, axis=1) - ref_num_collisions = np.mean(ref_collision_indication, axis=1) + sim_num_collisions = np.sum(sim_collision_indication, axis=1) + ref_num_collisions = np.sum(ref_collision_indication, axis=1) collision_log_likelihood = estimators.log_likelihood_estimate_scenario_level( log_values=ref_collision_indication[:, 0], @@ -546,13 +411,14 @@ def compute_metrics( num_bins=2, use_bernoulli=True, ) + collision_likelihood = np.exp(collision_log_likelihood) # Offroad likelihood (same pattern as collision) sim_offroad_indication = np.any(np.where(eval_ref_valid, sim_offroad_per_step, False), axis=2) ref_offroad_indication = np.any(np.where(eval_ref_valid, ref_offroad_per_step, False), axis=2) - sim_num_offroad = np.mean(sim_offroad_indication, axis=1) - ref_num_offroad = np.mean(ref_offroad_indication, axis=1) + sim_num_offroad = np.sum(sim_offroad_indication, axis=1) + ref_num_offroad = np.sum(ref_offroad_indication, axis=1) offroad_log_likelihood = estimators.log_likelihood_estimate_scenario_level( log_values=ref_offroad_indication[:, 0], @@ -562,6 +428,7 @@ def compute_metrics( num_bins=2, use_bernoulli=True, ) + offroad_likelihood = np.exp(offroad_log_likelihood) # Get agent IDs eval_agent_ids = ground_truth_trajectories["id"][eval_mask] @@ -576,70 +443,60 @@ def compute_metrics( "num_offroad_ref": ref_num_offroad.flatten(), "ade": ade, "min_ade": min_ade, - "likelihood_linear_speed": speed_log_likelihood, - "likelihood_linear_acceleration": accel_log_likelihood, - "likelihood_angular_speed": angular_speed_log_likelihood, - "likelihood_angular_acceleration": angular_accel_log_likelihood, - "likelihood_distance_to_nearest_object": distance_to_nearest_object_log_likelihood, - "likelihood_time_to_collision": time_to_collision_log_likelihood, - "likelihood_collision_indication": collision_log_likelihood, - "likelihood_distance_to_road_edge": distance_to_road_edge_log_likelihood, - "likelihood_offroad_indication": offroad_log_likelihood, + "likelihood_linear_speed": speed_likelihood, + "likelihood_linear_acceleration": accel_likelihood, + "likelihood_angular_speed": angular_speed_likelihood, + "likelihood_angular_acceleration": angular_accel_likelihood, + "likelihood_distance_to_nearest_object": distance_to_nearest_object_likelihood, + "likelihood_time_to_collision": time_to_collision_likelihood, + "likelihood_collision_indication": collision_likelihood, + "likelihood_distance_to_road_edge": distance_to_road_edge_likelihood, + "likelihood_offroad_indication": offroad_likelihood, } ) - # Aggregate along agent dimenision: Obtain one score per scenario - df_scene_level = df.groupby("scenario_id", as_index=True).mean().drop(columns=["agent_id"]).dropna() - - # Exponentiate the averaged log-likelihoods to get final likelihoods - likelihood_columns = [col for col in df_scene_level.columns if col.startswith("likelihood_")] - df_scene_level[likelihood_columns] = np.exp(df_scene_level[likelihood_columns]) - - df_scene_level["realism_meta_score"] = df_scene_level.apply(self._compute_metametric, axis=1) - df_scene_level["num_agents_per_scene"] = df.groupby("scenario_id").size() - df_scene_level = df_scene_level.round(3) - - # Get group summary metrics - kinematic_metrics = np.mean( + scene_level_results = df.groupby("scenario_id")[ [ - df_scene_level["likelihood_linear_speed"], - df_scene_level["likelihood_linear_acceleration"], - df_scene_level["likelihood_angular_speed"], - df_scene_level["likelihood_angular_acceleration"], + "ade", + "min_ade", + "num_collisions_sim", + "num_collisions_ref", + "num_offroad_sim", + "num_offroad_ref", + "likelihood_linear_speed", + "likelihood_linear_acceleration", + "likelihood_angular_speed", + "likelihood_angular_acceleration", + "likelihood_distance_to_nearest_object", + "likelihood_time_to_collision", + "likelihood_collision_indication", + "likelihood_distance_to_road_edge", + "likelihood_offroad_indication", ] - ) + ].mean() - interactive_metrics = np.mean( - [ - df_scene_level["likelihood_collision_indication"], - df_scene_level["likelihood_distance_to_nearest_object"], - df_scene_level["likelihood_time_to_collision"], - ] - ) - - map_metrics = np.mean( - [ - df_scene_level["likelihood_distance_to_road_edge"], - df_scene_level["likelihood_offroad_indication"], - ] - ) - - df_scene_level["kinematic_metrics"] = kinematic_metrics - df_scene_level["interactive_metrics"] = interactive_metrics - df_scene_level["map_based_metrics"] = map_metrics - - # Safety: drop the last scenario (potentially incomplete) from the scene-level results - if last_scenario_id in df_scene_level.index: - df_scene_level = df_scene_level.drop(last_scenario_id) + scene_level_results["realism_meta_score"] = scene_level_results.apply(self._compute_metametric, axis=1) + scene_level_results["num_agents"] = df.groupby("scenario_id").size() + scene_level_results = scene_level_results[ + ["num_agents"] + [col for col in scene_level_results.columns if col != "num_agents"] + ] if aggregate_results: - # Aggregate over scenarios - aggregate_metrics = df_scene_level.mean().to_dict() - aggregate_metrics["total_num_agents"] = df_scene_level["num_agents_per_scene"].sum() - aggregate_metrics["realism_score_std"] = df_scene_level["realism_meta_score"].std() - return aggregate_metrics + aggregate_metrics = scene_level_results.mean().to_dict() + aggregate_metrics["total_num_agents"] = scene_level_results["num_agents"].sum() + # Convert numpy types to Python native types + return {k: v.item() if hasattr(v, "item") else v for k, v in aggregate_metrics.items()} else: - return df_scene_level + print("\n Scene-level results:\n") + print(scene_level_results) + + print(f"\n Overall realism meta score: {scene_level_results['realism_meta_score'].mean():.4f}") + print(f"\n Overall minADE: {scene_level_results['min_ade'].mean():.4f}") + print(f"\n Overall ADE: {scene_level_results['ade'].mean():.4f}") + + # print(f"\n Full agent-level results:\n") + # print(df) + return scene_level_results def _quick_sanity_check(self, gt_trajectories, simulated_trajectories, agent_idx=None, max_agents_to_plot=10): if agent_idx is None: @@ -763,183 +620,58 @@ def _quick_sanity_check(self, gt_trajectories, simulated_trajectories, agent_idx plt.savefig(f"trajectory_comparison_agent_{agent_idx}.png") -class Evaluator: - """Evaluates policies in self_play or human_replay mode, with optional rendering. - - Initializes the eval envs needed based on eval config flags: - - human_replay_eval: creates sp_env + hr_env - - render_eval: creates sp_env (if not already created) - """ - - RENDER_FIRST = "first" - RENDER_RANDOM = "random" - RENDER_WORST_SCORE = "worst_score" - RENDER_WORST_COLLISION = "worst_collision" - - def __init__(self, configs, logger=None): - self.configs = configs - self.logger = logger - self.sim_steps = 90 - self.self_play_stats = None - self.human_replay_stats = None - self.sp_env = None - self.hr_env = None - - self._unpack_eval_configs(configs) - - def _unpack_eval_configs(self, configs): - eval_config = copy.deepcopy(configs) - # Create separate evaluation environments based on specified configs - eval_config["env"]["termination_mode"] = 0 - backend = eval_config["eval"].get("backend", "PufferEnv") - eval_config["env"]["map_dir"] = eval_config["eval"]["map_dir"] - eval_config["env"]["num_agents"] = eval_config["eval"]["num_eval_agents"] - eval_config["env"]["episode_length"] = 91 # WOMD scenario length - eval_config["vec"] = dict(backend=backend, num_envs=1) - - self.hr_eval_config = copy.deepcopy(eval_config) - self.hr_eval_config["env"]["control_mode"] = "control_sdc_only" - self.sp_eval_config = copy.deepcopy(eval_config) - self.sp_eval_config["env"]["control_mode"] = "control_agents" - self.render_select_mode = self.configs["eval"]["render_select_mode"] - self.render_sp_rollout = self.configs["eval"]["render_self_play_eval"] - self.render_hr_rollout = self.configs["eval"]["render_human_replay_eval"] - - def select_render_env(self, env_logs): - """Select which environment to render based on per-env rollout statistics. - Args: - env_logs: List of dicts, one per environment. Each dict contains - aggregated agent statistics (score, collision_rate, offroad_rate, etc.) - with 'n' being the number of controlled agents in that env. - Empty dicts indicate no data was collected for that env. +class HumanReplayEvaluator: + """Evaluates policies against human replays in PufferDrive.""" - Returns: - int: Index of the environment to render. - """ - mode = self.render_select_mode - if mode == self.RENDER_FIRST: - return 0 - if mode == self.RENDER_RANDOM: - return np.random.randint(len(env_logs)) - - populated = [(i, log) for i, log in enumerate(env_logs) if log] - - if not populated: - return 0 - - if mode == self.RENDER_WORST_SCORE: - return min(populated, key=lambda x: x[1].get("score", 1.0))[0] - elif mode == self.RENDER_WORST_COLLISION: - return max(populated, key=lambda x: x[1].get("collision_rate", 0.0))[0] - # Add other modes based on desiderata here - return 0 - - def rollout(self, policy, mode="self_play"): - env = self.hr_env if mode == "human_replay" else self.sp_env - render_eval = self.render_sp_rollout if mode == "self_play" else self.render_hr_rollout - driver = env.driver_env - - needs_stats_first = render_eval and self.render_select_mode not in (self.RENDER_FIRST, self.RENDER_RANDOM) - - if needs_stats_first: - env_logs = self._run_rollout(policy, env, per_env_logs=True) - render_env_idx = self.select_render_env(env_logs) - else: - render_env_idx = self.select_render_env([{}] * driver.num_envs) + def __init__(self, config: Dict): + self.config = config + self.sim_steps = 91 - self.config["env"]["init_steps"] - info_list = self._run_rollout(policy, env, render_env_idx if render_eval else None) + def rollout(self, args, puffer_env, policy): + """Roll out policy in env with human replays. Store statistics. - final_info = info_list[0] if info_list else {} - if mode == "self_play": - self.self_play_stats = final_info - self.self_play_stats["render_env_idx"] = render_env_idx - elif mode == "human_replay": - self.human_replay_stats = final_info - self.human_replay_stats["render_env_idx"] = render_env_idx + In human replay mode, only the SDC (self-driving car) is controlled by the policy + while all other agents replay their human trajectories. This tests how compatible + the policy is with (static) human partners. - def _run_rollout(self, policy, env, render_env_idx=None, per_env_logs=False): - """Run a single rollout. If render_env_idx is not None, render that env.""" - driver = env.driver_env - num_agents = env.observation_space.shape[0] - device = self.configs["train"]["device"] + Args: + args: Config dict with train settings (device, use_rnn, etc.) + puffer_env: PufferLib environment wrapper + policy: Trained policy to evaluate - # Reset environment - obs, info = env.reset() + Returns: + dict: Aggregated metrics including: + - avg_collisions_per_agent: Average collisions per agent + - avg_offroad_per_agent: Average offroad events per agent + """ + import numpy as np + import torch + import pufferlib - # Initialize RNN state if needed + num_agents = puffer_env.observation_space.shape[0] + device = args["train"]["device"] + + obs, info = puffer_env.reset() state = {} - if self.configs["train"]["use_rnn"]: + if args["train"]["use_rnn"]: state = dict( lstm_h=torch.zeros(num_agents, policy.hidden_size, device=device), lstm_c=torch.zeros(num_agents, policy.hidden_size, device=device), ) - info_list = [] for time_idx in range(self.sim_steps): - if render_env_idx is not None: - driver.render(env_id=render_env_idx) - - # Get action from policy + # Step policy with torch.no_grad(): ob_tensor = torch.as_tensor(obs).to(device) logits, value = policy.forward_eval(ob_tensor, state) action, logprob, _ = pufferlib.pytorch.sample_logits(logits) - action_np = action.cpu().numpy().reshape(env.action_space.shape) + action_np = action.cpu().numpy().reshape(puffer_env.action_space.shape) - # Clip continuous actions to valid range if isinstance(logits, torch.distributions.Normal): - action_np = np.clip(action_np, env.action_space.low, env.action_space.high) - - # Step environment - obs, rewards, dones, truncs, info_list = env.step(action_np, per_env_logs=per_env_logs) + action_np = np.clip(action_np, puffer_env.action_space.low, puffer_env.action_space.high) - if truncs.all(): - break - - return info_list - - def log_videos(self, eval_mode, epoch): - """Log all mp4s in local path to wandb after env close has flushed ffmpeg pipes.""" - import os - import glob - - if not (self.logger and hasattr(self.logger, "wandb") and self.logger.wandb): - # Still clean up even if not logging - for p in glob.glob("*.mp4"): - os.remove(p) - return - - import wandb - - video_files = glob.glob("*.mp4") - if not video_files: - print("Warning: no render videos found in local path") - return - - render_mode = self.render_select_mode - for p in video_files: - scenario_id = os.path.splitext(os.path.basename(p))[0] - caption = f"scene_{scenario_id}_epoch_{epoch}_select_{render_mode}" - self.logger.wandb.log({f"render/{eval_mode}": wandb.Video(p, format="mp4", caption=caption)}) - - # Clean up - for p in video_files: - os.remove(p) - - def log_stats(self): - if not (self.logger and hasattr(self.logger, "wandb") and self.logger.wandb): - return - - eval_stats = {} - - if self.human_replay_stats is not None: - eval_stats["eval/hr_collision_rate"] = self.human_replay_stats["collision_rate"] - eval_stats["eval/hr_score"] = self.human_replay_stats["score"] - if self.self_play_stats is not None: - eval_stats["eval/sp_collision_rate"] = self.self_play_stats["collision_rate"] - eval_stats["eval/sp_score"] = self.self_play_stats["score"] - eval_stats["eval/num_agents"] = self.self_play_stats["n"] - else: - return + obs, rewards, dones, truncs, info_list = puffer_env.step(action_np) - self.logger.wandb.log(eval_stats) + if len(info_list) > 0: # Happens at the end of episode + results = info_list[0] + return results diff --git a/pufferlib/ocean/benchmark/metrics.py b/pufferlib/ocean/benchmark/metrics.py index 7f34da1c6c..cf1af358ee 100644 --- a/pufferlib/ocean/benchmark/metrics.py +++ b/pufferlib/ocean/benchmark/metrics.py @@ -249,7 +249,7 @@ def compute_interaction_features( scenario_mask = torch.as_tensor(scenario_mask_np, dtype=torch.bool, device=x_t.device) scenario_x = x_t[scenario_mask] scenario_y = y_t[scenario_mask] - episode_length = length_broadcast[scenario_mask] + scenario_length = length_broadcast[scenario_mask] scenario_width = width_broadcast[scenario_mask] scenario_heading = heading_t[scenario_mask] scenario_valid = valid_t[scenario_mask] @@ -260,7 +260,7 @@ def compute_interaction_features( distances_to_objects = interaction_features.compute_distance_to_nearest_object( center_x=scenario_x, center_y=scenario_y, - length=episode_length, + length=scenario_length, width=scenario_width, heading=scenario_heading, valid=scenario_valid, @@ -273,7 +273,7 @@ def compute_interaction_features( times_to_collision = interaction_features.compute_time_to_collision( center_x=scenario_x, center_y=scenario_y, - length=episode_length, + length=scenario_length, width=scenario_width, heading=scenario_heading, valid=scenario_valid, diff --git a/pufferlib/ocean/benchmark/metrics_sanity_check.py b/pufferlib/ocean/benchmark/metrics_sanity_check.py index 9cabc42377..dcda26b691 100644 --- a/pufferlib/ocean/benchmark/metrics_sanity_check.py +++ b/pufferlib/ocean/benchmark/metrics_sanity_check.py @@ -26,11 +26,11 @@ def replace_rollouts_with_gt(simulated_traj, gt_traj, num_replacements): return modified -def run_validation_experiment(config, vecenv): +def run_validation_experiment(config, vecenv, policy): evaluator = WOSACEvaluator(config) gt_trajectories = evaluator.collect_ground_truth_trajectories(vecenv) - simulated_trajectories = evaluator.collect_wosac_random_baseline(vecenv) + simulated_trajectories = evaluator.collect_simulated_trajectories(config, vecenv, policy) agent_state = vecenv.driver_env.get_global_agent_state() road_edge_polylines = vecenv.driver_env.get_road_edge_polylines() @@ -89,16 +89,17 @@ def main(): config["vec"]["num_envs"] = 1 config["eval"]["enabled"] = True config["eval"]["wosac_num_rollouts"] = 32 - config["env"]["map_dir"] = config["eval"]["map_dir"] + config["env"]["num_agents"] = config["eval"]["wosac_num_agents"] config["env"]["init_mode"] = config["eval"]["wosac_init_mode"] config["env"]["control_mode"] = config["eval"]["wosac_control_mode"] config["env"]["init_steps"] = config["eval"]["wosac_init_steps"] config["env"]["goal_behavior"] = config["eval"]["wosac_goal_behavior"] vecenv = load_env(args.env, config) + policy = load_policy(config, vecenv, args.env) - results = run_validation_experiment(config, vecenv) + results = run_validation_experiment(config, vecenv, policy) print("\n" + format_results_table(results)) diff --git a/pufferlib/ocean/benchmark/visual_sanity_check.py b/pufferlib/ocean/benchmark/visual_sanity_check.py index 33f9380e46..ca46574418 100644 --- a/pufferlib/ocean/benchmark/visual_sanity_check.py +++ b/pufferlib/ocean/benchmark/visual_sanity_check.py @@ -92,22 +92,17 @@ def main(): args = parser.parse_args() config = load_config(args.env) - - config["load_model_path"] = "resources/drive/pufferdrive_weights.pt" - config["vec"]["backend"] = "PufferEnv" config["vec"]["num_envs"] = 1 config["eval"]["enabled"] = True config["eval"]["wosac_num_rollouts"] = 1 + config["env"]["num_agents"] = config["eval"]["wosac_num_agents"] config["env"]["init_mode"] = config["eval"]["wosac_init_mode"] config["env"]["control_mode"] = config["eval"]["wosac_control_mode"] config["env"]["init_steps"] = config["eval"]["wosac_init_steps"] config["env"]["goal_behavior"] = config["eval"]["wosac_goal_behavior"] - config["env"]["map_dir"] = config["eval"]["map_dir"] - config["env"]["num_maps"] = config["eval"]["wosac_num_maps"] - vecenv = load_env(args.env, config) policy = load_policy(config, vecenv, args.env) diff --git a/pufferlib/ocean/benchmark/wosac.ini b/pufferlib/ocean/benchmark/wosac.ini index a63f11f98c..a7632e65d3 100644 --- a/pufferlib/ocean/benchmark/wosac.ini +++ b/pufferlib/ocean/benchmark/wosac.ini @@ -1,6 +1,5 @@ -# Taken from WOSAC 2024 Sim Agents Challenge configuration -# Note: 2024 challenge does not include traffic_light_violation metric (weight = 0.0) -# Traffic light violation was added in 2025 challenge with weight 0.05 +# Taken from WOSAC 2025 Sim Agents Challenge configuration +# Link: https://github.com/waymo-research/waymo-open-dataset/blob/master/src/waymo_open_dataset/wdl_limited/sim_agents_metrics/challenge_2025_sim_agents_config.textproto [linear_speed] histogram.min_val = 0.0 @@ -52,7 +51,7 @@ histogram.max_val = 40 histogram.num_bins = 10 histogram.additive_smoothing_pseudocount = 0.1 independent_timesteps = true -metametric_weight = 0.1 +metametric_weight = 0.05 [offroad_indication] bernoulli = true @@ -68,4 +67,4 @@ metametric_weight = 0.1 [traffic_light_violation] bernoulli = true -metametric_weight = 0.0 +metametric_weight = 0.05 diff --git a/pufferlib/ocean/drive/README.md b/pufferlib/ocean/drive/README.md new file mode 100644 index 0000000000..a012eddd33 --- /dev/null +++ b/pufferlib/ocean/drive/README.md @@ -0,0 +1,108 @@ +# PufferDrive + +This readme contains several important assumptions and definions about the `PufferDrive` environment. + +## Agent initialization and control + +### `init_mode` + +Determines which agents are **created** in the environment. + +| Option | Description | +| ------------------------ | ---------------------------------------------------------------------------- | +| `create_all_valid` | Create all entities valid at initialization (`traj_valid[init_steps] == 1`). | +| `create_only_controlled` | Create only those agents that are controlled by the policy. | + +### `control_mode` + +Determines which created agents are **controlled** by the policy. + +| Option | Description | +| ----------------------------------------- | ------------------------------------------------------------------------------------------------- | +| `control_vehicles` (default) | Control only valid **vehicles** (not experts, beyond `MIN_DISTANCE_TO_GOAL`, under `MAX_AGENTS`). | +| `control_agents` | Control all valid **agent types** (vehicles, cyclists, pedestrians). | +| `control_wosac` *(WOMD only)* | Control all agents with their valid flag to `True` at the `init_step`. | + + +## Termination conditions (`done`) + +Episodes are never truncated before reaching `episode_len`. The `reach_goal_behavior` argument controls agent behavior after reaching a goal early: + +* **`reach_goal_behavior=0` (default):** Agents respawn at their initial position after reaching their goal (last valid log position). +* **`reach_goal_behavior=1`:** Agents receive new goals indefinitely after reaching each goal. +* **`reach_goal_behavior=2`:** Agents stop after reaching their goal. + +## Logged performance metrics + +We record multiple performance metrics during training, aggregated over all *active agents* (alive and controlled). Key metrics include: + +- `score`: Goals reached cleanly (goal was achieved without collision or going off-road) +- `collision_rate`: Binary flag (0 or 1) if agent hit another vehicle. +- `offroad_rate`: Binary flag (0 or 1) if agent left road bounds. +- `completion_rate`: Whether the agent reached its goal in this episode (even if it collided or went off-road). + + +### Metric aggregation + +The `num_agents` parameter in `drive.ini` defines the total number of agents used to collect experience. +At runtime, **Puffer** uses `num_maps` to create enough environments to populate the buffer with `num_agents`, distributing them evenly across `num_envs`. + +Because agents are respawned immediately after reaching their goal, they remain active throughout the episode. + +At the end of each episode (i.e., when `timestep == TRAJECTORY_LENGTH`), metrics are logged once via: + +```C +if (env->timestep == TRAJECTORY_LENGTH) { + add_log(env); + c_reset(env); + return; +} +``` + +Metrics are normalized and aggregated in `vec_log` (`pufferlib/ocean/env_binding.h`). They are averaged over all active agents across all environments. For example, the aggregated collision rate is computed as: + +$$ +r^{agg}_{\text{collision}} = \frac{\mathbb{I}[\text{collided in episode}]}{N} +$$ + +where $N$ is the number of controlled agents. +This value represents the fraction of agents that collided at least once during the episode. So, cases **A** and **B** below would yield identical off-road and collision rates: + +![alt text](../../resources/drive/examples_a_b.png) + +Since these metrics do not capture *multiple* events per agent, we additionally log the **average number of collision and off-road events per episode**. This is computed as: + +$$ +c^{avg}_{\text{collision}} = \frac{\text{total number of collision events across all agents and environments}}{N} +$$ + +where $N$ is the total number of controlled agents. +For example, an `avg_collisions_per_agent` value of 4 indicates that, on average, each agent collides four times per episode. + +### Effect of respawning on metrics + +By default, agents are reset to their initial position when they reach their goal before the episode ends. Upon respawn, `respawn_timestep` is updated from `-1` to the current step index. + +This raises the question: **how does repeated respawning affect aggregated metrics?** + +To begin, note that the environment is a bit different before and after respawn. After an agent respawns, all other agents are "removed" from the environment. As a result, collisions with other agents cannot occur post-respawn. + +This effectively transforms the scenario into a single-agent environment, simplifying the task since the agent no longer needs to coordinate with others. + +![alt text](../../resources/drive/pre_and_post_respawn.png) + +#### `score` + +Consider an episode of 91 steps where an agent is initialized relatively close to the goal position and reaches its goal three times: + +1. **First attempt:** reaches the goal without collisions +2. **Second attempt:** reaches the goal without collisions +3. **Third attempt:** reaches the goal but goes off-road along the way + +![alt text](../../resources/drive/realistic_collision_event_post_respawn.png) + +The highlighted trajectory shows the first attempt. In this case, the recorded score is `0.0` — a single off-road event invalidates the score for the entire episode. This behavior is desired: the score metric is unforgiving. + +#### `offroad_rate` and `collision_rate` + +Same logic holds as above. diff --git a/pufferlib/ocean/drive/binding.c b/pufferlib/ocean/drive/binding.c index e86dad727a..109eee702b 100644 --- a/pufferlib/ocean/drive/binding.c +++ b/pufferlib/ocean/drive/binding.c @@ -2,6 +2,7 @@ #define Env Drive #define MY_SHARED #define MY_PUT +#define MY_GET #include "../env_binding.h" static int my_put(Env *env, PyObject *args, PyObject *kwargs) { @@ -67,81 +68,1655 @@ static int my_put(Env *env, PyObject *args, PyObject *kwargs) { return 0; } +static PyObject *my_get(PyObject *dict, Env *env) { + PyObject *v; + if (!env) { + PyErr_SetString(PyExc_ValueError, "env is NULL"); + return NULL; + } + + /* Validate main array pointers before accessing */ + if (env->num_total_agents > 0 && !env->agents) { + PyErr_SetString(PyExc_ValueError, "agents is NULL but count > 0"); + return NULL; + } + if (env->num_road_elements > 0 && !env->road_elements) { + PyErr_SetString(PyExc_ValueError, "road_elements is NULL but count > 0"); + return NULL; + } + if (env->num_traffic_elements > 0 && !env->traffic_elements) { + PyErr_SetString(PyExc_ValueError, "traffic_elements is NULL but count > 0"); + return NULL; + } + + v = PyLong_FromLong(env->active_agent_count); + if (!v) + return NULL; + if (PyDict_SetItemString(dict, "active_agent_count", v) < 0) { + Py_DECREF(v); + return NULL; + } + Py_DECREF(v); + + v = PyLong_FromLong(env->num_total_agents); + if (!v) + return NULL; + if (PyDict_SetItemString(dict, "num_total_agents", v) < 0) { + Py_DECREF(v); + return NULL; + } + Py_DECREF(v); + + v = PyLong_FromLong(env->num_road_elements); + if (!v) + return NULL; + if (PyDict_SetItemString(dict, "num_road_elements", v) < 0) { + Py_DECREF(v); + return NULL; + } + Py_DECREF(v); + + v = PyLong_FromLong(env->num_traffic_elements); + if (!v) + return NULL; + if (PyDict_SetItemString(dict, "num_traffic_elements", v) < 0) { + Py_DECREF(v); + return NULL; + } + Py_DECREF(v); + + /* Map name / string fields */ + if (env->map_name) { + PyObject *s = PyUnicode_FromString(env->map_name); + if (!s) + return NULL; + if (PyDict_SetItemString(dict, "map_name", s) < 0) { + Py_DECREF(s); + return NULL; + } + Py_DECREF(s); + } else { + if (PyDict_SetItemString(dict, "map_name", Py_None) < 0) + return NULL; + } + + /* Metadata fields */ + if (env->scenario_id[0] != '\0') { + PyObject *s = PyUnicode_FromString(env->scenario_id); + if (!s) + return NULL; + if (PyDict_SetItemString(dict, "scenario_id", s) < 0) { + Py_DECREF(s); + return NULL; + } + Py_DECREF(s); + } else { + if (PyDict_SetItemString(dict, "scenario_id", Py_None) < 0) + return NULL; + } + + if (env->dataset_name[0] != '\0') { + PyObject *s = PyUnicode_FromString(env->dataset_name); + if (!s) + return NULL; + if (PyDict_SetItemString(dict, "dataset_name", s) < 0) { + Py_DECREF(s); + return NULL; + } + Py_DECREF(s); + } else { + if (PyDict_SetItemString(dict, "dataset_name", Py_None) < 0) + return NULL; + } + + v = PyLong_FromLong(env->log_length); + if (!v) + return NULL; + if (PyDict_SetItemString(dict, "length", v) < 0) { + Py_DECREF(v); + return NULL; + } + Py_DECREF(v); + + v = PyLong_FromLong(env->dynamics_model); + if (!v) + return NULL; + if (PyDict_SetItemString(dict, "dynamics_model", v) < 0) { + Py_DECREF(v); + return NULL; + } + Py_DECREF(v); + + /* objects_of_interest array */ + if (env->objects_of_interest && env->num_objects_of_interest > 0) { + PyObject *lst = PyList_New(env->num_objects_of_interest); + if (!lst) + return NULL; + for (int i = 0; i < env->num_objects_of_interest; i++) { + PyObject *it = PyLong_FromLong(env->objects_of_interest[i]); + if (!it) { + Py_DECREF(lst); + return NULL; + } + PyList_SetItem(lst, i, it); + } + if (PyDict_SetItemString(dict, "objects_of_interest", lst) < 0) { + Py_DECREF(lst); + return NULL; + } + Py_DECREF(lst); + } else { + if (PyDict_SetItemString(dict, "objects_of_interest", Py_None) < 0) + return NULL; + } + + /* tracks_to_predict array */ + if (env->tracks_to_predict && env->num_tracks_to_predict > 0) { + PyObject *lst = PyList_New(env->num_tracks_to_predict); + if (!lst) + return NULL; + for (int i = 0; i < env->num_tracks_to_predict; i++) { + PyObject *it = PyLong_FromLong(env->tracks_to_predict[i]); + if (!it) { + Py_DECREF(lst); + return NULL; + } + PyList_SetItem(lst, i, it); + } + if (PyDict_SetItemString(dict, "tracks_to_predict", lst) < 0) { + Py_DECREF(lst); + return NULL; + } + Py_DECREF(lst); + } else { + if (PyDict_SetItemString(dict, "tracks_to_predict", Py_None) < 0) + return NULL; + } + + /* Lists (active agent indices) */ + if (env->active_agent_indices && env->active_agent_count > 0) { + PyObject *lst = PyList_New(env->active_agent_count); + if (!lst) + return NULL; + for (int i = 0; i < env->active_agent_count; i++) { + PyObject *it = PyLong_FromLong(env->active_agent_indices[i]); + if (!it) { + Py_DECREF(lst); + return NULL; + } + /* PyList_SetItem steals reference */ + PyList_SetItem(lst, i, it); + } + if (PyDict_SetItemString(dict, "active_agent_indices", lst) < 0) { + Py_DECREF(lst); + return NULL; + } + Py_DECREF(lst); + } else { + if (PyDict_SetItemString(dict, "active_agent_indices", Py_None) < 0) + return NULL; + } + + /* Optionally expose static car indices if present */ + if (env->static_agent_indices && env->static_agent_count > 0) { + PyObject *lst = PyList_New(env->static_agent_count); + if (!lst) + return NULL; + for (int i = 0; i < env->static_agent_count; i++) { + PyObject *it = PyLong_FromLong(env->static_agent_indices[i]); + if (!it) { + Py_DECREF(lst); + return NULL; + } + PyList_SetItem(lst, i, it); + } + if (PyDict_SetItemString(dict, "static_agent_indices", lst) < 0) { + Py_DECREF(lst); + return NULL; + } + Py_DECREF(lst); + } else { + if (PyDict_SetItemString(dict, "static_agent_indices", Py_None) < 0) + return NULL; + } + + /* Expose agents array as a list of dicts */ + if (env->agents && env->num_total_agents > 0) { + PyObject *agents_list = PyList_New(env->num_total_agents); + if (!agents_list) + return NULL; + for (int i = 0; i < env->num_total_agents; i++) { + Agent *a = &env->agents[i]; + + PyObject *agent = PyDict_New(); + if (!agent) { + Py_DECREF(agents_list); + return NULL; + } + + /* ID and type */ + PyObject *tmp = PyLong_FromLong(a->id); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + PyDict_SetItemString(agent, "id", tmp); + Py_DECREF(tmp); + + tmp = PyLong_FromLong(a->type); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + PyDict_SetItemString(agent, "type", tmp); + Py_DECREF(tmp); + + /* Validate trajectory_length before using it */ + int traj_len = (a->trajectory_length > 0 && a->trajectory_length < 10000) ? a->trajectory_length : 0; + tmp = PyLong_FromLong(traj_len); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + PyDict_SetItemString(agent, "trajectory_length", tmp); + Py_DECREF(tmp); + + /* Log trajectory arrays - validate each pointer individually before access */ + if (a->log_trajectory_x && traj_len > 0) { + PyObject *lx = PyList_New(traj_len); + if (!lx) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + for (int j = 0; j < traj_len; j++) { + PyObject *fv = PyFloat_FromDouble((double)a->log_trajectory_x[j]); + if (!fv) { + Py_DECREF(lx); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + PyList_SetItem(lx, j, fv); + } + PyDict_SetItemString(agent, "log_trajectory_x", lx); + Py_DECREF(lx); + } else { + PyDict_SetItemString(agent, "log_trajectory_x", Py_None); + } + if (a->log_trajectory_y && traj_len > 0) { + PyObject *ly = PyList_New(traj_len); + if (!ly) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + for (int j = 0; j < traj_len; j++) { + PyObject *fv = PyFloat_FromDouble((double)a->log_trajectory_y[j]); + if (!fv) { + Py_DECREF(ly); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + PyList_SetItem(ly, j, fv); + } + PyDict_SetItemString(agent, "log_trajectory_y", ly); + Py_DECREF(ly); + } else { + PyDict_SetItemString(agent, "log_trajectory_y", Py_None); + } + if (a->log_trajectory_z && traj_len > 0) { + PyObject *lz = PyList_New(traj_len); + if (!lz) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + for (int j = 0; j < traj_len; j++) { + PyObject *fv = PyFloat_FromDouble((double)a->log_trajectory_z[j]); + if (!fv) { + Py_DECREF(lz); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + PyList_SetItem(lz, j, fv); + } + PyDict_SetItemString(agent, "log_trajectory_z", lz); + Py_DECREF(lz); + } else { + PyDict_SetItemString(agent, "log_trajectory_z", Py_None); + } + if (a->log_heading && traj_len > 0) { + PyObject *lh = PyList_New(traj_len); + if (!lh) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + for (int j = 0; j < traj_len; j++) { + PyObject *fv = PyFloat_FromDouble((double)a->log_heading[j]); + if (!fv) { + Py_DECREF(lh); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + PyList_SetItem(lh, j, fv); + } + PyDict_SetItemString(agent, "log_heading", lh); + Py_DECREF(lh); + } else { + PyDict_SetItemString(agent, "log_heading", Py_None); + } + if (a->log_velocity_x && traj_len > 0) { + PyObject *lvx = PyList_New(traj_len); + if (!lvx) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + for (int j = 0; j < traj_len; j++) { + PyObject *fv = PyFloat_FromDouble((double)a->log_velocity_x[j]); + if (!fv) { + Py_DECREF(lvx); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + PyList_SetItem(lvx, j, fv); + } + PyDict_SetItemString(agent, "log_velocity_x", lvx); + Py_DECREF(lvx); + } else { + PyDict_SetItemString(agent, "log_velocity_x", Py_None); + } + if (a->log_velocity_y && traj_len > 0) { + PyObject *lvy = PyList_New(traj_len); + if (!lvy) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + for (int j = 0; j < traj_len; j++) { + PyObject *fv = PyFloat_FromDouble((double)a->log_velocity_y[j]); + if (!fv) { + Py_DECREF(lvy); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + PyList_SetItem(lvy, j, fv); + } + PyDict_SetItemString(agent, "log_velocity_y", lvy); + Py_DECREF(lvy); + } else { + PyDict_SetItemString(agent, "log_velocity_y", Py_None); + } + if (a->log_valid && traj_len > 0) { + PyObject *lv = PyList_New(traj_len); + if (!lv) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + for (int j = 0; j < traj_len; j++) { + PyObject *iv = PyLong_FromLong(a->log_valid[j]); + if (!iv) { + Py_DECREF(lv); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + PyList_SetItem(lv, j, iv); + } + PyDict_SetItemString(agent, "log_valid", lv); + Py_DECREF(lv); + } else { + PyDict_SetItemString(agent, "log_valid", Py_None); + } + + /* Simulation state (current) */ + PyObject *pf = PyFloat_FromDouble((double)a->sim_x); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "sim_x", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)a->sim_y); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "sim_y", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)a->sim_z); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "sim_z", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)a->sim_heading); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "sim_heading", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)a->sim_vx); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "sim_vx", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)a->sim_vy); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "sim_vy", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)a->sim_speed); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "sim_speed", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)a->sim_length); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "sim_length", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)a->sim_width); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "sim_width", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)a->sim_height); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "sim_height", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)a->wheelbase); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "wheelbase", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + tmp = PyLong_FromLong(a->sim_valid); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "sim_valid", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(tmp); + + tmp = PyLong_FromLong(a->closest_path_idx_wp); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "closest_path_idx_wp", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(tmp); + + /* Goal position */ + pf = PyFloat_FromDouble((double)a->goal_position_x); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "goal_position_x", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)a->goal_position_y); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "goal_position_y", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)a->goal_position_z); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "goal_position_z", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + /* Status flags */ + tmp = PyLong_FromLong(a->stopped); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "stopped", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(tmp); + + tmp = PyLong_FromLong(a->current_lane_index); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "current_lane_index", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(tmp); + + tmp = PyLong_FromLong(a->active_agent); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "active_agent", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(tmp); + + tmp = PyLong_FromLong(a->mark_as_expert); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "mark_as_expert", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(tmp); + + tmp = PyLong_FromLong(a->reached_goal_this_episode); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "reached_goal_this_episode", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(tmp); + + /* Debug metrics */ + tmp = PyLong_FromLong(a->num_waypoints_reached); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "num_waypoints_reached", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(tmp); + + tmp = PyLong_FromLong(a->current_route_index); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "current_route_index", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(tmp); + + pf = PyFloat_FromDouble((double)a->cumulative_displacement); + if (!pf) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "cumulative_displacement", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(pf); + + tmp = PyLong_FromLong(a->displacement_sample_count); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "displacement_sample_count", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(tmp); + + /* Metrics array: [collision, offroad, reached_goal, lane_aligned, avg_displacement_error, + * red_light_violation] */ + PyObject *metrics = PyList_New(NUM_METRICS); + if (!metrics) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + for (int j = 0; j < NUM_METRICS; j++) { + PyObject *metric_val = PyFloat_FromDouble((double)a->metrics_array[j]); + if (!metric_val) { + Py_DECREF(metrics); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + PyList_SetItem(metrics, j, metric_val); + } + if (PyDict_SetItemString(agent, "metrics_array", metrics) < 0) { + Py_DECREF(metrics); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(metrics); + + /* Export route information */ + tmp = PyLong_FromLong(a->route_length); + if (!tmp) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + if (PyDict_SetItemString(agent, "route_length", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(tmp); + + if (a->route && a->route_length > 0) { + PyObject *route_list = PyList_New(a->route_length); + if (!route_list) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + + for (int j = 0; j < a->route_length; j++) { + PyObject *lane_id = PyLong_FromLong(a->route[j]); + if (!lane_id) { + Py_DECREF(route_list); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + PyList_SetItem(route_list, j, lane_id); + } + + if (PyDict_SetItemString(agent, "route", route_list) < 0) { + Py_DECREF(route_list); + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(route_list); + } else { + if (PyDict_SetItemString(agent, "route", Py_None) < 0) { + Py_DECREF(agent); + Py_DECREF(agents_list); + return NULL; + } + } + + PyList_SetItem(agents_list, i, agent); + } + + if (PyDict_SetItemString(dict, "agents", agents_list) < 0) { + Py_DECREF(agents_list); + return NULL; + } + Py_DECREF(agents_list); + } else { + if (PyDict_SetItemString(dict, "agents", Py_None) < 0) + return NULL; + } + + /* SDC Paths */ + if (env->agents && env->active_agent_count > 0) { + PyObject *sdc_list = PyList_New(env->active_agent_count); + if (!sdc_list) + return NULL; + + for (int i = 0; i < env->active_agent_count; i++) { + Agent *a = &env->agents[env->active_agent_indices[i]]; + if (a->path) { + struct Path *path = a->path; + PyObject *path_dict = PyDict_New(); + if (!path_dict) { + Py_DECREF(sdc_list); + return NULL; + } + + PyObject *tmp_val = PyLong_FromLong(path->num_waypoints); + if (!tmp_val) { + Py_DECREF(path_dict); + Py_DECREF(sdc_list); + return NULL; + } + if (PyDict_SetItemString(path_dict, "num_waypoints", tmp_val) < 0) { + Py_DECREF(tmp_val); + Py_DECREF(path_dict); + Py_DECREF(sdc_list); + return NULL; + } + Py_DECREF(tmp_val); + + PyObject *wp_list = PyList_New(path->num_waypoints); + if (!wp_list) { + Py_DECREF(path_dict); + Py_DECREF(sdc_list); + return NULL; + } + + for (int j = 0; j < path->num_waypoints; j++) { + struct Waypoint *wp = &path->waypoints[j]; + PyObject *wp_dict = PyDict_New(); + if (!wp_dict) { + Py_DECREF(wp_list); + Py_DECREF(path_dict); + Py_DECREF(sdc_list); + return NULL; + } + +#define SET_WAYPOINT_FLOAT(key, val) \ + tmp_val = PyFloat_FromDouble((double)val); \ + if (!tmp_val) { \ + Py_DECREF(wp_dict); \ + Py_DECREF(wp_list); \ + Py_DECREF(path_dict); \ + Py_DECREF(sdc_list); \ + return NULL; \ + } \ + if (PyDict_SetItemString(wp_dict, key, tmp_val) < 0) { \ + Py_DECREF(tmp_val); \ + Py_DECREF(wp_dict); \ + Py_DECREF(wp_list); \ + Py_DECREF(path_dict); \ + Py_DECREF(sdc_list); \ + return NULL; \ + } \ + Py_DECREF(tmp_val) + + SET_WAYPOINT_FLOAT("s", wp->s); + SET_WAYPOINT_FLOAT("x", wp->x); + SET_WAYPOINT_FLOAT("y", wp->y); + SET_WAYPOINT_FLOAT("heading", wp->heading); + SET_WAYPOINT_FLOAT("kappa", wp->kappa); + + tmp_val = PyLong_FromLong(wp->lane_id); + if (!tmp_val) { + Py_DECREF(wp_dict); + Py_DECREF(wp_list); + Py_DECREF(path_dict); + Py_DECREF(sdc_list); + return NULL; + } + if (PyDict_SetItemString(wp_dict, "lane_id", tmp_val) < 0) { + Py_DECREF(tmp_val); + Py_DECREF(wp_dict); + Py_DECREF(wp_list); + Py_DECREF(path_dict); + Py_DECREF(sdc_list); + return NULL; + } + Py_DECREF(tmp_val); + + PyList_SetItem(wp_list, j, wp_dict); + } + + if (PyDict_SetItemString(path_dict, "waypoints", wp_list) < 0) { + Py_DECREF(wp_list); + Py_DECREF(path_dict); + Py_DECREF(sdc_list); + return NULL; + } + Py_DECREF(wp_list); + PyList_SetItem(sdc_list, i, path_dict); + } else { + Py_INCREF(Py_None); + PyList_SetItem(sdc_list, i, Py_None); + } + } + + if (PyDict_SetItemString(dict, "sdc_paths", sdc_list) < 0) { + Py_DECREF(sdc_list); + return NULL; + } + Py_DECREF(sdc_list); + } else { + if (PyDict_SetItemString(dict, "sdc_paths", Py_None) < 0) + return NULL; + } + + /* Expose road_elements array as a list of dicts */ + if (env->road_elements && env->num_road_elements > 0) { + PyObject *road_list = PyList_New(env->num_road_elements); + if (!road_list) + return NULL; + for (int i = 0; i < env->num_road_elements; i++) { + RoadMapElement *r = &env->road_elements[i]; + PyObject *road = PyDict_New(); + if (!road) { + Py_DECREF(road_list); + return NULL; + } + + PyObject *tmp = PyLong_FromLong(r->id); + if (!tmp) { + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + if (PyDict_SetItemString(road, "id", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + Py_DECREF(tmp); + + tmp = PyLong_FromLong(r->type); + if (!tmp) { + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + if (PyDict_SetItemString(road, "type", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + Py_DECREF(tmp); + + /* Validate segment_length before using it */ + int seg_len = (r->segment_length > 0 && r->segment_length < 100000) ? r->segment_length : 0; + tmp = PyLong_FromLong(seg_len); + if (!tmp) { + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + if (PyDict_SetItemString(road, "segment_length", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + Py_DECREF(tmp); + + /* Geometry arrays - validate each pointer individually before access */ + if (r->x && seg_len > 0) { + PyObject *lx = PyList_New(seg_len); + if (!lx) { + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + for (int j = 0; j < seg_len; j++) { + PyObject *fv = PyFloat_FromDouble((double)r->x[j]); + if (!fv) { + Py_DECREF(lx); + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + PyList_SetItem(lx, j, fv); + } + if (PyDict_SetItemString(road, "x", lx) < 0) { + Py_DECREF(lx); + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + Py_DECREF(lx); + } else { + if (PyDict_SetItemString(road, "x", Py_None) < 0) { + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + } + if (r->y && seg_len > 0) { + PyObject *ly = PyList_New(seg_len); + if (!ly) { + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + for (int j = 0; j < seg_len; j++) { + PyObject *fv = PyFloat_FromDouble((double)r->y[j]); + if (!fv) { + Py_DECREF(ly); + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + PyList_SetItem(ly, j, fv); + } + if (PyDict_SetItemString(road, "y", ly) < 0) { + Py_DECREF(ly); + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + Py_DECREF(ly); + } else { + if (PyDict_SetItemString(road, "y", Py_None) < 0) { + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + } + if (r->z && seg_len > 0) { + PyObject *lz = PyList_New(seg_len); + if (!lz) { + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + for (int j = 0; j < seg_len; j++) { + PyObject *fv = PyFloat_FromDouble((double)r->z[j]); + if (!fv) { + Py_DECREF(lz); + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + PyList_SetItem(lz, j, fv); + } + if (PyDict_SetItemString(road, "z", lz) < 0) { + Py_DECREF(lz); + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + Py_DECREF(lz); + } else { + if (PyDict_SetItemString(road, "z", Py_None) < 0) { + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + } + + /* Lane-specific fields */ + if (is_road_lane(r->type) && r->entry_lanes != NULL && r->num_entries > 0) { + tmp = PyList_New(r->num_entries); + } else { + tmp = PyList_New(0); + } + if (!tmp) { + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + if (is_road_lane(r->type) && r->entry_lanes != NULL && r->num_entries > 0) { + for (int k = 0; k < r->num_entries; k++) { + PyList_SET_ITEM(tmp, k, PyLong_FromLong(r->entry_lanes[k])); + } + } + if (PyDict_SetItemString(road, "entry_lanes", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + Py_DECREF(tmp); + + if (is_road_lane(r->type) && r->exit_lanes != NULL && r->num_exits > 0) { + tmp = PyList_New(r->num_exits); + } else { + tmp = PyList_New(0); + } + if (!tmp) { + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + if (is_road_lane(r->type) && r->exit_lanes != NULL && r->num_exits > 0) { + for (int k = 0; k < r->num_exits; k++) { + PyList_SET_ITEM(tmp, k, PyLong_FromLong(r->exit_lanes[k])); + } + } + if (PyDict_SetItemString(road, "exit_lanes", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + Py_DECREF(tmp); + + PyObject *pf = PyFloat_FromDouble((double)r->speed_limit); + if (!pf) { + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + if (PyDict_SetItemString(road, "speed_limit", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(road); + Py_DECREF(road_list); + return NULL; + } + Py_DECREF(pf); + + PyList_SetItem(road_list, i, road); + } + if (PyDict_SetItemString(dict, "road_elements", road_list) < 0) { + Py_DECREF(road_list); + return NULL; + } + Py_DECREF(road_list); + } else { + if (PyDict_SetItemString(dict, "road_elements", Py_None) < 0) + return NULL; + } + + /* Expose traffic_elements array as a list of dicts */ + if (env->traffic_elements && env->num_traffic_elements > 0) { + PyObject *traffic_list = PyList_New(env->num_traffic_elements); + if (!traffic_list) + return NULL; + for (int i = 0; i < env->num_traffic_elements; i++) { + TrafficControlElement *t = &env->traffic_elements[i]; + PyObject *traffic = PyDict_New(); + if (!traffic) { + Py_DECREF(traffic_list); + return NULL; + } + + PyObject *tmp = PyLong_FromLong(t->id); + if (!tmp) { + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + if (PyDict_SetItemString(traffic, "id", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + Py_DECREF(tmp); + + tmp = PyLong_FromLong(t->type); + if (!tmp) { + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + if (PyDict_SetItemString(traffic, "type", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + Py_DECREF(tmp); + + /* Validate state_length before using it */ + int state_len = (t->state_length > 0 && t->state_length < 10000) ? t->state_length : 0; + tmp = PyLong_FromLong(state_len); + if (!tmp) { + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + if (PyDict_SetItemString(traffic, "state_length", tmp) < 0) { + Py_DECREF(tmp); + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + Py_DECREF(tmp); + + /* States array - validate pointer before access */ + if (t->states && state_len > 0) { + PyObject *ls = PyList_New(state_len); + if (!ls) { + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + for (int j = 0; j < state_len; j++) { + PyObject *iv = PyLong_FromLong(t->states[j]); + if (!iv) { + Py_DECREF(ls); + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + PyList_SetItem(ls, j, iv); + } + if (PyDict_SetItemString(traffic, "states", ls) < 0) { + Py_DECREF(ls); + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + Py_DECREF(ls); + } else { + if (PyDict_SetItemString(traffic, "states", Py_None) < 0) { + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + } + + /* Stop line endpoints */ + PyObject *sl = PyList_New(6); + if (!sl) { + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + for (int k = 0; k < 6; k++) { + PyList_SetItem(sl, k, PyFloat_FromDouble((double)t->stop_line[k])); + } + if (PyDict_SetItemString(traffic, "stop_line", sl) < 0) { + Py_DECREF(sl); + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + Py_DECREF(sl); + + /* Position (stop_line midpoint for backward compat) */ + float mid_x = (t->stop_line[0] + t->stop_line[3]) * 0.5f; + float mid_y = (t->stop_line[1] + t->stop_line[4]) * 0.5f; + PyObject *pf = PyFloat_FromDouble((double)mid_x); + if (!pf) { + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + if (PyDict_SetItemString(traffic, "x", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + Py_DECREF(pf); + + pf = PyFloat_FromDouble((double)mid_y); + if (!pf) { + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + if (PyDict_SetItemString(traffic, "y", pf) < 0) { + Py_DECREF(pf); + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + Py_DECREF(pf); + + /* Controlled lanes array - validate pointer before access */ + if (t->controlled_lanes && t->num_controlled_lanes > 0) { + PyObject *ll = PyList_New(t->num_controlled_lanes); + if (!ll) { + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + for (int j = 0; j < t->num_controlled_lanes; j++) { + PyObject *lane_id = PyLong_FromLong(t->controlled_lanes[j]); + if (!lane_id) { + Py_DECREF(ll); + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + PyList_SetItem(ll, j, lane_id); + } + if (PyDict_SetItemString(traffic, "controlled_lanes", ll) < 0) { + Py_DECREF(ll); + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + Py_DECREF(ll); + } else { + if (PyDict_SetItemString(traffic, "controlled_lanes", Py_None) < 0) { + Py_DECREF(traffic); + Py_DECREF(traffic_list); + return NULL; + } + } + + PyList_SetItem(traffic_list, i, traffic); + } + if (PyDict_SetItemString(dict, "traffic_elements", traffic_list) < 0) { + Py_DECREF(traffic_list); + return NULL; + } + Py_DECREF(traffic_list); + } else { + if (PyDict_SetItemString(dict, "traffic_elements", Py_None) < 0) + return NULL; + } + + /* Map corners (bounding box) from GridMap */ + if (env->grid_map) { + PyObject *corners_list = PyList_New(4); + if (!corners_list) + return NULL; + + PyObject *brx = PyFloat_FromDouble((double)env->grid_map->bottom_right_x); + PyObject *bry = PyFloat_FromDouble((double)env->grid_map->bottom_right_y); + PyObject *tlx = PyFloat_FromDouble((double)env->grid_map->top_left_x); + PyObject *tly = PyFloat_FromDouble((double)env->grid_map->top_left_y); + + if (!tlx || !tly || !brx || !bry) { + Py_XDECREF(tlx); + Py_XDECREF(tly); + Py_XDECREF(brx); + Py_XDECREF(bry); + Py_DECREF(corners_list); + return NULL; + } + + PyList_SetItem(corners_list, 0, tlx); // min_x = top_left_x + PyList_SetItem(corners_list, 1, bry); // min_y = bottom_right_y + PyList_SetItem(corners_list, 2, brx); // max_x = bottom_right_x + PyList_SetItem(corners_list, 3, tly); // max_y = top_left_y + + if (PyDict_SetItemString(dict, "map_corners", corners_list) < 0) { + Py_DECREF(corners_list); + return NULL; + } + Py_DECREF(corners_list); + } else { + if (PyDict_SetItemString(dict, "map_corners", Py_None) < 0) + return NULL; + } + if (env->observations && env->active_agent_count > 0) { + /* Agent observations */ + int max_obs = compute_observation_size(env); + PyObject *obs_data = PyList_New(env->active_agent_count); + if (!obs_data) + return NULL; + + float (*observations)[max_obs] = (float (*)[max_obs])env->observations; + + for (int i = 0; i < env->active_agent_count; i++) { + PyObject *agent_obs = PyList_New(max_obs); + if (!agent_obs) { + Py_DECREF(obs_data); + return NULL; + } + + for (int j = 0; j < max_obs; j++) { + PyObject *obs_val = PyFloat_FromDouble((double)observations[i][j]); + if (!obs_val) { + Py_DECREF(agent_obs); + Py_DECREF(obs_data); + return NULL; + } + PyList_SetItem(agent_obs, j, obs_val); + } + + PyList_SetItem(obs_data, i, agent_obs); + } + + if (PyDict_SetItemString(dict, "agent_observations", obs_data) < 0) { + Py_DECREF(obs_data); + return NULL; + } + Py_DECREF(obs_data); + } else { + if (PyDict_SetItemString(dict, "agent_observations", Py_None) < 0) + return NULL; + } + + return dict; +} + static PyObject *my_shared(PyObject *self, PyObject *args, PyObject *kwargs) { - char *map_dir = unpack_str(kwargs, "map_dir"); + PyObject *map_files = PyDict_GetItemString(kwargs, "map_files"); + if (!map_files || !PyList_Check(map_files)) { + PyErr_SetString(PyExc_TypeError, "map_files must be a list of strings"); + return NULL; + } int num_agents = unpack(kwargs, "num_agents"); int num_maps = unpack(kwargs, "num_maps"); + int starting_map_counter = unpack(kwargs, "starting_map_counter"); + int eval_mode = unpack(kwargs, "eval_mode"); + int s_map_counter = starting_map_counter; int init_mode = unpack(kwargs, "init_mode"); int control_mode = unpack(kwargs, "control_mode"); + int simulation_mode = unpack(kwargs, "simulation_mode"); int init_steps = unpack(kwargs, "init_steps"); - int goal_behavior = unpack(kwargs, "goal_behavior"); - float goal_target_distance = unpack(kwargs, "goal_target_distance"); - int max_controlled_agents = unpack(kwargs, "max_controlled_agents"); + int seed = unpack(kwargs, "seed"); + int min_agents_per_env = unpack(kwargs, "min_agents_per_env"); + int max_agents_per_env = unpack(kwargs, "max_agents_per_env"); + int num_eval_scenarios = unpack(kwargs, "num_eval_scenarios"); + + if (min_agents_per_env <= 0 || max_agents_per_env <= 0) { + PyErr_SetString(PyExc_ValueError, "min_agents_per_env and max_agents_per_env must be > 0"); + return NULL; + } + if (min_agents_per_env > max_agents_per_env) { + PyErr_SetString(PyExc_ValueError, "min_agents_per_env must be <= max_agents_per_env"); + return NULL; + } + if (num_agents < min_agents_per_env) { + PyErr_SetString(PyExc_ValueError, "num_agents must be >= min_agents_per_env"); + return NULL; + } + + srand(seed); + + // GIGAFLOW mode: use random sampling for agent counts per env + if (simulation_mode == SIMULATION_GIGAFLOW) { + if (eval_mode) { + // Eval mode: fixed agent count, sequential map cycling + int agents_per_env = max_agents_per_env; + int env_count = (num_agents + agents_per_env - 1) / agents_per_env; + env_count--; + + env_count = env_count > num_eval_scenarios ? num_eval_scenarios : env_count; + + PyObject *agent_offsets = PyList_New(env_count + 1); + PyObject *map_ids_list = PyList_New(env_count); + + int offset = 0; + for (int i = 0; i < env_count; i++) { + PyList_SetItem(agent_offsets, i, PyLong_FromLong(offset)); + PyList_SetItem(map_ids_list, i, PyLong_FromLong((s_map_counter + i) % num_maps)); + offset += agents_per_env; + } + PyList_SetItem(agent_offsets, env_count, PyLong_FromLong(offset)); + + PyObject *tuple = PyTuple_New(3); + PyTuple_SetItem(tuple, 0, agent_offsets); + PyTuple_SetItem(tuple, 1, map_ids_list); + PyTuple_SetItem(tuple, 2, PyLong_FromLong(env_count)); + return tuple; + } + + // Training mode: random agent counts per env + int *agent_counts = malloc((num_agents / min_agents_per_env + 1) * sizeof(int)); + int remaining = num_agents; + int env_count = 0; + + while (remaining > 0) { + int count; + if (remaining <= max_agents_per_env) { + count = remaining; + } else { + // 1. We must leave at least min_agents_per_env for the future. + int absolute_max_allowed = remaining - min_agents_per_env; + + // 2. We cannot take more than max_agents_per_env right now. + int current_upper_bound = + (absolute_max_allowed < max_agents_per_env) ? absolute_max_allowed : max_agents_per_env; + + // 3. We must take at least min_agents_per_env right now. + int current_lower_bound = min_agents_per_env; + + // Safety check: if constraints are tight, lower might equal upper. + // If absolute_max_allowed < min_lower_bound for example leading to + // current_upper_bound < current_lower_bound + if (current_upper_bound <= current_lower_bound) { + count = current_lower_bound; + } else { + // Now the range is guaranteed to be positive. + int range = current_upper_bound - current_lower_bound + 1; + count = current_lower_bound + (rand() % range); + } + } + agent_counts[env_count++] = count; + remaining -= count; + } + + // Build Python return lists + PyObject *agent_offsets = PyList_New(env_count + 1); + PyObject *map_ids_list = PyList_New(env_count); + + int offset = 0; + for (int i = 0; i < env_count; i++) { + PyList_SetItem(agent_offsets, i, PyLong_FromLong(offset)); + PyList_SetItem(map_ids_list, i, PyLong_FromLong(rand() % num_maps)); + offset += agent_counts[i]; + } + PyList_SetItem(agent_offsets, env_count, PyLong_FromLong(num_agents)); + + free(agent_counts); - clock_gettime(CLOCK_REALTIME, &ts); - srand(ts.tv_nsec); // Always use random sampling with replacement + PyObject *tuple = PyTuple_New(3); + PyTuple_SetItem(tuple, 0, agent_offsets); + PyTuple_SetItem(tuple, 1, map_ids_list); + PyTuple_SetItem(tuple, 2, PyLong_FromLong(env_count)); + return tuple; + } + // REPLAY mode - existing logic with max_agents_per_env cap int total_agent_count = 0; + int map_id = 0; int env_count = 0; - int max_envs = num_agents; - int maps_checked = 0; + + if (eval_mode) { + max_envs = num_eval_scenarios; + } + // Define the upper boundary for the map window + int end_map_index = starting_map_counter + num_eval_scenarios; + PyObject *agent_offsets = PyList_New(max_envs + 1); PyObject *map_ids = PyList_New(max_envs); - // Getting env count - while (total_agent_count < num_agents && env_count < max_envs) { - char map_file[512]; + // Added condition: s_map_counter < end_map_index + while (total_agent_count < num_agents && env_count < max_envs && (!eval_mode || s_map_counter < end_map_index)) { - // Always sample randomly with replacement - int map_id = rand() % num_maps; + if (eval_mode) { + map_id = s_map_counter % num_maps; + s_map_counter += 1; // This increments towards end_map_index + } else { + map_id = rand() % num_maps; + } - // printf("Sampling map_id: %d\n", map_id); + const char *map_file = PyUnicode_AsUTF8(PyList_GetItem(map_files, map_id)); Drive *env = calloc(1, sizeof(Drive)); env->init_mode = init_mode; env->control_mode = control_mode; + env->simulation_mode = simulation_mode; env->init_steps = init_steps; - env->goal_behavior = goal_behavior; - env->goal_target_distance = goal_target_distance; - env->max_controlled_agents = max_controlled_agents; - snprintf(map_file, sizeof(map_file), "%s/map_%03d.bin", map_dir, map_id); - env->entities = load_map_binary(map_file, env); - // Count the number of controllable agents in map + env->num_max_agents = max_agents_per_env; + load_map_binary(map_file, env); + set_active_agents(env); // Skip map if it doesn't contain any controllable agents if (env->active_agent_count == 0) { maps_checked++; - + // Fix the safeguard, the maps_checked is increased even when the same map is picked. // Safeguard: if we've checked all available maps and found no active agents, raise an error - if (maps_checked >= num_maps) { - for (int j = 0; j < env->num_entities; j++) { - free_entity(&env->entities[j]); - } - free(env->entities); - free(env->active_agent_indices); - free(env->static_agent_indices); - free(env->expert_static_agent_indices); - free(env->tracks_to_predict_indices); - free(env); - Py_DECREF(agent_offsets); - Py_DECREF(map_ids); - char error_msg[256]; - sprintf(error_msg, "No controllable agents found in any of the %d available maps", num_maps); - PyErr_SetString(PyExc_ValueError, error_msg); - return NULL; - } + // if(maps_checked >= num_maps) { + // for(int j=0;jnum_total_agents;j++) free_agent(&env->agents[j]); + // for (int j=0;jnum_road_elements;j++) free_road_element(&env->road_elements[j]); + // for (int j=0;jnum_traffic_elements;j++) free_traffic_element(&env->traffic_elements[j]); + // free(env->agents); + // free(env->road_elements); + // free(env->traffic_elements); + // free(env->active_agent_indices); + // free(env->static_agent_indices); + // free(env->expert_static_agent_indices); + // free(env); + // Py_DECREF(agent_offsets); + // Py_DECREF(map_ids); + // char error_msg[256]; + // sprintf(error_msg, "No controllable agents found in any of the %d available maps", num_maps); + // PyErr_SetString(PyExc_ValueError, error_msg); + // return NULL; + // } - for (int j = 0; j < env->num_entities; j++) { - free_entity(&env->entities[j]); - } - free(env->entities); + for (int j = 0; j < env->num_total_agents; j++) + free_agent(&env->agents[j]); + for (int j = 0; j < env->num_road_elements; j++) + free_road_element(&env->road_elements[j]); + for (int j = 0; j < env->num_traffic_elements; j++) + free_traffic_element(&env->traffic_elements[j]); + free(env->agents); + free(env->road_elements); + free(env->traffic_elements); free(env->active_agent_indices); free(env->static_agent_indices); free(env->expert_static_agent_indices); - free(env->tracks_to_predict_indices); free(env); continue; } @@ -154,25 +1729,28 @@ static PyObject *my_shared(PyObject *self, PyObject *args, PyObject *kwargs) { PyList_SetItem(agent_offsets, env_count, offset); total_agent_count += env->active_agent_count; env_count++; - for (int j = 0; j < env->num_entities; j++) { - free_entity(&env->entities[j]); - } - free(env->entities); + for (int j = 0; j < env->num_total_agents; j++) + free_agent(&env->agents[j]); + for (int j = 0; j < env->num_road_elements; j++) + free_road_element(&env->road_elements[j]); + for (int j = 0; j < env->num_traffic_elements; j++) + free_traffic_element(&env->traffic_elements[j]); + free(env->agents); + free(env->road_elements); + free(env->traffic_elements); free(env->active_agent_indices); free(env->static_agent_indices); - free(env->tracks_to_predict_indices); free(env->expert_static_agent_indices); free(env); } - + // printf("Generated %d environments to cover %d agents (requested %d agents)\n", env_count, total_agent_count, + // num_agents); if (total_agent_count >= num_agents) { total_agent_count = num_agents; } - PyObject *final_total_agent_count = PyLong_FromLong(total_agent_count); PyList_SetItem(agent_offsets, env_count, final_total_agent_count); PyObject *final_env_count = PyLong_FromLong(env_count); - // resize lists PyObject *resized_agent_offsets = PyList_GetSlice(agent_offsets, 0, env_count + 1); PyObject *resized_map_ids = PyList_GetSlice(map_ids, 0, env_count); @@ -184,102 +1762,116 @@ static PyObject *my_shared(PyObject *self, PyObject *args, PyObject *kwargs) { } static int my_init(Env *env, PyObject *args, PyObject *kwargs) { - env->human_agent_idx = unpack(kwargs, "human_agent_idx"); env->ini_file = unpack_str(kwargs, "ini_file"); - env_init_config conf = {0}; - if (ini_parse(env->ini_file, handler, &conf) < 0) { - printf("Error while loading %s", env->ini_file); - } - if (kwargs && PyDict_GetItemString(kwargs, "episode_length")) { - conf.episode_length = (int)unpack(kwargs, "episode_length"); - } - if (conf.episode_length <= 0) { - PyErr_SetString(PyExc_ValueError, "episode_length must be > 0 (set in INI or kwargs)"); - return -1; - } - -// Allow all settings to be overridden via kwargs (ini provides defaults) -#define OVERRIDE_INT(field) \ - if (kwargs && PyDict_GetItemString(kwargs, #field)) { \ - conf.field = (int)unpack(kwargs, #field); \ - } -#define OVERRIDE_FLOAT(field) \ - if (kwargs && PyDict_GetItemString(kwargs, #field)) { \ - conf.field = (float)unpack(kwargs, #field); \ - } - - OVERRIDE_INT(render_mode); - OVERRIDE_INT(action_type); - OVERRIDE_INT(dynamics_model); - OVERRIDE_FLOAT(reward_vehicle_collision); - OVERRIDE_FLOAT(reward_offroad_collision); - OVERRIDE_FLOAT(reward_goal); - OVERRIDE_FLOAT(reward_goal_post_respawn); - OVERRIDE_INT(collision_behavior); - OVERRIDE_INT(offroad_behavior); - OVERRIDE_FLOAT(dt); - OVERRIDE_INT(termination_mode); - OVERRIDE_INT(init_mode); - OVERRIDE_INT(control_mode); - OVERRIDE_INT(goal_behavior); - OVERRIDE_FLOAT(goal_target_distance); - OVERRIDE_FLOAT(goal_radius); - OVERRIDE_FLOAT(goal_speed); - OVERRIDE_INT(max_controlled_agents); - -#undef OVERRIDE_INT -#undef OVERRIDE_FLOAT - - env->action_type = conf.action_type; - env->dynamics_model = conf.dynamics_model; - env->reward_vehicle_collision = conf.reward_vehicle_collision; - env->reward_offroad_collision = conf.reward_offroad_collision; - env->reward_goal = conf.reward_goal; - env->reward_goal_post_respawn = conf.reward_goal_post_respawn; - env->episode_length = conf.episode_length; - env->termination_mode = conf.termination_mode; - env->collision_behavior = conf.collision_behavior; - env->offroad_behavior = conf.offroad_behavior; - env->max_controlled_agents = unpack(kwargs, "max_controlled_agents"); - env->dt = conf.dt; - env->init_mode = (int)unpack(kwargs, "init_mode"); - env->control_mode = (int)unpack(kwargs, "control_mode"); - env->goal_behavior = (int)unpack(kwargs, "goal_behavior"); - env->goal_target_distance = (float)unpack(kwargs, "goal_target_distance"); + // env_init_config conf = {0}; + // if (ini_parse(env->ini_file, handler, &conf) < 0) { + // printf("Error while loading %s", env->ini_file); + // } + // if (kwargs && PyDict_GetItemString(kwargs, "scenario_length")) { + // conf.scenario_length = (int)unpack(kwargs, "scenario_length"); + // } + // if (kwargs && PyDict_GetItemString(kwargs, "termination_mode")) { + // conf.termination_mode = (int)unpack(kwargs, "termination_mode"); + // } + // if (conf.scenario_length <= 0) { + // PyErr_SetString(PyExc_ValueError, "scenario_length must be > 0 (set in INI or kwargs)"); + // return -1; + // } + env->action_type = (int)unpack(kwargs, "action_type"); + env->dynamics_model = (int)unpack(kwargs, "dynamics_model"); + env->reward_goal = (float)unpack(kwargs, "reward_goal"); + env->reward_vehicle_collision = (float)unpack(kwargs, "reward_vehicle_collision"); + env->reward_offroad_collision = (float)unpack(kwargs, "reward_offroad_collision"); + env->reward_comfort = (float)unpack(kwargs, "reward_comfort"); + env->reward_lane_align = (float)unpack(kwargs, "reward_lane_align"); + env->reward_vel_align = (float)unpack(kwargs, "reward_vel_align"); + env->reward_lane_center = (float)unpack(kwargs, "reward_lane_center"); + env->reward_center_bias = (float)unpack(kwargs, "reward_center_bias"); + env->reward_velocity = (float)unpack(kwargs, "reward_velocity"); + env->reward_reverse = (float)unpack(kwargs, "reward_reverse"); + env->reward_traffic_light_violation = (float)unpack(kwargs, "reward_traffic_light_violation"); + env->reward_timestep = (float)unpack(kwargs, "reward_timestep"); + env->reward_overspeed = (float)unpack(kwargs, "reward_overspeed"); + env->reward_ade = (float)unpack(kwargs, "reward_ade"); + env->collision_behavior = (int)unpack(kwargs, "collision_behavior"); + env->offroad_behavior = (int)unpack(kwargs, "offroad_behavior"); + env->traffic_light_behavior = (int)unpack(kwargs, "traffic_light_behavior"); env->goal_radius = (float)unpack(kwargs, "goal_radius"); - env->goal_speed = (float)unpack(kwargs, "goal_speed"); - env->render_mode = (int)unpack(kwargs, "render_mode"); - char *map_dir = unpack_str(kwargs, "map_dir"); - int map_id = unpack(kwargs, "map_id"); - int max_agents = unpack(kwargs, "max_agents"); - int init_steps = unpack(kwargs, "init_steps"); - char map_file[512]; - snprintf(map_file, sizeof(map_file), "%s/map_%03d.bin", map_dir, map_id); - env->num_agents = max_agents; - env->map_name = strdup(map_file); + env->min_waypoint_spacing = (float)unpack(kwargs, "min_waypoint_spacing"); + env->max_waypoint_spacing = (float)unpack(kwargs, "max_waypoint_spacing"); + env->num_target_waypoints = (int)unpack(kwargs, "num_target_waypoints"); + if (env->num_target_waypoints > MAX_TARGET_WAYPOINTS) { + env->num_target_waypoints = MAX_TARGET_WAYPOINTS; + } + env->target_type = (int)unpack(kwargs, "target_type"); + env->use_rear_axle = (int)unpack(kwargs, "use_rear_axle"); + env->max_boundary_segment_observations = (int)unpack(kwargs, "max_boundary_segment_observations"); + env->max_lane_segment_observations = (int)unpack(kwargs, "max_lane_segment_observations"); + env->max_partner_observations = (int)unpack(kwargs, "max_partner_observations"); + env->max_traffic_light_observations = (int)unpack(kwargs, "max_traffic_light_observations"); + env->max_stop_sign_observations = (int)unpack(kwargs, "max_stop_sign_observations"); + env->dt = (float)unpack(kwargs, "dt"); + env->spawn_initial_speed = (float)unpack(kwargs, "spawn_initial_speed"); + env->goal_speed_threshold = (float)unpack(kwargs, "goal_speed_threshold"); + env->scenario_length = (int)unpack(kwargs, "scenario_length"); + env->termination_mode = (int)unpack(kwargs, "termination_mode"); + env->inactive_agent_threshold = (float)unpack(kwargs, "inactive_agent_threshold"); + char *map_file = unpack_str(kwargs, "map_file"); + env->map_name = map_file; + int max_agents = (int)unpack(kwargs, "max_agents"); + env->num_controllable_agents = max_agents; + int max_agents_per_env = (int)unpack(kwargs, "max_agents_per_env"); + env->num_max_agents = max_agents_per_env; + + int init_steps = (int)unpack(kwargs, "init_steps"); env->init_steps = init_steps; env->timestep = init_steps; + env->init_mode = (int)unpack(kwargs, "init_mode"); + env->control_mode = (int)unpack(kwargs, "control_mode"); + env->simulation_mode = (int)unpack(kwargs, "simulation_mode"); + env->reward_conditioning = (bool)unpack(kwargs, "reward_conditioning"); + env->reward_randomization = (bool)unpack(kwargs, "reward_randomization"); + env->compute_eval_metrics = (bool)unpack(kwargs, "compute_eval_metrics"); + env->eval_mode = (int)unpack(kwargs, "eval_mode"); + init(env); return 0; } -static int my_log(PyObject *dict, Log *log) { +static int my_log(PyObject *dict, Env *env, Log *log, float n) { + float total_distance_travelled = log->total_distance_travelled * n; + float total_infractions = log->total_infractions * n; + float avg_distance_per_infraction = total_distance_travelled / fmaxf(1.0f, total_infractions); + assign_to_dict(dict, "n", log->n); - assign_to_dict(dict, "score", log->score); assign_to_dict(dict, "offroad_rate", log->offroad_rate); - assign_to_dict(dict, "collision_rate", log->collision_rate); assign_to_dict(dict, "episode_length", log->episode_length); + assign_to_dict(dict, "collision_rate", log->collision_rate); assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "dnf_rate", log->dnf_rate); - assign_to_dict(dict, "completion_rate", log->completion_rate); - assign_to_dict(dict, "lane_alignment_rate", log->lane_alignment_rate); - assign_to_dict(dict, "perc_controlled", log->perc_controlled); - assign_to_dict(dict, "perc_other", log->perc_other); - assign_to_dict(dict, "offroad_per_agent", log->offroad_per_agent); - assign_to_dict(dict, "collisions_per_agent", log->collisions_per_agent); - assign_to_dict(dict, "goals_sampled_this_episode", log->goals_sampled_this_episode); - assign_to_dict(dict, "goals_reached_this_episode", log->goals_reached_this_episode); - assign_to_dict(dict, "speed_at_goal", log->speed_at_goal); + assign_to_dict(dict, "red_light_violation_rate", log->red_light_violation_rate); + assign_to_dict(dict, "comfort_violation_count", log->comfort_violation_count); // assign_to_dict(dict, "avg_displacement_error", log->avg_displacement_error); + assign_to_dict(dict, "velocity_progress_sum", log->velocity_progress_sum); + assign_to_dict(dict, "num_goals_reached", log->num_goals_reached); + assign_to_dict(dict, "lane_center_rate", log->lane_center_rate); + assign_to_dict(dict, "dnf_rate", log->dnf_rate); + assign_to_dict(dict, "score", log->score); + assign_to_dict(dict, "avg_speed_per_agent", log->avg_speed_per_agent); + assign_to_dict(dict, "avg_distance_per_infraction", avg_distance_per_infraction); + + if (env->compute_eval_metrics) { + // Puffer score components + assign_to_dict(dict, "at_fault_collision_rate", log->at_fault_collision_rate); + assign_to_dict(dict, "puffer_score", log->puffer_score); + assign_to_dict(dict, "ttc_within_bound_rate", log->ttc_within_bound_rate); + assign_to_dict(dict, "driving_direction_score", log->driving_direction_score); + assign_to_dict(dict, "speed_limit_compliance", log->speed_limit_compliance); + assign_to_dict(dict, "making_progress_rate", log->making_progress_rate); + assign_to_dict(dict, "progress_ratio", log->progress_ratio); + assign_to_dict(dict, "comfort_score", log->comfort_score); + assign_to_dict(dict, "multi_lane_time", log->multi_lane_time); + assign_to_dict(dict, "multi_lane_score", log->multi_lane_score); + } + return 0; } diff --git a/pufferlib/ocean/drive/datatypes.h b/pufferlib/ocean/drive/datatypes.h new file mode 100644 index 0000000000..1904c4d258 --- /dev/null +++ b/pufferlib/ocean/drive/datatypes.h @@ -0,0 +1,352 @@ +#define UNKNOWN 0 + +// -- REWARD CONDITIONING COEFFICIENTS +#define REWARD_COEF_GOAL_RADIUS 0 +#define REWARD_COEF_COLLISION 1 +#define REWARD_COEF_OFFROAD 2 +#define REWARD_COEF_COMFORT 3 +#define REWARD_COEF_LANE_ALIGN 4 +#define REWARD_COEF_VEL_ALIGN 5 +#define REWARD_COEF_LANE_CENTER 6 +#define REWARD_COEF_CENTER_BIAS 7 +#define REWARD_COEF_VELOCITY 8 +#define REWARD_COEF_REVERSE 9 +#define REWARD_COEF_TRAFFIC_LIGHT 10 +#define REWARD_COEF_TIMESTEP 11 +#define REWARD_COEF_OVERSPEED 12 +// Dynamic conditioning coefficients +#define REWARD_COEF_THROTTLE 13 +#define REWARD_COEF_STEER 14 +#define REWARD_COEF_ACC 15 +#define NUM_REWARD_COEFS 16 + +// -- AGENT TYPE +#define VEHICLE 1 +#define PEDESTRIAN 2 +#define CYCLIST 3 +#define OTHER 4 + +// -- ROAD TYPE +#define LANE_FREEWAY 1 +#define LANE_SURFACE_STREET 2 +#define LANE_BIKE_LANE 3 + +#define ROAD_LINE_UNKNOWN 10 +#define ROAD_LINE_BROKEN_SINGLE_WHITE 11 +#define ROAD_LINE_SOLID_SINGLE_WHITE 12 +#define ROAD_LINE_SOLID_DOUBLE_WHITE 13 +#define ROAD_LINE_BROKEN_SINGLE_YELLOW 14 +#define ROAD_LINE_BROKEN_DOUBLE_YELLOW 15 +#define ROAD_LINE_SOLID_SINGLE_YELLOW 16 +#define ROAD_LINE_SOLID_DOUBLE_YELLOW 17 +#define ROAD_LINE_PASSING_DOUBLE_YELLOW 18 + +#define ROAD_EDGE_UNKNOWN 20 +#define ROAD_EDGE_BOUNDARY 21 +#define ROAD_EDGE_MEDIAN 22 +#define ROAD_EDGE_SIDEWALK 23 + +#define CROSSWALK 31 +#define DRIVEWAY 32 + +// -- TRAFFIC CONTROL TYPE +#define TRAFFIC_LIGHT 1 +#define STOP_SIGN 2 +#define YIELD_SIGN 3 +#define SPEED_LIMIT_SIGN 4 + +#define TL_STATE_DISABLED 0 +#define TL_STATE_YELLOW 2 +#define TL_STATE_GREEN 3 +#define TL_STATE_RED 4 +// Number of normalized traffic light states: disabled, red, yellow, green +#define NUM_TRAFFIC_LIGHT_STATES 4 + +// Metrics array indices +#define NUM_METRICS 18 +#define COLLISION_IDX 0 +#define OFFROAD_IDX 1 +#define RED_LIGHT_IDX 2 +#define STOP_SIGN_IDX 3 +#define REACHED_GOAL_IDX 4 +#define LANE_DIST_IDX 5 +#define LANE_ANGLE_IDX 6 +#define COMFORT_VIOLATION_IDX 7 +#define VELOCITY_PROGRESS_IDX 8 +#define SPEED_LIMIT_IDX 9 +#define AVG_DISPLACEMENT_ERROR_IDX 10 +#define PROGRESSION_IDX 11 +// Evaluation metrics +#define AT_FAULT_COLLISION_IDX 12 +#define TTC_IDX 13 +#define TTC_TFL_IDX 14 +#define PROGRESS_RATIO_IDX 15 +#define MULTI_LANE_TIME_IDX 16 +#define MULTI_LANE_SCORE_IDX 17 + +// Path +#define MAX_NUM_WP_PATH 200 +#define MAX_TARGET_WAYPOINTS 20 + +struct Waypoint { + float s; // Arc length (cumulative distance from the start) - init position + float x; // Global x-coordinate + float y; // Global y-coordinate + float z; // Global z-coordinate + float heading; // Global heading (tangent angle) in radians + float cos_heading; // Cached cosf(heading) - set in build_path + float sin_heading; // Cached sinf(heading) - set in build_path + float kappa; // Curvature at this point + int lane_id; // Lane id of the waypoint +}; +struct Path { + struct Waypoint waypoints[MAX_NUM_WP_PATH]; + int num_waypoints; +}; + +struct ttc_result { + float min_ttc; + int other_idx; + float distance_to_collision; + float closing_speed; +}; + +static inline int is_road_lane(int type) { return (type >= 1 && type <= 9); } + +static inline int is_drivable_road_lane(int type) { return (type == LANE_FREEWAY || type == LANE_SURFACE_STREET); } + +static inline int is_road_line(int type) { return (type >= 10 && type <= 19); } + +static inline int is_road_edge(int type) { return (type >= 20 && type <= 29); } + +static inline int is_road(int type) { return is_road_lane(type) || is_road_line(type) || is_road_edge(type); } + +static inline int is_controllable_agent(int type) { return (type == VEHICLE || type == PEDESTRIAN || type == CYCLIST); } + +static inline int is_traffic_light_red(int state) { return state == 1 || state == TL_STATE_RED || state == 7; } + +static inline int is_traffic_light_green(int state) { return state == TL_STATE_GREEN || state == 6 || state == 9; } + +static inline int is_traffic_light_yellow(int state) { return state == TL_STATE_YELLOW || state == 5 || state == 8; } + +static inline int normalize_road_type(int type) { + if (is_road_lane(type)) { + return 0; + } else if (is_road_line(type)) { + return 1; + } else if (is_road_edge(type)) { + return 2; + } else { + return -1; + } +} + +static inline int unnormalize_road_type(int norm_type) { + if (norm_type == 0) { + return LANE_SURFACE_STREET; + } else if (norm_type == 1) { + return ROAD_LINE_BROKEN_SINGLE_WHITE; + } else if (norm_type == 2) { + return ROAD_EDGE_BOUNDARY; + } else { + return -1; // Invalid + } +} + +static inline int normalize_traffic_light_state(int state) { + if (is_traffic_light_red(state)) { + return 1; + } else if (is_traffic_light_yellow(state)) { + return 2; + } else if (is_traffic_light_green(state)) { + return 3; + } else { + return TL_STATE_DISABLED; // Invalid or disabled + } +} + +static inline int unnormalize_traffic_light_state(int norm_state) { + if (norm_state == 1) { + return TL_STATE_RED; + } else if (norm_state == 2) { + return TL_STATE_YELLOW; + } else if (norm_state == 3) { + return TL_STATE_GREEN; + } else { + return TL_STATE_DISABLED; // Invalid or disabled + } +} + +struct Agent { + int id; + int type; + + // Log trajectory + int trajectory_length; + float *log_trajectory_x; + float *log_trajectory_y; + float *log_trajectory_z; + float *log_heading; + float *log_velocity_x; + float *log_velocity_y; + float *log_length; + float *log_width; + float *log_height; + int *log_valid; + + // Simulation state (always center-based, even when trajectory control uses the rear axle) + float sim_x; // Vehicle center x-coordinate + float sim_y; // Vehicle center y-coordinate + float sim_z; + float sim_heading; + float cos_heading; // Cached cosf(sim_heading) - updated in move_dynamics + float sin_heading; // Cached sinf(sim_heading) - updated in move_dynamics + float sim_vx; // Vehicle center velocity x-component + float sim_vy; // Vehicle center velocity y-component + float yaw_rate; // Angular velocity used to derive rear-axle velocity + float sim_speed; + float sim_speed_signed; + float sim_length; + float sim_width; + float sim_height; + int sim_valid; + float render_corners[4][2]; // Bounding box corners computed by simulation + + // Route information + int route_length; + int *route; + int route_gt_len; // Number of leading route lanes supported by GT before extension + int current_route_index; // Tracks progress through route array + + // Path + struct Path *path; + int closest_path_idx_wp; + + // Metrics and status tracking (size must match NUM_METRICS in drive.h) + float metrics_array[NUM_METRICS]; // [collision, offroad, red_light, stop_sign, reached_goal, lane_dist, lane_angle, + // comfort_violation, velocity_progress, speed_limit, avg_displacement_error, + // progression, at_fault_collision, ttc, ttc_tfl, progress_ratio, + // multi_lane_time, multi_lane_score] + int current_lane_index; + int previous_lane_index; + int current_lane_geometry_idx; + int reached_goal_this_episode; + int num_waypoints_reached; + int num_goals_reached; + int active_agent; + int mark_as_expert; + float cumulative_displacement; + int displacement_sample_count; + float path_progression; + float distance_since_spawn; + + // Goal positions (N sequential waypoints) + float goal_positions_x[MAX_TARGET_WAYPOINTS]; + float goal_positions_y[MAX_TARGET_WAYPOINTS]; + float goal_positions_z[MAX_TARGET_WAYPOINTS]; + float goal_position_x; // alias = goal_positions_x[current_goal_idx] + float goal_position_y; // alias = goal_positions_y[current_goal_idx] + float goal_position_z; // alias = goal_positions_z[current_goal_idx] + int current_goal_idx; // index of next goal to reach (0..N-1) + + int stopped; // 0/1 -> freeze if set + int removed; // 0/1 -> remove from sim if set + + // Jerk dynamics + float a_long; + float a_lat; + float jerk_long; + float jerk_lat; + float steering_angle; + float wheelbase; + + // Reward conditioning coefficients (per-agent, randomized at spawn) + float reward_coefs[NUM_REWARD_COEFS]; + + // Puffer score tracking (per-episode accumulators) + struct ttc_result cached_ttc; // Filled once per step before reward computation + float wrong_way_distance; // Accumulated wrong-way distance + float speed_violation_sum; // For nuPlan speed compliance formula + int ttc_violations; // Count of TTC < 0.95s violations + int ttc_samples; // Total TTC samples for rate + int at_fault_collision; // 1 if at-fault collision occurred this episode + float multi_lane_time; // Accumulated time (s) on multiple lanes +}; + +struct RoadMapElement { + int id; + int type; + + int segment_length; + float *x; + float *y; + float *z; + float *headings; // Pre-computed heading for each segment + + // Lane specific info + int num_entries; + int *entry_lanes; + int num_exits; + int *exit_lanes; + float speed_limit; +}; + +struct TrafficControlElement { + int id; + int type; + + int state_length; + int *states; + float stop_line[6]; // Two 3D endpoints: [x1,y1,z1, x2,y2,z2] + float heading; + int num_controlled_lanes; + int *controlled_lanes; +}; + +typedef struct { + float z_dis; + float euclidean_dis; + float z; +} DepthPoint; + +struct LaneGraph { + int n_lanes; + int *lane_ids; + float *lane_lengths; + float *distances; // n_lanes * n_lanes row-major +}; + +void free_agent(struct Agent *agent) { + free(agent->log_trajectory_x); + free(agent->log_trajectory_y); + free(agent->log_trajectory_z); + free(agent->log_heading); + free(agent->log_velocity_x); + free(agent->log_velocity_y); + free(agent->log_length); + free(agent->log_width); + free(agent->log_height); + free(agent->log_valid); + free(agent->route); + free(agent->path); +} + +void free_road_element(struct RoadMapElement *element) { + free(element->x); + free(element->y); + free(element->z); + free(element->headings); + free(element->entry_lanes); + free(element->exit_lanes); +} + +void free_traffic_element(struct TrafficControlElement *element) { + free(element->states); + free(element->controlled_lanes); +} + +void free_lane_graph(struct LaneGraph *graph) { + free(graph->lane_ids); + free(graph->lane_lengths); + free(graph->distances); +} diff --git a/pufferlib/ocean/drive/drive.c b/pufferlib/ocean/drive/drive.c index 7a714ac4a1..f99c4b0a2e 100644 --- a/pufferlib/ocean/drive/drive.c +++ b/pufferlib/ocean/drive/drive.c @@ -1,8 +1,7 @@ +#include "drive.h" #include "drivenet.h" -#include "error.h" -#include "libgen.h" -#include "../env_config.h" #include +#include "../env_config.h" // Use this test if the network changes to ensure that the forward pass // matches the torch implementation to the 3rd or ideally 4th decimal place @@ -34,122 +33,76 @@ void test_drivenet() { free(weights); } -int demo(const char *map_name, const char *policy_name, int show_grid, int obs_only, int lasers, int show_human_logs, - int frame_skip, const char *view_mode, const char *output_topdown, const char *output_agent, int num_maps, - int zoom_in) { - - // Parse configuration from INI file +void demo() { + // Read configuration from INI file env_init_config conf = {0}; const char *ini_file = "pufferlib/config/ocean/drive.ini"; - if (ini_parse(ini_file, handler, &conf) < 0) { + if (load_env_config(ini_file, &conf) < 0) { fprintf(stderr, "Error: Could not load %s. Cannot determine environment configuration.\n", ini_file); - return -1; - } - - char map_buffer[100]; - if (map_name == NULL) { - srand(time(NULL)); - int random_map = rand() % num_maps; - sprintf(map_buffer, "%s/map_%03d.bin", conf.map_dir, random_map); - map_name = map_buffer; + exit(1); } - // Initialize environment with all config values from INI [env] section Drive env = { - .action_type = conf.action_type, + .human_agent_idx = 0, .dynamics_model = conf.dynamics_model, .reward_vehicle_collision = conf.reward_vehicle_collision, .reward_offroad_collision = conf.reward_offroad_collision, - .reward_goal = conf.reward_goal, - .reward_goal_post_respawn = conf.reward_goal_post_respawn, + .reward_ade = conf.reward_ade, .goal_radius = conf.goal_radius, - .goal_behavior = conf.goal_behavior, - .goal_target_distance = conf.goal_target_distance, - .goal_speed = conf.goal_speed, .dt = conf.dt, - .episode_length = conf.episode_length, - .termination_mode = conf.termination_mode, + .map_name = "resources/drive/binaries/map_000.bin", + .init_steps = conf.init_steps, .collision_behavior = conf.collision_behavior, .offroad_behavior = conf.offroad_behavior, - .init_steps = conf.init_steps, - .init_mode = conf.init_mode, - .control_mode = conf.control_mode, - .map_name = (char *)map_name, + .compute_eval_metrics = conf.compute_eval_metrics, }; allocate(&env); - if (env.active_agent_count == 0) { - fprintf(stderr, "Error: No active agents found in map '%s' with init_mode=%d. Cannot run demo.\n", env.map_name, - conf.init_mode); - free_allocated(&env); - return -1; - } c_reset(&env); c_render(&env); - Weights *weights = load_weights((char *)policy_name); + Weights *weights = load_weights("resources/drive/puffer_drive_weights.bin"); DriveNet *net = init_drivenet(weights, env.active_agent_count, env.dynamics_model); - + // Client* client = make_client(&env); int accel_delta = 2; int steer_delta = 4; while (!WindowShouldClose()) { - int *actions = (int *)env.actions; // Single integer per agent - - forward(net, env.observations, actions); - + // Handle camera controls + int (*actions)[2] = (int (*)[2])env.actions; + forward(net, env.observations, env.actions); if (IsKeyDown(KEY_LEFT_SHIFT)) { - if (env.dynamics_model == CLASSIC) { - // Classic dynamics: acceleration and steering - int accel_idx = 3; // neutral (0 m/s²) - int steer_idx = 6; // neutral (0.0 steering) - - if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) { - accel_idx += accel_delta; - if (accel_idx > 6) - accel_idx = 6; - } - if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) { - accel_idx -= accel_delta; - if (accel_idx < 0) - accel_idx = 0; - } - if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) { - steer_idx += steer_delta; // Increase steering index for left turn - if (steer_idx > 12) - steer_idx = 12; + actions[env.human_agent_idx][0] = 3; + actions[env.human_agent_idx][1] = 6; + if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) { + actions[env.human_agent_idx][0] += accel_delta; + // Cap acceleration to maximum of 6 + if (actions[env.human_agent_idx][0] > 6) { + actions[env.human_agent_idx][0] = 6; } - if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) { - steer_idx -= steer_delta; // Decrease steering index for right turn - if (steer_idx < 0) - steer_idx = 0; - } - - // Encode into single integer: action = accel_idx * 13 + steer_idx - actions[env.human_agent_idx] = accel_idx * 13 + steer_idx; - - } else if (env.dynamics_model == JERK) { - // Jerk dynamics: longitudinal and lateral jerk - // JERK_LONG[4] = {-15.0f, -4.0f, 0.0f, 4.0f} - // JERK_LAT[3] = {-4.0f, 0.0f, 4.0f} - int jerk_long_idx = 2; // neutral (0.0) - int jerk_lat_idx = 1; // neutral (0.0) - - if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) { - jerk_long_idx = 3; // acceleration (4.0) - } - if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) { - jerk_long_idx = 0; // hard braking (-15.0) + } + if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) { + actions[env.human_agent_idx][0] -= accel_delta; + // Cap acceleration to minimum of 0 + if (actions[env.human_agent_idx][0] < 0) { + actions[env.human_agent_idx][0] = 0; } - if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) { - jerk_lat_idx = 2; // left turn (4.0) + } + if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) { + actions[env.human_agent_idx][1] += steer_delta; + // Cap steering to minimum of 0 + if (actions[env.human_agent_idx][1] < 0) { + actions[env.human_agent_idx][1] = 0; } - if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) { - jerk_lat_idx = 0; // right turn (-4.0) + } + if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) { + actions[env.human_agent_idx][1] -= steer_delta; + // Cap steering to maximum of 12 + if (actions[env.human_agent_idx][1] > 12) { + actions[env.human_agent_idx][1] = 12; } - - // Encode into single integer: action = jerk_long_idx * 3 + jerk_lat_idx - actions[env.human_agent_idx] = jerk_long_idx * 3 + jerk_lat_idx; + } + if (IsKeyPressed(KEY_TAB)) { + env.human_agent_idx = (env.human_agent_idx + 1) % env.active_agent_count; } } - c_step(&env); c_render(&env); } @@ -158,137 +111,114 @@ int demo(const char *map_name, const char *policy_name, int show_grid, int obs_o free_allocated(&env); free_drivenet(net); free(weights); - return 0; } void performance_test() { + // Read configuration from INI file + env_init_config conf = {0}; + const char *ini_file = "pufferlib/config/ocean/drive.ini"; + if (load_env_config(ini_file, &conf) < 0) { + fprintf(stderr, "Error: Could not load %s. Cannot determine environment configuration.\n", ini_file); + exit(1); + } long test_time = 10; Drive env = { .human_agent_idx = 0, - .dynamics_model = CLASSIC, // Classic dynamics - .action_type = 0, // Discrete - .map_name = "resources/drive/binaries/map_000.bin", - .dt = 0.1f, - .init_steps = 0, + .map_name = strdup("pufferlib/resources/drive/binaries/carla/map_000.bin"), + .ini_file = strdup(ini_file), + .num_controllable_agents = conf.max_agents_per_env, + // From conf + .action_type = conf.action_type, + .dynamics_model = conf.dynamics_model, + .reward_vehicle_collision = conf.reward_vehicle_collision, + .reward_offroad_collision = conf.reward_offroad_collision, + .reward_traffic_light_violation = conf.reward_traffic_light_violation, + .reward_goal = conf.reward_goal, + .reward_ade = conf.reward_ade, + .reward_overspeed = conf.reward_overspeed, + .reward_comfort = conf.reward_comfort, + .reward_velocity = conf.reward_velocity, + .reward_lane_align = conf.reward_lane_align, + .reward_vel_align = conf.reward_vel_align, + .reward_lane_center = conf.reward_lane_center, + .reward_center_bias = conf.reward_center_bias, + .reward_reverse = conf.reward_reverse, + .reward_timestep = conf.reward_timestep, + .goal_radius = conf.goal_radius, + .collision_behavior = conf.collision_behavior, + .offroad_behavior = conf.offroad_behavior, + .traffic_light_behavior = conf.traffic_light_behavior, + .dt = conf.dt, + .target_type = conf.target_type, + .scenario_length = conf.scenario_length, + .termination_mode = conf.termination_mode, + .init_steps = conf.init_steps, + .init_mode = conf.init_mode, + .control_mode = conf.control_mode, + .simulation_mode = conf.simulation_mode, + .min_waypoint_spacing = conf.min_waypoint_spacing, + .max_waypoint_spacing = conf.max_waypoint_spacing, + .num_target_waypoints = conf.num_target_waypoints, + .reward_conditioning = conf.reward_conditioning, + .reward_randomization = conf.reward_randomization, + .compute_eval_metrics = conf.compute_eval_metrics, + .num_max_agents = conf.max_agents_per_env, + .use_rear_axle = conf.use_rear_axle, + .max_lane_segment_observations = conf.max_lane_segment_observations, + .max_boundary_segment_observations = conf.max_boundary_segment_observations, + .max_partner_observations = conf.max_partner_observations, + .max_traffic_light_observations = conf.max_traffic_light_observations, + .max_stop_sign_observations = conf.max_stop_sign_observations, }; - clock_t start_time, end_time; - double cpu_time_used; - start_time = clock(); + struct timespec ts_total_start, ts_total_end; + struct timespec ts_init_start, ts_init_end; + struct timespec ts_step_start, ts_step_end; + double init_time = 0, step_time = 0, total_time = 0; + + clock_gettime(CLOCK_MONOTONIC, &ts_total_start); + + clock_gettime(CLOCK_MONOTONIC, &ts_init_start); allocate(&env); c_reset(&env); - end_time = clock(); - cpu_time_used = ((double)(end_time - start_time)) / CLOCKS_PER_SEC; - printf("Init time: %f\n", cpu_time_used); + clock_gettime(CLOCK_MONOTONIC, &ts_init_end); + init_time = (ts_init_end.tv_sec - ts_init_start.tv_sec) + (ts_init_end.tv_nsec - ts_init_start.tv_nsec) / 1e9; + printf("Init time: %.4f s\n", init_time); long start = time(NULL); int i = 0; - int (*actions)[2] = (int (*)[2])env.actions; + // Reallocate actions buffer for trajectory mode (needs num_trajectory_scaling_factors per agent) + + clock_gettime(CLOCK_MONOTONIC, &ts_step_start); while (time(NULL) - start < test_time) { - // Set random actions for all agents + // Set random discrete actions for all agents + int (*actions)[2] = (int (*)[2])env.actions; for (int j = 0; j < env.active_agent_count; j++) { - int accel = rand() % 7; - int steer = rand() % 13; - actions[j][0] = accel; // -1, 0, or 1 - actions[j][1] = steer; // Random steering + actions[j][0] = rand() % 7; + actions[j][1] = rand() % 13; } - c_step(&env); i++; } + clock_gettime(CLOCK_MONOTONIC, &ts_step_end); + step_time = (ts_step_end.tv_sec - ts_step_start.tv_sec) + (ts_step_end.tv_nsec - ts_step_start.tv_nsec) / 1e9; + long end = time(NULL); + printf("Steps: %d | Agents: %d\n", i, env.active_agent_count); + printf("Step loop time: %.4f s\n", step_time); printf("SPS: %ld\n", (i * env.active_agent_count) / (end - start)); - free_allocated(&env); -} - -int main(int argc, char *argv[]) { - // Visualization-only parameters (not in [env] section) - int show_grid = 0; - int obs_only = 0; - int lasers = 0; - int show_human_logs = 0; - int frame_skip = 1; - int zoom_in = 0; - const char *view_mode = "both"; - // File paths and num_maps (not in [env] section) - const char *map_name = NULL; - const char *policy_name = "resources/drive/puffer_drive_weights.bin"; - const char *output_topdown = NULL; - const char *output_agent = NULL; - int num_maps = 1; + free_allocated(&env); - // Parse command line arguments - for (int i = 1; i < argc; i++) { - if (strcmp(argv[i], "--show-grid") == 0) { - show_grid = 1; - } else if (strcmp(argv[i], "--obs-only") == 0) { - obs_only = 1; - } else if (strcmp(argv[i], "--lasers") == 0) { - lasers = 1; - } else if (strcmp(argv[i], "--log-trajectories") == 0) { - show_human_logs = 1; - } else if (strcmp(argv[i], "--frame-skip") == 0) { - if (i + 1 < argc) { - frame_skip = atoi(argv[i + 1]); - i++; - if (frame_skip <= 0) { - frame_skip = 1; - } - } - } else if (strcmp(argv[i], "--zoom-in") == 0) { - zoom_in = 1; - } else if (strcmp(argv[i], "--view") == 0) { - if (i + 1 < argc) { - view_mode = argv[i + 1]; - i++; - if (strcmp(view_mode, "both") != 0 && strcmp(view_mode, "topdown") != 0 && - strcmp(view_mode, "agent") != 0) { - fprintf(stderr, "Error: --view must be 'both', 'topdown', or 'agent'\n"); - return 1; - } - } else { - fprintf(stderr, "Error: --view option requires a value (both/topdown/agent)\n"); - return 1; - } - } else if (strcmp(argv[i], "--map-name") == 0) { - if (i + 1 < argc) { - map_name = argv[i + 1]; - i++; - } else { - fprintf(stderr, "Error: --map-name option requires a map file path\n"); - return 1; - } - } else if (strcmp(argv[i], "--policy-name") == 0) { - if (i + 1 < argc) { - policy_name = argv[i + 1]; - i++; - } else { - fprintf(stderr, "Error: --policy-name option requires a policy file path\n"); - return 1; - } - } else if (strcmp(argv[i], "--output-topdown") == 0) { - if (i + 1 < argc) { - output_topdown = argv[i + 1]; - i++; - } - } else if (strcmp(argv[i], "--output-agent") == 0) { - if (i + 1 < argc) { - output_agent = argv[i + 1]; - i++; - } - } else if (strcmp(argv[i], "--num-maps") == 0) { - if (i + 1 < argc) { - num_maps = atoi(argv[i + 1]); - i++; - } - } - } + clock_gettime(CLOCK_MONOTONIC, &ts_total_end); + total_time = (ts_total_end.tv_sec - ts_total_start.tv_sec) + (ts_total_end.tv_nsec - ts_total_start.tv_nsec) / 1e9; + printf("Total time: %.4f s\n", total_time); +} - // performance_test(); - demo(map_name, policy_name, show_grid, obs_only, lasers, show_human_logs, frame_skip, view_mode, output_topdown, - output_agent, num_maps, zoom_in); +int main() { + performance_test(); + // demo(); // test_drivenet(); return 0; } diff --git a/pufferlib/ocean/drive/drive.h b/pufferlib/ocean/drive/drive.h index 2a55867120..8a7a579530 100644 --- a/pufferlib/ocean/drive/drive.h +++ b/pufferlib/ocean/drive/drive.h @@ -1,5 +1,6 @@ -#include -#include +#ifndef DRIVE_H +#define DRIVE_H + #include #include #include @@ -13,40 +14,10 @@ #include "rlgl.h" #include #include "error.h" - -// Render modes -#define RENDER_WINDOW 0 -#define RENDER_HEADLESS 1 - -// View modes -#define VIEW_MODE_SIM_STATE 0 -#define VIEW_MODE_BEV_AGENT_OBS 1 -#define VIEW_MODE_AGENT_PERSP 2 - -// Order of entities in rendering (lower is rendered first) -#define Z_ROAD_SURFACE 0.0f -#define Z_ROAD_MARKINGS 0.05f // Lane lines, road lines, traces -#define Z_AGENT_DETAILS 0.4f // Arrow, goal markers, obs overlays -#define Z_AGENTS 0.6f // Vehicles, cyclists, pedestrians - -// Entity Types -#define NONE 0 -#define VEHICLE 1 -#define PEDESTRIAN 2 -#define CYCLIST 3 -#define ROAD_LANE 4 -#define ROAD_LINE 5 -#define ROAD_EDGE 6 -#define STOP_SIGN 7 -#define CROSSWALK 8 -#define SPEED_BUMP 9 -#define DRIVEWAY 10 +#include "datatypes.h" #define INVALID_POSITION -10000.0f -// Trajectory Length -#define TRAJECTORY_LENGTH 91 - // Initialization modes #define INIT_ALL_VALID 0 #define INIT_ONLY_CONTROLLABLE_AGENTS 1 @@ -56,72 +27,106 @@ #define CONTROL_AGENTS 1 #define CONTROL_WOSAC 2 #define CONTROL_SDC_ONLY 3 -#define CONTROL_MIXED_PLAY 4 - -// Minimum distance to goal position -#define MIN_DISTANCE_TO_GOAL 2.0f -// Actions -#define NOOP 0 - -// Dynamics Models -#define CLASSIC 0 -#define JERK 1 +// Simulation modes +#define SIMULATION_GIGAFLOW 0 +#define SIMULATION_REPLAY 1 + +// Lane selection scoring +#define LANE_SELECTION_DISTANCE_WEIGHT 0.7f +#define LANE_SELECTION_HEADING_WEIGHT 0.3f +#define LANE_DISTANCE_NORMALIZATION 4.0f +#define LANE_SWITCH_THRESHOLD 0.05f // Hysteresis: new lane must be 5% better to switch +#define LANE_ALIGN_COS_THRESHOLD 0.5f + +// Collision and distance thresholds +#define MAX_CHECKED_LANES 32 +#define COLLISION_QUICK_CHECK_DIST 15.0f // Quick distance check before OBB SAT +#define INIT_COLLISION_SHRINK_FACTOR 0.7f // Shrink agent dims at init to prevent collisions +#define AGENT_STOPPED_SPEED_THRESHOLD 0.2f +#define TRAFFIC_LIGHT_DISTANCE_THRESHOLD 10.0f +#define STOP_LINE_EXTENSION_FACTOR 1.5f +#define RED_LIGHT_HEADING_THRESHOLD (M_PI / 4.0f) + +// TTC default value when no vehicle ahead +#define DEFAULT_TTC 5.0f +// TTC violation threshold for "within bound" rate +#define TTC_VIOLATION_THRESHOLD 0.95f +// Multi-lane detection thresholds +#define LANE_WIDTH 3.7f +#define LANE_MARGIN 0.2f +#define MULTI_LANE_THRESHOLD (LANE_WIDTH / 2.0f + LANE_MARGIN) // 2.05m +#define MULTI_LANE_FULL_SCORE_TIME 3.4f // seconds +#define MULTI_LANE_HALF_SCORE_TIME 5.7f // seconds // Collision state #define NO_COLLISION 0 #define VEHICLE_COLLISION 1 #define OFFROAD 2 +#define TRAFFIC_LIGHT_VIOLATION 3 -// Metrics array indices -#define COLLISION_IDX 0 -#define OFFROAD_IDX 1 -#define REACHED_GOAL_IDX 2 -#define LANE_ALIGNED_IDX 3 +// Collision/Infraction behaviors +#define STOP_AGENT 1 +#define REMOVE_AGENT 2 // Grid cell size #define GRID_CELL_SIZE 5.0f -#define MAX_ENTITIES_PER_CELL \ - 30 // Depends on resolution of data Formula: 3 * (2 + GRID_CELL_SIZE*sqrt(2)/resolution) => For each entity type in - // gridmap, diagonal poly-lines -> sqrt(2), include diagonal ends -> 2 - -// Observation constants -#define MAX_ROAD_SEGMENT_OBSERVATIONS 128 - -// Maximum number of agents per scene -#ifndef MAX_AGENTS -#define MAX_AGENTS 32 -#endif -#define STOP_AGENT 1 -#define REMOVE_AGENT 2 +// Depends on resolution of data Formula: 3 * (2 + GRID_CELL_SIZE*sqrt(2)/resolution) +// => For each entity type in gridmap, diagonal poly-lines -> sqrt(2), include diagonal ends -> 2 +#define MAX_ENTITIES_PER_CELL 30 +// GridMapEntity types +#define ENTITY_TYPE_ROAD_ELEMENT 1 +#define ENTITY_TYPE_TRAFFIC_CONTROL 2 + +// Max road segment observation +#define ROAD_OBS_FRONT_DIST 100.0f +#define ROAD_OBS_BEHIND_DIST 20.0f +#define ROAD_OBS_SIDE_DIST 40.0f +#define VISION_HALF_RANGE \ + ((int)ceilf(fmaxf(fmaxf(ROAD_OBS_FRONT_DIST, ROAD_OBS_BEHIND_DIST), ROAD_OBS_SIDE_DIST) / GRID_CELL_SIZE)) + +// Traffic light observations +#define MAX_TRAFFIC_LIGHT_DISTANCE 100.0f + +// Agent observations +#define AGENT_OBS_MAX_DIST 100.0f // Max distance for observing other agents + +// TARGET_TYPE modes (controls what target info is in observations) +#define TARGET_STATIC 0 +#define TARGET_DYNAMIC 1 +// Observation normalization constants +#define MAX_GOAL_POSITION 100.0f // Goal position scaling (m) +#define MAX_POSITION 100.0f // Max position for normalization (m) +#define MAX_SPEED 40.0f // Max speed for normalization (m/s) +#define MAX_VEH_LEN 15.0f // Max vehicle length for normalization (m) +#define MAX_VEH_WIDTH 10.0f // Max vehicle width for normalization (m) +#define MAX_ROAD_SCALE 100.0f // Max road feature scaling (m) +#define MAX_ROAD_SEGMENT_LENGTH 100.0f // Max road segment length (m) + +// Observation feature counts +#define EGO_FEATURES_CLASSIC 7 +#define EGO_FEATURES_JERK 9 #define ROAD_FEATURES 7 -#define ROAD_FEATURES_ONEHOT 13 -#define PARTNER_FEATURES 7 - -// Ego features depend on dynamics model -#define EGO_FEATURES_CLASSIC 8 -#define EGO_FEATURES_JERK 11 +#define PARTNER_FEATURES 8 +#define TRAFFIC_LIGHT_FEATURES 6 +#define STOP_SIGN_FEATURES 3 +#define STATIC_TARGET_FEATURES 3 +#define DYNAMIC_TARGET_FEATURES 5 + +// GIGAFLOW specific +#define MAX_ROUTE_LENGTH 64 +// Traffic light generation +#define TL_DEFAULT_RED_DURATION 2.0f +#define TL_DEFAULT_YELLOW_DURATION 3.0f +#define TL_DEFAULT_GREEN_DURATION 10.0f +#define TL_EPISODE_DISABLE_PROB 0.20f +#define TL_INDIVIDUAL_REMOVE_PROB 0.20f +#define TL_ALWAYS_GREEN_PROB 0.05f -// Observation normalization constants -#define MAX_SPEED 100.0f -#define MAX_VEH_LEN 30.0f -#define MAX_VEH_WIDTH 15.0f -#define MAX_VEH_HEIGHT 10.0f -#define MIN_REL_GOAL_COORD -1000.0f -#define MAX_REL_GOAL_COORD 1000.0f -#define MIN_REL_AGENT_POS -1000.0f -#define MAX_REL_AGENT_POS 1000.0f -#define MAX_ORIENTATION_RAD 2 * PI -#define MIN_RG_COORD -1000.0f -#define MAX_RG_COORD 1000.0f -#define MAX_ROAD_SCALE 100.0f -#define MAX_ROAD_SEGMENT_LENGTH 100.0f - -// Goal behavior -#define GOAL_RESPAWN 0 -#define GOAL_GENERATE_NEW 1 -#define GOAL_STOP 2 +// Dynamics Models +#define CLASSIC 0 +#define JERK 1 // Jerk action space (for JERK dynamics model) static const float JERK_LONG[4] = {-15.0f, -4.0f, 0.0f, 4.0f}; @@ -129,8 +134,7 @@ static const float JERK_LAT[3] = {-4.0f, 0.0f, 4.0f}; // Classic action space (for CLASSIC dynamics model) static const float ACCELERATION_VALUES[7] = {-4.0000f, -2.6670f, -1.3330f, -0.0000f, 1.3330f, 2.6670f, 4.0000f}; -static const float STEERING_VALUES[13] = {-1.000f, -0.833f, -0.667f, -0.500f, -0.333f, -0.167f, 0.000f, - 0.167f, 0.333f, 0.500f, 0.667f, 0.833f, 1.000f}; +static const float STEERING_VALUES[9] = {-0.667f, -0.500f, -0.333f, -0.167f, 0.000f, 0.167f, 0.333f, 0.500f, 0.667f}; static const float offsets[4][2] = { {-1, 1}, // top-left @@ -147,143 +151,65 @@ static const int collision_offsets[25][2] = { {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2} // Bottom row }; -const Color STONE_GRAY = (Color){80, 80, 80, 255}; -const Color PUFF_RED = (Color){187, 0, 0, 255}; -const Color PUFF_CYAN = (Color){0, 187, 187, 255}; -const Color PUFF_WHITE = (Color){241, 241, 241, 241}; -const Color PUFF_BACKGROUND = (Color){6, 24, 24, 255}; -const Color PUFF_BACKGROUND2 = (Color){18, 72, 72, 255}; -const Color LIGHTGREEN = (Color){152, 255, 152, 255}; -const Color LIGHTYELLOW = (Color){255, 255, 152, 255}; -const Color SOFT_YELLOW = (Color){245, 245, 220, 255}; -const Color ROAD_COLOR = (Color){35, 35, 37, 255}; -const Color LIGHTBLUE = (Color){167, 204, 255, 255}; -const Color DEEPBLUE = (Color){45, 112, 226, 255}; -const Color EXPERT_REPLAY = (Color){162, 220, 183, 255}; -const Color EXPERT_REPLAY_SMALL = (Color){95, 112, 93, 255}; -const Color LIGHT_ORANGE = (Color){255, 160, 80, 255}; -const Color LIGHT_PURPLE = (Color){204, 204, 255, 255}; - -struct timespec ts; +#define Z_COMPUTATION_OFFSET_COUNT 9 +#define Z_BUFFER 4.0f +#define Z_NUM_PT_AVG 30 + +static const int z_computation_offsets[Z_COMPUTATION_OFFSET_COUNT][2] = { + {-1, -1}, {0, -1}, {1, -1}, {-1, 0}, {0, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}, +}; typedef struct Drive Drive; typedef struct Client Client; typedef struct Log Log; +typedef struct Agent Agent; +typedef struct RoadMapElement RoadMapElement; +typedef struct TrafficControlElement TrafficControlElement; struct Log { + float n; float episode_return; float episode_length; + float expert_static_car_count; + float static_car_count; float score; - float goals_reached_this_episode; - float goals_sampled_this_episode; float offroad_rate; float collision_rate; - float completion_rate; - float offroad_per_agent; - float collisions_per_agent; + float red_light_violation_rate; + float num_waypoints_reached; + float num_goals_reached; + float comfort_violation_count; + float velocity_progress_sum; + float lane_center_rate; + float lane_heading_aligned_rate; float dnf_rate; - float n; - float lane_alignment_rate; - float speed_at_goal; - float active_agent_count; - float expert_static_agent_count; - float static_agent_count; - float perc_controlled; - float perc_other; + float avg_displacement_error; + float avg_speed_per_agent; + // Puffer score components + float at_fault_collision_rate; + float ttc_within_bound_rate; + float driving_direction_score; + float speed_limit_compliance; + float making_progress_rate; + float progress_ratio; + float comfort_score; + float puffer_score; + // Puffer score intermediate accumulators (for aggregation) + float wrong_way_distance; + float speed_violation_sum; + float ttc_violations; + float ttc_samples; + float multi_lane_time; + float multi_lane_score; + float total_distance_travelled; + float total_infractions; }; -typedef struct Entity Entity; -struct Entity { - int scenario_id; - int type; - int id; - int array_size; - float *traj_x; - float *traj_y; - float *traj_z; - float *traj_vx; - float *traj_vy; - float *traj_vz; - float *traj_heading; - int *traj_valid; - float width; - float length; - float height; - float goal_position_x; - float goal_position_y; - float goal_position_z; - float init_goal_x; - float init_goal_y; - int mark_as_expert; - int collision_state; - float metrics_array[5]; // metrics_array: [collision, offroad, reached_goal, lane_aligned - float x; - float y; - float z; - float vx; - float vy; - float vz; - float heading; - float heading_x; - float heading_y; - int current_lane_idx; - int valid; - int respawn_timestep; - int respawn_count; - int collided_before_goal; - float goals_reached_this_episode; - float goals_sampled_this_episode; - int current_goal_reached; - int active_agent; - int stopped; - int removed; - - // Jerk dynamics - float a_long; - float a_lat; - float jerk_long; - float jerk_lat; - float steering_angle; - float wheelbase; -}; - -void free_entity(Entity *entity) { - // free trajectory arrays - free(entity->traj_x); - free(entity->traj_y); - free(entity->traj_z); - free(entity->traj_vx); - free(entity->traj_vy); - free(entity->traj_vz); - free(entity->traj_heading); - free(entity->traj_valid); -} - -// Utility functions -float relative_distance(float a, float b) { - float distance = sqrtf(powf(a - b, 2)); - return distance; -} - -float relative_distance_2d(float x1, float y1, float x2, float y2) { - float dx = x2 - x1; - float dy = y2 - y1; - float distance = sqrtf(dx * dx + dy * dy); - return distance; -} - -float clip(float value, float min, float max) { - if (value < min) - return min; - if (value > max) - return max; - return value; -} - typedef struct GridMapEntity GridMapEntity; struct GridMapEntity { - int entity_idx; - int geometry_idx; + int entity_type; // Entity type: 1=Agent, 2=RoadMapElement, 3=TrafficControlElement + int entity_idx; // Index into the corresponding typed array + int geometry_idx; // Index into entity's trajectory/geometry array }; typedef struct GridMap GridMap; @@ -302,6 +228,8 @@ struct GridMap { int vision_range; int *neighbor_cache_count; // number of entities in each cells neighbor cache GridMapEntity **neighbor_cache_entities; // preallocated array to hold neighbor entities + int *grid_index_drivable; + int num_drivable_grid_cell; }; struct Drive { @@ -311,18 +239,24 @@ struct Drive { float *rewards; unsigned char *terminals; unsigned char *truncations; + unsigned char *masks; Log log; Log *logs; - int num_agents; - int active_agent_count; + int num_controllable_agents; // Max number of controllable agents + int active_agent_count; // Current number of controllable agents int *active_agent_indices; + int num_total_agents; // Total agents in a log scenario + int num_max_agents; // Max agents allocated in the environment + int num_agents; // Current number of agents in the environment int action_type; int human_agent_idx; - Entity *entities; - int num_entities; - int num_actors; + Agent *agents; + RoadMapElement *road_elements; + TrafficControlElement *traffic_elements; + int num_road_elements; + int num_traffic_elements; int num_objects; - int num_roads; + struct LaneGraph lane_graph; int static_agent_count; int *static_agent_indices; int expert_static_agent_count; @@ -332,222 +266,377 @@ struct Drive { int dynamics_model; GridMap *grid_map; int *neighbor_offsets; - int episode_length; - int termination_mode; + int scenario_length; + float reward_goal; float reward_vehicle_collision; float reward_offroad_collision; + float reward_comfort; + float reward_lane_align; + float reward_vel_align; + float reward_lane_center; + float reward_center_bias; + float reward_velocity; + float reward_reverse; + float reward_traffic_light_violation; + float reward_timestep; + float reward_overspeed; + float reward_ade; char *map_name; float world_mean_x; float world_mean_y; float dt; - float reward_goal; - float reward_goal_post_respawn; + float spawn_initial_speed; float goal_radius; - float goal_speed; + float goal_speed_threshold; + float min_waypoint_spacing; + float max_waypoint_spacing; + int num_target_waypoints; int logs_capacity; - int goal_behavior; - float goal_target_distance; + int target_type; char *ini_file; - char scenario_id[16]; - int collision_behavior; - int offroad_behavior; - int sdc_track_index; + int collision_behavior; // 0 = none, 1=stop, 2 = remove + int offroad_behavior; // 0 = none, 1=stop, 2 = remove + int traffic_light_behavior; // 0 = none, 1=stop, 2 = remove + // Metadata fields + char scenario_id[128]; + char dataset_name[32]; + int log_length; + float log_dt; + int num_objects_of_interest; + int *objects_of_interest; int num_tracks_to_predict; - int *tracks_to_predict_indices; + int *tracks_to_predict; int init_mode; int control_mode; - int max_controlled_agents; - int render_mode; + int simulation_mode; + int termination_mode; + float inactive_agent_threshold; + int reward_conditioning; + int reward_randomization; + int compute_eval_metrics; + int use_rear_axle; + int max_boundary_segment_observations; + int max_lane_segment_observations; + int max_partner_observations; + int max_traffic_light_observations; + int max_stop_sign_observations; + int eval_mode; }; -void add_log(Drive *env) { - for (int i = 0; i < env->active_agent_count; i++) { - Entity *e = &env->entities[env->active_agent_indices[i]]; +// ======================================== +// Utility Functions +// ======================================== - env->log.goals_reached_this_episode += e->goals_reached_this_episode; - env->log.goals_sampled_this_episode += e->goals_sampled_this_episode; +typedef struct { + int index; + float dist_sq; + float dx; // Store dx/dy to avoid re-calculating + float dy; + float dz; +} AgentDistance; - int offroad = env->logs[i].offroad_rate; - env->log.offroad_rate += offroad; - int collided = env->logs[i].collision_rate; - env->log.collision_rate += collided; - float offroad_per_agent = env->logs[i].offroad_per_agent; - env->log.offroad_per_agent += offroad_per_agent; - float collisions_per_agent = env->logs[i].collisions_per_agent; - env->log.collisions_per_agent += collisions_per_agent; +static float compute_euclidean_distance(float x1, float y1, float x2, float y2) { + float dx = x2 - x1; + float dy = y2 - y1; + float distance = sqrtf(dx * dx + dy * dy); + return distance; +} - float frac_goal_reached = e->goals_reached_this_episode / e->goals_sampled_this_episode; +static int compare_depthpoint(const void *a, const void *b) { + float diff = ((const DepthPoint *)a)->euclidean_dis - ((const DepthPoint *)b)->euclidean_dis; + return (diff > 0.0f) - (diff < 0.0f); +} - // Update score, which is an aggregate measure whether the agent fully solved its task - float threshold = 1.0f; // Default threshold for 1 goal (must complete it) - if (e->goals_sampled_this_episode > 1) { - // For multiple goals, require n-1 goals to be reached - threshold = (e->goals_sampled_this_episode - 1.0f) / e->goals_sampled_this_episode; - } +static float clip(float value, float min, float max) { + if (value < min) + return min; + if (value > max) + return max; + return value; +} - int collision_occurred = - (env->goal_behavior == GOAL_RESPAWN) ? e->collided_before_goal : env->logs[i].collision_rate; - if (frac_goal_reached >= threshold && !collision_occurred) { - env->log.score += 1.0f; - } - if (!offroad && !collided && frac_goal_reached < 1.0f) { - env->log.dnf_rate += 1.0f; - } - int lane_aligned = env->logs[i].lane_alignment_rate; - env->log.lane_alignment_rate += lane_aligned; - env->log.speed_at_goal += env->logs[i].speed_at_goal; - env->log.episode_length += env->logs[i].episode_length; - env->log.episode_return += env->logs[i].episode_return; - // Log composition counts per agent so vec_log averaging recovers the per-env value - env->log.active_agent_count += env->active_agent_count; - env->log.expert_static_agent_count += env->expert_static_agent_count; - env->log.static_agent_count += env->static_agent_count; - int total = env->active_agent_count + env->static_agent_count; - env->log.perc_controlled += (float)env->active_agent_count / (float)total; - env->log.perc_other += (float)env->static_agent_count / (float)total; - env->log.n += 1; - } +// Normalize heading to [-pi, pi] +static float normalize_heading(float heading) { + heading = fmodf(heading, 2.0f * M_PI); + if (heading > M_PI) + heading -= 2.0f * M_PI; + else if (heading < -M_PI) + heading += 2.0f * M_PI; + return heading; } -Entity *load_map_binary(const char *filename, Drive *env) { - FILE *file = fopen(filename, "rb"); - if (!file) - return NULL; +static float compute_heading_diff(float heading1, float heading2) { + float heading_diff = heading1 - heading2; + return normalize_heading(heading_diff); +} - // Read scenario_id - fread(env->scenario_id, sizeof(char), 16, file); +static void invalidate_agent(Agent *agent) { + agent->sim_x = INVALID_POSITION; + agent->sim_y = INVALID_POSITION; + agent->sim_z = 0.0f; + agent->sim_heading = 0.0f; + agent->cos_heading = 1.0f; + agent->sin_heading = 0.0f; + agent->sim_vx = 0.0f; + agent->sim_vy = 0.0f; + agent->yaw_rate = 0.0f; + agent->sim_speed = 0.0f; + agent->sim_speed_signed = 0.0f; + agent->a_long = 0.0f; + agent->a_lat = 0.0f; + agent->jerk_long = 0.0f; + agent->jerk_lat = 0.0f; + agent->steering_angle = 0.0f; + agent->sim_valid = 0; +} + +static void update_agent_speed(Agent *agent) { + float speed = sqrtf(agent->sim_vx * agent->sim_vx + agent->sim_vy * agent->sim_vy); + float v_dot_heading = agent->sim_vx * agent->cos_heading + agent->sim_vy * agent->sin_heading; + agent->sim_speed = speed; + agent->sim_speed_signed = copysignf(speed, v_dot_heading); +} - // Read sdc_track_index - fread(&env->sdc_track_index, sizeof(int), 1, file); +// Trajectory planning/control can operate in the rear-axle frame even though sim state stays center-based. +static inline float compute_log_yaw_rate(const Agent *agent, int timestep, float dt) { + if (dt <= 0.0f) + return 0.0f; - // Read tracks_to_predict - fread(&env->num_tracks_to_predict, sizeof(int), 1, file); - if (env->num_tracks_to_predict > 0) { - env->tracks_to_predict_indices = (int *)malloc(env->num_tracks_to_predict * sizeof(int)); + const int prev_t = timestep - 1; + const int next_t = timestep + 1; + const int has_prev = (prev_t >= 0) && (agent->log_valid[prev_t] == 1); + const int has_next = (next_t < agent->trajectory_length) && (agent->log_valid[next_t] == 1); - for (int i = 0; i < env->num_tracks_to_predict; i++) { - fread(&env->tracks_to_predict_indices[i], sizeof(int), 1, file); - } + if (has_prev && has_next) { + float dtheta = normalize_heading(agent->log_heading[next_t] - agent->log_heading[prev_t]); + return dtheta / (2.0f * dt); + } + if (has_next) { + float dtheta = normalize_heading(agent->log_heading[next_t] - agent->log_heading[timestep]); + return dtheta / dt; + } + if (has_prev) { + float dtheta = normalize_heading(agent->log_heading[timestep] - agent->log_heading[prev_t]); + return dtheta / dt; + } + + return 0.0f; +} + +// Random uniform in [min, max] +static float random_uniform(float min_val, float max_val) { + float scale = (float)rand() / (float)RAND_MAX; + return min_val + scale * (max_val - min_val); +} + +// Mixed uniform distribution X(a) = 0.5*U(1/a, 1) + 0.5*U(1, a) +static float mixed_uniform(float a) { + if ((float)rand() / (float)RAND_MAX < 0.5f) { + return random_uniform(1.0f / a, 1.0f); } else { - env->tracks_to_predict_indices = NULL; - } - - fread(&env->num_objects, sizeof(int), 1, file); - fread(&env->num_roads, sizeof(int), 1, file); - env->num_entities = env->num_objects + env->num_roads; - Entity *entities = (Entity *)malloc(env->num_entities * sizeof(Entity)); - for (int i = 0; i < env->num_entities; i++) { - // Read base entity data - fread(&entities[i].scenario_id, sizeof(int), 1, file); - fread(&entities[i].type, sizeof(int), 1, file); - fread(&entities[i].id, sizeof(int), 1, file); - fread(&entities[i].array_size, sizeof(int), 1, file); - // Allocate arrays based on type - int size = entities[i].array_size; - entities[i].traj_x = (float *)malloc(size * sizeof(float)); - entities[i].traj_y = (float *)malloc(size * sizeof(float)); - entities[i].traj_z = (float *)malloc(size * sizeof(float)); - if (entities[i].type == VEHICLE || entities[i].type == PEDESTRIAN || - entities[i].type == CYCLIST) { // Object type - // Allocate arrays for object-specific data - entities[i].traj_vx = (float *)malloc(size * sizeof(float)); - entities[i].traj_vy = (float *)malloc(size * sizeof(float)); - entities[i].traj_vz = (float *)malloc(size * sizeof(float)); - entities[i].traj_heading = (float *)malloc(size * sizeof(float)); - entities[i].traj_valid = (int *)malloc(size * sizeof(int)); - } else { - // Roads don't use these arrays - entities[i].traj_vx = NULL; - entities[i].traj_vy = NULL; - entities[i].traj_vz = NULL; - entities[i].traj_heading = NULL; - entities[i].traj_valid = NULL; - } - // Read array data - fread(entities[i].traj_x, sizeof(float), size, file); - fread(entities[i].traj_y, sizeof(float), size, file); - fread(entities[i].traj_z, sizeof(float), size, file); - if (entities[i].type == VEHICLE || entities[i].type == PEDESTRIAN || - entities[i].type == CYCLIST) { // Object type - fread(entities[i].traj_vx, sizeof(float), size, file); - fread(entities[i].traj_vy, sizeof(float), size, file); - fread(entities[i].traj_vz, sizeof(float), size, file); - fread(entities[i].traj_heading, sizeof(float), size, file); - fread(entities[i].traj_valid, sizeof(int), size, file); - } - // Read remaining scalar fields - fread(&entities[i].width, sizeof(float), 1, file); - fread(&entities[i].length, sizeof(float), 1, file); - fread(&entities[i].height, sizeof(float), 1, file); - fread(&entities[i].goal_position_x, sizeof(float), 1, file); - fread(&entities[i].goal_position_y, sizeof(float), 1, file); - fread(&entities[i].goal_position_z, sizeof(float), 1, file); - fread(&entities[i].mark_as_expert, sizeof(int), 1, file); + return random_uniform(1.0f, a); } +} - fclose(file); - return entities; +typedef struct { + float min_val; + float max_val; +} RewardBound; + +static const RewardBound REWARD_BOUNDS[NUM_REWARD_COEFS] = { + {2.0f, 12.0f}, // REWARD_COEF_GOAL_RADIUS δ_goal ~ U(2, 12) + {0.0f, 3.0f}, // REWARD_COEF_COLLISION α_collision ~ U(0, 3) + {0.0f, 3.0f}, // REWARD_COEF_OFFROAD α_boundary ~ U(0, 3) + {0.0f, 0.1f}, // REWARD_COEF_COMFORT α_comfort ~ U(0, 0.1) + {2.5e-4f, 2.5e-2f}, // REWARD_COEF_LANE_ALIGN α_l-align ~ U(2.5e-4, 2.5e-2) + {0.0f, 1.0f}, // REWARD_COEF_VEL_ALIGN α_vel-align ~ U(0, 1) + {2.5e-4f, 7.5e-3f}, // REWARD_COEF_LANE_CENTER α_l-center ~ U(2.5e-4, 7.5e-3) + {-0.5f, 0.5f}, // REWARD_COEF_CENTER_BIAS α_center-bias ~ U(-0.5, 0.5) + {0.0f, 5e-3f}, // REWARD_COEF_VELOCITY α_velocity = 2.5e-3 (fixed) + {2.5e-4f, 7.5e-3f}, // REWARD_COEF_REVERSE α_reverse ~ U(2.5e-4, 7.5e-3) + {0.0f, 1.0f}, // REWARD_COEF_TRAFFIC_LIGHT α_stop-line ~ U(0, 1) + {0.0f, 5e-5f}, // REWARD_COEF_TIMESTEP α_timestep = 2.5e-5 (fixed) + {0.0f, 1.0f}, // REWARD_COEF_OVERSPEED + {0.8f, 1.25f}, // REWARD_COEF_THROTTLE C_throttle + {0.8f, 1.25f}, // REWARD_COEF_STEER C_steer + {0.666f, 1.5f}, // REWARD_COEF_ACC C_acc +}; + +// Forward declarations +void move_expert(Drive *env, float *actions, int agent_idx); + +// Generate per-agent reward conditioning coefficients +static void generate_reward_coefs(Drive *env, Agent *agent) { + if (env->reward_randomization) { + // Standard Uniform Randomizations (referencing the bounds array) + agent->reward_coefs[REWARD_COEF_GOAL_RADIUS] = random_uniform(REWARD_BOUNDS[REWARD_COEF_GOAL_RADIUS].min_val, + REWARD_BOUNDS[REWARD_COEF_GOAL_RADIUS].max_val); + agent->reward_coefs[REWARD_COEF_COLLISION] = + random_uniform(REWARD_BOUNDS[REWARD_COEF_COLLISION].min_val, REWARD_BOUNDS[REWARD_COEF_COLLISION].max_val); + agent->reward_coefs[REWARD_COEF_OFFROAD] = + random_uniform(REWARD_BOUNDS[REWARD_COEF_OFFROAD].min_val, REWARD_BOUNDS[REWARD_COEF_OFFROAD].max_val); + agent->reward_coefs[REWARD_COEF_COMFORT] = + random_uniform(REWARD_BOUNDS[REWARD_COEF_COMFORT].min_val, REWARD_BOUNDS[REWARD_COEF_COMFORT].max_val); + agent->reward_coefs[REWARD_COEF_LANE_ALIGN] = random_uniform(REWARD_BOUNDS[REWARD_COEF_LANE_ALIGN].min_val, + REWARD_BOUNDS[REWARD_COEF_LANE_ALIGN].max_val); + agent->reward_coefs[REWARD_COEF_LANE_CENTER] = random_uniform(REWARD_BOUNDS[REWARD_COEF_LANE_CENTER].min_val, + REWARD_BOUNDS[REWARD_COEF_LANE_CENTER].max_val); + agent->reward_coefs[REWARD_COEF_TRAFFIC_LIGHT] = random_uniform( + REWARD_BOUNDS[REWARD_COEF_TRAFFIC_LIGHT].min_val, REWARD_BOUNDS[REWARD_COEF_TRAFFIC_LIGHT].max_val); + agent->reward_coefs[REWARD_COEF_CENTER_BIAS] = random_uniform(REWARD_BOUNDS[REWARD_COEF_CENTER_BIAS].min_val, + REWARD_BOUNDS[REWARD_COEF_CENTER_BIAS].max_val); + agent->reward_coefs[REWARD_COEF_VEL_ALIGN] = + random_uniform(REWARD_BOUNDS[REWARD_COEF_VEL_ALIGN].min_val, REWARD_BOUNDS[REWARD_COEF_VEL_ALIGN].max_val); + agent->reward_coefs[REWARD_COEF_OVERSPEED] = + random_uniform(REWARD_BOUNDS[REWARD_COEF_OVERSPEED].min_val, REWARD_BOUNDS[REWARD_COEF_OVERSPEED].max_val); + agent->reward_coefs[REWARD_COEF_REVERSE] = + random_uniform(REWARD_BOUNDS[REWARD_COEF_REVERSE].min_val, REWARD_BOUNDS[REWARD_COEF_REVERSE].max_val); + // Fixed values (Must fall within the bounds defined above) + agent->reward_coefs[REWARD_COEF_VELOCITY] = 2.5e-3f; + agent->reward_coefs[REWARD_COEF_TIMESTEP] = 2.5e-5f; + // Dynamic conditioning (Mixed Uniform) + agent->reward_coefs[REWARD_COEF_THROTTLE] = mixed_uniform(1.25f); + agent->reward_coefs[REWARD_COEF_STEER] = mixed_uniform(1.25f); + agent->reward_coefs[REWARD_COEF_ACC] = mixed_uniform(1.5f); + } else { + // Fixed coefficients + agent->reward_coefs[REWARD_COEF_GOAL_RADIUS] = env->goal_radius; + agent->reward_coefs[REWARD_COEF_COLLISION] = env->reward_vehicle_collision; + agent->reward_coefs[REWARD_COEF_OFFROAD] = env->reward_offroad_collision; + agent->reward_coefs[REWARD_COEF_COMFORT] = env->reward_comfort; + agent->reward_coefs[REWARD_COEF_LANE_ALIGN] = env->reward_lane_align; + agent->reward_coefs[REWARD_COEF_LANE_CENTER] = env->reward_lane_center; + agent->reward_coefs[REWARD_COEF_VELOCITY] = env->reward_velocity; + agent->reward_coefs[REWARD_COEF_TRAFFIC_LIGHT] = env->reward_traffic_light_violation; + agent->reward_coefs[REWARD_COEF_CENTER_BIAS] = env->reward_center_bias; + agent->reward_coefs[REWARD_COEF_VEL_ALIGN] = env->reward_vel_align; + agent->reward_coefs[REWARD_COEF_OVERSPEED] = env->reward_overspeed; + agent->reward_coefs[REWARD_COEF_TIMESTEP] = env->reward_timestep; + agent->reward_coefs[REWARD_COEF_REVERSE] = env->reward_reverse; + // Dynamic conditioning coefficients + agent->reward_coefs[REWARD_COEF_THROTTLE] = 1.0f; + agent->reward_coefs[REWARD_COEF_STEER] = 1.0f; + agent->reward_coefs[REWARD_COEF_ACC] = 1.0f; + } } -void set_start_position(Drive *env) { - for (int i = 0; i < env->num_entities; i++) { - int is_active = 0; - for (int j = 0; j < env->active_agent_count; j++) { - if (env->active_agent_indices[j] == i) { - is_active = 1; - break; - } - } - Entity *e = &env->entities[i]; +// Generate procedural traffic light states for GIGAFLOW mode +static void generate_traffic_light_states(Drive *env) { + int steps = env->scenario_length; + float dt = env->dt; + + // 20% chance: disable ALL lights for this episode + int disable_all = (!env->eval_mode) && (random_uniform(0.0f, 1.0f) < TL_EPISODE_DISABLE_PROB); + + for (int i = 0; i < env->num_traffic_elements; i++) { + TrafficControlElement *traffic = &env->traffic_elements[i]; + if (traffic->type != TRAFFIC_LIGHT || traffic->states == NULL || traffic->state_length <= 0) + continue; - // Clamp init_steps to ensure we don't go out of bounds - int step = env->init_steps; - if (step >= e->array_size) - step = e->array_size - 1; - if (step < 0) - step = 0; + int fill_steps = steps; + if (traffic->state_length < fill_steps) + fill_steps = traffic->state_length; - e->x = e->traj_x[step]; - e->y = e->traj_y[step]; - e->z = e->traj_z[step]; - if (e->type > CYCLIST || e->type == 0) { + if (disable_all) { + memset(traffic->states, TL_STATE_DISABLED, fill_steps * sizeof(int)); continue; } - if (is_active == 0) { - e->vx = 0; - e->vy = 0; - e->vz = 0; - e->collided_before_goal = 0; + + if (!env->eval_mode) { + // Individual removal + if (random_uniform(0.0f, 1.0f) < TL_INDIVIDUAL_REMOVE_PROB) { + memset(traffic->states, TL_STATE_DISABLED, fill_steps * sizeof(int)); + continue; + } + // Always green + if (random_uniform(0.0f, 1.0f) < TL_ALWAYS_GREEN_PROB) { + for (int t = 0; t < fill_steps; t++) + traffic->states[t] = TL_STATE_GREEN; + continue; + } + } + + // Compute phase durations + float dur_green, dur_yellow, dur_red; + if (env->eval_mode) { + dur_green = TL_DEFAULT_GREEN_DURATION; + dur_yellow = TL_DEFAULT_YELLOW_DURATION; + dur_red = TL_DEFAULT_RED_DURATION; } else { - e->vx = e->traj_vx[env->init_steps]; - e->vy = e->traj_vy[env->init_steps]; - e->vz = e->traj_vz[env->init_steps]; - } - e->heading = e->traj_heading[env->init_steps]; - e->heading_x = cosf(e->heading); - e->heading_y = sinf(e->heading); - e->valid = e->traj_valid[env->init_steps]; - e->collision_state = 0; - e->metrics_array[COLLISION_IDX] = 0.0f; // vehicle collision - e->metrics_array[OFFROAD_IDX] = 0.0f; // offroad - e->metrics_array[REACHED_GOAL_IDX] = 0.0f; // reached goal - e->metrics_array[LANE_ALIGNED_IDX] = 0.0f; // lane aligned - e->respawn_timestep = -1; - e->stopped = 0; - e->removed = 0; - e->respawn_count = 0; - - // Dynamics - e->a_long = 0.0f; - e->a_lat = 0.0f; - e->jerk_long = 0.0f; - e->jerk_lat = 0.0f; - e->steering_angle = 0.0f; - e->wheelbase = 0.6f * e->length; - } -} - -int getGridIndex(Drive *env, float x1, float y1) { + dur_green = random_uniform(0.1 * TL_DEFAULT_GREEN_DURATION, TL_DEFAULT_GREEN_DURATION); + dur_yellow = random_uniform(0.5f * TL_DEFAULT_YELLOW_DURATION, 0.75f * TL_DEFAULT_YELLOW_DURATION); + dur_red = random_uniform(0.15f * TL_DEFAULT_RED_DURATION, 5.0f * TL_DEFAULT_RED_DURATION); + } + + int steps_green = (int)(dur_green / dt); + if (steps_green < 1) + steps_green = 1; + int steps_yellow = (int)(dur_yellow / dt); + if (steps_yellow < 1) + steps_yellow = 1; + int steps_red = (int)(dur_red / dt); + if (steps_red < 1) + steps_red = 1; + int cycle_length = steps_green + steps_yellow + steps_red; + + // Random phase offset + int offset = rand() % cycle_length; + + // Fill states: GREEN -> YELLOW -> RED -> repeat + for (int t = 0; t < fill_steps; t++) { + int phase = (t + offset) % cycle_length; + if (phase < steps_green) + traffic->states[t] = TL_STATE_GREEN; + else if (phase < steps_green + steps_yellow) + traffic->states[t] = TL_STATE_YELLOW; + else + traffic->states[t] = TL_STATE_RED; + } + } +} + +// Normalize a reward coefficient to [-1, 1] range for observations +static float normalize_reward_coef(float value, int coef_idx) { + // NOTE: This prevents having coefficients outside of hardcoded bounds + // What if we want to allow that? + float min_value = REWARD_BOUNDS[coef_idx].min_val; + float max_value = REWARD_BOUNDS[coef_idx].max_val; + float range = max_value - min_value; + + // Safety: prevent division by zero if range is singular + if (range < 1e-9f) { + return 0.0f; + } + + // Normalize to [0, 1] + float normalized = (value - min_value) / range; + + // Clamp to [0, 1] to handle floating point noise + if (normalized < 0.0f) + normalized = 0.0f; + if (normalized > 1.0f) + normalized = 1.0f; + + // Scale to [-1, 1] + return 2.0f * normalized - 1.0f; +} + +// Find entity index given a lane ID +static int find_lane_index_by_id(Drive *env, int lane_id) { + // NOTE: Maps should ensure lane IDs == Indexes for efficiency + for (int i = 0; i < env->num_road_elements; i++) { + if (env->road_elements[i].id == lane_id && is_drivable_road_lane(env->road_elements[i].type)) { + return i; + } + } + return -1; +} + +// ======================================== +// Grid Map Functions +// ======================================== + +static int get_grid_index(Drive *env, float x1, float y1) { if (env->grid_map->top_left_x >= env->grid_map->bottom_right_x || env->grid_map->bottom_right_y >= env->grid_map->top_left_y) { return -1; // Invalid grid coordinates @@ -564,7 +653,8 @@ int getGridIndex(Drive *env, float x1, float y1) { return index; } -void add_entity_to_grid(Drive *env, int grid_index, int entity_idx, int geometry_idx, int *cell_entities_insert_index) { +static void add_entity_to_grid(Drive *env, int grid_index, int entity_type, int entity_idx, int geometry_idx, + int *cell_entities_insert_index) { if (grid_index == -1) { return; } @@ -577,45 +667,47 @@ void add_entity_to_grid(Drive *env, int grid_index, int entity_idx, int geometry return; } + env->grid_map->cells[grid_index][count].entity_type = entity_type; env->grid_map->cells[grid_index][count].entity_idx = entity_idx; env->grid_map->cells[grid_index][count].geometry_idx = geometry_idx; cell_entities_insert_index[grid_index] = count + 1; } -void init_grid_map(Drive *env) { +static void init_grid_map(Drive *env) { // Allocate memory for the grid map structure env->grid_map = (GridMap *)malloc(sizeof(GridMap)); + env->grid_map->num_drivable_grid_cell = 0; // Find top left and bottom right points of the map - float top_left_x; - float top_left_y; - float bottom_right_x; - float bottom_right_y; - int first_valid_point = 0; - for (int i = 0; i < env->num_entities; i++) { - if (env->entities[i].type > 3 && env->entities[i].type < 7) { - // Check all points in the trajectory for road elements - Entity *e = &env->entities[i]; - for (int j = 0; j < e->array_size; j++) { - if (e->traj_x[j] == INVALID_POSITION) - continue; - if (e->traj_y[j] == INVALID_POSITION) - continue; - if (!first_valid_point) { - top_left_x = bottom_right_x = e->traj_x[j]; - top_left_y = bottom_right_y = e->traj_y[j]; - first_valid_point = true; - continue; - } - if (e->traj_x[j] < top_left_x) - top_left_x = e->traj_x[j]; - if (e->traj_x[j] > bottom_right_x) - bottom_right_x = e->traj_x[j]; - if (e->traj_y[j] > top_left_y) - top_left_y = e->traj_y[j]; - if (e->traj_y[j] < bottom_right_y) - bottom_right_y = e->traj_y[j]; + float top_left_x = 0.0f; + float top_left_y = 0.0f; + float bottom_right_x = 0.0f; + float bottom_right_y = 0.0f; + bool first_valid_point = false; + for (int i = 0; i < env->num_road_elements; i++) { + // Check all points in the geometry for road elements (ROAD_LANE, ROAD_LINE, ROAD_EDGE) + if (!is_road(env->road_elements[i].type)) + continue; + RoadMapElement *element = &env->road_elements[i]; + for (int j = 0; j < element->segment_length; j++) { + if (element->x[j] == INVALID_POSITION) + continue; + if (element->y[j] == INVALID_POSITION) + continue; + if (!first_valid_point) { + top_left_x = bottom_right_x = element->x[j]; + top_left_y = bottom_right_y = element->y[j]; + first_valid_point = true; + continue; } + if (element->x[j] < top_left_x) + top_left_x = element->x[j]; + if (element->x[j] > bottom_right_x) + bottom_right_x = element->x[j]; + if (element->y[j] > top_left_y) + top_left_y = element->y[j]; + if (element->y[j] < bottom_right_y) + bottom_right_y = element->y[j]; } } @@ -636,18 +728,18 @@ void init_grid_map(Drive *env) { env->grid_map->cell_entities_count = (int *)calloc(grid_cell_count, sizeof(int)); // Calculate number of entities in each grid cell - for (int i = 0; i < env->num_entities; i++) { - if (env->entities[i].type > 3 && env->entities[i].type < 7) { - for (int j = 0; j < env->entities[i].array_size - 1; j++) { - float x_center = (env->entities[i].traj_x[j] + env->entities[i].traj_x[j + 1]) / 2; - float y_center = (env->entities[i].traj_y[j] + env->entities[i].traj_y[j + 1]) / 2; - int grid_index = getGridIndex(env, x_center, y_center); - env->grid_map->cell_entities_count[grid_index]++; - } + for (int i = 0; i < env->num_road_elements; i++) { + for (int j = 0; j < env->road_elements[i].segment_length - 1; j++) { + float x_center = (env->road_elements[i].x[j] + env->road_elements[i].x[j + 1]) / 2; + float y_center = (env->road_elements[i].y[j] + env->road_elements[i].y[j + 1]) / 2; + int grid_index = get_grid_index(env, x_center, y_center); + if (grid_index == -1) + continue; // Skip out-of-bounds entities + env->grid_map->cell_entities_count[grid_index]++; } } - int cell_entities_insert_index[grid_cell_count]; // Helper array for insertion index - memset(cell_entities_insert_index, 0, grid_cell_count * sizeof(int)); + + int *cell_entities_insert_index = (int *)calloc(grid_cell_count, sizeof(int)); // Initialize grid cells for (int grid_index = 0; grid_index < grid_cell_count; grid_index++) { @@ -661,21 +753,40 @@ void init_grid_map(Drive *env) { } } - // Populate grid cells - for (int i = 0; i < env->num_entities; i++) { - if (env->entities[i].type > 3 && - env->entities[i].type < 7) { // NOTE: Only Road Edges, Lines, and Lanes in grid map - for (int j = 0; j < env->entities[i].array_size - 1; j++) { - float x_center = (env->entities[i].traj_x[j] + env->entities[i].traj_x[j + 1]) / 2; - float y_center = (env->entities[i].traj_y[j] + env->entities[i].traj_y[j + 1]) / 2; - int grid_index = getGridIndex(env, x_center, y_center); - add_entity_to_grid(env, grid_index, i, j, cell_entities_insert_index); + // Track which grid cells contain drivable lanes (for spawning) + bool *drivable_grid_seen = (bool *)calloc(grid_cell_count, sizeof(bool)); + + // Populate grid cells and count unique drivable grid cells + for (int i = 0; i < env->num_road_elements; i++) { + for (int j = 0; j < env->road_elements[i].segment_length - 1; j++) { + float x_center = (env->road_elements[i].x[j] + env->road_elements[i].x[j + 1]) / 2; + float y_center = (env->road_elements[i].y[j] + env->road_elements[i].y[j + 1]) / 2; + int grid_index = get_grid_index(env, x_center, y_center); + if (grid_index == -1) + continue; // Skip out-of-bounds entities + add_entity_to_grid(env, grid_index, ENTITY_TYPE_ROAD_ELEMENT, i, j, cell_entities_insert_index); + // Count unique drivable grid cells + if (is_drivable_road_lane(env->road_elements[i].type) && !drivable_grid_seen[grid_index]) { + drivable_grid_seen[grid_index] = true; + env->grid_map->num_drivable_grid_cell++; } } } + + // Allocate and fill drivable grid index array + env->grid_map->grid_index_drivable = (int *)malloc(env->grid_map->num_drivable_grid_cell * sizeof(int)); + int drivable_idx = 0; + for (int i = 0; i < grid_cell_count; i++) { + if (drivable_grid_seen[i]) { + env->grid_map->grid_index_drivable[drivable_idx++] = i; + } + } + + free(drivable_grid_seen); + free(cell_entities_insert_index); } -void init_neighbor_offsets(Drive *env) { +static void init_neighbor_offsets(Drive *env) { // Allocate memory for the offsets env->neighbor_offsets = (int *)calloc(env->grid_map->vision_range * env->grid_map->vision_range * 2, sizeof(int)); // neighbor offsets in a spiral pattern @@ -719,7 +830,7 @@ void init_neighbor_offsets(Drive *env) { } } -void cache_neighbor_offsets(Drive *env) { +static void cache_neighbor_offsets(Drive *env) { int count = 0; int cell_count = env->grid_map->grid_cols * env->grid_map->grid_rows; env->grid_map->neighbor_cache_entities = (GridMapEntity **)calloc(cell_count, sizeof(GridMapEntity *)); @@ -775,126 +886,21 @@ void cache_neighbor_offsets(Drive *env) { } } -int get_neighbor_cache_entities(Drive *env, int cell_idx, GridMapEntity *entities, int max_entities) { +static const GridMapEntity *get_neighbor_cache_entities(Drive *env, int cell_idx, int *out_count) { GridMap *grid_map = env->grid_map; if (cell_idx < 0 || cell_idx >= (grid_map->grid_cols * grid_map->grid_rows)) { - return 0; // Invalid cell index - } - - int count = grid_map->neighbor_cache_count[cell_idx]; - // Limit to available space - if (count > max_entities) { - count = max_entities; - } - memcpy(entities, grid_map->neighbor_cache_entities[cell_idx], count * sizeof(GridMapEntity)); - return count; -} - -void set_means(Drive *env) { - float mean_x = 0.0f; - float mean_y = 0.0f; - int64_t point_count = 0; - - // Compute single mean for all entities (vehicles and roads) - for (int i = 0; i < env->num_entities; i++) { - if (env->entities[i].type == VEHICLE || env->entities[i].type == PEDESTRIAN || - env->entities[i].type == CYCLIST) { - for (int j = 0; j < env->entities[i].array_size; j++) { - // Assume a validity flag exists (e.g., valid[j]); adjust if not available - if (env->entities[i].traj_valid[j]) { // Add validity check if applicable - point_count++; - mean_x += (env->entities[i].traj_x[j] - mean_x) / point_count; - mean_y += (env->entities[i].traj_y[j] - mean_y) / point_count; - } - } - } else if (env->entities[i].type >= 4) { - for (int j = 0; j < env->entities[i].array_size; j++) { - point_count++; - mean_x += (env->entities[i].traj_x[j] - mean_x) / point_count; - mean_y += (env->entities[i].traj_y[j] - mean_y) / point_count; - } - } - } - env->world_mean_x = mean_x; - env->world_mean_y = mean_y; - for (int i = 0; i < env->num_entities; i++) { - if (env->entities[i].type == VEHICLE || env->entities[i].type == PEDESTRIAN || - env->entities[i].type == CYCLIST || env->entities[i].type >= 4) { - for (int j = 0; j < env->entities[i].array_size; j++) { - if (env->entities[i].traj_x[j] == INVALID_POSITION) - continue; - env->entities[i].traj_x[j] -= mean_x; - env->entities[i].traj_y[j] -= mean_y; - } - env->entities[i].goal_position_x -= mean_x; - env->entities[i].goal_position_y -= mean_y; - } - } -} - -void move_expert(Drive *env, float *actions, int agent_idx) { - Entity *agent = &env->entities[agent_idx]; - int t = env->timestep; - if (t < 0 || t >= agent->array_size) { - agent->x = INVALID_POSITION; - agent->y = INVALID_POSITION; - agent->z = 0.0f; - agent->heading = 0.0f; - agent->heading_x = 1.0f; - agent->heading_y = 0.0f; - return; - } - if (agent->traj_valid && agent->traj_valid[t] == 0) { - agent->x = INVALID_POSITION; - agent->y = INVALID_POSITION; - agent->z = 0.0f; - agent->heading = 0.0f; - agent->heading_x = 1.0f; - agent->heading_y = 0.0f; - return; + *out_count = 0; + return NULL; } - agent->x = agent->traj_x[t]; - agent->y = agent->traj_y[t]; - agent->z = agent->traj_z[t]; - agent->heading = agent->traj_heading[t]; - agent->heading_x = cosf(agent->heading); - agent->heading_y = sinf(agent->heading); -} - -bool check_line_intersection(float p1[2], float p2[2], float q1[2], float q2[2]) { - if (fmax(p1[0], p2[0]) < fmin(q1[0], q2[0]) || fmin(p1[0], p2[0]) > fmax(q1[0], q2[0]) || - fmax(p1[1], p2[1]) < fmin(q1[1], q2[1]) || fmin(p1[1], p2[1]) > fmax(q1[1], q2[1])) - return false; - - // Calculate vectors - float dx1 = p2[0] - p1[0]; - float dy1 = p2[1] - p1[1]; - float dx2 = q2[0] - q1[0]; - float dy2 = q2[1] - q1[1]; - - // Calculate cross products - float cross = dx1 * dy2 - dy1 * dx2; - - // If lines are parallel - if (cross == 0) - return false; - - // Calculate relative vectors between start points - float dx3 = p1[0] - q1[0]; - float dy3 = p1[1] - q1[1]; - - // Calculate parameters for intersection point - float s = (dx1 * dy3 - dy1 * dx3) / cross; - float t = (dx2 * dy3 - dy2 * dx3) / cross; - // Check if intersection point lies within both line segments - return (s >= 0 && s <= 1 && t >= 0 && t <= 1); + *out_count = grid_map->neighbor_cache_count[cell_idx]; + return grid_map->neighbor_cache_entities[cell_idx]; } -int checkNeighbors(Drive *env, float x, float y, GridMapEntity *entity_list, int max_size, - const int (*local_offsets)[2], int offset_size) { +static int get_neighbors_entities(Drive *env, float x, float y, GridMapEntity *entity_list, int max_size, + const int (*local_offsets)[2], int offset_size) { // Get the grid index for the given position (x, y) - int index = getGridIndex(env, x, y); + int index = get_grid_index(env, x, y); if (index == -1) return 0; // Return 0 size if position invalid // Calculate 2D grid coordinates @@ -915,513 +921,2289 @@ int checkNeighbors(Drive *env, float x, float y, GridMapEntity *entity_list, int for (int j = 0; j < count && entity_list_count < max_size; j++) { int entityId = env->grid_map->cells[neighborIndex][j].entity_idx; int geometry_idx = env->grid_map->cells[neighborIndex][j].geometry_idx; + int entity_type = env->grid_map->cells[neighborIndex][j].entity_type; entity_list[entity_list_count].entity_idx = entityId; entity_list[entity_list_count].geometry_idx = geometry_idx; + entity_list[entity_list_count].entity_type = entity_type; entity_list_count += 1; } } return entity_list_count; } -int check_aabb_collision(Entity *car1, Entity *car2) { - // Get car corners in world space - float cos1 = car1->heading_x; - float sin1 = car1->heading_y; - float cos2 = car2->heading_x; - float sin2 = car2->heading_y; - - // Calculate half dimensions - float half_len1 = car1->length * 0.5f; - float half_width1 = car1->width * 0.5f; - float half_len2 = car2->length * 0.5f; - float half_width2 = car2->width * 0.5f; - - // Calculate car1's corners in world space - float car1_corners[4][2] = { - {car1->x + (half_len1 * cos1 - half_width1 * sin1), car1->y + (half_len1 * sin1 + half_width1 * cos1)}, - {car1->x + (half_len1 * cos1 + half_width1 * sin1), car1->y + (half_len1 * sin1 - half_width1 * cos1)}, - {car1->x + (-half_len1 * cos1 - half_width1 * sin1), car1->y + (-half_len1 * sin1 + half_width1 * cos1)}, - {car1->x + (-half_len1 * cos1 + half_width1 * sin1), car1->y + (-half_len1 * sin1 - half_width1 * cos1)}}; - - // Calculate car2's corners in world space - float car2_corners[4][2] = { - {car2->x + (half_len2 * cos2 - half_width2 * sin2), car2->y + (half_len2 * sin2 + half_width2 * cos2)}, - {car2->x + (half_len2 * cos2 + half_width2 * sin2), car2->y + (half_len2 * sin2 - half_width2 * cos2)}, - {car2->x + (-half_len2 * cos2 - half_width2 * sin2), car2->y + (-half_len2 * sin2 + half_width2 * cos2)}, - {car2->x + (-half_len2 * cos2 + half_width2 * sin2), car2->y + (-half_len2 * sin2 - half_width2 * cos2)}}; +// ======================================== +// Map Loading Functions +// ======================================== - // Get the axes to check (normalized vectors perpendicular to each edge) - float axes[4][2] = { - {cos1, sin1}, // Car1's length axis - {-sin1, cos1}, // Car1's width axis - {cos2, sin2}, // Car2's length axis - {-sin2, cos2} // Car2's width axis - }; +int load_map_binary(const char *filename, Drive *drive) { + FILE *file = fopen(filename, "rb"); + if (!file) + return -1; - // Check each axis - for (int i = 0; i < 4; i++) { - float min1 = INFINITY, max1 = -INFINITY; - float min2 = INFINITY, max2 = -INFINITY; + int num_total_agents, num_roads, num_traffic, num_objects; + if (fread(&num_total_agents, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&num_roads, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&num_traffic, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&num_objects, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } - // Project car1's corners onto the axis - for (int j = 0; j < 4; j++) { - float proj = car1_corners[j][0] * axes[i][0] + car1_corners[j][1] * axes[i][1]; - min1 = fminf(min1, proj); - max1 = fmaxf(max1, proj); - } + drive->num_total_agents = num_total_agents; + drive->num_road_elements = num_roads; + drive->num_traffic_elements = num_traffic; + drive->num_objects = num_objects; - // Project car2's corners onto the axis - for (int j = 0; j < 4; j++) { - float proj = car2_corners[j][0] * axes[i][0] + car2_corners[j][1] * axes[i][1]; - min2 = fminf(min2, proj); - max2 = fmaxf(max2, proj); - } + if (num_total_agents > 0) { + drive->agents = (Agent *)calloc(num_total_agents, sizeof(Agent)); + } - // If there's a gap on this axis, the boxes don't intersect - if (max1 < min2 || min1 > max2) { - return 0; // No collision - } + if (num_roads > 0) { + drive->road_elements = (RoadMapElement *)calloc(num_roads, sizeof(RoadMapElement)); } - // If we get here, there's no separating axis, so the boxes intersect - return 1; // Collision -} + if (num_traffic > 0) { + drive->traffic_elements = (TrafficControlElement *)calloc(num_traffic, sizeof(TrafficControlElement)); + } -int collision_check(Drive *env, int agent_idx) { - Entity *agent = &env->entities[agent_idx]; + for (int i = 0; i < num_total_agents; i++) { + Agent *agent = &drive->agents[i]; - if (agent->x == INVALID_POSITION) - return -1; + if (fread(&agent->id, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&agent->type, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&agent->trajectory_length, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } - // Skip collision checking for pedestrians because they are often too - // close to other entities at initialization. - if (agent->type == PEDESTRIAN) - return -1; + int tlen = agent->trajectory_length; + agent->log_trajectory_x = (float *)malloc(tlen * sizeof(float)); + agent->log_trajectory_y = (float *)malloc(tlen * sizeof(float)); + agent->log_trajectory_z = (float *)malloc(tlen * sizeof(float)); + agent->log_heading = (float *)malloc(tlen * sizeof(float)); + agent->log_velocity_x = (float *)malloc(tlen * sizeof(float)); + agent->log_velocity_y = (float *)malloc(tlen * sizeof(float)); + agent->log_length = (float *)malloc(tlen * sizeof(float)); + agent->log_width = (float *)malloc(tlen * sizeof(float)); + agent->log_height = (float *)malloc(tlen * sizeof(float)); + agent->log_valid = (int *)malloc(tlen * sizeof(int)); + + if ((size_t)tlen > 0 && fread(agent->log_trajectory_x, sizeof(float), tlen, file) != (size_t)tlen) { + fclose(file); + return -1; + } + if ((size_t)tlen > 0 && fread(agent->log_trajectory_y, sizeof(float), tlen, file) != (size_t)tlen) { + fclose(file); + return -1; + } + if ((size_t)tlen > 0 && fread(agent->log_trajectory_z, sizeof(float), tlen, file) != (size_t)tlen) { + fclose(file); + return -1; + } + if ((size_t)tlen > 0 && fread(agent->log_heading, sizeof(float), tlen, file) != (size_t)tlen) { + fclose(file); + return -1; + } + if ((size_t)tlen > 0 && fread(agent->log_velocity_x, sizeof(float), tlen, file) != (size_t)tlen) { + fclose(file); + return -1; + } + if ((size_t)tlen > 0 && fread(agent->log_velocity_y, sizeof(float), tlen, file) != (size_t)tlen) { + fclose(file); + return -1; + } + if ((size_t)tlen > 0 && fread(agent->log_length, sizeof(float), tlen, file) != (size_t)tlen) { + fclose(file); + return -1; + } + if ((size_t)tlen > 0 && fread(agent->log_width, sizeof(float), tlen, file) != (size_t)tlen) { + fclose(file); + return -1; + } + if ((size_t)tlen > 0 && fread(agent->log_height, sizeof(float), tlen, file) != (size_t)tlen) { + fclose(file); + return -1; + } + if ((size_t)tlen > 0 && fread(agent->log_valid, sizeof(int), tlen, file) != (size_t)tlen) { + fclose(file); + return -1; + } - int car_collided_with_index = -1; + if (fread(&agent->route_length, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } - if (agent->respawn_timestep != -1) - return car_collided_with_index; // Skip respawning entities + if (agent->route_length > 0) { + agent->route = (int *)malloc(agent->route_length * sizeof(int)); + if (fread(agent->route, sizeof(int), agent->route_length, file) != (size_t)agent->route_length) { + fclose(file); + return -1; + } + } else { + agent->route = NULL; + } - for (int i = 0; i < MAX_AGENTS; i++) { - int index = -1; - if (i < env->active_agent_count) { - index = env->active_agent_indices[i]; - } else if (i < env->num_actors && env->static_agent_count > 0) { - index = env->static_agent_indices[i - env->active_agent_count]; + if (fread(&agent->route_gt_len, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; } - if (index == -1) - continue; - if (index == agent_idx) - continue; - Entity *entity = &env->entities[index]; - if (entity->respawn_timestep != -1) - continue; // Skip respawning entities - float x1 = entity->x; - float y1 = entity->y; - float dist = ((x1 - agent->x) * (x1 - agent->x) + (y1 - agent->y) * (y1 - agent->y)); - if (dist > 225.0f) - continue; - if (check_aabb_collision(agent, entity)) { - car_collided_with_index = index; - break; + + if (fread(&agent->goal_position_x, sizeof(float), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&agent->goal_position_y, sizeof(float), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&agent->goal_position_z, sizeof(float), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&agent->mark_as_expert, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; } } - return car_collided_with_index; -} + for (int i = 0; i < num_roads; i++) { + RoadMapElement *road = &drive->road_elements[i]; -int check_lane_aligned(Entity *car, Entity *lane, int geometry_idx) { - // Validate lane geometry length - if (!lane || lane->array_size < 2) - return 0; + if (fread(&road->id, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&road->type, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&road->segment_length, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } - // Clamp geometry index to valid segment range [0, array_size-2] - if (geometry_idx < 0) - geometry_idx = 0; - if (geometry_idx >= lane->array_size - 1) - geometry_idx = lane->array_size - 2; - - // Compute local lane segment heading - float heading_x1, heading_y1; - if (geometry_idx > 0) { - heading_x1 = lane->traj_x[geometry_idx] - lane->traj_x[geometry_idx - 1]; - heading_y1 = lane->traj_y[geometry_idx] - lane->traj_y[geometry_idx - 1]; - } else { - // For first segment, just use the forward direction - heading_x1 = lane->traj_x[geometry_idx + 1] - lane->traj_x[geometry_idx]; - heading_y1 = lane->traj_y[geometry_idx + 1] - lane->traj_y[geometry_idx]; - } + int slen = road->segment_length; - float heading_x2 = lane->traj_x[geometry_idx + 1] - lane->traj_x[geometry_idx]; - float heading_y2 = lane->traj_y[geometry_idx + 1] - lane->traj_y[geometry_idx]; + road->x = (float *)malloc(slen * sizeof(float)); + road->y = (float *)malloc(slen * sizeof(float)); + road->z = (float *)malloc(slen * sizeof(float)); - float heading_1 = atan2f(heading_y1, heading_x1); - float heading_2 = atan2f(heading_y2, heading_x2); - float heading = (heading_1 + heading_2) / 2.0f; + if ((size_t)slen > 0 && fread(road->x, sizeof(float), slen, file) != (size_t)slen) { + fclose(file); + return -1; + } + if ((size_t)slen > 0 && fread(road->y, sizeof(float), slen, file) != (size_t)slen) { + fclose(file); + return -1; + } + if ((size_t)slen > 0 && fread(road->z, sizeof(float), slen, file) != (size_t)slen) { + fclose(file); + return -1; + } - // Normalize to [-pi, pi] - if (heading > M_PI) - heading -= 2.0f * M_PI; - if (heading < -M_PI) - heading += 2.0f * M_PI; + road->headings = (float *)malloc(slen * sizeof(float)); + if ((size_t)slen > 0 && fread(road->headings, sizeof(float), slen, file) != (size_t)slen) { + fclose(file); + return -1; + } - // Compute heading difference - float car_heading = car->heading; // radians - float heading_diff = fabsf(car_heading - heading); + if (road->type >= 0 && road->type <= 9) { + if (fread(&road->num_entries, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (road->num_entries > 0) { + road->entry_lanes = (int *)malloc(road->num_entries * sizeof(int)); + if (fread(road->entry_lanes, sizeof(int), road->num_entries, file) != (size_t)road->num_entries) { + fclose(file); + return -1; + } + } else { + road->entry_lanes = NULL; + } - if (heading_diff > M_PI) - heading_diff = 2.0f * M_PI - heading_diff; + if (fread(&road->num_exits, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (road->num_exits > 0) { + road->exit_lanes = (int *)malloc(road->num_exits * sizeof(int)); + if (fread(road->exit_lanes, sizeof(int), road->num_exits, file) != (size_t)road->num_exits) { + fclose(file); + return -1; + } + } else { + road->exit_lanes = NULL; + } - // within 15 degrees - return (heading_diff < (M_PI / 12.0f)) ? 1 : 0; -} + if (fread(&road->speed_limit, sizeof(float), 1, file) != 1) { + fclose(file); + return -1; + } + } else { + road->num_entries = 0; + road->num_exits = 0; + road->entry_lanes = NULL; + road->exit_lanes = NULL; + road->speed_limit = 0.0f; + } + } -void reset_agent_metrics(Drive *env, int agent_idx) { - Entity *agent = &env->entities[agent_idx]; - agent->metrics_array[COLLISION_IDX] = 0.0f; // vehicle collision - agent->metrics_array[OFFROAD_IDX] = 0.0f; // offroad - agent->metrics_array[LANE_ALIGNED_IDX] = 0.0f; // lane aligned - agent->collision_state = 0; -} + for (int i = 0; i < num_traffic; i++) { + TrafficControlElement *traffic = &drive->traffic_elements[i]; -float point_to_segment_distance_2d(float px, float py, float x1, float y1, float x2, float y2) { - float dx = x2 - x1; - float dy = y2 - y1; + if (fread(&traffic->id, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&traffic->type, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(traffic->stop_line, sizeof(float), 6, file) != 6) { + fclose(file); + return -1; + } + if (fread(&traffic->heading, sizeof(float), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&traffic->state_length, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + + int state_len = traffic->state_length; + + traffic->states = (int *)malloc(state_len * sizeof(int)); + if ((size_t)state_len > 0 && fread(traffic->states, sizeof(int), state_len, file) != (size_t)state_len) { + fclose(file); + return -1; + } + + if (fread(&traffic->num_controlled_lanes, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (traffic->num_controlled_lanes > 0) { + traffic->controlled_lanes = (int *)malloc(traffic->num_controlled_lanes * sizeof(int)); + if (fread(traffic->controlled_lanes, sizeof(int), traffic->num_controlled_lanes, file) != + (size_t)traffic->num_controlled_lanes) { + fclose(file); + return -1; + } + } else { + traffic->controlled_lanes = NULL; + } + } - if (dx == 0 && dy == 0) { - // The segment is a point - return sqrtf((px - x1) * (px - x1) + (py - y1) * (py - y1)); + // Skip objects section + for (int i = 0; i < num_objects; i++) { + int obj_id, obj_type, T; + if (fread(&obj_id, sizeof(int), 1, file) != 1 || fread(&obj_type, sizeof(int), 1, file) != 1 || + fread(&T, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + // Skip: x,y,z,heading,vx,vy,length,width,height (9 float arrays) + valid (1 int array) + fseek(file, 9 * T * sizeof(float) + T * sizeof(int), SEEK_CUR); } - // Calculate the t that minimizes the distance - float t = ((px - x1) * dx + (py - y1) * dy) / (dx * dx + dy * dy); + // Lane graph section + int n_lanes_graph; + if (fread(&n_lanes_graph, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + drive->lane_graph.n_lanes = n_lanes_graph; + drive->lane_graph.lane_ids = NULL; + drive->lane_graph.lane_lengths = NULL; + drive->lane_graph.distances = NULL; + if (n_lanes_graph > 0) { + drive->lane_graph.lane_ids = (int *)malloc(n_lanes_graph * sizeof(int)); + if (fread(drive->lane_graph.lane_ids, sizeof(int), n_lanes_graph, file) != (size_t)n_lanes_graph) { + fclose(file); + return -1; + } + drive->lane_graph.lane_lengths = (float *)malloc(n_lanes_graph * sizeof(float)); + if (fread(drive->lane_graph.lane_lengths, sizeof(float), n_lanes_graph, file) != (size_t)n_lanes_graph) { + fclose(file); + return -1; + } + drive->lane_graph.distances = (float *)malloc(n_lanes_graph * n_lanes_graph * sizeof(float)); + if (fread(drive->lane_graph.distances, sizeof(float), n_lanes_graph * n_lanes_graph, file) != + (size_t)(n_lanes_graph * n_lanes_graph)) { + fclose(file); + return -1; + } + } - // Clamp t to the segment - if (t < 0) - t = 0; - else if (t > 1) - t = 1; + // Metadata + if (fread(drive->scenario_id, sizeof(char), 128, file) != 128) { + fclose(file); + return -1; + } + if (fread(drive->dataset_name, sizeof(char), 32, file) != 32) { + fclose(file); + return -1; + } + if (fread(&drive->log_length, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&drive->log_dt, sizeof(float), 1, file) != 1) { + fclose(file); + return -1; + } + if (fread(&drive->num_objects_of_interest, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } - // Find the closest point on the segment - float closestX = x1 + t * dx; - float closestY = y1 + t * dy; + if (drive->num_objects_of_interest > 0) { + drive->objects_of_interest = (int *)malloc(drive->num_objects_of_interest * sizeof(int)); + if (fread(drive->objects_of_interest, sizeof(int), drive->num_objects_of_interest, file) != + (size_t)drive->num_objects_of_interest) { + fclose(file); + return -1; + } + } else { + drive->objects_of_interest = NULL; + } - // Return the distance from p to the closest point - return sqrtf((px - closestX) * (px - closestX) + (py - closestY) * (py - closestY)); -} + if (fread(&drive->num_tracks_to_predict, sizeof(int), 1, file) != 1) { + fclose(file); + return -1; + } -void compute_agent_metrics(Drive *env, int agent_idx) { - Entity *agent = &env->entities[agent_idx]; + if (drive->num_tracks_to_predict > 0) { + drive->tracks_to_predict = (int *)malloc(drive->num_tracks_to_predict * sizeof(int)); + if (fread(drive->tracks_to_predict, sizeof(int), drive->num_tracks_to_predict, file) != + (size_t)drive->num_tracks_to_predict) { + fclose(file); + return -1; + } + } else { + drive->tracks_to_predict = NULL; + } - reset_agent_metrics(env, agent_idx); + fclose(file); + return 0; +} - if (agent->x == INVALID_POSITION) - return; // invalid agent position +// ======================================== +// Road Utility Functions +// ======================================== - int collided = 0; - float half_length = agent->length / 2.0f; - float half_width = agent->width / 2.0f; - float cos_heading = cosf(agent->heading); - float sin_heading = sinf(agent->heading); - float min_distance = (float)INT16_MAX; +// Compute multi-segment average heading around a center segment +static float compute_multi_segment_alignment(RoadMapElement *element, int center_seg_idx) { + // NOTE: This function returns the average heading in radians for a lane segment, + // with more weight given to the center segment. - int closest_lane_entity_idx = -1; - int closest_lane_geometry_idx = -1; + float avg_heading = 0.0f; + float total_weight = 0.0f; - float corners[4][2]; - for (int i = 0; i < 4; i++) { - corners[i][0] = - agent->x + (offsets[i][0] * half_length * cos_heading - offsets[i][1] * half_width * sin_heading); - corners[i][1] = - agent->y + (offsets[i][0] * half_length * sin_heading + offsets[i][1] * half_width * cos_heading); - } + int start = (center_seg_idx > 0) ? (center_seg_idx - 1) : center_seg_idx; + int end = (center_seg_idx < element->segment_length - 2) ? (center_seg_idx + 1) : (element->segment_length - 2); - GridMapEntity entity_list[MAX_ENTITIES_PER_CELL * 25]; // Array big enough for all neighboring cells - int list_size = - checkNeighbors(env, agent->x, agent->y, entity_list, MAX_ENTITIES_PER_CELL * 25, collision_offsets, 25); - for (int i = 0; i < list_size; i++) { - if (entity_list[i].entity_idx == -1) - continue; - if (entity_list[i].entity_idx == agent_idx) + for (int seg_idx = start; seg_idx <= end; seg_idx++) { + if (seg_idx < 0 || seg_idx >= element->segment_length - 1) continue; - Entity *entity; - entity = &env->entities[entity_list[i].entity_idx]; - - // Check for offroad collision with road edges (only for vehicles and cyclists) - if (entity->type == ROAD_EDGE && agent->type != PEDESTRIAN) { - int geometry_idx = entity_list[i].geometry_idx; - float start[2] = {entity->traj_x[geometry_idx], entity->traj_y[geometry_idx]}; - float end[2] = {entity->traj_x[geometry_idx + 1], entity->traj_y[geometry_idx + 1]}; - for (int k = 0; k < 4; k++) { // Check each edge of the bounding box - int next = (k + 1) % 4; - if (check_line_intersection(corners[k], corners[next], start, end)) { - collided = OFFROAD; - break; - } - } - } - if (collided == OFFROAD) - break; + float seg_heading = element->headings[seg_idx]; - // Find closest point on the road centerline to the agent - if (entity->type == ROAD_LANE) { - int entity_idx = entity_list[i].entity_idx; - int geometry_idx = entity_list[i].geometry_idx; + float weight = (seg_idx == center_seg_idx) ? 2.0f : 1.0f; + + if (total_weight == 0.0f) { + avg_heading = seg_heading; + } else { + float angle_diff = compute_heading_diff(seg_heading, avg_heading); + avg_heading += weight * angle_diff / (total_weight + weight); + } + total_weight += weight; + } - float start[2] = {entity->traj_x[geometry_idx], entity->traj_y[geometry_idx]}; - float end[2] = {entity->traj_x[geometry_idx + 1], entity->traj_y[geometry_idx + 1]}; + return avg_heading; +} - float dist = point_to_segment_distance_2d(agent->x, agent->y, start[0], start[1], end[0], end[1]); - float heading_diff = fabsf(atan2f(end[1] - start[1], end[0] - start[0]) - agent->heading); +// Compute the length of a lane +static float compute_lane_length(RoadMapElement *lane) { + float length = 0.0f; + for (int i = 1; i < lane->segment_length; i++) { + float dx = lane->x[i] - lane->x[i - 1]; + float dy = lane->y[i] - lane->y[i - 1]; + length += sqrtf(dx * dx + dy * dy); + } + return length; +} - // Normalize heading difference to [0, pi] - if (heading_diff > M_PI) - heading_diff = 2.0f * M_PI - heading_diff; +// Compute the remaining distance on a lane from a given position to the end of the lane +static float compute_remaining_lane_distance(RoadMapElement *lane, float pos_x, float pos_y) { + // Find the closest segment to the position + int closest_seg = 0; + float closest_t = 0.0f; + float min_dist_sq = 1e30f; + + for (int i = 0; i < lane->segment_length - 1; i++) { + float x0 = lane->x[i]; + float y0 = lane->y[i]; + float x1 = lane->x[i + 1]; + float y1 = lane->y[i + 1]; + + float dx = x1 - x0; + float dy = y1 - y0; + float seg_len_sq = dx * dx + dy * dy; + + float t = 0.0f; + if (seg_len_sq > 1e-6f) { + t = ((pos_x - x0) * dx + (pos_y - y0) * dy) / seg_len_sq; + t = fmaxf(0.0f, fminf(1.0f, t)); + } - // Penalize if heading differs by more than 30 degrees - if (heading_diff > (M_PI / 6.0f)) - dist += 3.0f; + float proj_x = x0 + t * dx; + float proj_y = y0 + t * dy; + float dist_sq = (pos_x - proj_x) * (pos_x - proj_x) + (pos_y - proj_y) * (pos_y - proj_y); - if (dist < min_distance) { - min_distance = dist; - closest_lane_entity_idx = entity_idx; - closest_lane_geometry_idx = geometry_idx; - } + if (dist_sq < min_dist_sq) { + min_dist_sq = dist_sq; + closest_seg = i; + closest_t = t; } } - // check if aligned with closest lane and set current lane - // 4.0m threshold: agents more than 4 meters from any lane are considered off-road - if (min_distance > 4.0f || closest_lane_entity_idx == -1) { - agent->metrics_array[LANE_ALIGNED_IDX] = 0.0f; - agent->current_lane_idx = -1; - } else { - agent->current_lane_idx = closest_lane_entity_idx; - int lane_aligned = - check_lane_aligned(agent, &env->entities[closest_lane_entity_idx], closest_lane_geometry_idx); - agent->metrics_array[LANE_ALIGNED_IDX] = lane_aligned; + // Compute remaining distance from closest point to end of lane + float remaining = 0.0f; + + // Partial distance in current segment (from t to end of segment) + float dx = lane->x[closest_seg + 1] - lane->x[closest_seg]; + float dy = lane->y[closest_seg + 1] - lane->y[closest_seg]; + float seg_len = sqrtf(dx * dx + dy * dy); + remaining += (1.0f - closest_t) * seg_len; + + // Full distance of remaining segments + for (int i = closest_seg + 1; i < lane->segment_length - 1; i++) { + dx = lane->x[i + 1] - lane->x[i]; + dy = lane->y[i + 1] - lane->y[i]; + remaining += sqrtf(dx * dx + dy * dy); } - // Check for vehicle collisions (skip for pedestrians) - int car_collided_with_index = -1; - if (agent->type != PEDESTRIAN) { - car_collided_with_index = collision_check(env, agent_idx); - if (car_collided_with_index != -1) - collided = VEHICLE_COLLISION; + return remaining; +} + +static float compute_lane_end_distance_sq(RoadMapElement *lane, float origin_x, float origin_y) { + if (lane->segment_length <= 0) { + return 0.0f; } - agent->collision_state = collided; + int last_idx = lane->segment_length - 1; + float dx = lane->x[last_idx] - origin_x; + float dy = lane->y[last_idx] - origin_y; + return dx * dx + dy * dy; +} - if (collided == VEHICLE_COLLISION) { - if (env->collision_behavior == STOP_AGENT && !agent->stopped) { - agent->stopped = 1; - agent->vx = agent->vy = 0.0f; - } else if (env->collision_behavior == REMOVE_AGENT && !agent->removed) { - Entity *agent_collided = &env->entities[car_collided_with_index]; - agent->removed = 1; - agent_collided->removed = 1; - agent->x = agent->y = -10000.0f; - agent_collided->x = agent_collided->y = -10000.0f; - } +// Returns signed distance to lane (left of lane = negative, right = positive) +static float find_closest_segment_on_lane(RoadMapElement *lane, float agent_x, float agent_y, int *out_segment_idx) { + int num_segments = lane->segment_length - 1; + if (num_segments < 1) { + *out_segment_idx = 0; + return 1e9f; } - if (collided == OFFROAD) { - agent->metrics_array[OFFROAD_IDX] = 1.0f; - if (env->offroad_behavior == STOP_AGENT && !agent->stopped) { - agent->stopped = 1; - agent->vx = agent->vy = 0.0f; - } else if (env->offroad_behavior == REMOVE_AGENT && !agent->removed) { - agent->removed = 1; - agent->x = agent->y = -10000.0f; + + float min_dist_sq = 1e18f; + int closest_idx = 0; + float closest_cross = 0.0f; + + for (int seg_idx = 0; seg_idx < num_segments; seg_idx++) { + float seg_start_x = lane->x[seg_idx]; + float seg_start_y = lane->y[seg_idx]; + float seg_end_x = lane->x[seg_idx + 1]; + float seg_end_y = lane->y[seg_idx + 1]; + + float seg_dx = seg_end_x - seg_start_x; + float seg_dy = seg_end_y - seg_start_y; + float seg_length_sq = seg_dx * seg_dx + seg_dy * seg_dy; + + float to_agent_x = agent_x - seg_start_x; + float to_agent_y = agent_y - seg_start_y; + + // cross > 0 means agent is left of lane direction + float cross = seg_dx * to_agent_y - seg_dy * to_agent_x; + + float dist_sq; + if (seg_length_sq > 1e-6f) { + float t = (to_agent_x * seg_dx + to_agent_y * seg_dy) / seg_length_sq; + if (t <= 0.0f) { + dist_sq = to_agent_x * to_agent_x + to_agent_y * to_agent_y; + } else if (t >= 1.0f) { + float dx = agent_x - seg_end_x; + float dy = agent_y - seg_end_y; + dist_sq = dx * dx + dy * dy; + } else { + dist_sq = (cross * cross) / seg_length_sq; + } + } else { + dist_sq = to_agent_x * to_agent_x + to_agent_y * to_agent_y; + } + + if (dist_sq < min_dist_sq) { + min_dist_sq = dist_sq; + closest_idx = seg_idx; + closest_cross = cross; } } - return; + *out_segment_idx = closest_idx; + float abs_dist = sqrtf(min_dist_sq); + return (closest_cross >= 0.0f) ? -abs_dist : abs_dist; } -bool should_control_agent(Drive *env, int agent_idx, int control_limit) { - // Check if we have room for more agents or are already at capacity - if (env->active_agent_count >= control_limit) { - return false; - } +static float compute_progression(Agent *agent) { + int num_wp = agent->path->num_waypoints; + if (num_wp < 2) + return agent->path->waypoints[0].s; - Entity *entity = &env->entities[agent_idx]; + int idx = agent->closest_path_idx_wp; + if (idx >= num_wp) + idx = num_wp - 1; - if (env->control_mode == CONTROL_SDC_ONLY) { - return agent_idx == env->sdc_track_index; - } + // closest_path_idx_wp is the closest waypoint IN FRONT of the agent, + // so the agent is on the segment ending at that waypoint (idx-1 to idx). + // Also check the next segment (idx to idx+1) in case agent is at the waypoint. + int start_seg = (idx > 0) ? (idx - 1) : 0; + int end_seg = (idx < num_wp - 1) ? (idx + 1) : (num_wp - 1); - bool is_vehicle = (entity->type == VEHICLE); - bool is_ped_or_bike = (entity->type == PEDESTRIAN || entity->type == CYCLIST); - bool type_is_valid = false; + float min_dist_sq = 1e18f; + float best_s = agent->path->waypoints[0].s; - switch (env->control_mode) { - case CONTROL_WOSAC: - // Valid types only, ignore expert flag and goal distance - return (is_vehicle || is_ped_or_bike); + for (int i = start_seg; i < end_seg; ++i) { + const struct Waypoint wp_a = agent->path->waypoints[i]; + const struct Waypoint wp_b = agent->path->waypoints[i + 1]; - case CONTROL_VEHICLES: - type_is_valid = is_vehicle; - break; + const float seg_dx = wp_b.x - wp_a.x; + const float seg_dy = wp_b.y - wp_a.y; + const float seg_len_sq = seg_dx * seg_dx + seg_dy * seg_dy; - default: - type_is_valid = (is_vehicle || is_ped_or_bike); - break; + float t; + if (seg_len_sq < 1e-6f) { + t = 0.0f; + } else { + const float agent_dx = agent->sim_x - wp_a.x; + const float agent_dy = agent->sim_y - wp_a.y; + t = (agent_dx * seg_dx + agent_dy * seg_dy) / seg_len_sq; + } + + const float clamped_t = fmaxf(0.0f, fminf(1.0f, t)); + const float closest_x = wp_a.x + clamped_t * seg_dx; + const float closest_y = wp_a.y + clamped_t * seg_dy; + const float dist_sq = (agent->sim_x - closest_x) * (agent->sim_x - closest_x) + + (agent->sim_y - closest_y) * (agent->sim_y - closest_y); + + if (dist_sq < min_dist_sq) { + min_dist_sq = dist_sq; + best_s = wp_a.s + clamped_t * (wp_b.s - wp_a.s); + } } - // Filter invalid types or experts - if (!type_is_valid || entity->mark_as_expert) { - return false; + return best_s; +} + +static float score_lane_candidate(Drive *env, float agent_heading, int *checked_lanes, int *num_checked_lanes, + int *closest_segment_index, GridMapEntity entity, float agent_x, float agent_y, + float max_distance_threshold, int current_lane_index, float *signed_dist_out, + float *lane_heading_out) { + if (entity.entity_idx == -1 || entity.entity_type != ENTITY_TYPE_ROAD_ELEMENT) + return -1; + + int entity_idx = entity.entity_idx; + RoadMapElement *element = &env->road_elements[entity_idx]; + + if (!is_drivable_road_lane(element->type)) + return -1; + + int already_checked = 0; + for (int c = 0; c < *num_checked_lanes; c++) { + if (checked_lanes[c] == entity_idx) { + already_checked = 1; + break; + } + } + if (already_checked) + return -1; + if (*num_checked_lanes < MAX_CHECKED_LANES) { + checked_lanes[*num_checked_lanes] = entity_idx; + (*num_checked_lanes)++; } - // Check distance to goal in agent's local frame - float cos_heading = cosf(entity->traj_heading[0]); - float sin_heading = sinf(entity->traj_heading[0]); - float goal_dx = entity->goal_position_x - entity->traj_x[0]; - float goal_dy = entity->goal_position_y - entity->traj_y[0]; + // Find closest segment on this lane + float signed_dist = find_closest_segment_on_lane(element, agent_x, agent_y, closest_segment_index); + float abs_dist = fabsf(signed_dist); - // Transform to agent's local frame - float local_goal_x = goal_dx * cos_heading + goal_dy * sin_heading; - float local_goal_y = -goal_dx * sin_heading + goal_dy * cos_heading; - float distance_to_goal = relative_distance_2d(0, 0, local_goal_x, local_goal_y); + if (abs_dist > max_distance_threshold) + return -1; - return distance_to_goal >= MIN_DISTANCE_TO_GOAL; -} + // Compute lane heading using multi-segment alignment + float avg_lane_heading = compute_multi_segment_alignment(element, *closest_segment_index); -void set_active_agents(Drive *env) { + // Compute heading alignment penalty (0.0 = perfect, 1.0 = opposite) + float heading_diff = compute_heading_diff(agent_heading, avg_lane_heading); + float heading_penalty = fabsf(heading_diff) / M_PI; // Normalize to [0, 1] - // Initialize - env->active_agent_count = 0; // Policy-controlled agents - env->static_agent_count = 0; // Non-moving background agents - env->expert_static_agent_count = 0; // Expert replay agents (non-controlled) - env->num_actors = 0; // Total agents created (there is always the SDC) + // Normalize distance for scoring + float distance_penalty = abs_dist / LANE_DISTANCE_NORMALIZATION; - int active_agent_indices[MAX_AGENTS]; - int static_agent_indices[MAX_AGENTS]; - int expert_static_agent_indices[MAX_AGENTS]; + // Combined score using defined weights + float score = LANE_SELECTION_DISTANCE_WEIGHT * distance_penalty + LANE_SELECTION_HEADING_WEIGHT * heading_penalty; - if (env->num_agents == 0) { - env->num_agents = MAX_AGENTS; + // Hysteresis: penalize switching away from current lane + if (current_lane_index != entity_idx && current_lane_index != -1) { + score += LANE_SWITCH_THRESHOLD; } - int control_limit; - if (env->control_mode == CONTROL_MIXED_PLAY) { - control_limit = (env->max_controlled_agents < env->num_agents) ? env->max_controlled_agents : env->num_agents; - } else { - control_limit = env->num_agents; - } + *signed_dist_out = signed_dist; + *lane_heading_out = avg_lane_heading; + return score; +} - // If we have a SDC index (WOMD), initialize it first: - int sdc_index = env->sdc_track_index; +static DepthPoint compute_z_distance_to_road_segment(const Agent *agent, const RoadMapElement *lane, int geometry_idx) { + float dx = agent->sim_x - lane->x[geometry_idx]; + float dy = agent->sim_y - lane->y[geometry_idx]; + float dz = agent->sim_z - lane->z[geometry_idx]; - if (sdc_index >= 0) { - active_agent_indices[0] = sdc_index; - env->num_actors++; - env->active_agent_count++; - env->entities[sdc_index].active_agent = 1; - } + DepthPoint point; + point.z_dis = fabsf(dz); + point.euclidean_dis = sqrtf(dx * dx + dy * dy + dz * dz); + point.z = lane->z[geometry_idx]; + return point; +} - // Iterate through entities to find agents to create and/or control - for (int i = 0; i < env->num_objects && env->num_actors < MAX_AGENTS; i++) { +// ======================================== +// Route/Path/Goal Functions +// ======================================== - // Skip if its the SDC - if (i == sdc_index) { - continue; - } +static int get_closest_waypoint_index_on_path(Drive *env, int agent_idx) { + const float MAX_DIST_SQ = 10000.0f; + const float MAX_ANGLE_DIFF = M_PI_2; // 90 degrees + const int WINDOW_FORWARD = 20; // 40m ahead (20 * 2m waypoint spacing) + const int WINDOW_BACKWARD = 10; // 20m behind - Entity *entity = &env->entities[i]; + Agent *agent = &env->agents[agent_idx]; + if (agent->path == NULL || agent->path->num_waypoints == 0) + return 0; - // Skip if not valid at initialization - if (entity->traj_valid[env->init_steps] != 1) { - continue; - } + int num_wp = agent->path->num_waypoints; + int prev_idx = agent->closest_path_idx_wp; + if (prev_idx >= num_wp) + prev_idx = 0; - // Determine if entity should be created - bool should_create = false; - if (env->init_mode == INIT_ALL_VALID) { - should_create = true; // All valid entities - } else if (env->control_mode == CONTROL_VEHICLES) { - should_create = (entity->type == VEHICLE); - } else { // Control all agents - should_create = (entity->type == VEHICLE || entity->type == PEDESTRIAN || entity->type == CYCLIST); - } + float heading_x = cosf(agent->sim_heading); + float heading_y = sinf(agent->sim_heading); - if (!should_create) - continue; + int best_idx = 0; + float min_dist_sq = MAX_DIST_SQ; - env->num_actors++; + // Try windowed search first, fallback to full search if no candidate found + int start_idx = fmaxf(0, prev_idx - WINDOW_BACKWARD); + int end_idx = fminf(num_wp, prev_idx + WINDOW_FORWARD); - // Determine if this agent should be policy-controlled - bool is_controlled = false; + for (int pass = 0; pass < 2; pass++) { + for (int i = start_idx; i < end_idx; i++) { + float dx = agent->path->waypoints[i].x - agent->sim_x; + float dy = agent->path->waypoints[i].y - agent->sim_y; - is_controlled = should_control_agent(env, i, control_limit); + // Skip waypoints behind agent + if (dx * heading_x + dy * heading_y <= 0) + continue; - if (is_controlled) { - active_agent_indices[env->active_agent_count] = i; - env->active_agent_count++; - env->entities[i].active_agent = 1; - } else if (env->init_mode != INIT_ONLY_CONTROLLABLE_AGENTS) { - static_agent_indices[env->static_agent_count] = i; - env->static_agent_count++; // Includes expert replay and static agents - env->entities[i].active_agent = 0; - if (env->entities[i].mark_as_expert == 1 || env->active_agent_count == control_limit) { - expert_static_agent_indices[env->expert_static_agent_count] = i; - env->expert_static_agent_count++; - env->entities[i].mark_as_expert = 1; + // Skip waypoints with heading too different from agent + float angle_diff = agent->sim_heading - agent->path->waypoints[i].heading; + angle_diff = atan2f(sinf(angle_diff), cosf(angle_diff)); + + if (fabsf(angle_diff) > MAX_ANGLE_DIFF) + continue; + + float dist_sq = dx * dx + dy * dy; + if (dist_sq < min_dist_sq) { + min_dist_sq = dist_sq; + best_idx = i; } } - } - // Set up initial active agents - env->active_agent_indices = (int *)malloc(env->active_agent_count * sizeof(int)); - env->static_agent_indices = (int *)malloc(env->static_agent_count * sizeof(int)); - env->expert_static_agent_indices = (int *)malloc(env->expert_static_agent_count * sizeof(int)); - for (int i = 0; i < env->active_agent_count; i++) { - env->active_agent_indices[i] = active_agent_indices[i]; - }; - for (int i = 0; i < env->static_agent_count; i++) { - env->static_agent_indices[i] = static_agent_indices[i]; + // If found in windowed search, done + if (min_dist_sq < MAX_DIST_SQ) + break; + + // Fallback: full search + start_idx = 0; + end_idx = num_wp; } - for (int i = 0; i < env->expert_static_agent_count; i++) { - env->expert_static_agent_indices[i] = expert_static_agent_indices[i]; + + return best_idx; +} + +static inline void initialize_agent_progression(Drive *env, int agent_idx) { + Agent *agent = &env->agents[agent_idx]; + if (agent->path == NULL || agent->path->num_waypoints == 0) { + agent->closest_path_idx_wp = 0; + agent->path_progression = 0.0f; + agent->distance_since_spawn = 0.0f; + return; } - // printf("Total actors: %d, Active agents: %d, Static agents: %d, Expert static agents: %d\n", env->num_actors, - // env->active_agent_count, env->static_agent_count, env->expert_static_agent_count); - // printf("Control mode: %d, max controlled agents: %d\n", env->control_mode, env->max_controlled_agents); - return; + agent->closest_path_idx_wp = get_closest_waypoint_index_on_path(env, agent_idx); + float baseline_progression = compute_progression(agent); + agent->path_progression = baseline_progression; + agent->distance_since_spawn = 0.0f; } -void remove_bad_trajectories(Drive *env) { +static inline void reset_agent_path_progression(Drive *env, int agent_idx) { + Agent *agent = &env->agents[agent_idx]; - if (env->control_mode != CONTROL_WOSAC) { - return; // Leave all trajectories in WOSAC control mode + if (agent->path == NULL || agent->path->num_waypoints == 0) { + agent->closest_path_idx_wp = 0; + agent->path_progression = 0.0f; + return; } - set_start_position(env); - int collided_agents[env->active_agent_count]; - int collided_with_indices[env->active_agent_count]; - memset(collided_agents, 0, env->active_agent_count * sizeof(int)); - for (int i = 0; i < env->active_agent_count; ++i) { - collided_with_indices[i] = -1; - } - // move experts through trajectories to check for collisions and remove as illegal agents - for (int t = 0; t < env->episode_length; t++) { - for (int i = 0; i < env->active_agent_count; i++) { - int agent_idx = env->active_agent_indices[i]; - move_expert(env, env->actions, agent_idx); - } - for (int i = 0; i < env->expert_static_agent_count; i++) { - int expert_idx = env->expert_static_agent_indices[i]; - if (env->entities[expert_idx].x == INVALID_POSITION) - continue; - move_expert(env, env->actions, expert_idx); + agent->closest_path_idx_wp = get_closest_waypoint_index_on_path(env, agent_idx); + agent->path_progression = compute_progression(agent); +} + +static void build_path(Drive *env, int agent_idx) { + // NOTE: This function assumes the agent's route is already set. + // It interpolates waypoints along the route lanes at fixed spacing. + // It is a mid-level representation between route and low-level goals waypoints. + + float waypoints_spacing = env->min_waypoint_spacing; + + Agent *agent = &env->agents[agent_idx]; + + if (agent->path != NULL) + free(agent->path); + agent->path = (struct Path *)malloc(sizeof(struct Path)); + + int wp_count = 0; + float prev_x, prev_y, prev_z, prev_s; + + // Interpolate waypoints along route lanes + for (int route_idx = 0; route_idx < agent->route_length && wp_count < MAX_NUM_WP_PATH; route_idx++) { + int lane_idx = find_lane_index_by_id(env, agent->route[route_idx]); + if (lane_idx == -1) + continue; + RoadMapElement *lane = &env->road_elements[lane_idx]; + + for (int i = 0; i < lane->segment_length && wp_count < MAX_NUM_WP_PATH; i++) { + float curr_x = lane->x[i]; + float curr_y = lane->y[i]; + float curr_z = lane->z[i]; + + // First point: add directly + if (wp_count == 0) { + agent->path->waypoints[0] = + (struct Waypoint){.x = curr_x, .y = curr_y, .z = curr_z, .s = 0.0f, .lane_id = lane->id}; + prev_x = curr_x; + prev_y = curr_y; + prev_z = curr_z; + prev_s = 0.0f; + wp_count++; + continue; + } + + float dx = curr_x - prev_x; + float dy = curr_y - prev_y; + float dz = curr_z - prev_z; + float seg_len = sqrtf(dx * dx + dy * dy + dz * dz); + if (seg_len < 1e-6f) { + prev_x = curr_x; + prev_y = curr_y; + prev_z = curr_z; + continue; + } + + float curr_s = prev_s + seg_len; + + // Interpolate waypoints within this segment + float target_s = (float)wp_count * waypoints_spacing; + while (target_s < curr_s && wp_count < MAX_NUM_WP_PATH) { + float t = (target_s - prev_s) / seg_len; + agent->path->waypoints[wp_count] = (struct Waypoint){ + .x = prev_x + t * dx, + .y = prev_y + t * dy, + .z = prev_z + t * dz, + .s = target_s, + .lane_id = lane->id, + }; + wp_count++; + target_s = (float)wp_count * waypoints_spacing; + } + + prev_x = curr_x; + prev_y = curr_y; + prev_z = curr_z; + prev_s = curr_s; + } + } + + agent->path->num_waypoints = wp_count; + if (wp_count < 2) + return; + + // Compute heading (tangent angle) and cache trig values + for (int i = 0; i < wp_count - 1; i++) { + float dx = agent->path->waypoints[i + 1].x - agent->path->waypoints[i].x; + float dy = agent->path->waypoints[i + 1].y - agent->path->waypoints[i].y; + float heading = atan2f(dy, dx); + agent->path->waypoints[i].heading = heading; + agent->path->waypoints[i].cos_heading = cosf(heading); + agent->path->waypoints[i].sin_heading = sinf(heading); + } + // Last waypoint copies from second-to-last + agent->path->waypoints[wp_count - 1].heading = agent->path->waypoints[wp_count - 2].heading; + agent->path->waypoints[wp_count - 1].cos_heading = agent->path->waypoints[wp_count - 2].cos_heading; + agent->path->waypoints[wp_count - 1].sin_heading = agent->path->waypoints[wp_count - 2].sin_heading; + + // Compute kappa (curvature = d_heading / ds) + for (int i = 1; i < wp_count - 1; i++) { + float d_heading = + compute_heading_diff(agent->path->waypoints[i + 1].heading, agent->path->waypoints[i].heading); + agent->path->waypoints[i].kappa = d_heading / waypoints_spacing; + } + agent->path->waypoints[0].kappa = agent->path->waypoints[1].kappa; + agent->path->waypoints[wp_count - 1].kappa = agent->path->waypoints[wp_count - 2].kappa; +} + +// Generate a route by random walk through lane graph until target distance is reached +static int generate_random_route(Drive *env, int start_lane_id, float target_distance, int *route, int max_route_length, + float agent_x, float agent_y) { + // NOTE: This function performs a random walk through the lane connectivity graph,starting from start_lane_id, + // until the accumulated distance exceeds target_distance or max_route_length is reached. + // Cycles are avoided by tracking visited lanes and trying to increase distance. + + int route_length = 0; + float accumulated_distance = 0.0f; + int current_lane_id = start_lane_id; + float start_x = agent_x; + float start_y = agent_y; + + // Track visited lanes to avoid loops + int visited_ids[MAX_ROUTE_LENGTH]; + int visited_count = 0; + + // Add start lane to route + route[route_length++] = current_lane_id; + visited_ids[visited_count++] = current_lane_id; + + // Get start lane and add its length + int current_lane_idx = find_lane_index_by_id(env, current_lane_id); + if (current_lane_idx == -1) { + return 0; // Invalid start lane + } + + RoadMapElement *current_lane = &env->road_elements[current_lane_idx]; + // Use remaining distance from agent position instead of full lane length + accumulated_distance += compute_remaining_lane_distance(current_lane, agent_x, agent_y); + float max_end_distance_sq = compute_lane_end_distance_sq(current_lane, start_x, start_y); + + // Random walk through lane graph + while (accumulated_distance < target_distance && route_length < max_route_length) { + current_lane_idx = find_lane_index_by_id(env, current_lane_id); + if (current_lane_idx == -1) + break; + + current_lane = &env->road_elements[current_lane_idx]; + + // Collect valid (unvisited, drivable) exit lanes + int valid_exits[8]; + float valid_exit_dist_sq[8]; + int num_valid_exits = 0; + + int progressing_exits[8]; + float progressing_dist_sq[8]; + int num_progressing_exits = 0; + + for (int e = 0; e < current_lane->num_exits && num_valid_exits < 8; e++) { + int exit_id = current_lane->exit_lanes[e]; + + // Check if already visited + int already_visited = 0; + for (int v = 0; v < visited_count; v++) { + if (visited_ids[v] == exit_id) { + already_visited = 1; + break; + } + } + if (already_visited) + continue; + + // Check if exit lane is drivable + int exit_lane_idx = find_lane_index_by_id(env, exit_id); + if (exit_lane_idx == -1) + continue; + + // NOTE: Dummy logic to prevent cycle, can be improved with better graph traversal + float exit_end_distance_sq = + compute_lane_end_distance_sq(&env->road_elements[exit_lane_idx], start_x, start_y); + valid_exits[num_valid_exits] = exit_id; + valid_exit_dist_sq[num_valid_exits] = exit_end_distance_sq; + num_valid_exits++; + + if (exit_end_distance_sq > max_end_distance_sq) { + progressing_exits[num_progressing_exits] = exit_id; + progressing_dist_sq[num_progressing_exits] = exit_end_distance_sq; + num_progressing_exits++; + } + } + + // If no valid exits, we've reached a dead end + if (num_valid_exits == 0) + break; + + // Pick a progressing exit lane if possible, otherwise pick the farthest available + int chosen_exit_id; + float chosen_exit_dist_sq; + if (num_progressing_exits > 0) { + int chosen_idx = rand() % num_progressing_exits; + chosen_exit_id = progressing_exits[chosen_idx]; + chosen_exit_dist_sq = progressing_dist_sq[chosen_idx]; + } else { + int best_idx = 0; + float best_dist_sq = valid_exit_dist_sq[0]; + for (int i = 1; i < num_valid_exits; i++) { + if (valid_exit_dist_sq[i] > best_dist_sq) { + best_dist_sq = valid_exit_dist_sq[i]; + best_idx = i; + } + } + chosen_exit_id = valid_exits[best_idx]; + chosen_exit_dist_sq = valid_exit_dist_sq[best_idx]; + } + int chosen_exit_idx = find_lane_index_by_id(env, chosen_exit_id); + + if (chosen_exit_idx == -1) + break; + + // Add to route + route[route_length++] = chosen_exit_id; + visited_ids[visited_count++] = chosen_exit_id; + + // Accumulate distance + RoadMapElement *exit_lane = &env->road_elements[chosen_exit_idx]; + accumulated_distance += compute_lane_length(exit_lane); + if (chosen_exit_dist_sq > max_end_distance_sq) { + max_end_distance_sq = chosen_exit_dist_sq; + } + + // Move to next lane + current_lane_id = chosen_exit_id; + } + + return route_length; +} + +// NOTE: Only works for closed maps with infinite looping routes +static int compute_new_route(Drive *env, int agent_idx, int current_lane_id) { + Agent *agent = &env->agents[agent_idx]; + + // Generate route by random walk through lane graph + // Use agent's current position to compute remaining distance on start lane + int num_target_waypoints = env->num_target_waypoints; + if (num_target_waypoints > MAX_TARGET_WAYPOINTS) { + num_target_waypoints = MAX_TARGET_WAYPOINTS; + } + + float min_route_distance; + // NOTE: make both multipliers config values and tune from a metric (route regenerations per 1k env steps). + if (env->target_type == TARGET_STATIC) { + min_route_distance = env->max_waypoint_spacing * num_target_waypoints * 2.0f; + } else { + min_route_distance = env->min_waypoint_spacing * num_target_waypoints * 20.0f; + } + + int temp_route[MAX_ROUTE_LENGTH]; + int route_length = generate_random_route(env, current_lane_id, min_route_distance, temp_route, MAX_ROUTE_LENGTH, + agent->sim_x, agent->sim_y); + + if (route_length == 0) { + printf("[GIGAFLOW WARNING] -> Failed to generate route for agent %d\n", agent->id); + agent->removed = 1; + return 0; + } + + // Free old route and allocate new one + if (agent->route != NULL) + free(agent->route); + + agent->route_length = route_length; + agent->route = (int *)malloc(route_length * sizeof(int)); + + for (int i = 0; i < route_length; i++) { + agent->route[i] = temp_route[i]; + } + + agent->current_route_index = 0; + + // Update path + build_path(env, agent_idx); + agent->closest_path_idx_wp = 0; // Reset before search (old index invalid on new path) + reset_agent_path_progression(env, agent_idx); + + return 1; // Success +} + +static void compute_goals(Drive *env, int agent_idx) { + Agent *agent = &env->agents[agent_idx]; + struct Path *path = agent->path; + + // Validate path exists + if (path == NULL || path->num_waypoints == 0) { + printf("[GIGAFLOW WARNING] -> Agent %d has no valid path\n", agent->id); + agent->removed = 1; + return; + } + + int num_target_waypoints = env->num_target_waypoints; + // Validate waypoint count in bounds + if (num_target_waypoints <= 0 || num_target_waypoints > MAX_TARGET_WAYPOINTS) { + num_target_waypoints = MAX_TARGET_WAYPOINTS; + } + + float goal_spacings[MAX_TARGET_WAYPOINTS]; + + // Iterative replacement for former recursion (bounded at 4 retries) + for (int iter = 0; iter <= 4; iter++) { + float total_spacing = 0.0f; + for (int i = 0; i < num_target_waypoints; i++) { + goal_spacings[i] = random_uniform(env->min_waypoint_spacing, env->max_waypoint_spacing); + total_spacing += goal_spacings[i]; + } + + // On iter 3, reset to path start to escape a short-path cycle + int base_idx = (iter == 3) ? 0 : get_closest_waypoint_index_on_path(env, agent_idx); + float base_s = path->waypoints[base_idx].s; + float needed_s = base_s + total_spacing; + float path_end_s = path->waypoints[path->num_waypoints - 1].s; + + // If we reached the end of the current path, compute a new route and retry. + // Bounded by iter <= 4 to prevent infinite loops on degenerate maps. + if (needed_s >= path_end_s) { + if (iter > 3) { + printf("[GIGAFLOW WARNING] -> Max iterations in compute_goals for agent %d\n", agent->id); + agent->removed = 1; + return; + } + if (env->simulation_mode == SIMULATION_GIGAFLOW) { + int route_ok = compute_new_route(env, agent_idx, path->waypoints[base_idx].lane_id); + if (route_ok == 0) { + agent->removed = 1; + return; + } + path = agent->path; + continue; + } + } + + // Place N goals along the path at random spacing intervals from current position + float cumulative_spacing = 0.0f; + for (int i = 0; i < num_target_waypoints; i++) { + cumulative_spacing += goal_spacings[i]; + float target_s = base_s + cumulative_spacing; + // Find waypoint at or past target_s + int wp_idx = path->num_waypoints - 1; + for (int j = base_idx + 1; j < path->num_waypoints; j++) { + if (path->waypoints[j].s >= target_s) { + wp_idx = j; + break; + } + } + agent->goal_positions_x[i] = path->waypoints[wp_idx].x; + agent->goal_positions_y[i] = path->waypoints[wp_idx].y; + agent->goal_positions_z[i] = path->waypoints[wp_idx].z; + } + + // Reset goal index and update alias + agent->current_goal_idx = 0; + agent->goal_position_x = agent->goal_positions_x[0]; + agent->goal_position_y = agent->goal_positions_y[0]; + agent->goal_position_z = agent->goal_positions_z[0]; + return; + } + + printf("[GIGAFLOW ERROR] -> Failed to compute goals for agent %d after multiple attempts\n", agent->id); + agent->removed = 1; +} + +// ======================================== +// Metrics/Collision Functions +// ======================================== + +static float compute_displacement_error(Agent *agent, int timestep) { + // Check if timestep is within valid range + if (timestep < 0 || timestep >= agent->trajectory_length) { + return 0.0f; + } + + // Check if reference trajectory is valid at this timestep + if (!agent->log_valid[timestep]) { + return 0.0f; + } + + // Get reference position from logged trajectory at current timestep + float ref_x = agent->log_trajectory_x[timestep]; + float ref_y = agent->log_trajectory_y[timestep]; + + if (ref_x == INVALID_POSITION || ref_y == INVALID_POSITION) { + return 0.0f; + } + + // Compute deltas: Euclidean distance between simulated and reference position + float dx = agent->sim_x - ref_x; + float dy = agent->sim_y - ref_y; + float displacement = sqrtf(dx * dx + dy * dy); + + return displacement; +} + +static bool check_line_intersection(float p1[2], float p2[2], float q1[2], float q2[2]) { + if (fmaxf(p1[0], p2[0]) < fminf(q1[0], q2[0]) || fminf(p1[0], p2[0]) > fmaxf(q1[0], q2[0]) || + fmaxf(p1[1], p2[1]) < fminf(q1[1], q2[1]) || fminf(p1[1], p2[1]) > fmaxf(q1[1], q2[1])) + return false; + + // Calculate vectors + float dx1 = p2[0] - p1[0]; + float dy1 = p2[1] - p1[1]; + float dx2 = q2[0] - q1[0]; + float dy2 = q2[1] - q1[1]; + + // Calculate cross products + float cross = dx1 * dy2 - dy1 * dx2; + + // If lines are parallel + if (cross == 0) + return false; + + // Calculate relative vectors between start points + float dx3 = p1[0] - q1[0]; + float dy3 = p1[1] - q1[1]; + + // Calculate parameters for intersection point + float s = (dx1 * dy3 - dy1 * dx3) / cross; + float t = (dx2 * dy3 - dy2 * dx3) / cross; + + // Check if intersection point lies within both line segments + return (s >= 0 && s <= 1 && t >= 0 && t <= 1); +} + +static bool check_stop_line_crossing(Drive *env, Agent *agent, int current_lane_id, float corners[4][2]) { + float agent_x = agent->sim_x; + float agent_y = agent->sim_y; + + for (int i = 0; i < env->num_traffic_elements; i++) { + TrafficControlElement *traffic = &env->traffic_elements[i]; + + if (traffic->type != TRAFFIC_LIGHT) + continue; + if (traffic->num_controlled_lanes == 0) + continue; + + int controls_lane = 0; + for (int j = 0; j < traffic->num_controlled_lanes; j++) { + if (traffic->controlled_lanes[j] == current_lane_id) { + controls_lane = 1; + break; + } + } + if (!controls_lane) + continue; + if (env->timestep >= traffic->state_length) + continue; + if (!is_traffic_light_red(traffic->states[env->timestep])) + continue; + + // Pre-filter: distance to stop line midpoint + float mid_x = (traffic->stop_line[0] + traffic->stop_line[3]) * 0.5f; + float mid_y = (traffic->stop_line[1] + traffic->stop_line[4]) * 0.5f; + float dx = agent_x - mid_x; + float dy = agent_y - mid_y; + if (dx * dx + dy * dy > TRAFFIC_LIGHT_DISTANCE_THRESHOLD * TRAFFIC_LIGHT_DISTANCE_THRESHOLD) + continue; + + // Heading check: agent must be heading towards the stop line + float heading_diff = compute_heading_diff(agent->sim_heading, traffic->heading); + if (fabsf(heading_diff) > RED_LIGHT_HEADING_THRESHOLD) + continue; + + // Extend stop line endpoints by STOP_LINE_EXTENSION_FACTOR + float sl_dx = traffic->stop_line[3] - traffic->stop_line[0]; + float sl_dy = traffic->stop_line[4] - traffic->stop_line[1]; + float ext = (STOP_LINE_EXTENSION_FACTOR - 1.0f) * 0.5f; + float ext_p1[2] = {traffic->stop_line[0] - ext * sl_dx, traffic->stop_line[1] - ext * sl_dy}; + float ext_p2[2] = {traffic->stop_line[3] + ext * sl_dx, traffic->stop_line[4] + ext * sl_dy}; + + // Check front + side edges vs extended stop line (skip back edge k=2) + for (int k = 0; k < 4; k++) { + if (k == 2) + continue; + int next = (k + 1) % 4; + if (check_line_intersection(corners[k], corners[next], ext_p1, ext_p2)) + return true; + } + } + return false; +} + +static bool check_lane_change_red_light(Drive *env, Agent *agent) { + if (agent->previous_lane_index == agent->current_lane_index) + return false; + if (agent->previous_lane_index == -1 || agent->current_lane_index == -1) + return false; + + int new_lane_id = env->road_elements[agent->current_lane_index].id; + float agent_x = agent->sim_x; + float agent_y = agent->sim_y; + + for (int i = 0; i < env->num_traffic_elements; i++) { + TrafficControlElement *traffic = &env->traffic_elements[i]; + + if (traffic->type != TRAFFIC_LIGHT) + continue; + if (traffic->num_controlled_lanes == 0) + continue; + if (env->timestep >= traffic->state_length) + continue; + if (!is_traffic_light_red(traffic->states[env->timestep])) + continue; + + for (int j = 0; j < traffic->num_controlled_lanes; j++) { + if (traffic->controlled_lanes[j] != new_lane_id) + continue; + + float mid_x = (traffic->stop_line[0] + traffic->stop_line[3]) * 0.5f; + float mid_y = (traffic->stop_line[1] + traffic->stop_line[4]) * 0.5f; + float dx = agent_x - mid_x; + float dy = agent_y - mid_y; + if (dx * dx + dy * dy > TRAFFIC_LIGHT_DISTANCE_THRESHOLD * TRAFFIC_LIGHT_DISTANCE_THRESHOLD) + continue; + + return true; + } + } + return false; +} + +static bool check_red_light_violation(Drive *env, int agent_idx) { + Agent *agent = &env->agents[agent_idx]; + int current_lane_index = agent->current_lane_index; + + if (current_lane_index == -1) + return false; + + // Compute bounding box corners: front-right(0), front-left(1), back-left(2), back-right(3) + static const float offsets[4][2] = {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}}; + float half_length = agent->sim_length / 2.0f; + float half_width = agent->sim_width / 2.0f; + float corners[4][2]; + for (int i = 0; i < 4; i++) { + corners[i][0] = agent->sim_x + (offsets[i][0] * half_length * agent->cos_heading - + offsets[i][1] * half_width * agent->sin_heading); + corners[i][1] = agent->sim_y + (offsets[i][0] * half_length * agent->sin_heading + + offsets[i][1] * half_width * agent->cos_heading); + } + + int current_lane_id = env->road_elements[current_lane_index].id; + + if (check_stop_line_crossing(env, agent, current_lane_id, corners)) + return true; + + if (check_lane_change_red_light(env, agent)) + return true; + + return false; +} + +// OBB collision via SAT (Separating Axis Theorem). +// Projects both boxes onto 4 axes (2 per car) and checks for overlap on all axes. +// No epsilon tolerance: exact boundary contact may flicker across steps. +static bool check_obb_collision(Agent *car1, Agent *car2) { + // Get car corners in world space + float cos1 = car1->cos_heading; + float sin1 = car1->sin_heading; + + float cos2 = car2->cos_heading; + float sin2 = car2->sin_heading; + + // Calculate half dimensions + float half_len1 = car1->sim_length * 0.5f; + float half_width1 = car1->sim_width * 0.5f; + float half_len2 = car2->sim_length * 0.5f; + float half_width2 = car2->sim_width * 0.5f; + + // Calculate car1's corners in world space + float car1_corners[4][2] = { + {car1->sim_x + (half_len1 * cos1 - half_width1 * sin1), car1->sim_y + (half_len1 * sin1 + half_width1 * cos1)}, + {car1->sim_x + (half_len1 * cos1 + half_width1 * sin1), car1->sim_y + (half_len1 * sin1 - half_width1 * cos1)}, + {car1->sim_x + (-half_len1 * cos1 - half_width1 * sin1), + car1->sim_y + (-half_len1 * sin1 + half_width1 * cos1)}, + {car1->sim_x + (-half_len1 * cos1 + half_width1 * sin1), + car1->sim_y + (-half_len1 * sin1 - half_width1 * cos1)}}; + + // Calculate car2's corners in world space + float car2_corners[4][2] = { + {car2->sim_x + (half_len2 * cos2 - half_width2 * sin2), car2->sim_y + (half_len2 * sin2 + half_width2 * cos2)}, + {car2->sim_x + (half_len2 * cos2 + half_width2 * sin2), car2->sim_y + (half_len2 * sin2 - half_width2 * cos2)}, + {car2->sim_x + (-half_len2 * cos2 - half_width2 * sin2), + car2->sim_y + (-half_len2 * sin2 + half_width2 * cos2)}, + {car2->sim_x + (-half_len2 * cos2 + half_width2 * sin2), + car2->sim_y + (-half_len2 * sin2 - half_width2 * cos2)}}; + + // Get the axes to check (normalized vectors perpendicular to each edge) + float axes[4][2] = { + {cos1, sin1}, // Car1's length axis + {-sin1, cos1}, // Car1's width axis + {cos2, sin2}, // Car2's length axis + {-sin2, cos2} // Car2's width axis + }; + + // Check each axis + for (int i = 0; i < 4; i++) { + float min1 = INFINITY, max1 = -INFINITY; + float min2 = INFINITY, max2 = -INFINITY; + + // Project car1's corners onto the axis + for (int j = 0; j < 4; j++) { + float proj = car1_corners[j][0] * axes[i][0] + car1_corners[j][1] * axes[i][1]; + min1 = fminf(min1, proj); + max1 = fmaxf(max1, proj); + } + + // Project car2's corners onto the axis + for (int j = 0; j < 4; j++) { + float proj = car2_corners[j][0] * axes[i][0] + car2_corners[j][1] * axes[i][1]; + min2 = fminf(min2, proj); + max2 = fmaxf(max2, proj); + } + + // If there's a gap on this axis, the boxes don't intersect + if (max1 < min2 || min1 > max2) { + return false; // No collision + } + } + + // If we get here, there's no separating axis, so the boxes intersect + return true; +} + +static bool check_z_collision_possibility(const Agent *car1, const Agent *car2) { + float car1_bottom = car1->sim_z; + float car1_top = car1->sim_z + car1->sim_height; + float car2_bottom = car2->sim_z; + float car2_top = car2->sim_z + car2->sim_height; + + return !(car1_top < car2_bottom || car2_top < car1_bottom); +} + +static int collision_check(Drive *env, int agent_idx) { + Agent *agent = &env->agents[agent_idx]; + + if (agent->sim_x == INVALID_POSITION || agent->removed) + return -1; + + int car_collided_with_index = -1; + + // O(N) linear scan over all agents (active + static); no spatial grid used here. + // COLLISION_QUICK_CHECK_DIST (15m) is the real bottleneck — the 5m-cell grid + // neighborhood covers ~50m but this quick check prunes at 15m. + for (int i = 0; i < env->num_agents; i++) { + int index = -1; + if (i < env->active_agent_count) { + index = env->active_agent_indices[i]; + } else { + index = env->static_agent_indices[i - env->active_agent_count]; + } + if (index == -1) + continue; + if (index == agent_idx) + continue; + + Agent *other_agent = &env->agents[index]; + + float dist_sq = ((other_agent->sim_x - agent->sim_x) * (other_agent->sim_x - agent->sim_x) + + (other_agent->sim_y - agent->sim_y) * (other_agent->sim_y - agent->sim_y)); + if (dist_sq > COLLISION_QUICK_CHECK_DIST * COLLISION_QUICK_CHECK_DIST) + continue; + if (!check_z_collision_possibility(agent, other_agent)) + continue; + if (check_obb_collision(agent, other_agent)) { + car_collided_with_index = index; + break; + } + } + + return car_collided_with_index; +} + +// Classify whether a collision is at-fault for the ego agent. +static bool is_at_fault_collision(Drive *env, int agent_idx, int other_idx) { + Agent *agent = &env->agents[agent_idx]; + Agent *other = &env->agents[other_idx]; + + // Rule 1: Collision with stopped vehicle = always at-fault. + if (other->sim_speed < AGENT_STOPPED_SPEED_THRESHOLD) + return true; + + // Rule 2: If ego is stopped = never at-fault. + if (agent->sim_speed < AGENT_STOPPED_SPEED_THRESHOLD) + return false; + + // Rule 3: Rear-bumper collision = not at-fault. + // Check if the other car hit our rear using the heading-aligned relative position. + float dx = other->sim_x - agent->sim_x; + float dy = other->sim_y - agent->sim_y; + float dot = dx * agent->cos_heading + dy * agent->sin_heading; + if (dot < 0) + return false; + + return true; +} + +static inline struct ttc_result default_ttc_result(void) { + return (struct ttc_result){DEFAULT_TTC, -1, INFINITY, 0.0f}; +} + +static inline void ttc_update_min_result(Agent *ego, int other_idx, float distance_to_collision, float closing_speed, + float ttc) { + if (ttc < ego->cached_ttc.min_ttc) { + ego->cached_ttc.min_ttc = ttc; + ego->cached_ttc.other_idx = other_idx; + ego->cached_ttc.distance_to_collision = distance_to_collision; + ego->cached_ttc.closing_speed = closing_speed; + } +} + +// Compute TTC using ego front and other rear points with ahead and lateral corridor filters. +static inline void compute_pairwise_ttc(Agent *ego, int ego_idx, Agent *other, int other_idx) { + if (other_idx == ego_idx) + return; + if (other->sim_x == INVALID_POSITION) + return; + + float ego_x = ego->sim_x; + float ego_y = ego->sim_y; + float other_x = other->sim_x; + float other_y = other->sim_y; + + float ego_heading_x = ego->cos_heading; + float ego_heading_y = ego->sin_heading; + float other_heading_x = other->cos_heading; + float other_heading_y = other->sin_heading; + + float ego_front_x = ego_x + 0.5f * ego->sim_length * ego_heading_x; + float ego_front_y = ego_y + 0.5f * ego->sim_length * ego_heading_y; + float other_rear_x = other_x - 0.5f * other->sim_length * other_heading_x; + float other_rear_y = other_y - 0.5f * other->sim_length * other_heading_y; + + float rel_x = other_rear_x - ego_front_x; + float rel_y = other_rear_y - ego_front_y; + float ahead = rel_x * ego_heading_x + rel_y * ego_heading_y; + if (ahead <= 0.0f) + return; + + float lateral = fabsf(rel_x * ego_heading_y - rel_y * ego_heading_x); + float allowed = 0.5f * (ego->sim_width + other->sim_width); + if (lateral > allowed) + return; + + float distance_to_collision = sqrtf(rel_x * rel_x + rel_y * rel_y); + float ego_radius = 0.5f * ego->sim_width; + float other_radius = 0.5f * other->sim_width; + float combined_radius = ego_radius + other_radius; + + float rel_vx = other->sim_vx - ego->sim_vx; + float rel_vy = other->sim_vy - ego->sim_vy; + float a = rel_vx * rel_vx + rel_vy * rel_vy; + float c = rel_x * rel_x + rel_y * rel_y - combined_radius * combined_radius; + if (c <= 0.0f) { + ttc_update_min_result(ego, other_idx, distance_to_collision, INFINITY, 0.0f); + return; + } + if (a < 1e-6f) + return; + + float b = 2.0f * (rel_x * rel_vx + rel_y * rel_vy); + float disc = b * b - 4.0f * a * c; + if (disc < 0.0f) + return; + + float sqrt_disc = sqrtf(disc); + float inv_two_a = 0.5f / a; + float t1 = (-b - sqrt_disc) * inv_two_a; + float t2 = (-b + sqrt_disc) * inv_two_a; + float ttc = INFINITY; + if (t1 > 0.0f) { + ttc = t1; + } else if (t2 > 0.0f) { + ttc = t2; + } + if (!isfinite(ttc)) + return; + + float closing_speed = sqrtf(a); + ttc_update_min_result(ego, other_idx, distance_to_collision, closing_speed, ttc); +} + +// Compute TTC for a single ego agent against all other agents using ahead and lateral filters. +static void compute_agent_ttc(Drive *env, int ego_idx) { + Agent *ego = &env->agents[ego_idx]; + ego->cached_ttc = default_ttc_result(); + + if (ego->sim_x == INVALID_POSITION) + return; + + for (int j = 0; j < env->num_agents; j++) { + int other_idx; + if (j < env->active_agent_count) { + other_idx = env->active_agent_indices[j]; + } else { + other_idx = env->static_agent_indices[j - env->active_agent_count]; + } + if (other_idx == -1) + continue; + compute_pairwise_ttc(ego, ego_idx, &env->agents[other_idx], other_idx); + } +} + +// Puffer score computation +// Uses hybrid weighted average: multiplier weights (binary gates) + average weights (continuous) +static float calculate_puffer_score(Log *log_agent, int scenario_length, float dt) { + if (!log_agent) { + return 0.0f; + } + + float T = scenario_length * dt; + if (T <= 0.0f) + T = 1.0f; // Avoid division by zero + + float no_at_fault = (log_agent->at_fault_collision_rate > 0) ? 0.0f : 1.0f; + float no_offroad = (log_agent->offroad_rate > 0) ? 0.0f : 1.0f; + float no_red_light = (log_agent->red_light_violation_rate > 0) ? 0.0f : 1.0f; + float making_progress = (log_agent->progress_ratio > 0.2f) ? 1.0f : 0.0f; + + // Driving direction: 1.0 if <=2m, 0.5 if 2-6m, 0 if >6m wrong-way distance + float wrong_dist = log_agent->wrong_way_distance; + float direction_compliance = (wrong_dist <= 2.0f) ? 1.0f : (wrong_dist <= 6.0f) ? 0.5f : 0.0f; + + float multiplier = no_at_fault * no_offroad * no_red_light * making_progress * direction_compliance; + + if (multiplier == 0.0f) + return 0.0f; + + // TTC within bound (>0.95s): weight 5 + float ttc_score = log_agent->ttc_within_bound_rate; // Already 0-1 + + // Progress ratio (capped at 1): weight 5 + float progress_score = fminf(log_agent->progress_ratio, 1.0f); + + // Speed compliance (nuPlan formula): max(0, 1 - sum(violation * dt) / T): weight 4 + float speed_threshold = fmaxf(T, 1e-3f); + float speed_score = fmaxf(0.0f, 1.0f - log_agent->speed_violation_sum / speed_threshold); + + // Comfort (binary per episode): weight 2 + float comfort_score = log_agent->comfort_score; // 0 or 1 + + // Multi-lane (weight 3): tiered score based on accumulated time + float multi_lane_score = log_agent->multi_lane_score; + + // Weighted average + float weighted_sum = + 5 * ttc_score + 5 * progress_score + 4 * speed_score + 3 * multi_lane_score + 2 * comfort_score; + float total_weight = 5 + 5 + 4 + 3 + 2; // = 19 + + return multiplier * (weighted_sum / total_weight); +} + +static void add_log(Drive *env) { + int safe_timestep = (env->timestep > 0) ? env->timestep : 1; + const float progress_ref_speed = 10.0f; + for (int i = 0; i < env->active_agent_count; i++) { + Agent *agent = &env->agents[env->active_agent_indices[i]]; + float episode_duration_s = env->logs[i].episode_length * env->dt; + float reference_progress_distance = progress_ref_speed * episode_duration_s; + reference_progress_distance = fmaxf(reference_progress_distance, 1.0f); + env->logs[i].progress_ratio = agent->distance_since_spawn / reference_progress_distance; + + int offroad = env->logs[i].offroad_rate; + env->log.offroad_rate += offroad; + int collided = env->logs[i].collision_rate; + env->log.collision_rate += collided; + int red_light_violations = env->logs[i].red_light_violation_rate; + env->log.red_light_violation_rate += red_light_violations; + int total_infractions = (offroad || collided || red_light_violations) ? 1 : 0; + float avg_speed_per_agent = env->logs[i].avg_speed_per_agent; + env->log.avg_speed_per_agent += avg_speed_per_agent / safe_timestep; + int num_waypoints_reached = env->logs[i].num_waypoints_reached; + env->log.num_waypoints_reached += num_waypoints_reached; + int num_goals_reached = env->logs[i].num_goals_reached; + env->log.num_goals_reached += num_goals_reached; + // TODO: define better scoring criteria ? + if (num_goals_reached >= 1 && !agent->removed && !agent->stopped) { + env->log.score += 1.0f; + } + if (!offroad && !collided && !red_light_violations && num_waypoints_reached < 1) { + env->log.dnf_rate += 1.0f; + } + env->log.total_distance_travelled += agent->distance_since_spawn; + if (total_infractions > 0) { + env->log.total_infractions += 1.0f; + } + float displacement_error = env->logs[i].avg_displacement_error; + env->log.avg_displacement_error += displacement_error; + env->log.episode_length += env->logs[i].episode_length; + env->log.episode_return += env->logs[i].episode_return; + // Comfort and velocity metrics (normalized per timestep) + env->log.comfort_violation_count += env->logs[i].comfort_violation_count / safe_timestep; + env->log.velocity_progress_sum += env->logs[i].velocity_progress_sum / safe_timestep; + // Lane metrics (normalized per timestep for average per episode) + env->log.lane_center_rate += env->logs[i].lane_center_rate / safe_timestep; + env->log.lane_heading_aligned_rate += env->logs[i].lane_heading_aligned_rate / safe_timestep; + if (env->compute_eval_metrics) { + env->logs[i].progress_ratio = agent->distance_since_spawn / reference_progress_distance; + env->log.at_fault_collision_rate += env->logs[i].at_fault_collision_rate; + env->log.ttc_within_bound_rate += env->logs[i].ttc_within_bound_rate; + env->log.wrong_way_distance += env->logs[i].wrong_way_distance; + env->log.speed_violation_sum += env->logs[i].speed_violation_sum; + env->log.progress_ratio += env->logs[i].progress_ratio; + env->log.comfort_score += env->logs[i].comfort_score; + env->log.ttc_violations += env->logs[i].ttc_violations; + env->log.ttc_samples += env->logs[i].ttc_samples; + env->log.multi_lane_time += env->logs[i].multi_lane_time; + env->log.multi_lane_score += env->logs[i].multi_lane_score; + + float wrong_dist = env->logs[i].wrong_way_distance; + float direction_score = (wrong_dist <= 2.0f) ? 1.0f : (wrong_dist <= 6.0f) ? 0.5f : 0.0f; + env->log.driving_direction_score += direction_score; + + float T = safe_timestep * env->dt; + float speed_compliance = fmaxf(0.0f, 1.0f - env->logs[i].speed_violation_sum / fmaxf(T, 1e-3f)); + env->log.speed_limit_compliance += speed_compliance; + + float making_progress = (env->logs[i].progress_ratio > 0.2f) ? 1.0f : 0.0f; + env->log.making_progress_rate += making_progress; + env->log.puffer_score += calculate_puffer_score(&env->logs[i], safe_timestep, env->dt); + } + + env->log.n += 1; + } + // Log composition counts per agent so vec_log averaging recovers the per-env value + env->log.expert_static_car_count += env->expert_static_agent_count; + env->log.static_car_count += env->static_agent_count; +} + +// ======================================== +// Initialization Functions +// ======================================== + +static void reset_agent_metrics(Drive *env, int agent_idx) { + Agent *agent = &env->agents[agent_idx]; + for (int i = 0; i < NUM_METRICS; i++) { + agent->metrics_array[i] = 0.0f; + } +} + +static void reset_agent_state(Agent *agent) { + agent->cumulative_displacement = 0.0f; + agent->displacement_sample_count = 0; + agent->stopped = 0; + agent->removed = 0; + agent->current_lane_index = -1; + agent->previous_lane_index = -1; + agent->current_route_index = 0; + agent->a_long = 0.0f; + agent->a_lat = 0.0f; + agent->jerk_long = 0.0f; + agent->jerk_lat = 0.0f; + agent->steering_angle = 0.0f; + agent->path_progression = 0.0f; + agent->distance_since_spawn = 0.0f; + agent->closest_path_idx_wp = 0; + // Puffer score tracking reset + agent->wrong_way_distance = 0.0f; + agent->speed_violation_sum = 0.0f; + agent->cached_ttc = default_ttc_result(); + agent->ttc_violations = 0; + agent->ttc_samples = 0; + agent->at_fault_collision = 0; + agent->multi_lane_time = 0.0f; +} + +// Check if a spawn position collides with any existing agent +static bool check_spawn_collision(Drive *env, int num_existing_agents, float spawn_x, float spawn_y, float spawn_z, + float spawn_heading, float spawn_length, float spawn_width, float spawn_height) { + // Create a temporary agent structure for collision checking + Agent temp_agent; + temp_agent.sim_x = spawn_x; + temp_agent.sim_y = spawn_y; + temp_agent.sim_z = spawn_z; + temp_agent.sim_heading = spawn_heading; + temp_agent.cos_heading = cosf(spawn_heading); + temp_agent.sin_heading = sinf(spawn_heading); + temp_agent.yaw_rate = 0.0f; + temp_agent.sim_length = spawn_length; + temp_agent.sim_width = spawn_width; + temp_agent.sim_height = spawn_height; + + // Minimum safe distance + float min_safe_dist_sq = (spawn_length + 5.0f) * (spawn_length + 5.0f); + + for (int i = 0; i < num_existing_agents; i++) { + Agent *other = &env->agents[i]; + + // Skip invalid agents + if (other->sim_x == INVALID_POSITION || other->sim_valid != 1) + continue; + + // Quick distance check first + float dx = other->sim_x - spawn_x; + float dy = other->sim_y - spawn_y; + float dist_sq = dx * dx + dy * dy; + + if (dist_sq > min_safe_dist_sq) + continue; + if (!check_z_collision_possibility(&temp_agent, other)) + continue; + if (check_obb_collision(&temp_agent, other)) + return true; // Collision detected + } + + return false; // No collision +} + +static bool check_spawn_offroad(Drive *env, float spawn_x, float spawn_y, float spawn_heading, float spawn_length, + float spawn_width, float spawn_z) { + // Compute bounding box corners (same as offroad detection in step) + static const float offsets[4][2] = {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}}; + // Increase length and width slightly for spawn offroad check + float half_length = (spawn_length * 1.1f) / 2.0f; + float half_width = (spawn_width * 1.1f) / 2.0f; + float cos_heading = cosf(spawn_heading); + float sin_heading = sinf(spawn_heading); + + float corners[4][2]; + for (int i = 0; i < 4; i++) { + corners[i][0] = + spawn_x + (offsets[i][0] * half_length * cos_heading - offsets[i][1] * half_width * sin_heading); + corners[i][1] = + spawn_y + (offsets[i][0] * half_length * sin_heading + offsets[i][1] * half_width * cos_heading); + } + + // Get neighboring road elements + GridMapEntity entity_list[MAX_ENTITIES_PER_CELL * 25]; + int list_size = + get_neighbors_entities(env, spawn_x, spawn_y, entity_list, MAX_ENTITIES_PER_CELL * 25, collision_offsets, 25); + + // Check intersection with road edges + for (int i = 0; i < list_size; i++) { + if (entity_list[i].entity_type != ENTITY_TYPE_ROAD_ELEMENT) + continue; + + int entity_idx = entity_list[i].entity_idx; + int geometry_idx = entity_list[i].geometry_idx; + RoadMapElement *element = &env->road_elements[entity_idx]; + + if (is_road_edge(element->type)) { + float abs_dz = fabsf(element->z[geometry_idx] - spawn_z); + if (abs_dz > Z_BUFFER) + continue; + float start[2] = {element->x[geometry_idx], element->y[geometry_idx]}; + float end[2] = {element->x[geometry_idx + 1], element->y[geometry_idx + 1]}; + for (int k = 0; k < 4; k++) { + int next = (k + 1) % 4; + if (check_line_intersection(corners[k], corners[next], start, end)) + return true; // Offroad detected + } + } + } + return false; +} + +static bool check_spawn_red_light_violation(Drive *env, float spawn_x, float spawn_y, float spawn_z, + float spawn_heading, float spawn_length, float spawn_width, + float spawn_height, int lane_id) { + Agent temp_agent; + temp_agent.sim_x = spawn_x; + temp_agent.sim_y = spawn_y; + temp_agent.sim_z = spawn_z; + temp_agent.sim_heading = spawn_heading; + temp_agent.cos_heading = cosf(spawn_heading); + temp_agent.sin_heading = sinf(spawn_heading); + temp_agent.sim_length = spawn_length; + temp_agent.sim_width = spawn_width; + temp_agent.sim_height = spawn_height; + + static const float offsets[4][2] = {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}}; + float half_length = spawn_length / 2.0f; + float half_width = spawn_width / 2.0f; + float corners[4][2]; + for (int i = 0; i < 4; i++) { + corners[i][0] = spawn_x + (offsets[i][0] * half_length * temp_agent.cos_heading - + offsets[i][1] * half_width * temp_agent.sin_heading); + corners[i][1] = spawn_y + (offsets[i][0] * half_length * temp_agent.sin_heading + + offsets[i][1] * half_width * temp_agent.cos_heading); + } + + return check_stop_line_crossing(env, &temp_agent, lane_id, corners); +} + +// NOTE: type of function -> void, int, bool ? +static int spawn_agent(Drive *env, int agent_idx, int num_agents) { + Agent *agent = &env->agents[agent_idx]; + + // Free existing route on reset + if (agent->route != NULL) { + free(agent->route); + agent->route = NULL; + } + + // Initialize identity fields + agent->id = agent_idx; + agent->type = VEHICLE; + agent->active_agent = 1; + agent->mark_as_expert = 0; + + // Default vehicle dimensions + // length: [0.8, 7.0] m + // width: [0.8, 3.0] m + // width = min(width, length) + float spawn_length, spawn_width; + if (env->eval_mode) { + // Fixed size for eval mode + spawn_length = random_uniform(2.0f, 5.5f); + spawn_width = random_uniform(1.5f, 2.5f); + } else { + // Random size for training mode + spawn_length = random_uniform(0.8f, 7.0f); + spawn_width = random_uniform(0.8f, 3.0f); + } + if (spawn_width > spawn_length) + spawn_width = spawn_length; + float spawn_height = 1.5f; // Fixed height + + // Set spawn position on start lane + float spawn_x, spawn_y, spawn_z, spawn_heading; + RoadMapElement *start_lane; + int start_lane_idx; + int success = 0; + + // Sampling rejection loop + // TARGET: Only one attempt should be sufficient in most cases + const int MAX_SPAWN_ATTEMPTS = 30; + for (int attempt = 0; attempt < MAX_SPAWN_ATTEMPTS; attempt++) { + int chosen_lane_idx = -1; + + int list_idx = rand() % env->grid_map->num_drivable_grid_cell; + int grid_idx = env->grid_map->grid_index_drivable[list_idx]; + + GridMapEntity cell_candidates[MAX_ENTITIES_PER_CELL]; + int candidate_count = 0; + + for (int i = 0; i < env->grid_map->cell_entities_count[grid_idx]; i++) { + GridMapEntity entity = env->grid_map->cells[grid_idx][i]; + + if (entity.entity_type == ENTITY_TYPE_ROAD_ELEMENT) { + if (is_drivable_road_lane(env->road_elements[entity.entity_idx].type)) { + cell_candidates[candidate_count++] = entity; + } + } + } + + if (candidate_count == 0) + continue; + + GridMapEntity chosen_entity = cell_candidates[rand() % candidate_count]; + chosen_lane_idx = chosen_entity.entity_idx; + + start_lane_idx = chosen_lane_idx; + start_lane = &env->road_elements[start_lane_idx]; + + spawn_x = start_lane->x[chosen_entity.geometry_idx]; + spawn_y = start_lane->y[chosen_entity.geometry_idx]; + spawn_z = start_lane->z[chosen_entity.geometry_idx]; + spawn_heading = start_lane->headings[chosen_entity.geometry_idx]; + + // Check for collision with existing/already-reset agents + if (check_spawn_collision(env, num_agents, spawn_x, spawn_y, spawn_z, spawn_heading, spawn_length, spawn_width, + spawn_height)) + continue; + + // Check for offroad (vehicle corners intersecting road edges) + if (check_spawn_offroad(env, spawn_x, spawn_y, spawn_heading, spawn_length, spawn_width, spawn_z)) + continue; + + // Check for red light violation at spawn (vehicle corners intersecting stop lines) + if (check_spawn_red_light_violation(env, spawn_x, spawn_y, spawn_z, spawn_heading, spawn_length, spawn_width, + spawn_height, start_lane->id)) + continue; + + success = 1; + break; + } + + if (!success) { + printf("[GIGAFLOW WARNING] -> Failed to find a collision-free spawn position for agent %d\n", agent->id); + return 0; // Failed to find collision-free spawn + } + + // Update simulation state + agent->sim_x = spawn_x; + agent->sim_y = spawn_y; + agent->sim_z = spawn_z; + agent->sim_heading = spawn_heading; + agent->cos_heading = cosf(spawn_heading); + agent->sin_heading = sinf(spawn_heading); + agent->sim_length = spawn_length; + agent->sim_width = spawn_width; + agent->sim_height = spawn_height; + agent->sim_valid = 1; + agent->wheelbase = 0.6f * spawn_length; + + float spawn_speed = clip(env->spawn_initial_speed, 0.0f, MAX_SPEED); + agent->sim_vx = spawn_speed * agent->cos_heading; + agent->sim_vy = spawn_speed * agent->sin_heading; + agent->yaw_rate = 0.0f; + update_agent_speed(agent); + + // Compute initial route + if (!compute_new_route(env, agent_idx, start_lane->id)) { + printf("[GIGAFLOW WARNING] -> Failed to compute a new route for agent %d\n", agent->id); + return 0; // Failed to compute new goal + } + + // Compute initial goal + compute_goals(env, agent_idx); + + return 1; // Success +} + +static void set_start_position(Drive *env) { + bool is_log_replay = (env->control_mode == CONTROL_SDC_ONLY); + + for (int i = 0; i < env->num_total_agents; i++) { + int is_active = 0; + for (int j = 0; j < env->active_agent_count; j++) { + if (env->active_agent_indices[j] == i) { + is_active = 1; + break; + } + } + Agent *agent = &env->agents[i]; + + // Initialize simulation trajectory from logged trajectory at init_steps + if (env->simulation_mode == SIMULATION_REPLAY) { + // Clamp init_steps to ensure we don't go out of bounds + int step = env->init_steps; + if (step >= agent->trajectory_length) + step = agent->trajectory_length - 1; + if (step < 0) + step = 0; + + // For agents invalid at init_steps, set INVALID_POSITION + // move_expert will update them when they become valid + if (agent->log_valid[step] != 1) { + invalidate_agent(agent); + agent->sim_length = agent->log_length[step]; + agent->sim_width = agent->log_width[step]; + agent->sim_height = agent->log_height[step]; + continue; + } + + agent->sim_x = agent->log_trajectory_x[step]; + agent->sim_y = agent->log_trajectory_y[step]; + agent->sim_z = agent->log_trajectory_z[step]; + agent->sim_heading = agent->log_heading[step]; + agent->cos_heading = cosf(agent->sim_heading); + agent->sin_heading = sinf(agent->sim_heading); + agent->sim_valid = agent->log_valid[step]; + agent->sim_length = agent->log_length[step]; + agent->sim_width = agent->log_width[step]; + agent->sim_height = agent->log_height[step]; + // Estimate wheelbase as 60% of length + agent->wheelbase = 0.6f * agent->sim_length; + + if (agent->type == UNKNOWN) + continue; + + if (is_active == 0) { + agent->sim_vx = 0.0f; + agent->sim_vy = 0.0f; + agent->yaw_rate = 0.0f; + agent->sim_speed = 0.0f; + agent->sim_speed_signed = 0.0f; + } else { + agent->yaw_rate = compute_log_yaw_rate(agent, step, env->dt); + agent->sim_vx = agent->log_velocity_x[step]; + agent->sim_vy = agent->log_velocity_y[step]; + update_agent_speed(agent); + } + + // Shrink width and length slightly to avoid initial collisions (not in log-replay) + if (!is_log_replay) { + agent->sim_length *= INIT_COLLISION_SHRINK_FACTOR; + agent->sim_width *= INIT_COLLISION_SHRINK_FACTOR; + } + } + + // Reset agent metrics and state + reset_agent_metrics(env, i); + reset_agent_state(agent); + generate_reward_coefs(env, agent); + } +} + +static bool should_control_agent(Drive *env, int agent_idx) { + // Check if we have room for more agents or are already at capacity + if (env->num_controllable_agents != 0 && env->active_agent_count >= env->num_controllable_agents) { + return false; + } + + Agent *agent = &env->agents[agent_idx]; + + if (env->control_mode == CONTROL_SDC_ONLY) { + return agent_idx == 0 && agent->route_length != 0; + } + + if (env->control_mode == CONTROL_WOSAC) { + for (int j = 0; j < env->num_tracks_to_predict; j++) { + if (env->tracks_to_predict[j] == agent_idx) { + return true; + } + } + return false; + } + + // Standard mode: check type, distance to goal, and expert status + bool type_is_controllable = false; + if (env->control_mode == CONTROL_VEHICLES) { + type_is_controllable = (agent->type == VEHICLE); + } else { // CONTROL_AGENTS mode + type_is_controllable = is_controllable_agent(agent->type); + } + + if (!type_is_controllable || agent->mark_as_expert) + return false; + + // Control if the agent has a route to follow + return agent->route_length != 0; +} + +void set_active_agents(Drive *env) { + // Initialize + env->active_agent_count = 0; // Policy-controlled agents + env->static_agent_count = 0; // Non-moving background agents + env->expert_static_agent_count = 0; // Expert replay agents (non-controlled) + env->num_agents = 0; // Total agents created + + // In GIGAFLOW mode, spawn agents dynamically on the map + if (env->simulation_mode == SIMULATION_GIGAFLOW) { + int num_agents_to_create = env->num_controllable_agents; + + // Initialize agents for GIGAFLOW mode + env->agents = (Agent *)calloc(num_agents_to_create, sizeof(Agent)); + + int successfully_created = 0; + for (int i = 0; i < num_agents_to_create; i++) { + // Pass the number of already successfully created agents for collision checking + if (spawn_agent(env, i, successfully_created)) { + successfully_created++; + } else { + // Failed spawn: ensure agent is properly invalidated + invalidate_agent(&env->agents[i]); + env->agents[i].removed = 1; + } + } + + env->num_total_agents = successfully_created; + + // Set up active agent indices + env->active_agent_indices = (int *)malloc(env->num_total_agents * sizeof(int)); + env->static_agent_indices = NULL; + env->expert_static_agent_indices = NULL; + + for (int i = 0; i < env->num_total_agents; i++) + env->active_agent_indices[i] = i; + + env->active_agent_count = env->num_total_agents; + env->num_agents = env->num_total_agents; + env->static_agent_count = 0; + env->expert_static_agent_count = 0; + + return; + } + + // In REPLAY mode, determine which agents to control + bool is_log_replay = (env->control_mode == CONTROL_SDC_ONLY); + // In log-replay mode, no cap on actors + int max_agents = is_log_replay ? env->num_total_agents : env->num_max_agents; + + int *active_agent_indices = (int *)malloc(max_agents * sizeof(int)); + int *static_agent_indices = (int *)malloc(max_agents * sizeof(int)); + int *expert_static_agent_indices = (int *)malloc(max_agents * sizeof(int)); + + // Iterate through entities to find agents to create and/or control + for (int i = 0; i < env->num_total_agents && env->num_agents < max_agents; i++) { + + Agent *agent = &env->agents[i]; + + // Skip if not valid at initialization + if (agent->log_valid[env->init_steps] != 1 && !is_log_replay) { + continue; + } + + // Determine if entity should be created + bool should_create = false; + if (is_log_replay) { + should_create = true; // Log-replay: all valid agents + } else if (env->init_mode == INIT_ALL_VALID) { + should_create = true; // All valid entities + } else if (env->control_mode == CONTROL_VEHICLES) { + should_create = (agent->type == VEHICLE); + } else { // Control all agents + should_create = (is_controllable_agent(agent->type)); + } + + if (!should_create) + continue; + + env->num_agents++; + + // Determine if this agent should be policy-controlled + bool is_controlled = should_control_agent(env, i); + + if (is_controlled) { + active_agent_indices[env->active_agent_count] = i; + env->active_agent_count++; + env->agents[i].active_agent = 1; + } else if (is_log_replay || env->init_mode != INIT_ONLY_CONTROLLABLE_AGENTS) { + // In log-replay mode, all non-controlled agents become expert_static + static_agent_indices[env->static_agent_count] = i; + env->static_agent_count++; + env->agents[i].active_agent = 0; + if (is_log_replay || env->agents[i].mark_as_expert == 1 || env->active_agent_count == env->num_max_agents) { + expert_static_agent_indices[env->expert_static_agent_count] = i; + env->expert_static_agent_count++; + env->agents[i].mark_as_expert = 1; + } + } + } + + // Set up initial active agents + env->active_agent_indices = (int *)malloc(env->active_agent_count * sizeof(int)); + env->static_agent_indices = (int *)malloc(env->static_agent_count * sizeof(int)); + env->expert_static_agent_indices = (int *)malloc(env->expert_static_agent_count * sizeof(int)); + for (int i = 0; i < env->active_agent_count; i++) { + env->active_agent_indices[i] = active_agent_indices[i]; + }; + for (int i = 0; i < env->static_agent_count; i++) { + env->static_agent_indices[i] = static_agent_indices[i]; + } + for (int i = 0; i < env->expert_static_agent_count; i++) { + env->expert_static_agent_indices[i] = expert_static_agent_indices[i]; + } + + // Free temporary buffers + free(active_agent_indices); + free(static_agent_indices); + free(expert_static_agent_indices); + + if (env->num_controllable_agents > 0 && env->active_agent_count != env->num_controllable_agents) { + printf("ERROR Between my_shared and init : Mismatch in active agent count: %d vs %d\n", env->active_agent_count, + env->num_controllable_agents); + } + + return; +} + +void move_expert(Drive *env, float *actions, int agent_idx) { + if (env->simulation_mode == SIMULATION_GIGAFLOW) { + printf("[GIGAFLOW ERROR] -> move_expert() called in GIGAFLOW mode\n"); + return; + } + + bool is_log_replay = (env->control_mode == CONTROL_SDC_ONLY); + + Agent *agent = &env->agents[agent_idx]; + int t = env->timestep; + + // If agent is invalid at this timestep, set simulated state to invalid + if (t < 0 || t >= agent->trajectory_length || agent->log_valid[t] == 0) { + invalidate_agent(agent); + return; + } + + // Copy from logged trajectory to simulated state + agent->sim_x = agent->log_trajectory_x[t]; + agent->sim_y = agent->log_trajectory_y[t]; + agent->sim_z = agent->log_trajectory_z[t]; + agent->sim_heading = agent->log_heading[t]; + agent->cos_heading = cosf(agent->sim_heading); + agent->sin_heading = sinf(agent->sim_heading); + agent->sim_valid = agent->log_valid[t]; + + if (is_log_replay) { + agent->sim_length = agent->log_length[t]; + agent->sim_width = agent->log_width[t]; + agent->sim_height = agent->log_height[t]; + agent->wheelbase = 0.6f * agent->sim_length; + } + + agent->yaw_rate = compute_log_yaw_rate(agent, t, env->dt); + agent->sim_vx = agent->log_velocity_x[t]; + agent->sim_vy = agent->log_velocity_y[t]; + + update_agent_speed(agent); + agent->sim_valid = agent->log_valid[t]; +} + +void remove_bad_trajectories(Drive *env) { + + if (env->control_mode == CONTROL_WOSAC) { + return; // Leave all trajectories in WOSAC control mode + } + + set_start_position(env); + int collided_agents[env->active_agent_count]; + int collided_with_indices[env->active_agent_count]; + memset(collided_agents, 0, env->active_agent_count * sizeof(int)); + for (int i = 0; i < env->active_agent_count; ++i) { + collided_with_indices[i] = -1; + } + // move experts through trajectories to check for collisions and remove as illegal agents + for (int t = 0; t < env->scenario_length; t++) { + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; + move_expert(env, env->actions, agent_idx); + } + for (int i = 0; i < env->expert_static_agent_count; i++) { + int expert_idx = env->expert_static_agent_indices[i]; + if (env->agents[expert_idx].sim_x == INVALID_POSITION) + continue; + move_expert(env, env->actions, expert_idx); } // check collisions for (int i = 0; i < env->active_agent_count; i++) { int agent_idx = env->active_agent_indices[i]; - env->entities[agent_idx].collision_state = 0; int collided_with_index = collision_check(env, agent_idx); if ((collided_with_index >= 0) && collided_agents[i] == 0) { collided_agents[i] = 1; @@ -1438,50 +3220,73 @@ void remove_bad_trajectories(Drive *env) { int static_agent_idx = env->static_agent_indices[j]; if (static_agent_idx != collided_with_indices[i]) continue; - env->entities[static_agent_idx].traj_x[0] = INVALID_POSITION; - env->entities[static_agent_idx].traj_y[0] = INVALID_POSITION; + env->agents[static_agent_idx].log_trajectory_x[0] = INVALID_POSITION; + env->agents[static_agent_idx].log_trajectory_y[0] = INVALID_POSITION; + env->agents[static_agent_idx].log_valid[0] = 0; } } env->timestep = 0; } -void init_goal_positions(Drive *env) { - for (int x = 0; x < env->active_agent_count; x++) { - int agent_idx = env->active_agent_indices[x]; - env->entities[agent_idx].init_goal_x = env->entities[agent_idx].goal_position_x; - env->entities[agent_idx].init_goal_y = env->entities[agent_idx].goal_position_y; - } -} - void init(Drive *env) { env->human_agent_idx = 0; env->timestep = 0; - env->entities = load_map_binary(env->map_name, env); - set_means(env); + load_map_binary(env->map_name, env); init_grid_map(env); - env->grid_map->vision_range = 21; // TODO: Why is this hardcoded? + env->grid_map->vision_range = 2 * VISION_HALF_RANGE + 1; init_neighbor_offsets(env); cache_neighbor_offsets(env); env->logs_capacity = 0; set_active_agents(env); env->logs_capacity = env->active_agent_count; - remove_bad_trajectories(env); + if (env->simulation_mode == SIMULATION_REPLAY) { + remove_bad_trajectories(env); + } set_start_position(env); - init_goal_positions(env); + if (env->simulation_mode == SIMULATION_GIGAFLOW) { + int steps = env->scenario_length; + if (steps > 0) { + for (int i = 0; i < env->num_traffic_elements; i++) { + TrafficControlElement *traffic = &env->traffic_elements[i]; + if (traffic->type != TRAFFIC_LIGHT) + continue; + if (traffic->states && traffic->state_length != steps) { + free(traffic->states); + traffic->states = NULL; + } + if (traffic->states == NULL) { + traffic->states = (int *)malloc(steps * sizeof(int)); + if (traffic->states == NULL) { + traffic->state_length = 0; + continue; + } + } + traffic->state_length = steps; + } + } + generate_traffic_light_states(env); + } env->logs = (Log *)calloc(env->active_agent_count, sizeof(Log)); -} -void close_client(Client *client); + if (env->simulation_mode == SIMULATION_REPLAY) { + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; + build_path(env, agent_idx); + compute_goals(env, agent_idx); + } + } +} void c_close(Drive *env) { - if (env->client != NULL) { - close_client(env->client); - env->client = NULL; - } - for (int i = 0; i < env->num_entities; i++) { - free_entity(&env->entities[i]); - } - free(env->entities); + for (int i = 0; i < env->num_total_agents; i++) + free_agent(&env->agents[i]); + for (int i = 0; i < env->num_road_elements; i++) + free_road_element(&env->road_elements[i]); + for (int i = 0; i < env->num_traffic_elements; i++) + free_traffic_element(&env->traffic_elements[i]); + free(env->agents); + free(env->road_elements); + free(env->traffic_elements); free(env->active_agent_indices); free(env->logs); // GridMap cleanup @@ -1491,6 +3296,7 @@ void c_close(Drive *env) { } free(env->grid_map->cells); free(env->grid_map->cell_entities_count); + free(env->grid_map->grid_index_drivable); free(env->neighbor_offsets); for (int i = 0; i < grid_cell_count; i++) { @@ -1501,20 +3307,50 @@ void c_close(Drive *env) { free(env->grid_map); free(env->static_agent_indices); free(env->expert_static_agent_indices); + free(env->objects_of_interest); + free(env->tracks_to_predict); + free_lane_graph(&env->lane_graph); + free(env->map_name); free(env->ini_file); - free(env->tracks_to_predict_indices); - env->tracks_to_predict_indices = NULL; +} + +static int compute_observation_size(Drive *env) { + int ego_dim = (env->dynamics_model == JERK) ? EGO_FEATURES_JERK : EGO_FEATURES_CLASSIC; + int num_target_waypoints = env->num_target_waypoints; + if (num_target_waypoints > MAX_TARGET_WAYPOINTS) { + num_target_waypoints = MAX_TARGET_WAYPOINTS; + } + + if (env->max_stop_sign_observations > 0) { + ego_dim += 1; + } + + int max_obs = ego_dim + PARTNER_FEATURES * env->max_partner_observations + + ROAD_FEATURES * (env->max_lane_segment_observations + env->max_boundary_segment_observations) + + TRAFFIC_LIGHT_FEATURES * env->max_traffic_light_observations + + STOP_SIGN_FEATURES * env->max_stop_sign_observations; + if (env->reward_conditioning) { + max_obs += NUM_REWARD_COEFS; + } + if (env->target_type == TARGET_STATIC) { + max_obs += num_target_waypoints * STATIC_TARGET_FEATURES; + } else if (env->target_type == TARGET_DYNAMIC) { + max_obs += num_target_waypoints * DYNAMIC_TARGET_FEATURES; + } + + return max_obs; } void allocate(Drive *env) { init(env); - int ego_dim = (env->dynamics_model == JERK) ? EGO_FEATURES_JERK : EGO_FEATURES_CLASSIC; - int max_obs = ego_dim + PARTNER_FEATURES * (MAX_AGENTS - 1) + ROAD_FEATURES * MAX_ROAD_SEGMENT_OBSERVATIONS; + int max_obs = compute_observation_size(env); + env->observations = (float *)calloc(env->active_agent_count * max_obs, sizeof(float)); env->actions = (float *)calloc(env->active_agent_count * 2, sizeof(float)); env->rewards = (float *)calloc(env->active_agent_count, sizeof(float)); env->terminals = (unsigned char *)calloc(env->active_agent_count, sizeof(unsigned char)); env->truncations = (unsigned char *)calloc(env->active_agent_count, sizeof(unsigned char)); + env->masks = (unsigned char *)calloc(env->active_agent_count, sizeof(unsigned char)); } void free_allocated(Drive *env) { @@ -1523,1666 +3359,1325 @@ void free_allocated(Drive *env) { free(env->rewards); free(env->terminals); free(env->truncations); + free(env->masks); c_close(env); } -float clipSpeed(float speed) { - const float maxSpeed = MAX_SPEED; - if (speed > maxSpeed) - return maxSpeed; - if (speed < -maxSpeed) - return -maxSpeed; - return speed; +// ======================================== +// Extra C API Functions +// ======================================== + +int get_track_id_or_placeholder(Drive *env, int agent_idx) { + if (env->tracks_to_predict == NULL || env->num_tracks_to_predict == 0) { + return -1; + } + for (int k = 0; k < env->num_tracks_to_predict; k++) { + if (env->tracks_to_predict[k] == agent_idx) { + return env->tracks_to_predict[k]; + } + } + return -1; +} + +void c_get_global_agent_state(Drive *env, float *x_out, float *y_out, float *z_out, float *heading_out, int *id_out, + float *length_out, float *width_out) { + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; + Agent *agent = &env->agents[agent_idx]; + + // For WOSAC, we need the original world coordinates, so we add the world means back + x_out[i] = agent->sim_x + env->world_mean_x; + y_out[i] = agent->sim_y + env->world_mean_y; + z_out[i] = agent->sim_z; + heading_out[i] = agent->sim_heading; + id_out[i] = get_track_id_or_placeholder(env, agent_idx); + length_out[i] = agent->sim_length; + width_out[i] = agent->sim_width; + } } -float normalize_heading(float heading) { - if (heading > M_PI) - heading -= 2 * M_PI; - if (heading < -M_PI) - heading += 2 * M_PI; - return heading; +void c_get_global_ground_truth_trajectories(Drive *env, float *x_out, float *y_out, float *z_out, float *heading_out, + int *valid_out, int *id_out, int *scenario_id_out) { + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; + Agent *agent = &env->agents[agent_idx]; + id_out[i] = get_track_id_or_placeholder(env, agent_idx); + scenario_id_out[i] = 0; // TODO: FIXME + + for (int t = env->init_steps; t < agent->trajectory_length; t++) { + int out_idx = i * (agent->trajectory_length - env->init_steps) + (t - env->init_steps); + // Add world means back to get original world coordinates + x_out[out_idx] = agent->log_trajectory_x[t] + env->world_mean_x; + y_out[out_idx] = agent->log_trajectory_y[t] + env->world_mean_y; + z_out[out_idx] = agent->log_trajectory_z[t]; + heading_out[out_idx] = agent->log_heading[t]; + valid_out[out_idx] = agent->log_valid[t]; + } + } +} + +void c_get_road_edge_counts(Drive *env, int *num_polylines_out, int *total_points_out) { + int count = 0, points = 0; + for (int i = 0; i < env->num_road_elements; i++) { + if (is_road_edge(env->road_elements[i].type)) { + count++; + points += env->road_elements[i].segment_length; + } + } + *num_polylines_out = count; + *total_points_out = points; +} + +void c_get_road_edge_polylines(Drive *env, float *x_out, float *y_out, int *lengths_out, int *scenario_ids_out) { + int poly_idx = 0, pt_idx = 0; + for (int i = 0; i < env->num_road_elements; i++) { + RoadMapElement *e = &env->road_elements[i]; + if (is_road_edge(e->type)) { + lengths_out[poly_idx] = e->segment_length; + scenario_ids_out[poly_idx] = 0; // TODO: FIXME + for (int j = 0; j < e->segment_length; j++) { + x_out[pt_idx] = e->x[j] + env->world_mean_x; + y_out[pt_idx] = e->y[j] + env->world_mean_y; + pt_idx++; + } + poly_idx++; + } + } } -float normalize_value(float value, float min, float max) { return (value - min) / (max - min); } +// ======================================== +// Core Simulation Functions +// ======================================== + +static void compute_metrics(Drive *env, int agent_idx) { + Agent *agent = &env->agents[agent_idx]; + + reset_agent_metrics(env, agent_idx); + + if (agent->sim_x == INVALID_POSITION) + return; // invalid agent position + + // Current agent is offgrid, treat as offroad + if (get_grid_index(env, agent->sim_x, agent->sim_y) == -1) { + agent->metrics_array[OFFROAD_IDX] = 1.0f; + if (env->offroad_behavior == STOP_AGENT && !agent->stopped) { + agent->stopped = 1; + } else if (env->offroad_behavior == REMOVE_AGENT && !agent->removed) { + agent->removed = 1; + } + return; + } + + // Compute log-replay metrics + if (env->simulation_mode == SIMULATION_REPLAY) { + // Compute displacement error + float displacement_error = compute_displacement_error(agent, env->timestep); + if (displacement_error > 0.0f) { // Only count valid displacements + agent->cumulative_displacement += displacement_error; + agent->displacement_sample_count++; + + // Compute running average + agent->metrics_array[AVG_DISPLACEMENT_ERROR_IDX] = + agent->cumulative_displacement / agent->displacement_sample_count; + } + } + + bool is_offroad = false; + float half_length = agent->sim_length / 2.0f; + float half_width = agent->sim_width / 2.0f; + // Use cached trig values from move_dynamics + float cos_heading = agent->cos_heading; + float sin_heading = agent->sin_heading; + + // Track best candidate by combined distance/heading score + float best_score = 1e9f; + int best_candidate_entity_idx = -1; + int best_candidate_geometry_idx = -1; + float best_candidate_signed_lane_distance = 0.0f; + float best_candidate_lane_heading = 0.0f; + + float corners[4][2]; + for (int i = 0; i < 4; i++) { + corners[i][0] = + agent->sim_x + (offsets[i][0] * half_length * cos_heading - offsets[i][1] * half_width * sin_heading); + corners[i][1] = + agent->sim_y + (offsets[i][0] * half_length * sin_heading + offsets[i][1] * half_width * cos_heading); + } + // Store for rendering + memcpy(agent->render_corners, corners, sizeof(corners)); + + GridMapEntity entity_list[MAX_ENTITIES_PER_CELL * 25]; // Array big enough for all neighboring cells + int list_size = get_neighbors_entities(env, agent->sim_x, agent->sim_y, entity_list, MAX_ENTITIES_PER_CELL * 25, + collision_offsets, 25); + + // Vehicle-width based distance threshold (3x width) + float max_distance_threshold = 3.0f * agent->sim_width; + + // Track already-checked drivable lanes to avoid redundant processing + int checked_lanes[MAX_CHECKED_LANES]; + int num_checked_lanes = 0; + + // Loop through road entities and compute associated metrics (offroad, lane alignment) + for (int i = 0; i < list_size; i++) { + if (entity_list[i].entity_idx == -1) + continue; + + // Get the road element (only road elements are in grid) + if (entity_list[i].entity_type != ENTITY_TYPE_ROAD_ELEMENT) + continue; + + int entity_idx = entity_list[i].entity_idx; + int geometry_idx = entity_list[i].geometry_idx; + RoadMapElement *element = &env->road_elements[entity_idx]; + + // Check for offroad collision with road edges + if (is_road_edge(element->type)) { + float start[2] = {element->x[geometry_idx], element->y[geometry_idx]}; + float end[2] = {element->x[geometry_idx + 1], element->y[geometry_idx + 1]}; + float abs_dz = fabsf(element->z[geometry_idx] - agent->sim_z); + if (abs_dz > Z_BUFFER) + continue; + for (int k = 0; k < 4; k++) { // Check each edge of the bounding box + int next = (k + 1) % 4; + if (check_line_intersection(corners[k], corners[next], start, end)) { + is_offroad = true; + printf("[OFFROAD] agent %d at (%.1f,%.1f,%.1f) hit edge elem %d geom %d at z=%.1f (dz=%.1f)\n", + agent_idx, agent->sim_x, agent->sim_y, agent->sim_z, + entity_idx, geometry_idx, element->z[geometry_idx], abs_dz); + break; + } + } + } + + if (is_offroad) + break; + + int closest_seg_idx; + float signed_dist_out; + float lane_heading_out; + float score = score_lane_candidate(env, agent->sim_heading, checked_lanes, &num_checked_lanes, &closest_seg_idx, + entity_list[i], agent->sim_x, agent->sim_y, max_distance_threshold, + agent->current_lane_index, &signed_dist_out, &lane_heading_out); + + if (score >= 0.0f && score < best_score) { + best_score = score; + best_candidate_entity_idx = entity_idx; + best_candidate_geometry_idx = closest_seg_idx; + best_candidate_signed_lane_distance = signed_dist_out; + best_candidate_lane_heading = lane_heading_out; + } + } + + // Update lane alignment metric (running average) + if (best_candidate_entity_idx != -1) { + agent->previous_lane_index = agent->current_lane_index; + agent->current_lane_index = best_candidate_entity_idx; + agent->current_lane_geometry_idx = best_candidate_geometry_idx; + + // Lane distance and angle metrics (GIGAFLOW Frenet coordinates) + // x_f = lateral offset from lane center (left = negative, right = positive) + agent->metrics_array[LANE_DIST_IDX] = best_candidate_signed_lane_distance; + // Multi-lane detection: vehicle edge exceeds lane boundary + float edge_dist = fabsf(best_candidate_signed_lane_distance) + half_width; + if (env->compute_eval_metrics && edge_dist > MULTI_LANE_THRESHOLD && agent->sim_speed > 0.0f) { + agent->multi_lane_time += env->dt; + } + // theta_f = angle relative to lane heading + float theta_f = compute_heading_diff(agent->sim_heading, best_candidate_lane_heading); + agent->metrics_array[LANE_ANGLE_IDX] = cosf(theta_f); // Store cos(θ_f) + } else { + // Agent not on any lane - use "bad" values to indicate offroad state + agent->previous_lane_index = -1; + agent->current_lane_index = -1; + agent->current_lane_geometry_idx = -1; + agent->metrics_array[LANE_DIST_IDX] = LANE_DISTANCE_NORMALIZATION; // Max distance (far from lane) + agent->metrics_array[LANE_ANGLE_IDX] = 0.0f; // Perpendicular (no alignment) + } + + agent->closest_path_idx_wp = get_closest_waypoint_index_on_path(env, agent_idx); + + // Speed limit metric (CUSTOM) + float target_speed = 15.0f; // Default target speed + int current_lane_index = agent->current_lane_index; + if (current_lane_index != -1 && env->road_elements[current_lane_index].speed_limit > 0) { + target_speed = env->road_elements[current_lane_index].speed_limit; + } + // Binary overspeed metric, 1.0 if overspeeding by more than 2 m/s + agent->metrics_array[SPEED_LIMIT_IDX] = (agent->sim_speed > target_speed + 2.0f) ? 1.0f : 0.0f; + if (env->compute_eval_metrics) { + agent->speed_violation_sum += fmaxf(agent->sim_speed - target_speed, 0.0f) * env->dt; + } + + // Velocity metric (GIGAFLOW) - forward progress aligned with lane + const float VELOCITY_MIN_SPEED = 2.5f; // m/s + if (agent->sim_speed > VELOCITY_MIN_SPEED && best_candidate_entity_idx != -1) { + float cos_theta = agent->metrics_array[LANE_ANGLE_IDX]; + agent->metrics_array[VELOCITY_PROGRESS_IDX] = fmaxf(cos_theta, 0.0f); + if (env->compute_eval_metrics && cos_theta < 0.0f) { + agent->wrong_way_distance += agent->sim_speed * env->dt; + } + } else { + agent->metrics_array[VELOCITY_PROGRESS_IDX] = 0.0f; + } + + // Comfort metric (GIGAFLOW) + const float COMFORT_ACCEL_THRESHOLD = 3.0f; // m/s² + const float COMFORT_JERK_THRESHOLD = 5.0f; // m/s³ + int accel_violation = + (fabsf(agent->a_long) > COMFORT_ACCEL_THRESHOLD) + (fabsf(agent->a_lat) > COMFORT_ACCEL_THRESHOLD); + int jerk_violation = + (fabsf(agent->jerk_long) > COMFORT_JERK_THRESHOLD || fabsf(agent->jerk_lat) > COMFORT_JERK_THRESHOLD) ? 1 : 0; + agent->metrics_array[COMFORT_VIOLATION_IDX] = (float)(accel_violation + jerk_violation); + + // Handle terminal events - NOTE: move it elsewhere? + // IMPORTANT: early returns after offroad and collision enforce mutual exclusivity of + // terminal flags. Red_light and stop_sign have NO early return and can coexist. + // Order matters: offroad > collision > red_light/stop_sign. + + // Priority 1: Handle offroad + if (is_offroad) { + agent->metrics_array[OFFROAD_IDX] = 1.0f; + if (env->offroad_behavior == STOP_AGENT && !agent->stopped) { // Stop + agent->stopped = 1; + } else if (env->offroad_behavior == REMOVE_AGENT && !agent->removed) { + agent->removed = 1; + } + return; // early return: no other terminal flags set when offroad + } + + // Priority 2: Handle vehicle collision + int car_collided_with_index = collision_check(env, agent_idx); + + if (car_collided_with_index != -1) { + agent->metrics_array[COLLISION_IDX] = 1.0f; + // Track at-fault collisions for evaluation metrics. + if (env->compute_eval_metrics && is_at_fault_collision(env, agent_idx, car_collided_with_index)) { + agent->at_fault_collision = 1; + agent->metrics_array[AT_FAULT_COLLISION_IDX] = 1.0f; + } + if (env->collision_behavior == STOP_AGENT && !agent->stopped) { // Stop + agent->stopped = 1; + } else if (env->collision_behavior == REMOVE_AGENT && !agent->removed) { + agent->removed = 1; + } -void move_dynamics(Drive *env, int action_idx, int agent_idx) { - Entity *agent = &env->entities[agent_idx]; - if (agent->removed) - return; + return; // early return: red_light/stop_sign not checked after collision + } - if (agent->stopped) { - agent->vx = 0.0f; - agent->vy = 0.0f; - return; + // Priority 3: Handle red light violation + // Guard: violations are invisible to rewards when max_traffic_light_observations == 0 + if (env->max_traffic_light_observations && check_red_light_violation(env, agent_idx)) { + agent->metrics_array[RED_LIGHT_IDX] = 1.0f; + if (env->traffic_light_behavior == STOP_AGENT && !agent->stopped) { + agent->stopped = 1; + } else if (env->traffic_light_behavior == REMOVE_AGENT && !agent->removed) { + agent->removed = 1; + } } - if (env->dynamics_model == CLASSIC) { - // Classic dynamics model - float acceleration = 0.0f; - float steering = 0.0f; + float distance_to_goal = + compute_euclidean_distance(agent->sim_x, agent->sim_y, agent->goal_position_x, agent->goal_position_y); + float goal_z_dist = fabsf(agent->sim_z - agent->goal_position_z); - if (env->action_type == 1) { // continuous - float (*action_array_f)[2] = (float (*)[2])env->actions; - acceleration = action_array_f[action_idx][0]; - steering = action_array_f[action_idx][1]; + // Goal reaching + if (distance_to_goal < agent->reward_coefs[REWARD_COEF_GOAL_RADIUS] && goal_z_dist < Z_BUFFER) { + agent->metrics_array[REACHED_GOAL_IDX] = 1.0f; + agent->current_goal_idx++; + } - acceleration *= ACCELERATION_VALUES[6]; - steering *= STEERING_VALUES[12]; - } else { // discrete - // Interpret action as a single integer: a = accel_idx * num_steer + steer_idx - int *action_array = (int *)env->actions; - int num_steer = sizeof(STEERING_VALUES) / sizeof(STEERING_VALUES[0]); - int action_val = action_array[action_idx]; - int acceleration_index = action_val / num_steer; - int steering_index = action_val % num_steer; - acceleration = ACCELERATION_VALUES[acceleration_index]; - steering = STEERING_VALUES[steering_index]; - } + return; +} - // Current state - float x = agent->x; - float y = agent->y; - float heading = agent->heading; - float vx = agent->vx; - float vy = agent->vy; +static void compute_rewards(Drive *env, int i) { + int agent_idx = env->active_agent_indices[i]; + Agent *agent = &env->agents[agent_idx]; - // Calculate current speed (signed based on direction relative to heading) - float speed_magnitude = sqrtf(vx * vx + vy * vy); - float v_dot_heading = vx * agent->heading_x + vy * agent->heading_y; - float signed_speed = copysignf(speed_magnitude, v_dot_heading); + // NOTE: compute_metrics enforces offroad > collision priority via early returns. + // Red_light and stop_sign can coexist with each other (both flags may be set). + // All penalty terms below are applied independently (no early returns here). - // Update speed with acceleration - signed_speed = signed_speed + acceleration * env->dt; - signed_speed = clipSpeed(signed_speed); - // Compute yaw rate - float beta = tanh(.5 * tanf(steering)); + // Collision reward (GIGAFLOW) + if (agent->metrics_array[COLLISION_IDX] > 0.0f) { + // Velocity-dependent penalty: incentivizes braking before unavoidable collision. + // At max speed (~20 m/s): extra -2.0 on top of base coefficient. + float reward_collision = -(agent->reward_coefs[REWARD_COEF_COLLISION] + 0.1f * agent->sim_speed); - // New heading - float yaw_rate = (signed_speed * cosf(beta) * tanf(steering)) / agent->length; + env->rewards[i] += reward_collision; + env->logs[i].episode_return += reward_collision; + env->logs[i].collision_rate = 1.0f; + } - // New velocity - float new_vx = signed_speed * cosf(heading + beta); - float new_vy = signed_speed * sinf(heading + beta); + // Offroad reward (GIGAFLOW) + if (agent->metrics_array[OFFROAD_IDX] > 0.0f) { + float reward_offroad = -agent->reward_coefs[REWARD_COEF_OFFROAD]; - // Update position - x = x + (new_vx * env->dt); - y = y + (new_vy * env->dt); - heading = heading + yaw_rate * env->dt; + env->rewards[i] += reward_offroad; + env->logs[i].offroad_rate = 1.0f; + env->logs[i].episode_return += reward_offroad; + } - // Apply updates to the agent's state - agent->x = x; - agent->y = y; - agent->heading = heading; - agent->heading_x = cosf(heading); - agent->heading_y = sinf(heading); - agent->vx = new_vx; - agent->vy = new_vy; - } else { - // JERK dynamics model - // Extract action components - float a_long, a_lat; - if (env->action_type == 1) { // continuous - float (*action_array_f)[2] = (float (*)[2])env->actions; + // Red light violation reward (GIGAFLOW) + if (agent->metrics_array[RED_LIGHT_IDX] > 0.0f) { + float reward_red_light = -agent->reward_coefs[REWARD_COEF_TRAFFIC_LIGHT]; - // Asymmetric scaling for longitudinal jerk to match discrete action space - // Discrete: JERK_LONG = [-15, -4, 0, 4] (more braking than acceleration) - float a_long_action = action_array_f[action_idx][0]; // [-1, 1] - if (a_long_action < 0) { - a_long = a_long_action * (-JERK_LONG[0]); // Negative: [-1, 0] → [-15, 0] (braking) - } else { - a_long = a_long_action * JERK_LONG[3]; // Positive: [0, 1] → [0, 4] (acceleration) - } + env->rewards[i] += reward_red_light; + env->logs[i].red_light_violation_rate = 1.0f; + env->logs[i].episode_return += reward_red_light; + } - // Symmetric scaling for lateral jerk - a_lat = action_array_f[action_idx][1] * JERK_LAT[2]; - } else { // discrete - // Interpret action as a single integer: a = long_idx * num_lat + lat_idx - int *action_array = (int *)env->actions; - int num_lat = sizeof(JERK_LAT) / sizeof(JERK_LAT[0]); - int action_val = action_array[action_idx]; - int a_long_idx = action_val / num_lat; - int a_lat_idx = action_val % num_lat; - a_long = JERK_LONG[a_long_idx]; - a_lat = JERK_LAT[a_lat_idx]; + // Goal reward + if (agent->metrics_array[REACHED_GOAL_IDX] > 0.0f) { + float weight = 1.0f; + if (env->simulation_mode == SIMULATION_GIGAFLOW) { + // current_goal_idx is already incremented in compute_metrics when goal is reached. + // == num_target_waypoints means the last waypoint was just reached. + // weight=0 suppresses the final goal reward when agent is already moving (> 3 m/s). + // This prevents rewarding a drive-through of the last waypoint. + if (agent->current_goal_idx == env->num_target_waypoints && agent->sim_speed > env->goal_speed_threshold) + weight = 0.0f; } - // Calculate new acceleration - float a_long_new = agent->a_long + a_long * env->dt; - float a_lat_new = agent->a_lat + a_lat * env->dt; + env->rewards[i] += env->reward_goal * weight; + env->logs[i].episode_return += env->reward_goal * weight; + env->logs[i].num_waypoints_reached += 1; + } - // Make it easy to stop with 0 accel - if (agent->a_long * a_long_new < 0) { - a_long_new = 0.0f; - } else { - a_long_new = clip(a_long_new, -5.0f, 2.5f); - } + // Get lane angle metric: cos(θ_f) where θ_f = heading diff from lane + float cos_theta = agent->metrics_array[LANE_ANGLE_IDX]; + float theta_f = acosf(fminf(fmaxf(cos_theta, -1.0f), 1.0f)); // Get |θ_f| from cos + env->logs[i].lane_heading_aligned_rate += (cos_theta >= LANE_ALIGN_COS_THRESHOLD) ? 1.0f : 0.0f; - if (agent->a_lat * a_lat_new < 0) { - a_lat_new = 0.0f; - } else { - a_lat_new = clip(a_lat_new, -4.0f, 4.0f); - } + // Rl-align (GIGAFLOW): min(cos,0) + vel_align*min(cos*v,0) + 0.0025*(1-|θ|/(π/2)) + float against_lane_penalty = fminf(cos_theta, 0.0f); // negative when >90 degrees off + float vel_aligned_penalty = agent->reward_coefs[REWARD_COEF_VEL_ALIGN] * fminf(cos_theta * agent->sim_speed, 0.0f); + float alignment_bonus = 0.0025f * (1.0f - theta_f / (M_PI / 2.0f)); - // Calculate new velocity - float v_dot_heading = agent->vx * agent->heading_x + agent->vy * agent->heading_y; - float signed_v = copysignf(sqrtf(agent->vx * agent->vx + agent->vy * agent->vy), v_dot_heading); - float v_new = signed_v + 0.5f * (a_long_new + agent->a_long) * env->dt; + float lane_align_reward = agent->reward_coefs[REWARD_COEF_LANE_ALIGN] * env->dt * + (against_lane_penalty + vel_aligned_penalty + alignment_bonus); - // Make it easy to stop with 0 vel - if (signed_v * v_new < 0) { - v_new = 0.0f; - } else { - v_new = clip(v_new, -2.0f, 20.0f); - } + env->rewards[i] += lane_align_reward; + env->logs[i].episode_return += lane_align_reward; - // Calculate new steering angle - float signed_curvature = a_lat_new / fmaxf(v_new * v_new, 1e-5f); - signed_curvature = copysignf(fmaxf(fabsf(signed_curvature), 1e-5f), signed_curvature); - float steering_angle = atanf(signed_curvature * agent->wheelbase); - float delta_steer = clip(steering_angle - agent->steering_angle, -0.6f * env->dt, 0.6f * env->dt); - float new_steering_angle = clip(agent->steering_angle + delta_steer, -0.55f, 0.55f); + // Rl-center (GIGAFLOW): -α * dt * (|x_f - bias| - 0.05 / exp(|x_f - bias| - 0.5)) + float lane_center_distance = agent->metrics_array[LANE_DIST_IDX]; + float adjusted_dist = fabsf(lane_center_distance - agent->reward_coefs[REWARD_COEF_CENTER_BIAS]); + float exp_decay = 0.05f / expf(adjusted_dist - 0.5f); - // Update curvature and accel to account for limited steering - signed_curvature = tanf(new_steering_angle) / agent->wheelbase; - a_lat_new = v_new * v_new * signed_curvature; + float lane_center_reward = + -agent->reward_coefs[REWARD_COEF_LANE_CENTER] * env->dt * ((cos_theta > 0.5f) * adjusted_dist - exp_decay); - // Calculate resulting movement using bicycle dynamics - float d = 0.5f * (v_new + signed_v) * env->dt; - float theta = d * signed_curvature; - float dx_local, dy_local; + env->rewards[i] += lane_center_reward; + env->logs[i].lane_center_rate += fabsf(lane_center_distance) < 0.5f ? 1.0f : 0.0f; + env->logs[i].episode_return += lane_center_reward; - if (fabsf(signed_curvature) < 1e-5f || fabsf(theta) < 1e-5f) { - dx_local = d; - dy_local = 0.0f; - } else { - dx_local = sinf(theta) / signed_curvature; - dy_local = (1.0f - cosf(theta)) / signed_curvature; - } + // Comfort reward (GIGAFLOW) + float comfort_violations = agent->metrics_array[COMFORT_VIOLATION_IDX]; + float comfort_penalty = -agent->reward_coefs[REWARD_COEF_COMFORT] * comfort_violations; - float dx = dx_local * agent->heading_x - dy_local * agent->heading_y; - float dy = dx_local * agent->heading_y + dy_local * agent->heading_x; + env->rewards[i] += comfort_penalty; + env->logs[i].comfort_violation_count += comfort_violations; + env->logs[i].episode_return += comfort_penalty; - // Update everything - agent->x += dx; - agent->y += dy; - agent->jerk_long = (a_long_new - agent->a_long) / env->dt; - agent->jerk_lat = (a_lat_new - agent->a_lat) / env->dt; - agent->a_long = a_long_new; - agent->a_lat = a_lat_new; - agent->heading = normalize_heading(agent->heading + theta); - agent->heading_x = cosf(agent->heading); - agent->heading_y = sinf(agent->heading); - agent->vx = v_new * agent->heading_x; - agent->vy = v_new * agent->heading_y; - agent->steering_angle = new_steering_angle; - } + // Velocity reward (GIGAFLOW) + float velocity_progress = agent->metrics_array[VELOCITY_PROGRESS_IDX]; + float velocity_reward = agent->reward_coefs[REWARD_COEF_VELOCITY] * env->dt * velocity_progress; - return; -} + env->rewards[i] += velocity_reward; + env->logs[i].episode_return += velocity_reward; + env->logs[i].velocity_progress_sum += velocity_progress; -static inline int is_in_track_to_predicts(Drive *env, int agent_idx) { - if (env->tracks_to_predict_indices == NULL || env->num_tracks_to_predict == 0) { - return 0; - } - for (int k = 0; k < env->num_tracks_to_predict; k++) { - if (env->tracks_to_predict_indices[k] == agent_idx) { - return 1; - } + // Timestep reward (GIGAFLOW) + float accel = sqrtf(agent->a_long * agent->a_long + agent->a_lat * agent->a_lat); + // Only penalize when moving (v > 0) or accelerating (a > 0) + if (agent->sim_speed > 0.01f || accel > 0.01f) { + float timestep_penalty = -agent->reward_coefs[REWARD_COEF_TIMESTEP] * env->dt; + + env->rewards[i] += timestep_penalty; + env->logs[i].episode_return += timestep_penalty; } - return 0; -} -void c_get_global_agent_state(Drive *env, float *x_out, float *y_out, float *z_out, float *heading_out, int *id_out, - float *length_out, float *width_out) { - for (int i = 0; i < env->active_agent_count; i++) { - int agent_idx = env->active_agent_indices[i]; - Entity *agent = &env->entities[agent_idx]; + // Reverse reward (GIGAFLOW) + if (agent->sim_speed_signed < -0.01f) { + float reverse_penalty = -agent->reward_coefs[REWARD_COEF_REVERSE] * env->dt; - // For WOSAC, we need the original world coordinates, so we add the world means back - x_out[i] = agent->x + env->world_mean_x; - y_out[i] = agent->y + env->world_mean_y; - z_out[i] = agent->z; - heading_out[i] = agent->heading; - id_out[i] = agent->id; - length_out[i] = agent->length; - width_out[i] = agent->width; + env->rewards[i] += reverse_penalty; + env->logs[i].episode_return += reverse_penalty; } -} -void c_get_global_ground_truth_trajectories(Drive *env, float *x_out, float *y_out, float *z_out, float *heading_out, - int *valid_out, int *id_out, bool *is_vehicle_out, - bool *is_track_to_predict_out, char *scenario_id_out) { - for (int i = 0; i < env->active_agent_count; i++) { - int agent_idx = env->active_agent_indices[i]; - Entity *agent = &env->entities[agent_idx]; - id_out[i] = agent->id; - is_vehicle_out[i] = agent->type == VEHICLE; - is_track_to_predict_out[i] = is_in_track_to_predicts(env, agent_idx); + // Over speed reward (GIGAFLOW++) + float speed_reward = -agent->reward_coefs[REWARD_COEF_OVERSPEED] * agent->metrics_array[SPEED_LIMIT_IDX]; - // The scenario_id is an array of 16 char - memcpy(scenario_id_out + (i * 16), env->scenario_id, 16); + env->rewards[i] += speed_reward; + env->logs[i].avg_speed_per_agent += agent->sim_speed; + agent->distance_since_spawn += agent->sim_speed * env->dt; + env->logs[i].episode_return += speed_reward; - for (int t = env->init_steps; t < agent->array_size; t++) { - int out_idx = i * (agent->array_size - env->init_steps) + (t - env->init_steps); - // Add world means back to get original world coordinates - x_out[out_idx] = agent->traj_x[t] + env->world_mean_x; - y_out[out_idx] = agent->traj_y[t] + env->world_mean_y; - z_out[out_idx] = agent->traj_z[t]; - heading_out[out_idx] = agent->traj_heading[t]; - valid_out[out_idx] = agent->traj_valid[t]; - } - } -} + // ADE reward (CUSTOM) + float current_ade = agent->metrics_array[AVG_DISPLACEMENT_ERROR_IDX]; + if (current_ade > 0.0f && env->reward_ade != 0.0f) { + float ade_reward = env->reward_ade * current_ade; -void c_get_road_edge_counts(Drive *env, int *num_polylines_out, int *total_points_out) { - int count = 0, points = 0; - for (int i = env->num_objects; i < env->num_entities; i++) { - if (env->entities[i].type == ROAD_EDGE) { - count++; - points += env->entities[i].array_size; - } + env->rewards[i] += ade_reward; + env->logs[i].episode_return += ade_reward; } - *num_polylines_out = count; - *total_points_out = points; -} + env->logs[i].avg_displacement_error = current_ade; -void c_get_road_edge_polylines(Drive *env, float *x_out, float *y_out, int *lengths_out, char *scenario_ids_out) { - int poly_idx = 0, pt_idx = 0; - for (int i = env->num_objects; i < env->num_entities; i++) { - Entity *e = &env->entities[i]; - if (e->type == ROAD_EDGE) { - lengths_out[poly_idx] = e->array_size; + if (env->compute_eval_metrics) { + if (agent->at_fault_collision > 0) { + env->logs[i].at_fault_collision_rate = 1.0f; + } - char *scenario_id_ptr = scenario_ids_out + poly_idx * 16; - memcpy(scenario_id_ptr, env->scenario_id, 16); + env->logs[i].wrong_way_distance = agent->wrong_way_distance; + env->logs[i].speed_violation_sum = agent->speed_violation_sum; + env->logs[i].multi_lane_time = agent->multi_lane_time; + float ml_time = env->logs[i].multi_lane_time; + float ml_score = (ml_time <= MULTI_LANE_FULL_SCORE_TIME) ? 1.0f + : (ml_time <= MULTI_LANE_HALF_SCORE_TIME) ? 0.5f + : 0.0f; + env->logs[i].multi_lane_score = ml_score; + agent->metrics_array[MULTI_LANE_TIME_IDX] = ml_time; + agent->metrics_array[MULTI_LANE_SCORE_IDX] = ml_score; + + compute_agent_ttc(env, agent_idx); + if (agent->metrics_array[COLLISION_IDX] > 0.0f) { + agent->cached_ttc.min_ttc = 0.0f; + agent->cached_ttc.other_idx = -1; + agent->cached_ttc.distance_to_collision = 0.0f; + agent->cached_ttc.closing_speed = INFINITY; + } + struct ttc_result ttc_agents = agent->cached_ttc; + float min_vehicle_ttc = ttc_agents.min_ttc; + agent->metrics_array[TTC_IDX] = min_vehicle_ttc; + agent->metrics_array[TTC_TFL_IDX] = DEFAULT_TTC; + agent->ttc_samples++; + if (min_vehicle_ttc < TTC_VIOLATION_THRESHOLD) { + agent->ttc_violations++; + } - for (int j = 0; j < e->array_size; j++) { - x_out[pt_idx] = e->traj_x[j] + env->world_mean_x; - y_out[pt_idx] = e->traj_y[j] + env->world_mean_y; - pt_idx++; - } - poly_idx++; + env->logs[i].ttc_violations = (float)agent->ttc_violations; + env->logs[i].ttc_samples = (float)agent->ttc_samples; + if (agent->ttc_samples > 0) { + env->logs[i].ttc_within_bound_rate = 1.0f - ((float)agent->ttc_violations / (float)agent->ttc_samples); + } else { + env->logs[i].ttc_within_bound_rate = 1.0f; } + + env->logs[i].comfort_score = (env->logs[i].comfort_violation_count > 0) ? 0.0f : 1.0f; + } else { + struct ttc_result default_ttc = default_ttc_result(); + agent->metrics_array[TTC_IDX] = default_ttc.min_ttc; + agent->metrics_array[TTC_TFL_IDX] = default_ttc.min_ttc; + agent->metrics_array[MULTI_LANE_TIME_IDX] = 0.0f; + agent->metrics_array[MULTI_LANE_SCORE_IDX] = 0.0f; + agent->metrics_array[AT_FAULT_COLLISION_IDX] = 0.0f; } } -void compute_observations(Drive *env) { - int ego_dim = (env->dynamics_model == JERK) ? EGO_FEATURES_JERK : EGO_FEATURES_CLASSIC; - int max_obs = ego_dim + PARTNER_FEATURES * (MAX_AGENTS - 1) + ROAD_FEATURES * MAX_ROAD_SEGMENT_OBSERVATIONS; +static void compute_observations(Drive *env) { + int max_obs = compute_observation_size(env); + memset(env->observations, 0, max_obs * env->active_agent_count * sizeof(float)); float (*observations)[max_obs] = (float (*)[max_obs])env->observations; for (int i = 0; i < env->active_agent_count; i++) { float *obs = &observations[i][0]; - Entity *ego_entity = &env->entities[env->active_agent_indices[i]]; - if (ego_entity->type > 3) - break; - - float cos_heading = ego_entity->heading_x; - float sin_heading = ego_entity->heading_y; - float speed_magnitude = sqrtf(ego_entity->vx * ego_entity->vx + ego_entity->vy * ego_entity->vy); - float v_dot_heading = ego_entity->vx * ego_entity->heading_x + ego_entity->vy * ego_entity->heading_y; - float signed_speed = copysignf(speed_magnitude, v_dot_heading); - - // Set goal distances - float goal_x = ego_entity->goal_position_x - ego_entity->x; - float goal_y = ego_entity->goal_position_y - ego_entity->y; + int obs_idx = 0; + Agent *ego_entity = &env->agents[env->active_agent_indices[i]]; - // Rotate to ego vehicle's frame - float rel_goal_x = goal_x * cos_heading + goal_y * sin_heading; - float rel_goal_y = -goal_x * sin_heading + goal_y * cos_heading; + // Use cached trig values (updated in move_dynamics/spawn) + float cos_heading = ego_entity->cos_heading; + float sin_heading = ego_entity->sin_heading; - obs[0] = rel_goal_x * 0.005f; - obs[1] = rel_goal_y * 0.005f; - obs[2] = signed_speed / MAX_SPEED; - obs[3] = ego_entity->width / MAX_VEH_WIDTH; - obs[4] = ego_entity->length / MAX_VEH_LEN; - obs[5] = (ego_entity->collision_state > 0) ? 1.0f : 0.0f; + obs[obs_idx++] = ego_entity->sim_speed_signed / MAX_SPEED; + obs[obs_idx++] = ego_entity->sim_width / MAX_VEH_WIDTH; + obs[obs_idx++] = ego_entity->sim_length / MAX_VEH_LEN; + obs[obs_idx++] = ego_entity->steering_angle / STEERING_VALUES[8]; if (env->dynamics_model == JERK) { - obs[6] = ego_entity->steering_angle / M_PI; - // Asymmetric normalization for a_long to match action space - obs[7] = + obs[obs_idx++] = (ego_entity->a_long < 0) ? ego_entity->a_long / (-JERK_LONG[0]) : ego_entity->a_long / JERK_LONG[3]; - obs[8] = ego_entity->a_lat / JERK_LAT[2]; - obs[9] = (ego_entity->respawn_timestep != -1) ? 1 : 0; - // Add normalized entity type (VEHICLE=1, PEDESTRIAN=2, CYCLIST=3) - obs[10] = ego_entity->type / 3.0f; - } else { - obs[6] = (ego_entity->respawn_timestep != -1) ? 1 : 0; - obs[7] = ego_entity->type / 3.0f; + obs[obs_idx++] = ego_entity->a_lat / JERK_LAT[2]; } - // Relative Pos of other cars - int obs_idx = ego_dim; - int cars_seen = 0; - for (int j = 0; j < MAX_AGENTS; j++) { + float lane_center_dist = ego_entity->metrics_array[LANE_DIST_IDX] / LANE_DISTANCE_NORMALIZATION; + lane_center_dist = fmaxf(-1.0f, fminf(1.0f, lane_center_dist)); + obs[obs_idx++] = lane_center_dist; + obs[obs_idx++] = ego_entity->metrics_array[LANE_ANGLE_IDX]; + + float speed_limit = 20.0f; + int current_lane_index = ego_entity->current_lane_index; + if (current_lane_index != -1 && env->road_elements[current_lane_index].speed_limit > 0) { + speed_limit = env->road_elements[current_lane_index].speed_limit; + } + obs[obs_idx++] = fminf(speed_limit / MAX_SPEED, 1.0f); + + // Encoder -> Conditioning and goal waypoints + if (env->reward_conditioning) { + for (int c = 0; c < NUM_REWARD_COEFS; c++) { + obs[obs_idx++] = normalize_reward_coef(ego_entity->reward_coefs[c], c); + } + } + + // Target observations (static or dynamic) + if (env->target_type == TARGET_STATIC) { + for (int wp = 0; wp < env->num_target_waypoints; wp++) { + if (wp < ego_entity->current_goal_idx) { + // Already reached - zeroed + obs[obs_idx++] = 0.0f; + obs[obs_idx++] = 0.0f; + obs[obs_idx++] = 0.0f; + } else { + float gx = ego_entity->goal_positions_x[wp] - ego_entity->sim_x; + float gy = ego_entity->goal_positions_y[wp] - ego_entity->sim_y; + obs[obs_idx++] = (gx * cos_heading + gy * sin_heading) / MAX_GOAL_POSITION; + obs[obs_idx++] = (-gx * sin_heading + gy * cos_heading) / MAX_GOAL_POSITION; + obs[obs_idx++] = (ego_entity->goal_positions_z[wp] - ego_entity->sim_z) / MAX_POSITION; + } + } + } else if (env->target_type == TARGET_DYNAMIC) { + if (ego_entity->path != NULL && ego_entity->path->num_waypoints > 0) { + for (int wp = 0; wp < env->num_target_waypoints; wp++) { + int wp_index = fmin(ego_entity->closest_path_idx_wp + wp, ego_entity->path->num_waypoints - 1); + if (wp_index < 0) + wp_index = 0; + struct Waypoint *wp = &ego_entity->path->waypoints[wp_index]; + float wp_x = wp->x - ego_entity->sim_x; + float wp_y = wp->y - ego_entity->sim_y; + float wp_z = wp->z - ego_entity->sim_z; + // Use pre-computed trig values from build_path + float wp_cos_h = wp->cos_heading; + float wp_sin_h = wp->sin_heading; + float rel_wp_x = wp_x * cos_heading + wp_y * sin_heading; + float rel_wp_y = -wp_x * sin_heading + wp_y * cos_heading; + float rel_heading_x = wp_cos_h * cos_heading + wp_sin_h * sin_heading; + float rel_heading_y = wp_sin_h * cos_heading - wp_cos_h * sin_heading; + obs[obs_idx++] = rel_wp_x / MAX_POSITION; + obs[obs_idx++] = rel_wp_y / MAX_POSITION; + obs[obs_idx++] = rel_heading_x; + obs[obs_idx++] = rel_heading_y; + obs[obs_idx++] = wp_z / MAX_POSITION; + } + } else { + // No valid path - zero out + obs_idx += DYNAMIC_TARGET_FEATURES * env->num_target_waypoints; + } + } + + // Encode -> Partner vehicle + AgentDistance candidates[env->num_agents]; + int candidate_count = 0; + for (int j = 0; j < env->num_agents; j++) { int index = -1; if (j < env->active_agent_count) { index = env->active_agent_indices[j]; - } else if (j < env->num_actors && env->static_agent_count > 0) { + } else if (j < env->num_agents) { index = env->static_agent_indices[j - env->active_agent_count]; } if (index == -1) continue; - if (env->entities[index].type > 3) - break; + if (env->agents[index].type >= OTHER) + continue; if (index == env->active_agent_indices[i]) continue; // Skip self, but don't increment obs_idx - Entity *other_entity = &env->entities[index]; - if (ego_entity->respawn_timestep != -1) - continue; - if (other_entity->respawn_timestep != -1) - continue; + Agent *other_entity = &env->agents[index]; // Store original relative positions - float dx = other_entity->x - ego_entity->x; - float dy = other_entity->y - ego_entity->y; - float dist = (dx * dx + dy * dy); - if (dist > 2500.0f) + float dx = other_entity->sim_x - ego_entity->sim_x; + float dy = other_entity->sim_y - ego_entity->sim_y; + float dz = other_entity->sim_z - ego_entity->sim_z; + float abs_dz = fabsf(dz); + float dist_sq = dx * dx + dy * dy + dz * dz; + if (dist_sq > AGENT_OBS_MAX_DIST * AGENT_OBS_MAX_DIST || abs_dz > Z_BUFFER) continue; - // Rotate to ego vehicle's frame - float rel_x = dx * cos_heading + dy * sin_heading; - float rel_y = -dx * sin_heading + dy * cos_heading; - // Store observations with correct indexing - obs[obs_idx] = rel_x * 0.02f; - obs[obs_idx + 1] = rel_y * 0.02f; - obs[obs_idx + 2] = other_entity->width / MAX_VEH_WIDTH; - obs[obs_idx + 3] = other_entity->length / MAX_VEH_LEN; - // relative heading - float rel_heading_x = - other_entity->heading_x * ego_entity->heading_x + - other_entity->heading_y * ego_entity->heading_y; // cos(a-b) = cos(a)cos(b) + sin(a)sin(b) - float rel_heading_y = - other_entity->heading_y * ego_entity->heading_x - - other_entity->heading_x * ego_entity->heading_y; // sin(a-b) = sin(a)cos(b) - cos(a)sin(b) - - obs[obs_idx + 4] = rel_heading_x; - obs[obs_idx + 5] = rel_heading_y; - - // relative speed - float other_speed_magnitude = - sqrtf(other_entity->vx * other_entity->vx + other_entity->vy * other_entity->vy); - float other_v_dot_heading = - other_entity->vx * other_entity->heading_x + other_entity->vy * other_entity->heading_y; - float other_signed_speed = copysignf(other_speed_magnitude, other_v_dot_heading); - obs[obs_idx + 6] = other_signed_speed / MAX_SPEED; - cars_seen++; - obs_idx += 7; // Move to next observation slot - } - int remaining_partner_obs = (MAX_AGENTS - 1 - cars_seen) * 7; + // Add to candidate list + candidates[candidate_count].index = index; + candidates[candidate_count].dist_sq = dist_sq; + candidates[candidate_count].dx = dx; + candidates[candidate_count].dy = dy; + candidates[candidate_count].dz = dz; + candidate_count++; + } + int cars_seen = 0; + // Find K closest candidates using partial selection (O(N*K) instead of O(N log N) qsort) + if (candidate_count > 0) { + int num_agents_to_observe = + (candidate_count < env->max_partner_observations) ? candidate_count : env->max_partner_observations; + + // Partial selection sort: find the k-th smallest for each k + for (int k = 0; k < num_agents_to_observe; k++) { + // Find minimum in remaining elements [k, candidate_count) + int min_idx = k; + for (int j = k + 1; j < candidate_count; j++) { + if (candidates[j].dist_sq < candidates[min_idx].dist_sq) { + min_idx = j; + } + } + // Swap to position k + if (min_idx != k) { + AgentDistance tmp = candidates[k]; + candidates[k] = candidates[min_idx]; + candidates[min_idx] = tmp; + } + } + + for (int k = 0; k < num_agents_to_observe; k++) { + // Get the data for the k-th closest agent + int index = candidates[k].index; + float dx = candidates[k].dx; + float dy = candidates[k].dy; + float dz = candidates[k].dz; + Agent *other_entity = &env->agents[index]; + // Rotate to ego vehicle's frame + float rel_x = dx * cos_heading + dy * sin_heading; + float rel_y = -dx * sin_heading + dy * cos_heading; + // Store observations with correct indexing + obs[obs_idx++] = rel_x / MAX_POSITION; + obs[obs_idx++] = rel_y / MAX_POSITION; + obs[obs_idx++] = other_entity->sim_width / MAX_VEH_WIDTH; + obs[obs_idx++] = other_entity->sim_length / MAX_VEH_LEN; + // relative heading + // Use cached trig values from other agent + float other_cos = other_entity->cos_heading; + float other_sin = other_entity->sin_heading; + float rel_heading_x = + other_cos * cos_heading + other_sin * sin_heading; // cos(a-b) = cos(a)cos(b) + sin(a)sin(b) + float rel_heading_y = + other_sin * cos_heading - other_cos * sin_heading; // sin(a-b) = sin(a)cos(b) - cos(a)sin(b) + + obs[obs_idx++] = rel_heading_x; + obs[obs_idx++] = rel_heading_y; + obs[obs_idx++] = other_entity->sim_speed / MAX_SPEED; + obs[obs_idx++] = dz / MAX_POSITION; + cars_seen++; + } + } + int remaining_partner_obs = (env->max_partner_observations - cars_seen) * PARTNER_FEATURES; memset(&obs[obs_idx], 0, remaining_partner_obs * sizeof(float)); obs_idx += remaining_partner_obs; - // map observations - GridMapEntity entity_list[MAX_ENTITIES_PER_CELL * 25]; - int grid_idx = getGridIndex(env, ego_entity->x, ego_entity->y); - int list_size = get_neighbor_cache_entities(env, grid_idx, entity_list, MAX_ROAD_SEGMENT_OBSERVATIONS); + // Encode -> Road segments (lanes and boundaries) + int grid_idx = get_grid_index(env, ego_entity->sim_x, ego_entity->sim_y); + int list_size; + const GridMapEntity *entity_list = get_neighbor_cache_entities(env, grid_idx, &list_size); + + int lane_added = 0; + int boundary_added = 0; + int lane_obs_idx = obs_idx; + int boundary_obs_idx = lane_obs_idx + env->max_lane_segment_observations * ROAD_FEATURES; for (int k = 0; k < list_size; k++) { + if (lane_added >= env->max_lane_segment_observations && + boundary_added >= env->max_boundary_segment_observations) { + break; + } + int entity_type = entity_list[k].entity_type; int entity_idx = entity_list[k].entity_idx; int geometry_idx = entity_list[k].geometry_idx; + // Only process road elements in observations + if (entity_type != ENTITY_TYPE_ROAD_ELEMENT) + continue; + // Validate entity_idx before accessing - if (entity_idx < 0 || entity_idx >= env->num_entities) { - printf("ERROR: Invalid entity_idx %d (max: %d)\n", entity_idx, env->num_entities - 1); + if (entity_idx < 0 || entity_idx >= env->num_road_elements) { + printf("ERROR: Invalid road element idx %d (max: %d)\n", entity_idx, env->num_road_elements - 1); continue; } - Entity *entity = &env->entities[entity_idx]; + RoadMapElement *element = &env->road_elements[entity_idx]; + int is_lane = is_road_lane(element->type); + int is_edge = is_road_edge(element->type); + if (!is_lane && !is_edge) { + continue; + } // Validate geometry_idx before accessing - if (geometry_idx < 0 || geometry_idx >= entity->array_size) { - printf("ERROR: Invalid geometry_idx %d for entity %d (max: %d)\n", geometry_idx, entity_idx, - entity->array_size - 1); + if (geometry_idx < 0 || geometry_idx >= element->segment_length - 1) { + printf("ERROR: Invalid geometry_idx %d for road element %d (max: %d)\n", geometry_idx, entity_idx, + element->segment_length - 2); continue; } - float start_x = entity->traj_x[geometry_idx]; - float start_y = entity->traj_y[geometry_idx]; - float end_x = entity->traj_x[geometry_idx + 1]; - float end_y = entity->traj_y[geometry_idx + 1]; + float start_x = element->x[geometry_idx]; + float start_y = element->y[geometry_idx]; + float start_z = element->z[geometry_idx]; + float end_x = element->x[geometry_idx + 1]; + float end_y = element->y[geometry_idx + 1]; + float end_z = element->z[geometry_idx + 1]; float mid_x = (start_x + end_x) / 2.0f; float mid_y = (start_y + end_y) / 2.0f; - float rel_x = mid_x - ego_entity->x; - float rel_y = mid_y - ego_entity->y; + float mid_z = (start_z + end_z) / 2.0f; + float rel_x = mid_x - ego_entity->sim_x; + float rel_y = mid_y - ego_entity->sim_y; + float rel_z = mid_z - ego_entity->sim_z; float x_obs = rel_x * cos_heading + rel_y * sin_heading; float y_obs = -rel_x * sin_heading + rel_y * cos_heading; - float length = relative_distance_2d(mid_x, mid_y, end_x, end_y); - float width = 0.1; - // Calculate angle from ego to midpoint (vector from ego to midpoint) - float dx = end_x - mid_x; - float dy = end_y - mid_y; - float dx_norm = dx; - float dy_norm = dy; - float hypot = sqrtf(dx * dx + dy * dy); - if (hypot > 0) { - dx_norm /= hypot; - dy_norm /= hypot; - } - // Compute sin and cos of relative angle directly without atan2f - float cos_angle = dx_norm * cos_heading + dy_norm * sin_heading; - float sin_angle = -dx_norm * sin_heading + dy_norm * cos_heading; - obs[obs_idx] = x_obs * 0.02f; - obs[obs_idx + 1] = y_obs * 0.02f; - obs[obs_idx + 2] = length / MAX_ROAD_SEGMENT_LENGTH; - obs[obs_idx + 3] = width / MAX_ROAD_SCALE; - obs[obs_idx + 4] = cos_angle; - obs[obs_idx + 5] = sin_angle; - obs[obs_idx + 6] = entity->type - 4.0f; - obs_idx += 7; - } - int remaining_obs = (MAX_ROAD_SEGMENT_OBSERVATIONS - list_size) * 7; - // Set the entire block to 0 at once - memset(&obs[obs_idx], 0, remaining_obs * sizeof(float)); - } -} - -void sample_new_goal(Drive *env, int agent_idx) { - // Samples a new goal position based on the existing road lane points - Entity *agent = &env->entities[agent_idx]; - float best_x = agent->x; - float best_y = agent->y; - float best_distance_error = 1e30f; - - // Sample points from all road lanes - for (int i = env->num_objects; i < env->num_entities; i++) { - if (env->entities[i].type != ROAD_LANE) - continue; - - Entity *lane = &env->entities[i]; - - // Check every point in the lane - for (int j = 0; j < lane->array_size; j++) { - float point_x = lane->traj_x[j]; - float point_y = lane->traj_y[j]; - - // Calculate vector from agent to point - float to_point_x = point_x - agent->x; - float to_point_y = point_y - agent->y; - // Check if point is ahead of agent - float dot = to_point_x * agent->heading_x + to_point_y * agent->heading_y; - if (dot <= 0.0f) + // Filter by asymmetric vision rectangle + if (x_obs < -ROAD_OBS_BEHIND_DIST || x_obs > ROAD_OBS_FRONT_DIST) + continue; + if (fabsf(y_obs) > ROAD_OBS_SIDE_DIST) + continue; + if (fabsf(rel_z) > Z_BUFFER) continue; - // Calculate distance to point - float distance = sqrtf(to_point_x * to_point_x + to_point_y * to_point_y); - - // Find point closest to target distance - float distance_error = fabsf(distance - env->goal_target_distance); - if (distance_error < best_distance_error) { - best_distance_error = distance_error; - best_x = point_x; - best_y = point_y; - } - } - } - - // If no valid goal found, use another agent's initial goal - if (best_distance_error >= 1e30f && env->active_agent_count > 1) { - int other_idx = env->active_agent_indices[(agent_idx + 1) % env->active_agent_count]; - best_x = env->entities[other_idx].init_goal_x; - best_y = env->entities[other_idx].init_goal_y; - } - - agent->goal_position_x = best_x; - agent->goal_position_y = best_y; - agent->goals_sampled_this_episode += 1; -} - -void c_reset(Drive *env) { - env->timestep = env->init_steps; - set_start_position(env); - for (int x = 0; x < env->active_agent_count; x++) { - env->logs[x] = (Log){0}; - int agent_idx = env->active_agent_indices[x]; - env->entities[agent_idx].respawn_timestep = -1; - env->entities[agent_idx].respawn_count = 0; - env->entities[agent_idx].collided_before_goal = 0; - env->entities[agent_idx].goals_reached_this_episode = 0.0f; - // Initialize to 1 because there is one goal in the data file - env->entities[agent_idx].goals_sampled_this_episode = 1.0f; - env->entities[agent_idx].current_goal_reached = 0; - env->entities[agent_idx].metrics_array[COLLISION_IDX] = 0.0f; - env->entities[agent_idx].metrics_array[OFFROAD_IDX] = 0.0f; - env->entities[agent_idx].metrics_array[REACHED_GOAL_IDX] = 0.0f; - env->entities[agent_idx].metrics_array[LANE_ALIGNED_IDX] = 0.0f; - env->entities[agent_idx].stopped = 0; - env->entities[agent_idx].removed = 0; - - if (env->goal_behavior == GOAL_GENERATE_NEW) { - env->entities[agent_idx].goal_position_x = env->entities[agent_idx].init_goal_x; - env->entities[agent_idx].goal_position_y = env->entities[agent_idx].init_goal_y; - } - - compute_agent_metrics(env, agent_idx); - } - compute_observations(env); -} - -void respawn_agent(Drive *env, int agent_idx) { - env->entities[agent_idx].x = env->entities[agent_idx].traj_x[0]; - env->entities[agent_idx].y = env->entities[agent_idx].traj_y[0]; - env->entities[agent_idx].heading = env->entities[agent_idx].traj_heading[0]; - env->entities[agent_idx].heading_x = cosf(env->entities[agent_idx].heading); - env->entities[agent_idx].heading_y = sinf(env->entities[agent_idx].heading); - env->entities[agent_idx].vx = env->entities[agent_idx].traj_vx[0]; - env->entities[agent_idx].vy = env->entities[agent_idx].traj_vy[0]; - env->entities[agent_idx].metrics_array[COLLISION_IDX] = 0.0f; - env->entities[agent_idx].metrics_array[OFFROAD_IDX] = 0.0f; - env->entities[agent_idx].metrics_array[REACHED_GOAL_IDX] = 0.0f; - env->entities[agent_idx].metrics_array[LANE_ALIGNED_IDX] = 0.0f; - - env->entities[agent_idx].respawn_timestep = env->timestep; - env->entities[agent_idx].collided_before_goal = 0; - env->entities[agent_idx].stopped = 0; - env->entities[agent_idx].removed = 0; - env->entities[agent_idx].a_long = 0.0f; - env->entities[agent_idx].a_lat = 0.0f; - env->entities[agent_idx].jerk_long = 0.0f; - env->entities[agent_idx].jerk_lat = 0.0f; - env->entities[agent_idx].steering_angle = 0.0f; -} - -void c_step(Drive *env) { - memset(env->rewards, 0, env->active_agent_count * sizeof(float)); - memset(env->terminals, 0, env->active_agent_count * sizeof(unsigned char)); - memset(env->truncations, 0, env->active_agent_count * sizeof(unsigned char)); - env->timestep++; - - // Move static experts - for (int i = 0; i < env->expert_static_agent_count; i++) { - int expert_idx = env->expert_static_agent_indices[i]; - if (env->entities[expert_idx].x == INVALID_POSITION) - continue; - move_expert(env, env->actions, expert_idx); - } - // Process actions for all active agents - for (int i = 0; i < env->active_agent_count; i++) { - env->logs[i].score = 0.0f; - env->logs[i].episode_length += 1; - int agent_idx = env->active_agent_indices[i]; - env->entities[agent_idx].collision_state = 0; - float prev_vx = env->entities[agent_idx].vx; - float prev_vy = env->entities[agent_idx].vy; - - move_dynamics(env, i, agent_idx); - - // Tiny jerk penalty for smoothness - if (env->dynamics_model == CLASSIC) { - float delta_vx = env->entities[agent_idx].vx - prev_vx; - float delta_vy = env->entities[agent_idx].vy - prev_vy; - float jerk_penalty = -0.0002f * sqrtf(delta_vx * delta_vx + delta_vy * delta_vy) / env->dt; - env->rewards[i] += jerk_penalty; - env->logs[i].episode_return += jerk_penalty; - } - } - - // Compute rewards - for (int i = 0; i < env->active_agent_count; i++) { - int agent_idx = env->active_agent_indices[i]; - env->entities[agent_idx].collision_state = 0; - - compute_agent_metrics(env, agent_idx); - int collision_state = env->entities[agent_idx].collision_state; - - if (collision_state > 0) { - if (collision_state == VEHICLE_COLLISION) { - env->rewards[i] += env->reward_vehicle_collision; - env->logs[i].episode_return += env->reward_vehicle_collision; - env->logs[i].collision_rate = 1.0f; - env->logs[i].collisions_per_agent += 1.0f; - } else if (collision_state == OFFROAD) { - env->rewards[i] += env->reward_offroad_collision; - env->logs[i].episode_return += env->reward_offroad_collision; - env->logs[i].offroad_rate = 1.0f; - env->logs[i].offroad_per_agent += 1.0f; - } - - env->entities[agent_idx].collided_before_goal = 1; - } - - float distance_to_goal = - relative_distance_2d(env->entities[agent_idx].x, env->entities[agent_idx].y, - env->entities[agent_idx].goal_position_x, env->entities[agent_idx].goal_position_y); - - float current_speed = sqrtf(env->entities[agent_idx].vx * env->entities[agent_idx].vx + - env->entities[agent_idx].vy * env->entities[agent_idx].vy); - - // Reward agent if it is within X meters of goal and speed is below threshold - bool within_distance = distance_to_goal < env->goal_radius; - bool within_speed = current_speed <= env->goal_speed; - - if (within_distance && within_speed && !env->entities[agent_idx].current_goal_reached) { - if (env->goal_behavior == GOAL_RESPAWN && env->entities[agent_idx].respawn_timestep != -1) { - env->rewards[i] += env->reward_goal_post_respawn; - env->logs[i].episode_return += env->reward_goal_post_respawn; - env->entities[agent_idx].current_goal_reached = 1; - } else if (env->goal_behavior == GOAL_GENERATE_NEW && (!env->entities[agent_idx].current_goal_reached)) { - env->rewards[i] += env->reward_goal; - env->logs[i].episode_return += env->reward_goal; - sample_new_goal(env, agent_idx); - env->entities[agent_idx].current_goal_reached = 0; - env->entities[agent_idx].goals_reached_this_episode += 1.0f; - } else { // Zero out the velocity so that the agent stops at the goal - env->rewards[i] = env->reward_goal; - env->logs[i].episode_return = env->reward_goal; - env->entities[agent_idx].stopped = 1; - env->entities[agent_idx].vx = env->entities[agent_idx].vy = 0.0f; - env->entities[agent_idx].goals_reached_this_episode += 1.0f; - } - env->entities[agent_idx].metrics_array[REACHED_GOAL_IDX] = 1.0f; - env->logs[i].speed_at_goal = current_speed; - } - - int lane_aligned = env->entities[agent_idx].metrics_array[LANE_ALIGNED_IDX]; - env->logs[i].lane_alignment_rate = lane_aligned; - } - - if (env->goal_behavior == GOAL_RESPAWN) { - for (int i = 0; i < env->active_agent_count; i++) { - int agent_idx = env->active_agent_indices[i]; - int reached_goal = env->entities[agent_idx].metrics_array[REACHED_GOAL_IDX]; - if (reached_goal) { - env->terminals[i] = 1; - respawn_agent(env, agent_idx); - env->entities[agent_idx].respawn_count++; - } - } - } else if (env->goal_behavior == GOAL_STOP) { - for (int i = 0; i < env->active_agent_count; i++) { - int agent_idx = env->active_agent_indices[i]; - int reached_goal = env->entities[agent_idx].metrics_array[REACHED_GOAL_IDX]; - if (reached_goal) { - env->entities[agent_idx].stopped = 1; - env->entities[agent_idx].vx = env->entities[agent_idx].vy = 0.0f; - } - } - } - - // Episode boundary after this step: treat time-limit and early-termination as truncation. - // `timestep` is incremented at step start, so truncate when `(timestep + 1) >= episode_length`. - int originals_remaining = 0; - for (int i = 0; i < env->active_agent_count; i++) { - int agent_idx = env->active_agent_indices[i]; - if (env->entities[agent_idx].respawn_count == 0) { - originals_remaining = 1; - break; - } - } - int reached_time_limit = (env->timestep + 1) >= env->episode_length; - int reached_early_termination = (!originals_remaining && env->termination_mode == 1); - if (reached_time_limit || reached_early_termination) { - for (int i = 0; i < env->active_agent_count; i++) { - env->truncations[i] = 1; - } - add_log(env); - c_reset(env); - return; - } - - compute_observations(env); -} + // Compute segment direction and length (single sqrt instead of two) + float dx = end_x - mid_x; + float dy = end_y - mid_y; + float length = sqrtf(dx * dx + dy * dy); + float dx_norm = (length > 0) ? dx / length : dx; + float dy_norm = (length > 0) ? dy / length : dy; + float cos_angle = dx_norm * cos_heading + dy_norm * sin_heading; + float sin_angle = -dx_norm * sin_heading + dy_norm * cos_heading; -typedef struct Client Client; + int write_idx = 0; + if (is_lane) { + if (lane_added >= env->max_lane_segment_observations) { + continue; + } + write_idx = lane_obs_idx + lane_added * ROAD_FEATURES; + lane_added++; + } else { + if (boundary_added >= env->max_boundary_segment_observations) { + continue; + } + write_idx = boundary_obs_idx + boundary_added * ROAD_FEATURES; + boundary_added++; + } -struct Client { - float width; - float height; - Texture2D puffers; - Vector3 camera_target; - float camera_zoom; - Camera3D camera; - Model cars[6]; - Model cyclist; - Model pedestrian; - ModelAnimation *cycle_anim; - int car_assignments[MAX_AGENTS]; - Vector3 default_camera_position; - Vector3 default_camera_target; - int recorder_pipefd[2]; - pid_t recorder_pid; - pid_t xvfb_pid; - int xvfb_display_num; -}; + obs[write_idx] = x_obs / MAX_POSITION; + obs[write_idx + 1] = y_obs / MAX_POSITION; + obs[write_idx + 2] = length / MAX_ROAD_SEGMENT_LENGTH; + obs[write_idx + 3] = 0.1f / MAX_ROAD_SCALE; + obs[write_idx + 4] = cos_angle; + obs[write_idx + 5] = sin_angle; + obs[write_idx + 6] = rel_z / MAX_POSITION; + } + int remaining_lane_obs = (env->max_lane_segment_observations - lane_added) * ROAD_FEATURES; + memset(&obs[lane_obs_idx + lane_added * ROAD_FEATURES], 0, remaining_lane_obs * sizeof(float)); + int remaining_boundary_obs = (env->max_boundary_segment_observations - boundary_added) * ROAD_FEATURES; + memset(&obs[boundary_obs_idx + boundary_added * ROAD_FEATURES], 0, remaining_boundary_obs * sizeof(float)); + obs_idx = boundary_obs_idx + env->max_boundary_segment_observations * ROAD_FEATURES; + + // Traffic light observations + typedef struct { + int idx; + float dist_sq; + } TrafficLightDist; + TrafficLightDist traffic_lights[env->num_traffic_elements > 0 ? env->num_traffic_elements : 1]; + int num_visible_lights = 0; + + // Collect traffic lights within range + for (int j = 0; j < env->num_traffic_elements; j++) { + TrafficControlElement *traffic = &env->traffic_elements[j]; + if (traffic->type != TRAFFIC_LIGHT) + continue; // Only traffic lights + + float mid_x = (traffic->stop_line[0] + traffic->stop_line[3]) * 0.5f; + float mid_y = (traffic->stop_line[1] + traffic->stop_line[4]) * 0.5f; + float mid_z = (traffic->stop_line[2] + traffic->stop_line[5]) * 0.5f; + float dx = mid_x - ego_entity->sim_x; + float dy = mid_y - ego_entity->sim_y; + float dz = mid_z - ego_entity->sim_z; + float abs_dz = fabsf(dz); + float dist_sq = dx * dx + dy * dy + dz * dz; + + if (dist_sq > MAX_TRAFFIC_LIGHT_DISTANCE * MAX_TRAFFIC_LIGHT_DISTANCE || abs_dz > Z_BUFFER) + continue; -Client *make_client(Drive *env) { - - Client *client = (Client *)calloc(1, sizeof(Client)); - - if (env->render_mode == RENDER_HEADLESS && getenv("DISPLAY") == NULL) { - - // Kill any existing Xvfb first - system("pkill -9 Xvfb"); - usleep(200000); - unlink("/tmp/.X99-lock"); - unlink("/tmp/.X11-unix/X99"); - - // Hardcode to single display because we only run this in one process at once - client->xvfb_display_num = 99; - - // Clean up stale lock if process is dead - FILE *f = fopen("/tmp/.X99-lock", "r"); - if (f) { - pid_t pid = -1; - fscanf(f, "%d", &pid); - fclose(f); - if (pid > 0 && kill(pid, 0) != 0) - unlink("/tmp/.X99-lock"); - } - - client->xvfb_pid = fork(); - if (client->xvfb_pid == 0) { - close(STDOUT_FILENO); - close(STDERR_FILENO); - execlp("Xvfb", "Xvfb", ":99", "-screen", "0", "1280x720x24", "+extension", "GLX", "-ac", "-noreset", NULL); - _exit(1); - } - - setenv("DISPLAY", ":99", 1); - // Xvfb starts asynchronously after fork(), so we poll until it creates its - // lock file (max 2s) then wait an extra 200ms for GLX to finish initializing. - // Without this, raylib's InitWindow() would try to connect before Xvfb is ready. - for (int i = 0; i < 20 && access("/tmp/.X99-lock", F_OK) != 0; i++) - usleep(100000); - usleep(200000); - } - - if (env->render_mode == RENDER_WINDOW) { - client->width = 1280; - client->height = 704; - SetConfigFlags(FLAG_MSAA_4X_HINT); - SetTargetFPS(30); - - // Set up camera for interactive window - Vector3 target_pos = {0, 0, 1}; // Y is up, Z is depth + traffic_lights[num_visible_lights].idx = j; + traffic_lights[num_visible_lights].dist_sq = dist_sq; + num_visible_lights++; + } - client->default_camera_position = (Vector3){ - 0, // Same X as target - 120.0f, // 20 units above target - 175.0f // 20 units behind target - }; - client->default_camera_target = target_pos; - client->camera.position = client->default_camera_position; - client->camera.target = client->default_camera_target; - client->camera.up = (Vector3){0.0f, -1.0f, 0.0f}; // Y is up - client->camera.fovy = 45.0f; - client->camera.projection = CAMERA_PERSPECTIVE; + // Partial selection sort: find K closest (O(N*K) instead of O(N²) bubble sort) + int num_lights_to_observe = (num_visible_lights < env->max_traffic_light_observations) + ? num_visible_lights + : env->max_traffic_light_observations; + for (int k = 0; k < num_lights_to_observe; k++) { + int min_idx = k; + for (int j = k + 1; j < num_visible_lights; j++) { + if (traffic_lights[j].dist_sq < traffic_lights[min_idx].dist_sq) { + min_idx = j; + } + } + if (min_idx != k) { + TrafficLightDist temp = traffic_lights[k]; + traffic_lights[k] = traffic_lights[min_idx]; + traffic_lights[min_idx] = temp; + } + } - } else { // Headless rendering - SetConfigFlags(FLAG_WINDOW_HIDDEN); - SetTargetFPS(6000); + // Add observations for closest traffic lights + int lights_added = 0; + for (int j = 0; j < num_lights_to_observe && lights_added < env->max_traffic_light_observations; j++) { + TrafficControlElement *traffic = &env->traffic_elements[traffic_lights[j].idx]; + + // Stop line endpoint 1 + float dx1 = traffic->stop_line[0] - ego_entity->sim_x; + float dy1 = traffic->stop_line[1] - ego_entity->sim_y; + float rel_x1 = dx1 * cos_heading + dy1 * sin_heading; + float rel_y1 = -dx1 * sin_heading + dy1 * cos_heading; + + // Stop line endpoint 2 + float dx2 = traffic->stop_line[3] - ego_entity->sim_x; + float dy2 = traffic->stop_line[4] - ego_entity->sim_y; + float rel_x2 = dx2 * cos_heading + dy2 * sin_heading; + float rel_y2 = -dx2 * sin_heading + dy2 * cos_heading; + float rel_z = ((traffic->stop_line[2] + traffic->stop_line[5]) * 0.5f - ego_entity->sim_z) / MAX_POSITION; + + // Get current state with bounds check + int t = env->timestep; + int state = TL_STATE_DISABLED; + if (t >= 0 && t < traffic->state_length) { + state = traffic->states[t]; + } - float map_width = env->grid_map->bottom_right_x - env->grid_map->top_left_x; - float map_height = env->grid_map->top_left_y - env->grid_map->bottom_right_y; - float scale = 6.0f; // Controls the resolution of the output video - int img_width = (int)roundf(map_width * scale / 2.0f) * 2; - int img_height = (int)roundf(map_height * scale / 2.0f) * 2; + obs[obs_idx++] = rel_x1 / MAX_POSITION; + obs[obs_idx++] = rel_y1 / MAX_POSITION; + obs[obs_idx++] = rel_x2 / MAX_POSITION; + obs[obs_idx++] = rel_y2 / MAX_POSITION; + obs[obs_idx++] = rel_z; + obs[obs_idx++] = normalize_traffic_light_state(state); + lights_added++; + } - client->width = img_width; - client->height = img_height; + // Zero out remaining traffic light slots + int remaining_traffic_obs = (env->max_traffic_light_observations - lights_added) * TRAFFIC_LIGHT_FEATURES; + memset(&obs[obs_idx], 0, remaining_traffic_obs * sizeof(float)); } +} - SetTraceLogLevel(LOG_WARNING); // Only show warnings and errors - InitWindow(client->width, client->height, "PufferDrive"); +static void move_dynamics(Drive *env, int action_idx, int agent_idx) { + Agent *agent = &env->agents[agent_idx]; - // Load assets - client->cars[0] = LoadModel("resources/drive/RedCar.glb"); - client->cars[1] = LoadModel("resources/drive/WhiteCar.glb"); - client->cars[2] = LoadModel("resources/drive/BlueCar.glb"); - client->cars[3] = LoadModel("resources/drive/YellowCar.glb"); - client->cars[4] = LoadModel("resources/drive/GreenCar.glb"); - client->cars[5] = LoadModel("resources/drive/GreyCar.glb"); - client->cyclist = LoadModel("resources/drive/cyclist.glb"); - client->pedestrian = LoadModel("resources/drive/pedestrian.glb"); - int animCountCyc = 0; - client->cycle_anim = LoadModelAnimations("resources/drive/cyclist.glb", &animCountCyc); - for (int i = 0; i < MAX_AGENTS; i++) { - client->car_assignments[i] = (rand() % 4) + 1; + // If agent is removed, set position to invalid and return + if (agent->removed) { + invalidate_agent(agent); + return; } - // Set up ffmpeg process for recording - if (env->render_mode == RENDER_HEADLESS) { - if (pipe(client->recorder_pipefd) == -1) { - fprintf(stderr, "Failed to create pipe\n"); - free(client); - return NULL; - } - - char size_str[64]; - snprintf(size_str, sizeof(size_str), "%dx%d", (int)client->width, (int)client->height); - - char filename[256]; - snprintf(filename, sizeof(filename), "%s.mp4", env->scenario_id); - - client->recorder_pid = fork(); - if (client->recorder_pid == -1) { - fprintf(stderr, "Failed to fork\n"); - free(client); - return NULL; - } - - if (client->recorder_pid == 0) { // Child process - close(client->recorder_pipefd[1]); - dup2(client->recorder_pipefd[0], STDIN_FILENO); - close(client->recorder_pipefd[0]); - for (int fd = 3; fd < 256; fd++) - close(fd); - execlp("ffmpeg", "ffmpeg", "-y", "-f", "rawvideo", "-pix_fmt", "rgba", "-s", size_str, "-r", "30", "-i", - "-", "-c:v", "libx264", "-pix_fmt", "yuv420p", "-preset", "ultrafast", "-crf", "23", "-loglevel", - "error", filename, NULL); - fprintf(stderr, "execlp ffmpeg failed\n"); - _exit(1); - } - close(client->recorder_pipefd[0]); - } - - return client; -} - -// Camera control functions -void handle_camera_controls(Client *client) { - static Vector2 prev_mouse_pos = {0}; - static bool is_dragging = false; - float camera_move_speed = 0.5f; - - // Handle mouse drag for camera movement - if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { - prev_mouse_pos = GetMousePosition(); - is_dragging = true; - } - - if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) { - is_dragging = false; - } - - if (is_dragging) { - Vector2 current_mouse_pos = GetMousePosition(); - Vector2 delta = {(current_mouse_pos.x - prev_mouse_pos.x) * camera_move_speed, - -(current_mouse_pos.y - prev_mouse_pos.y) * camera_move_speed}; - - // Update camera position (only X and Y) - client->camera.position.x += delta.x; - client->camera.position.y += delta.y; - - // Update camera target (only X and Y) - client->camera.target.x += delta.x; - client->camera.target.y += delta.y; - - prev_mouse_pos = current_mouse_pos; - } + // If agent is stopped, zero out velocities and accelerations + if (agent->stopped) { + agent->sim_vx = 0.0f; + agent->sim_vy = 0.0f; + agent->yaw_rate = 0.0f; + agent->sim_speed = 0.0f; + agent->sim_speed_signed = 0.0f; + agent->a_long = 0.0f; + agent->a_lat = 0.0f; + agent->jerk_long = 0.0f; + agent->jerk_lat = 0.0f; + agent->steering_angle = 0.0f; + return; + } - // Handle mouse wheel for zoom - float wheel = GetMouseWheelMove(); - if (wheel != 0) { - float zoom_factor = 1.0f - (wheel * 0.1f); - // Calculate the current direction vector from target to position - Vector3 direction = {client->camera.position.x - client->camera.target.x, - client->camera.position.y - client->camera.target.y, - client->camera.position.z - client->camera.target.z}; + if (env->dynamics_model == CLASSIC) { + // Classic dynamics model + float acceleration = 0.0f; + float steering = 0.0f; - // Scale the direction vector by the zoom factor - direction.x *= zoom_factor; - direction.y *= zoom_factor; - direction.z *= zoom_factor; - - // Update the camera position based on the scaled direction - client->camera.position.x = client->camera.target.x + direction.x; - client->camera.position.y = client->camera.target.y + direction.y; - client->camera.position.z = client->camera.target.z + direction.z; - } -} + if (env->action_type == 0) { // discrete + // Interpret action as a single integer: a = accel_idx * num_steer + steer_idx + int *action_array = (int *)env->actions; + int num_steer = sizeof(STEERING_VALUES) / sizeof(STEERING_VALUES[0]); + int action_val = action_array[action_idx]; + int acceleration_index = action_val / num_steer; + int steering_index = action_val % num_steer; + acceleration = ACCELERATION_VALUES[acceleration_index]; + steering = STEERING_VALUES[steering_index]; + } else if (env->action_type == 1) { // continuous + float (*action_array_f)[2] = (float (*)[2])env->actions; + acceleration = action_array_f[action_idx][0]; + steering = action_array_f[action_idx][1]; -void draw_agent_obs(Drive *env, int agent_index, int mode, int obs_only, int lasers) { - // Diamond dimensions - float diamond_height = 3.0f; // Total height of diamond - float diamond_width = 1.5f; // Width of diamond - float diamond_z = 8.0f; // Base Z position + acceleration *= ACCELERATION_VALUES[6]; + steering *= STEERING_VALUES[8]; + } - // Define diamond points - Vector3 top_point = (Vector3){0.0f, 0.0f, diamond_z + diamond_height / 2}; // Top point - Vector3 bottom_point = (Vector3){0.0f, 0.0f, diamond_z - diamond_height / 2}; // Bottom point - Vector3 front_point = (Vector3){0.0f, diamond_width / 2, diamond_z}; // Front point - Vector3 back_point = (Vector3){0.0f, -diamond_width / 2, diamond_z}; // Back point - Vector3 left_point = (Vector3){-diamond_width / 2, 0.0f, diamond_z}; // Left point - Vector3 right_point = (Vector3){diamond_width / 2, 0.0f, diamond_z}; // Right point + // Limit the steering rate similar to the jerk model + float delta_steer = clip(steering - agent->steering_angle, -0.6f * env->dt, 0.6f * env->dt); + steering = clip(agent->steering_angle + delta_steer, -0.667f, 0.667f); + agent->steering_angle = steering; - // Draw the diamond faces - // Top pyramid - if (mode == 0) { - DrawTriangle3D(top_point, front_point, right_point, PUFF_CYAN); // Front-right face - DrawTriangle3D(top_point, right_point, back_point, PUFF_CYAN); // Back-right face - DrawTriangle3D(top_point, back_point, left_point, PUFF_CYAN); // Back-left face - DrawTriangle3D(top_point, left_point, front_point, PUFF_CYAN); // Front-left face + // Current state + float x = agent->sim_x; + float y = agent->sim_y; + float heading = agent->sim_heading; + float speed = agent->sim_speed_signed; - // Bottom pyramid - DrawTriangle3D(bottom_point, right_point, front_point, PUFF_CYAN); // Front-right face - DrawTriangle3D(bottom_point, back_point, right_point, PUFF_CYAN); // Back-right face - DrawTriangle3D(bottom_point, left_point, back_point, PUFF_CYAN); // Back-left face - DrawTriangle3D(bottom_point, front_point, left_point, PUFF_CYAN); // Front-left face - } - if (!IsKeyDown(KEY_LEFT_CONTROL) && obs_only == 0) { - return; - } + // Update speed with acceleration + speed += acceleration * env->dt; + speed = clip(speed, -MAX_SPEED, MAX_SPEED); + // Compute yaw rate + float beta = atanf(0.5f * tanf(steering)); + // New heading + float yaw_rate = (speed * cosf(beta) * tanf(steering)) / agent->wheelbase; - int ego_dim = (env->dynamics_model == JERK) ? EGO_FEATURES_JERK : EGO_FEATURES_CLASSIC; - int max_obs = ego_dim + PARTNER_FEATURES * (MAX_AGENTS - 1) + ROAD_FEATURES * MAX_ROAD_SEGMENT_OBSERVATIONS; - float (*observations)[max_obs] = (float (*)[max_obs])env->observations; - float *agent_obs = &observations[agent_index][0]; - // self - int active_idx = env->active_agent_indices[agent_index]; - float heading_self_x = env->entities[active_idx].heading_x; - float heading_self_y = env->entities[active_idx].heading_y; - float px = env->entities[active_idx].x; - float py = env->entities[active_idx].y; - // draw goal - float goal_x = agent_obs[0] * 200; - float goal_y = agent_obs[1] * 200; - - int agent_type = env->entities[active_idx].type; - Color goal_color = LIGHTBLUE; - if (agent_type == PEDESTRIAN) - goal_color = LIGHT_ORANGE; - else if (agent_type == CYCLIST) - goal_color = LIGHT_PURPLE; - - if (mode == 0) { // agent-relative coordinates - DrawSphere((Vector3){goal_x, goal_y, Z_AGENT_DETAILS}, 0.5f, goal_color); - DrawCircle3D((Vector3){goal_x, goal_y, Z_AGENT_DETAILS}, env->goal_radius, (Vector3){0, 0, 1}, 90.0f, - Fade(goal_color, 0.3f)); - } - - if (mode == 1) { // world coordinates - - float goal_x_world = px + (goal_x * heading_self_x - goal_y * heading_self_y); - float goal_y_world = py + (goal_x * heading_self_y + goal_y * heading_self_x); - DrawSphere((Vector3){goal_x_world, goal_y_world, Z_AGENT_DETAILS}, 0.5f, goal_color); - DrawCircle3D((Vector3){goal_x_world, goal_y_world, Z_AGENT_DETAILS}, env->goal_radius, (Vector3){0, 0, 1}, - 90.0f, Fade(goal_color, 0.3f)); - } - // First draw other agent observations - int obs_idx = ego_dim; // Start after ego obs - for (int j = 0; j < MAX_AGENTS - 1; j++) { - if (agent_obs[obs_idx] == 0 || agent_obs[obs_idx + 1] == 0) { - obs_idx += 7; // Move to next agent observation - continue; - } - // Draw position of other agents - float x = agent_obs[obs_idx] * 50; - float y = agent_obs[obs_idx + 1] * 50; - if (lasers && mode == 0) { - DrawLine3D((Vector3){0, 0, 0}, (Vector3){x, y, Z_AGENT_DETAILS}, ORANGE); - } - - float partner_x = px + (x * heading_self_x - y * heading_self_y); - float partner_y = py + (x * heading_self_y + y * heading_self_x); - if (lasers && mode == 1) { - DrawLine3D((Vector3){px, py, Z_AGENT_DETAILS}, (Vector3){partner_x, partner_y, Z_AGENT_DETAILS}, ORANGE); - } - - float half_width = 0.5 * agent_obs[obs_idx + 2] * MAX_VEH_WIDTH; - float half_len = 0.5 * agent_obs[obs_idx + 3] * MAX_VEH_LEN; - float theta_x = agent_obs[obs_idx + 4]; - float theta_y = agent_obs[obs_idx + 5]; - float partner_angle = atan2f(theta_y, theta_x); - float cos_heading = cosf(partner_angle); - float sin_heading = sinf(partner_angle); - Vector3 corners[4] = { - (Vector3){x + (half_len * cos_heading - half_width * sin_heading), - y + (half_len * sin_heading + half_width * cos_heading), Z_AGENT_DETAILS}, - (Vector3){x + (half_len * cos_heading + half_width * sin_heading), - y + (half_len * sin_heading - half_width * cos_heading), Z_AGENT_DETAILS}, - (Vector3){x + (-half_len * cos_heading + half_width * sin_heading), - y + (-half_len * sin_heading - half_width * cos_heading), Z_AGENT_DETAILS}, - (Vector3){x + (-half_len * cos_heading - half_width * sin_heading), - y + (-half_len * sin_heading + half_width * cos_heading), Z_AGENT_DETAILS}, - }; - - if (mode == 0) { - for (int j = 0; j < 4; j++) { - DrawLine3D(corners[j], corners[(j + 1) % 4], ORANGE); - } - } + // New velocity + float new_vx = speed * cosf(heading + beta); + float new_vy = speed * sinf(heading + beta); - if (mode == 1) { - Vector3 world_corners[4]; - for (int j = 0; j < 4; j++) { - float lx = corners[j].x; - float ly = corners[j].y; + // Update position + x = x + (new_vx * env->dt); + y = y + (new_vy * env->dt); + heading = heading + yaw_rate * env->dt; - world_corners[j].x = px + (lx * heading_self_x - ly * heading_self_y); - world_corners[j].y = py + (lx * heading_self_y + ly * heading_self_x); - world_corners[j].z = 1; - } - for (int j = 0; j < 4; j++) { - DrawLine3D(world_corners[j], world_corners[(j + 1) % 4], ORANGE); - } - } + // Apply updates to the agent's state + agent->sim_x = x; + agent->sim_y = y; + agent->sim_heading = normalize_heading(heading); + agent->cos_heading = cosf(agent->sim_heading); + agent->sin_heading = sinf(agent->sim_heading); + agent->sim_vx = new_vx; + agent->sim_vy = new_vy; + agent->yaw_rate = yaw_rate; + update_agent_speed(agent); + + // Compute acceleration and jerk from finite differences (for comfort metric) + float new_a_long = acceleration; // commanded longitudinal acceleration + float new_a_lat = speed * yaw_rate; // centripetal: v * omega + agent->jerk_long = (new_a_long - agent->a_long) / env->dt; + agent->jerk_lat = (new_a_lat - agent->a_lat) / env->dt; + agent->a_long = new_a_long; + agent->a_lat = new_a_lat; + } else { + // JERK dynamics model + // Extract jerk action components + float j_long, j_lat; + if (env->action_type == 1) { // continuous + float (*action_array_f)[2] = (float (*)[2])env->actions; - // draw an arrow above the car pointing in the direction that the partner is going - float arrow_length = 2.5f; - float arrow_x = x + arrow_length * cosf(partner_angle); - float arrow_y = y + arrow_length * sinf(partner_angle); - float arrow_x_world; - float arrow_y_world; - if (mode == 0) { - DrawLine3D((Vector3){x, y, Z_AGENT_DETAILS}, (Vector3){arrow_x, arrow_y, Z_AGENT_DETAILS}, PUFF_WHITE); - } - if (mode == 1) { - arrow_x_world = px + (arrow_x * heading_self_x - arrow_y * heading_self_y); - arrow_y_world = py + (arrow_x * heading_self_y + arrow_y * heading_self_x); - DrawLine3D((Vector3){partner_x, partner_y, Z_AGENT_DETAILS}, - (Vector3){arrow_x_world, arrow_y_world, Z_AGENT_DETAILS}, PUFF_WHITE); - } - // Calculate perpendicular offsets for arrow head - float arrow_size = 0.3f; // Size of the arrow head - float dx = arrow_x - x; - float dy = arrow_y - y; - float length = sqrtf(dx * dx + dy * dy); - if (length > 0) { - // Normalize direction vector - dx /= length; - dy /= length; - - // Calculate perpendicular vector - float perp_x = -dy * arrow_size; - float perp_y = dx * arrow_size; - - float arrow_x_end1 = arrow_x - dx * arrow_size + perp_x; - float arrow_y_end1 = arrow_y - dy * arrow_size + perp_y; - float arrow_x_end2 = arrow_x - dx * arrow_size - perp_x; - float arrow_y_end2 = arrow_y - dy * arrow_size - perp_y; - - // Draw the two lines forming the arrow head - if (mode == 0) { - DrawLine3D((Vector3){arrow_x, arrow_y, 0.0}, (Vector3){arrow_x_end1, arrow_y_end1, 0.0}, PUFF_WHITE); - DrawLine3D((Vector3){arrow_x, arrow_y, 0.0}, (Vector3){arrow_x_end2, arrow_y_end2, 0.0}, PUFF_WHITE); + // Asymmetric scaling for longitudinal jerk to match discrete action space + // Discrete: JERK_LONG = [-15, -4, 0, 4] (more braking than acceleration) + float j_long_action = action_array_f[action_idx][0]; // [-1, 1] + if (j_long_action < 0) { + j_long = j_long_action * (-JERK_LONG[0]); // Negative: [-1, 0] → [-15, 0] (braking) + } else { + j_long = j_long_action * JERK_LONG[3]; // Positive: [0, 1] → [0, 4] (acceleration) } - if (mode == 1) { - float arrow_x_end1_world = px + (arrow_x_end1 * heading_self_x - arrow_y_end1 * heading_self_y); - float arrow_y_end1_world = py + (arrow_x_end1 * heading_self_y + arrow_y_end1 * heading_self_x); - float arrow_x_end2_world = px + (arrow_x_end2 * heading_self_x - arrow_y_end2 * heading_self_y); - float arrow_y_end2_world = py + (arrow_x_end2 * heading_self_y + arrow_y_end2 * heading_self_x); - DrawLine3D((Vector3){arrow_x_world, arrow_y_world, 0.0}, - (Vector3){arrow_x_end1_world, arrow_y_end1_world, 0.0}, PUFF_WHITE); - DrawLine3D((Vector3){arrow_x_world, arrow_y_world, 0.0}, - (Vector3){arrow_x_end2_world, arrow_y_end2_world, 0.0}, PUFF_WHITE); - } + // Symmetric scaling for lateral jerk + j_lat = action_array_f[action_idx][1] * JERK_LAT[2]; + } else if (env->action_type == 0) { // discrete + // Interpret action as a single integer: a = long_idx * num_lat + lat_idx + int *action_array = (int *)env->actions; + int num_lat = sizeof(JERK_LAT) / sizeof(JERK_LAT[0]); + int action_val = action_array[action_idx]; + int j_long_idx = action_val / num_lat; + int j_lat_idx = action_val % num_lat; + j_long = JERK_LONG[j_long_idx]; + j_lat = JERK_LAT[j_lat_idx]; } - obs_idx += PARTNER_FEATURES; // Move to next agent observation (7 values per agent) - } - // Then draw map observations - int map_start_idx = ego_dim + PARTNER_FEATURES * (MAX_AGENTS - 1); // Start after agent observations - for (int k = 0; k < MAX_ROAD_SEGMENT_OBSERVATIONS; k++) { // Loop through potential map entities - int entity_idx = map_start_idx + k * 7; - if (agent_obs[entity_idx] == 0 && agent_obs[entity_idx + 1] == 0) { - continue; - } - Color lineColor = BLUE; // Default color - int entity_type = (int)agent_obs[entity_idx + 6]; - // Choose color based on entity type - if (entity_type + 4 != ROAD_EDGE) { - continue; - } - lineColor = PUFF_CYAN; - // For road segments, draw line between start and end points - float x_middle = agent_obs[entity_idx] * 50; - float y_middle = agent_obs[entity_idx + 1] * 50; - float rel_angle_x = (agent_obs[entity_idx + 4]); - float rel_angle_y = (agent_obs[entity_idx + 5]); - float rel_angle = atan2f(rel_angle_y, rel_angle_x); - float segment_length = agent_obs[entity_idx + 2] * MAX_ROAD_SEGMENT_LENGTH; - // Calculate endpoint using the relative angle directly - // Calculate endpoint directly - float x_start = x_middle - segment_length * cosf(rel_angle); - float y_start = y_middle - segment_length * sinf(rel_angle); - float x_end = x_middle + segment_length * cosf(rel_angle); - float y_end = y_middle + segment_length * sinf(rel_angle); - - if (lasers && mode == 0) { - DrawLine3D((Vector3){0, 0, 0}, (Vector3){x_middle, y_middle, 1}, lineColor); - } - - if (mode == 1) { - float x_middle_world = px + (x_middle * heading_self_x - y_middle * heading_self_y); - float y_middle_world = py + (x_middle * heading_self_y + y_middle * heading_self_x); - float x_start_world = px + (x_start * heading_self_x - y_start * heading_self_y); - float y_start_world = py + (x_start * heading_self_y + y_start * heading_self_x); - float x_end_world = px + (x_end * heading_self_x - y_end * heading_self_y); - float y_end_world = py + (x_end * heading_self_y + y_end * heading_self_x); - DrawCube((Vector3){x_middle_world, y_middle_world, 1}, 0.5f, 0.5f, 0.5f, lineColor); - DrawLine3D((Vector3){x_start_world, y_start_world, 1}, (Vector3){x_end_world, y_end_world, 1}, BLUE); - if (lasers) - DrawLine3D((Vector3){px, py, 1}, (Vector3){x_middle_world, y_middle_world, 1}, lineColor); - } - if (mode == 0) { - DrawCube((Vector3){x_middle, y_middle, 1}, 0.5f, 0.5f, 0.5f, lineColor); - DrawLine3D((Vector3){x_start, y_start, 1}, (Vector3){x_end, y_end, 1}, BLUE); - } - } -} - -void draw_road_edge(Drive *env, float start_x, float start_y, float end_x, float end_y) { - Color CURB_TOP = (Color){220, 220, 220, 255}; // Top surface - lightest - Color CURB_SIDE = (Color){180, 180, 180, 255}; // Side faces - medium - Color CURB_BOTTOM = (Color){160, 160, 160, 255}; - // Calculate curb dimensions - float curb_height = 0.5f; // Height of the curb - float curb_width = 0.3f; // Width/thickness of the curb - float road_z = 0.0f; // Ensure z-level for roads is below agents - - // Calculate direction vector between start and end - Vector3 direction = {end_x - start_x, end_y - start_y, 0.0f}; - - // Calculate length of the segment - float length = sqrtf(direction.x * direction.x + direction.y * direction.y); - - // Normalize direction vector - Vector3 normalized_dir = {direction.x / length, direction.y / length, 0.0f}; - - // Calculate perpendicular vector for width - Vector3 perpendicular = {-normalized_dir.y, normalized_dir.x, 0.0f}; - - // Calculate the four bottom corners of the curb - Vector3 b1 = {start_x - perpendicular.x * curb_width / 2, start_y - perpendicular.y * curb_width / 2, road_z}; - Vector3 b2 = {start_x + perpendicular.x * curb_width / 2, start_y + perpendicular.y * curb_width / 2, road_z}; - Vector3 b3 = {end_x + perpendicular.x * curb_width / 2, end_y + perpendicular.y * curb_width / 2, road_z}; - Vector3 b4 = {end_x - perpendicular.x * curb_width / 2, end_y - perpendicular.y * curb_width / 2, road_z}; - - // Draw the curb faces - // Bottom face - DrawTriangle3D(b1, b2, b3, CURB_BOTTOM); - DrawTriangle3D(b1, b3, b4, CURB_BOTTOM); - - // Top face (raised by curb_height) - Vector3 t1 = {b1.x, b1.y, b1.z + curb_height}; - Vector3 t2 = {b2.x, b2.y, b2.z + curb_height}; - Vector3 t3 = {b3.x, b3.y, b3.z + curb_height}; - Vector3 t4 = {b4.x, b4.y, b4.z + curb_height}; - DrawTriangle3D(t1, t3, t2, CURB_TOP); - DrawTriangle3D(t1, t4, t3, CURB_TOP); - - // Side faces - DrawTriangle3D(b1, t1, b2, CURB_SIDE); - DrawTriangle3D(t1, t2, b2, CURB_SIDE); - DrawTriangle3D(b2, t2, b3, CURB_SIDE); - DrawTriangle3D(t2, t3, b3, CURB_SIDE); - DrawTriangle3D(b3, t3, b4, CURB_SIDE); - DrawTriangle3D(t3, t4, b4, CURB_SIDE); - DrawTriangle3D(b4, t4, b1, CURB_SIDE); - DrawTriangle3D(t4, t1, b1, CURB_SIDE); -} - -void draw_scene(Drive *env, Client *client, int mode, int obs_only, int lasers, int show_grid) { - - if (show_grid) { - float grid_start_x = env->grid_map->top_left_x; - float grid_start_y = env->grid_map->bottom_right_y; - for (int i = 0; i < env->grid_map->grid_cols; i++) { - for (int j = 0; j < env->grid_map->grid_rows; j++) { - float x = grid_start_x + i * GRID_CELL_SIZE; - float y = grid_start_y + j * GRID_CELL_SIZE; - DrawCubeWires((Vector3){x + GRID_CELL_SIZE / 2, y + GRID_CELL_SIZE / 2, 0.0f}, GRID_CELL_SIZE, - GRID_CELL_SIZE, 0.1f, Fade(PUFF_BACKGROUND2, 0.3f)); - } - } - } + // Get dynamic conditioning coefficients + float c_throttle = agent->reward_coefs[REWARD_COEF_THROTTLE]; + float c_steer = agent->reward_coefs[REWARD_COEF_STEER]; + float c_acc = agent->reward_coefs[REWARD_COEF_ACC]; - // Draw a grid to help with orientation - for (int i = 0; i < env->num_entities; i++) { - // Draw objects - if (env->entities[i].type == VEHICLE || env->entities[i].type == PEDESTRIAN || - env->entities[i].type == CYCLIST) { - // Check if this vehicle is an active agent - bool is_active_agent = false; - bool is_static_agent = false; - int agent_index = -1; - for (int j = 0; j < env->active_agent_count; j++) { - if (env->active_agent_indices[j] == i) { - is_active_agent = true; - agent_index = j; - break; - } - } + // Calculate new longitudinal acceleration from jerk (Eq. 1 in paper) + float a_long_new = agent->a_long + c_throttle * j_long * env->dt; - for (int j = 0; j < env->expert_static_agent_count; j++) { - if (env->expert_static_agent_indices[j] == i) { - is_static_agent = true; - break; - } - } + // Zero-crossing: snap to 0 when crossing zero + if (agent->a_long * a_long_new < 0) { + a_long_new = 0.0f; + } else { + a_long_new = clip(a_long_new, -5.0f, 2.5f * c_acc); + } - for (int j = 0; j < env->static_agent_count; j++) { - if (env->static_agent_indices[j] == i) { - is_static_agent = true; - break; - } - } + // Calculate new lateral acceleration from jerk (Eq. 2 in paper) + float a_lat_new = agent->a_lat + c_steer * j_lat * env->dt; - if ((!is_active_agent && !is_static_agent) || env->entities[i].respawn_timestep != -1) { - continue; - } - Vector3 position; - float heading; - position = (Vector3){env->entities[i].x, env->entities[i].y, Z_AGENTS}; - heading = env->entities[i].heading; - - // Create size vector - Vector3 size = {env->entities[i].length, env->entities[i].width, env->entities[i].height}; - - bool is_expert = (!is_active_agent) && (env->entities[i].mark_as_expert == 1); - - // Save current transform - if (mode == 1) { - float cos_heading = env->entities[i].heading_x; - float sin_heading = env->entities[i].heading_y; - - // Calculate half dimensions - float half_len = env->entities[i].length * 0.5f; - float half_width = env->entities[i].width * 0.5f; - - // Calculate the four corners of the collision box - Vector3 corners[4] = { - (Vector3){position.x + (half_len * cos_heading - half_width * sin_heading), - position.y + (half_len * sin_heading + half_width * cos_heading), position.z}, - (Vector3){position.x + (half_len * cos_heading + half_width * sin_heading), - position.y + (half_len * sin_heading - half_width * cos_heading), position.z}, - (Vector3){position.x + (-half_len * cos_heading + half_width * sin_heading), - position.y + (-half_len * sin_heading - half_width * cos_heading), position.z}, - (Vector3){position.x + (-half_len * cos_heading - half_width * sin_heading), - position.y + (-half_len * sin_heading + half_width * cos_heading), position.z}, + // Zero-crossing: snap to 0 when crossing zero + if (agent->a_lat * a_lat_new < 0) { + a_lat_new = 0.0f; + } else { + a_lat_new = clip(a_lat_new, -4.0f, 4.0f); + } - }; + float heading_x = agent->cos_heading; + float heading_y = agent->sin_heading; - if (agent_index == env->human_agent_idx && - !env->entities[agent_index].metrics_array[REACHED_GOAL_IDX]) { - draw_agent_obs(env, agent_index, mode, obs_only, lasers); - } + // Calculate new velocity using trapezoidal integration + float v_dot_heading = agent->sim_vx * heading_x + agent->sim_vy * heading_y; + float signed_v = copysignf(sqrtf(agent->sim_vx * agent->sim_vx + agent->sim_vy * agent->sim_vy), v_dot_heading); + float v_new = signed_v + 0.5f * (a_long_new + agent->a_long) * env->dt; - if ((obs_only || IsKeyDown(KEY_LEFT_CONTROL)) && agent_index != env->human_agent_idx) { - continue; - } + // Zero-crossing: snap to 0 when crossing zero + if (signed_v * v_new < 0) { + v_new = 0.0f; + } else { + v_new = clip(v_new, -2.0f, 20.0f); + } - // Draw the agent bounding boxes - Color agent_color = GRAY; - if (is_expert) { - if (env->entities[i].type == PEDESTRIAN || env->entities[i].type == CYCLIST) - agent_color = EXPERT_REPLAY_SMALL; - else - agent_color = EXPERT_REPLAY; - } - if (is_active_agent) { - if (env->entities[i].type == PEDESTRIAN) - agent_color = LIGHT_ORANGE; - else if (env->entities[i].type == CYCLIST) - agent_color = LIGHT_PURPLE; - else - agent_color = BLUE; - } - if (is_active_agent && env->entities[i].collision_state > 0) - agent_color = RED; + // GIGAFLOW paper approach: a_lat → curvature → steering + // v_eff = max(|v|, 1.0) to avoid division issues at low speed + float v_eff = fmaxf(fabsf(v_new), 1.0f); + float signed_curvature = a_lat_new / (v_eff * v_eff); - rlPushMatrix(); - rlTranslatef(position.x, position.y, position.z); - rlRotatef(heading * RAD2DEG, 0.0f, 0.0f, 1.0f); - DrawCube((Vector3){0.0f, 0.0f, 0.0f}, size.x, size.y, 1.0f, Fade(agent_color, 0.5f)); - DrawCubeWires((Vector3){0.0f, 0.0f, 0.0f}, size.x, size.y, 1.0f, agent_color); - rlPopMatrix(); + // Convert curvature to steering angle + float steering_angle = atanf(signed_curvature * agent->wheelbase); - // Draw a heading arrow pointing forward - Vector3 arrowStart = position; - Vector3 arrowEnd = {position.x + cos_heading * half_len * 1.5f, // extend arrow beyond car - position.y + sin_heading * half_len * 1.5f, position.z}; + // Apply steering rate limit (±0.6 rad/s) + float delta_steer = clip(steering_angle - agent->steering_angle, -0.6f * env->dt, 0.6f * env->dt); - DrawLine3D(arrowStart, arrowEnd, agent_color); - DrawSphere(arrowEnd, 0.2f, agent_color); // arrow tip + // Apply steering position limit (±0.55 rad) + float new_steering_angle = clip(agent->steering_angle + delta_steer, -0.55f, 0.55f); - } else { // Agent view - rlPushMatrix(); - // Translate to position, rotate around Y axis, then draw - rlTranslatef(position.x, position.y, position.z); - rlRotatef(heading * RAD2DEG, 0.0f, 0.0f, 1.0f); // Convert radians to degrees + // Recalculate curvature from limited steering + signed_curvature = tanf(new_steering_angle) / agent->wheelbase; - // Select car model (skip index 0) - Model car_model = client->cars[(i % 5) + 1]; // Cycles through indices 1-5 + // Recalculate lateral acceleration from actual curvature + a_lat_new = v_new * v_new * signed_curvature; - if (agent_index == env->human_agent_idx) { - car_model = client->cars[0]; // Ego agent always uses red car - } else if (is_active_agent) { + // Calculate resulting movement using bicycle dynamics + float d = 0.5f * (v_new + signed_v) * env->dt; + float theta = d * signed_curvature; + float dx_local, dy_local; - car_model = client->cars[(i % 5) + 1]; + if (fabsf(signed_curvature) < 1e-5f || fabsf(theta) < 1e-5f) { + dx_local = d; + dy_local = 0.0f; + } else { + dx_local = sinf(theta) / signed_curvature; + dy_local = (1.0f - cosf(theta)) / signed_curvature; + } - if (env->entities[i].collision_state > 0) { - car_model = client->cars[0]; // Collided agents use red - } - } - // Draw obs for selected agent index - if (agent_index == env->human_agent_idx && - (!env->entities[agent_index].metrics_array[REACHED_GOAL_IDX] || - env->goal_behavior == GOAL_GENERATE_NEW || env->goal_behavior == GOAL_STOP)) { - draw_agent_obs(env, agent_index, mode, obs_only, lasers); - } + float dx = dx_local * heading_x - dy_local * heading_y; + float dy = dx_local * heading_y + dy_local * heading_x; + + // Update agent state + agent->sim_x += dx; + agent->sim_y += dy; + agent->sim_heading = normalize_heading(agent->sim_heading + theta); + agent->cos_heading = cosf(agent->sim_heading); + agent->sin_heading = sinf(agent->sim_heading); + agent->sim_vx = v_new * cosf(agent->sim_heading); + agent->sim_vy = v_new * sinf(agent->sim_heading); + const float yaw_rate = v_new * signed_curvature; + agent->yaw_rate = yaw_rate; + + update_agent_speed(agent); + // Update jerk and acceleration + agent->jerk_long = (a_long_new - agent->a_long) / env->dt; + agent->jerk_lat = (a_lat_new - agent->a_lat) / env->dt; + agent->a_long = a_long_new; + agent->a_lat = a_lat_new; + agent->steering_angle = new_steering_angle; + } - // Draw cube for cars static and active - // Calculate scale factors based on desired size and model dimensions - BoundingBox bounds = GetModelBoundingBox(car_model); - Vector3 model_size = {bounds.max.x - bounds.min.x, bounds.max.y - bounds.min.y, - bounds.max.z - bounds.min.z}; - Vector3 scale = {size.x / model_size.x, size.y / model_size.y, size.z / model_size.z}; + GridMapEntity entity_list[MAX_ENTITIES_PER_CELL * Z_COMPUTATION_OFFSET_COUNT]; + int list_size = get_neighbors_entities(env, agent->sim_x, agent->sim_y, entity_list, + MAX_ENTITIES_PER_CELL * Z_COMPUTATION_OFFSET_COUNT, z_computation_offsets, + Z_COMPUTATION_OFFSET_COUNT); + if (list_size > 0) { + DepthPoint road_neighbors[list_size]; + DepthPoint current_lane_neighbors[list_size]; + int valid_count = 0; + int current_lane_count = 0; + for (int i = 0; i < list_size; i++) { + if (entity_list[i].entity_idx == -1) + continue; + if (entity_list[i].entity_type != ENTITY_TYPE_ROAD_ELEMENT) + continue; - if (env->entities[i].type == CYCLIST) { - scale = (Vector3){0.01, 0.01, 0.01}; - car_model = client->cyclist; - } - if (env->entities[i].type == PEDESTRIAN) { - scale = (Vector3){2, 2, 2}; - car_model = client->pedestrian; + const RoadMapElement *entity = &env->road_elements[entity_list[i].entity_idx]; + DepthPoint point = compute_z_distance_to_road_segment(agent, entity, entity_list[i].geometry_idx); + if (point.z_dis < Z_BUFFER) { + road_neighbors[valid_count++] = point; + if (entity_list[i].entity_idx == agent->current_lane_index) { + current_lane_neighbors[current_lane_count++] = point; } - DrawModelEx(car_model, (Vector3){0, 0, 0}, (Vector3){1, 0, 0}, 90.0f, scale, WHITE); - { - float half_len = env->entities[i].length * 0.5f; - float half_width = env->entities[i].width * 0.5f; - Vector3 corners[4] = { - (Vector3){half_len, -half_width, 0}, // Front-left - (Vector3){half_len, half_width, 0}, // Front-right - (Vector3){-half_len, half_width, 0}, // Back-right - (Vector3){-half_len, -half_width, 0}, // Back-left - }; - Color wire_color = GRAY; - if (!is_active_agent && env->entities[i].mark_as_expert == 1) - wire_color = EXPERT_REPLAY; - if (is_active_agent) - wire_color = BLUE; // Policy-controlled - if (is_active_agent && env->entities[i].collision_state > 0) - wire_color = RED; - rlSetLineWidth(2.0f); - for (int j = 0; j < 4; j++) { - DrawLine3D(corners[j], corners[(j + 1) % 4], wire_color); - } - } - rlPopMatrix(); - } - - // FPV Camera Control - if (IsKeyDown(KEY_SPACE) && env->human_agent_idx == agent_index) { - Vector3 camera_position = (Vector3){position.x - (25.0f * cosf(heading)), - position.y - (25.0f * sinf(heading)), position.z + 15}; - - Vector3 camera_target = (Vector3){position.x + 40.0f * cosf(heading), - position.y + 40.0f * sinf(heading), position.z - 5.0f}; - client->camera.position = camera_position; - client->camera.target = camera_target; - client->camera.up = (Vector3){0, 0, 1}; - } - if (IsKeyReleased(KEY_SPACE)) { - client->camera.position = client->default_camera_position; - client->camera.target = client->default_camera_target; - client->camera.up = (Vector3){0, 0, 1}; - } - // Draw goal position for active agents - if (!is_active_agent || env->entities[i].valid == 0) { - continue; } - if (!IsKeyDown(KEY_LEFT_CONTROL) && obs_only == 0) { - Color goal_color = DEEPBLUE; - if (env->entities[i].type == PEDESTRIAN) - goal_color = LIGHT_ORANGE; - else if (env->entities[i].type == CYCLIST) - goal_color = LIGHT_PURPLE; - - DrawSphere( - (Vector3){env->entities[i].goal_position_x, env->entities[i].goal_position_y, Z_AGENT_DETAILS}, - 0.5f, goal_color); - DrawCircle3D( - (Vector3){env->entities[i].goal_position_x, env->entities[i].goal_position_y, Z_AGENT_DETAILS}, - env->goal_radius, (Vector3){0, 0, Z_AGENT_DETAILS}, 90.0f, Fade(goal_color, 0.9f)); - } - } - // Draw road elements - if (env->entities[i].type <= 3 && env->entities[i].type >= 7) { - continue; } - for (int j = 0; j < env->entities[i].array_size - 1; j++) { - Vector3 start = {env->entities[i].traj_x[j], env->entities[i].traj_y[j], Z_ROAD_MARKINGS}; - Vector3 end = {env->entities[i].traj_x[j + 1], env->entities[i].traj_y[j + 1], Z_ROAD_MARKINGS}; - Color lineColor = GRAY; - if (env->entities[i].type == ROAD_LANE) - lineColor = Fade(SOFT_YELLOW, 0.25f); - else if (env->entities[i].type == ROAD_LINE) - lineColor = WHITE; - else if (env->entities[i].type == ROAD_EDGE) - lineColor = Fade(WHITE, 0.7f); - else if (env->entities[i].type == DRIVEWAY) - lineColor = RED; - - if (!IsKeyDown(KEY_LEFT_CONTROL) && obs_only == 0) { - if (env->entities[i].type == ROAD_EDGE) { - draw_road_edge(env, start.x, start.y, end.x, end.y); - } else if (env->entities[i].type == ROAD_LANE || env->entities[i].type == ROAD_LINE) { - // Draw road lanes and lines as purple lines - rlSetLineWidth(2.0f); - DrawLine3D(start, end, lineColor); - } + + int neighbor_count = (current_lane_count > 0) ? current_lane_count : valid_count; + if (neighbor_count > 0) { + DepthPoint *neighbors = (current_lane_count > 0) ? current_lane_neighbors : road_neighbors; + qsort(neighbors, neighbor_count, sizeof(DepthPoint), compare_depthpoint); + int check_count = (neighbor_count < Z_NUM_PT_AVG) ? neighbor_count : Z_NUM_PT_AVG; + float sum_z = 0.0f; + for (int i = 0; i < check_count; i++) { + sum_z += neighbors[i].z; } + agent->sim_z = sum_z / check_count; } } - EndMode3D(); - - // Draw track indices for the tracks to predict - if (mode == 1 && env->control_mode == CONTROL_WOSAC) { - float map_height = env->grid_map->top_left_y - env->grid_map->bottom_right_y; - float pixels_per_world_unit = client->height / map_height; + return; +} - for (int i = 0; i < env->active_agent_count; i++) { - // Ignore respawned agents - if (env->entities[i].respawn_timestep != -1) { - continue; - } - int agent_idx = env->active_agent_indices[i]; - int womd_track_idx = env->tracks_to_predict_indices[i]; +void c_reset(Drive *env) { + if (env->timestep == 0) { + for (int x = 0; x < env->active_agent_count; x++) { + env->logs[x] = (Log){0}; + int agent_idx = env->active_agent_indices[x]; + initialize_agent_progression(env, agent_idx); + compute_metrics(env, agent_idx); + } + compute_observations(env); + return; + } - float raw_x = -env->entities[agent_idx].x * pixels_per_world_unit; - float raw_y = env->entities[agent_idx].y * pixels_per_world_unit; + env->timestep = env->init_steps; - int screen_x = (int)raw_x + client->width / 2 + 20; - int screen_y = (int)raw_y + client->height / 2 - 25; + if (env->simulation_mode == SIMULATION_GIGAFLOW) { + generate_traffic_light_states(env); + int num_reset = 0; + for (int x = 0; x < env->active_agent_count; x++) { + int agent_idx = env->active_agent_indices[x]; - if (screen_x >= 0 && screen_x <= client->width && screen_y >= 0 && screen_y <= client->height) { - char text[32]; - snprintf(text, sizeof(text), "%d", womd_track_idx); - int text_width = MeasureText(text, 20); - DrawText(text, screen_x - text_width / 2, screen_y, 20, PUFF_WHITE); + // Respawn agent at new random position + if (spawn_agent(env, agent_idx, num_reset)) { + num_reset++; + } else { + // Failed spawn: ensure agent is properly invalidated + invalidate_agent(&env->agents[agent_idx]); + env->agents[agent_idx].removed = 1; } } - } -} -void c_render(Drive *env, int view_mode, int draw_traces) { + if (num_reset != env->active_agent_count) { + printf("[GIGAFLOW ERROR] -> Only respawned %d out of %d agents during reset\n", num_reset, + env->active_agent_count); + } - // Create client on first render call - if (env->client == NULL) { - env->client = make_client(env); + // GIGAFLOW: spawn_agent already set positions, routes, paths, goals. + // Only need to generate reward coefs and compute initial metrics. + for (int x = 0; x < env->active_agent_count; x++) { + env->logs[x] = (Log){0}; + int agent_idx = env->active_agent_indices[x]; + Agent *agent = &env->agents[agent_idx]; + if (agent->removed) + continue; + reset_agent_metrics(env, agent_idx); + reset_agent_state(agent); + generate_reward_coefs(env, agent); + initialize_agent_progression(env, agent_idx); + compute_metrics(env, agent_idx); + } + compute_observations(env); + return; } - Client *client = env->client; + set_start_position(env); + for (int x = 0; x < env->active_agent_count; x++) { + env->logs[x] = (Log){0}; + int agent_idx = env->active_agent_indices[x]; + Agent *agent = &env->agents[agent_idx]; - if (env->render_mode == RENDER_HEADLESS) { // Headless rendering via ffmpeg - float map_width = env->grid_map->bottom_right_x - env->grid_map->top_left_x; - float map_height = env->grid_map->top_left_y - env->grid_map->bottom_right_y; + // Common resets + reset_agent_metrics(env, agent_idx); + reset_agent_state(agent); + generate_reward_coefs(env, agent); - Camera3D camera = {0}; + compute_goals(env, agent_idx); + initialize_agent_progression(env, agent_idx); + compute_metrics(env, agent_idx); + } + compute_observations(env); +} - if (view_mode == VIEW_MODE_SIM_STATE) { - // Orthographic bird's-eye view over the entire map (fully observable) - camera.position = (Vector3){0.0, 0.0, 400.0f}; // Above the scene - camera.target = (Vector3){0.0, 0.0, 0.0}; // Look at origin - camera.up = (Vector3){0.0f, -1.0f, 0.0f}; - camera.projection = CAMERA_ORTHOGRAPHIC; - camera.fovy = map_height; +void c_step(Drive *env) { + memset(env->rewards, 0, env->active_agent_count * sizeof(float)); + memset(env->terminals, 0, env->active_agent_count * sizeof(unsigned char)); + memset(env->truncations, 0, env->active_agent_count * sizeof(unsigned char)); - BeginDrawing(); - ClearBackground(ROAD_COLOR); - BeginMode3D(camera); + // Update masks for stopped/removed agents + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; + if (env->agents[agent_idx].stopped || env->agents[agent_idx].removed) { + env->masks[i] = 0; + } else { + env->masks[i] = 1; + } + } - if (draw_traces) { // Show logged trajectories of active agents and expert static agents - for (int i = 0; i < env->active_agent_count; i++) { - int idx = env->active_agent_indices[i]; - for (int t = env->init_steps; t < env->episode_length; t++) { - Color agent_color = LIGHTBLUE; - if (env->entities[idx].type == PEDESTRIAN) { - agent_color = LIGHT_ORANGE; - } else if (env->entities[idx].type == CYCLIST) { - agent_color = LIGHT_PURPLE; - } - DrawSphere( - (Vector3){env->entities[idx].traj_x[t], env->entities[idx].traj_y[t], Z_AGENT_DETAILS}, - 0.15f, agent_color); - } - } + env->timestep++; - for (int i = 0; i < env->expert_static_agent_count; i++) { - int idx = env->expert_static_agent_indices[i]; - for (int t = env->init_steps; t < env->episode_length; t++) { - DrawSphere( - (Vector3){env->entities[idx].traj_x[t], env->entities[idx].traj_y[t], Z_AGENT_DETAILS}, - 0.15f, EXPERT_REPLAY); - } - } + // -> 1. Check for episode termination + int early_reset = 0; + // Special early reset condition for GIGAFLOW + if (env->simulation_mode == SIMULATION_GIGAFLOW && env->termination_mode == 1) { + int count_inactive = 0; + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; + if (env->agents[agent_idx].removed || env->agents[agent_idx].stopped) { + count_inactive++; } + } + float ratio_inactive = (float)count_inactive / (float)env->active_agent_count; + // If more than inactive_agent_threshold of agents are removed/stopped, reset the environment + if (ratio_inactive > env->inactive_agent_threshold) { + early_reset = 1; + } + } - draw_scene(env, client, 1, 0, 0, 0); - - } else if (view_mode == VIEW_MODE_BEV_AGENT_OBS) { - // Orthographic bird's-eye view centered on the selected agent, - // showing only that agent's observations - int agent_idx = env->active_agent_indices[env->human_agent_idx]; - Entity *agent = &env->entities[agent_idx]; - - Camera3D camera = {0}; - camera.position = (Vector3){agent->x, agent->y, 400.0f}; - camera.target = (Vector3){agent->x, agent->y, 0.0f}; - camera.up = (Vector3){0.0f, -1.0f, 0.0f}; - camera.projection = CAMERA_ORTHOGRAPHIC; - camera.fovy = env->grid_map->vision_range * GRID_CELL_SIZE * 2.0f; - - BeginDrawing(); - ClearBackground(ROAD_COLOR); - BeginMode3D(camera); - draw_scene(env, client, 1, 1, 0, 0); + if (env->timestep == env->scenario_length || early_reset) { + for (int i = 0; i < env->active_agent_count; i++) { + env->truncations[i] = 1; + } + add_log(env); + c_reset(env); + return; + } - } else { // First-person perspective from a selected agent - int agent_idx = env->active_agent_indices[env->human_agent_idx]; - Entity *agent = &env->entities[agent_idx]; + // -> 2. Apply actions and move agents + // Move static experts + for (int i = 0; i < env->expert_static_agent_count; i++) { + int expert_idx = env->expert_static_agent_indices[i]; + move_expert(env, env->actions, expert_idx); + } + // Move active agents with policy actions + for (int i = 0; i < env->active_agent_count; i++) { + env->logs[i].score = 0.0f; + env->logs[i].episode_length += 1; + int agent_idx = env->active_agent_indices[i]; + move_dynamics(env, i, agent_idx); + // move_expert(env, env->actions, agent_idx); + } - Camera3D camera = {0}; - // Position camera behind and above the agent - camera.position = - (Vector3){agent->x - (25.0f * cosf(agent->heading)), agent->y - (25.0f * sinf(agent->heading)), 15.0f}; - camera.target = - (Vector3){agent->x + 40.0f * cosf(agent->heading), agent->y + 40.0f * sinf(agent->heading), 1.0f}; - camera.up = (Vector3){0.0f, 0.0f, 1.0f}; - camera.fovy = 60.0f; - camera.projection = CAMERA_PERSPECTIVE; + // -> 3. Compute metrics and rewards + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; - BeginDrawing(); - ClearBackground(ROAD_COLOR); - BeginMode3D(camera); - draw_scene(env, client, 0, 0, 0, 1); - } + if (env->agents[agent_idx].stopped || env->agents[agent_idx].removed) + continue; - EndDrawing(); + // Compute metrics + compute_metrics(env, agent_idx); - unsigned char *screen_data = rlReadScreenPixels((int)client->width, (int)client->height); - if (screen_data) { - write(client->recorder_pipefd[1], screen_data, (int)client->width * (int)client->height * 4); - RL_FREE(screen_data); - } - } else { // Pop-up window - BeginDrawing(); - ClearBackground(ROAD_COLOR); - BeginMode3D(client->camera); - handle_camera_controls(env->client); - draw_scene(env, client, 0, 0, 0, 0); + // Compute rewards + compute_rewards(env, i); + } - if (IsKeyPressed(KEY_TAB) && env->active_agent_count > 0) { - env->human_agent_idx = (env->human_agent_idx + 1) % env->active_agent_count; + // Mark terminals for stopped or removed agents + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; + if (env->agents[agent_idx].stopped || env->agents[agent_idx].removed) { + env->terminals[i] = 1; } + } - DrawText(TextFormat("Timestep: %d", env->timestep), 10, 50, 20, PUFF_WHITE); - DrawText(TextFormat("Controlling agent: %d", env->human_agent_idx), 10, 70, 20, PUFF_WHITE); - int human_idx = env->active_agent_indices[env->human_agent_idx]; - - Color action_color = IsKeyDown(KEY_LEFT_SHIFT) ? YELLOW : PUFF_WHITE; + // -> 5. Compute observations + compute_observations(env); - if (env->action_type == 0) { // discrete - int *action_array = (int *)env->actions; - int action_val = action_array[env->human_agent_idx]; - - if (env->dynamics_model == CLASSIC) { - int num_steer = 13; - int accel_idx = action_val / num_steer; - int steer_idx = action_val % num_steer; - float accel_value = ACCELERATION_VALUES[accel_idx]; - float steer_value = STEERING_VALUES[steer_idx]; - - DrawText(TextFormat("Acceleration: %.2f m/s^2", accel_value), 10, 110, 20, action_color); - DrawText(TextFormat("Steering: %.3f", steer_value), 10, 130, 20, action_color); - } else if (env->dynamics_model == JERK) { - int num_lat = 3; - int jerk_long_idx = action_val / num_lat; - int jerk_lat_idx = action_val % num_lat; - float jerk_long_value = JERK_LONG[jerk_long_idx]; - float jerk_lat_value = JERK_LAT[jerk_lat_idx]; - - DrawText(TextFormat("Longitudinal Jerk: %.2f m/s^3", jerk_long_value), 10, 110, 20, action_color); - DrawText(TextFormat("Lateral Jerk: %.2f m/s^3", jerk_lat_value), 10, 130, 20, action_color); + // -> 6. Update goals for agents that reached their goal + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; + Agent *agent = &env->agents[agent_idx]; + if (agent->metrics_array[REACHED_GOAL_IDX] > 0.0f) { + if (agent->current_goal_idx == env->num_target_waypoints) { + // Last goal reached - generate new set of goals + env->logs[i].num_goals_reached += 1; + compute_goals(env, agent_idx); + } else { + // Advance alias to next goal + agent->goal_position_x = agent->goal_positions_x[agent->current_goal_idx]; + agent->goal_position_y = agent->goal_positions_y[agent->current_goal_idx]; + agent->goal_position_z = agent->goal_positions_z[agent->current_goal_idx]; } - } else { // continuous - float (*action_array_f)[2] = (float (*)[2])env->actions; - DrawText(TextFormat("Acceleration: %.2f", action_array_f[env->human_agent_idx][0]), 10, 110, 20, - action_color); - DrawText(TextFormat("Steering: %.2f", action_array_f[env->human_agent_idx][1]), 10, 130, 20, action_color); } - - int status_y = 150; - if (IsKeyDown(KEY_LEFT_SHIFT)) { - DrawText("[shift pressed]", 10, status_y, 20, YELLOW); - status_y += 20; - } - if (IsKeyDown(KEY_SPACE)) { - DrawText("[space pressed]", 10, status_y, 20, YELLOW); - status_y += 20; - } - if (IsKeyDown(KEY_LEFT_CONTROL)) { - DrawText("[ctrl pressed]", 10, status_y, 20, YELLOW); - status_y += 20; - } - - DrawText("Controls: SHIFT + W/S - Accelerate/Brake, SHIFT + A/D - Steer, TAB - Switch Agent", 10, - client->height - 30, 20, PUFF_WHITE); - DrawText(TextFormat("Grid Rows: %d", env->grid_map->grid_rows), 10, status_y, 20, PUFF_WHITE); - DrawText(TextFormat("Grid Cols: %d", env->grid_map->grid_cols), 10, status_y + 20, 20, PUFF_WHITE); - EndDrawing(); } } -void close_client(Client *client) { - if (client->recorder_pid > 0) { - close(client->recorder_pipefd[1]); - waitpid(client->recorder_pid, NULL, 0); - } - for (int i = 0; i < 6; i++) - UnloadModel(client->cars[i]); - UnloadModel(client->cyclist); - UnloadModel(client->pedestrian); - CloseWindow(); - if (client->xvfb_pid > 0) { - kill(client->xvfb_pid, SIGTERM); - waitpid(client->xvfb_pid, NULL, 0); - unlink("/tmp/.X99-lock"); - unsetenv("DISPLAY"); - } +#include "render.h" - free(client); -} +#endif // DRIVE_H diff --git a/pufferlib/ocean/drive/drive.py b/pufferlib/ocean/drive/drive.py index 571b6dce28..08300e990c 100644 --- a/pufferlib/ocean/drive/drive.py +++ b/pufferlib/ocean/drive/drive.py @@ -1,100 +1,188 @@ +import argparse +from pathlib import Path import numpy as np import gymnasium import json import struct import os import pufferlib -from enum import IntEnum from pufferlib.ocean.drive import binding -from multiprocessing import Pool, cpu_count -from tqdm import tqdm - - -class RenderView(IntEnum): - FULL_SIM_STATE = 0 # Orthographic top-down, fully observable simulator state - BEV_AGENT_OBS = 1 # Orthographic top-down, only show what the selected agent can observe - AGENT_PERSP = 2 # Third-person perspective following selected agent class Drive(pufferlib.PufferEnv): def __init__( self, - render_mode=RenderView.FULL_SIM_STATE, + render_mode=None, report_interval=1, width=1280, height=1024, human_agent_idx=0, - reward_vehicle_collision=-0.1, - reward_offroad_collision=-0.1, reward_goal=1.0, - reward_goal_post_respawn=0.5, - goal_behavior=0, - goal_target_distance=10.0, + reward_vehicle_collision=3.0, + reward_offroad_collision=3.0, + reward_comfort=0.05, + reward_lane_align=0.025, + reward_vel_align=1.0, + reward_lane_center=0.0038, + reward_center_bias=0.0, + reward_velocity=0.0025, + reward_reverse=0.005, + reward_traffic_light_violation=1.0, + reward_timestep=0.000025, + reward_overspeed=0.05, + reward_ade=0.0, + min_waypoint_spacing=20.0, + max_waypoint_spacing=60.0, + num_target_waypoints=3, goal_radius=2.0, - goal_speed=20.0, collision_behavior=0, offroad_behavior=0, + traffic_light_behavior=0, dt=0.1, - episode_length=None, - termination_mode=None, + spawn_initial_speed=0.0, + goal_speed_threshold=3.0, + scenario_length=None, resample_frequency=91, num_maps=100, num_agents=512, + min_agents_per_env=32, + max_agents_per_env=64, action_type="discrete", dynamics_model="classic", + simulation_mode="gigaflow", + termination_mode=0, + inactive_agent_threshold=0.4, buf=None, seed=1, init_steps=0, + eval_mode=0, + num_eval_scenarios=16, init_mode="create_all_valid", control_mode="control_vehicles", - max_controlled_agents=32, - map_dir="resources/drive/binaries/training", + map_dir=None, + target_type="static", + reward_conditioning=False, + reward_randomization=False, + compute_eval_metrics=True, + split_network=False, + use_rear_axle=False, + max_lane_segment_observations=32, + max_boundary_segment_observations=32, + max_partner_observations=16, + max_traffic_light_observations=10, + max_stop_sign_observations=10, + starting_map=0, ): - # env self.dt = dt + self.spawn_initial_speed = float(spawn_initial_speed) + self.goal_speed_threshold = float(goal_speed_threshold) + self.reward_conditioning = reward_conditioning + self.reward_randomization = reward_randomization + self.compute_eval_metrics = compute_eval_metrics + self.split_network = split_network self.render_mode = render_mode self.num_maps = num_maps self.report_interval = report_interval + self.reward_goal = reward_goal self.reward_vehicle_collision = reward_vehicle_collision self.reward_offroad_collision = reward_offroad_collision - self.reward_goal = reward_goal - self.reward_goal_post_respawn = reward_goal_post_respawn + self.reward_comfort = reward_comfort + self.reward_lane_align = reward_lane_align + self.reward_vel_align = reward_vel_align + self.reward_lane_center = reward_lane_center + self.reward_center_bias = reward_center_bias + self.reward_velocity = reward_velocity + self.reward_reverse = reward_reverse + self.reward_traffic_light_violation = reward_traffic_light_violation + self.reward_timestep = reward_timestep + self.reward_overspeed = reward_overspeed + self.reward_ade = reward_ade self.goal_radius = goal_radius - self.goal_speed = goal_speed - self.goal_behavior = goal_behavior - self.goal_target_distance = goal_target_distance + self.min_waypoint_spacing = min_waypoint_spacing + self.max_waypoint_spacing = max_waypoint_spacing + if num_target_waypoints > binding.MAX_TARGET_WAYPOINTS: + num_target_waypoints = binding.MAX_TARGET_WAYPOINTS + self.num_target_waypoints = num_target_waypoints + self.target_type_str = target_type + if target_type == "static": + self.target_type = binding.TARGET_STATIC + elif target_type == "dynamic": + self.target_type = binding.TARGET_DYNAMIC + else: + raise ValueError(f"target_type must be 'static' or 'dynamic'. Got: {target_type}") self.collision_behavior = collision_behavior self.offroad_behavior = offroad_behavior + self.traffic_light_behavior = traffic_light_behavior self.human_agent_idx = human_agent_idx - self.episode_length = episode_length - self.termination_mode = termination_mode + self.scenario_length = scenario_length self.resample_frequency = resample_frequency self.dynamics_model = dynamics_model - self.max_controlled_agents = max_controlled_agents - - # Observation space calculation - self.ego_features = {"classic": binding.EGO_FEATURES_CLASSIC, "jerk": binding.EGO_FEATURES_JERK}.get( - dynamics_model - ) - + if dynamics_model == "classic": + self.dynamics_model_flag = 0 + elif dynamics_model == "jerk": + self.dynamics_model_flag = 1 + else: + raise ValueError(f"dynamics_model must be 'classic' or 'jerk'. Got: {dynamics_model}") + self.eval_mode = eval_mode + self.num_eval_scenarios = num_eval_scenarios + self.termination_mode = termination_mode + self.inactive_agent_threshold = inactive_agent_threshold + self.rng = np.random.default_rng(seed) + self.min_agents_per_env = min_agents_per_env + self.max_agents_per_env = max_agents_per_env + + # Observation space calculation based on target_type + self.ego_features = { + "classic": binding.EGO_FEATURES_CLASSIC, + "jerk": binding.EGO_FEATURES_JERK, + }.get(dynamics_model) + + self.use_rear_axle = use_rear_axle # Extract observation shapes from constants - # These need to be defined in C, since they determine the shape of the arrays - self.max_road_objects = binding.MAX_ROAD_SEGMENT_OBSERVATIONS - self.max_partner_objects = binding.MAX_AGENTS - 1 + self.max_lane_segment_observations = max_lane_segment_observations + self.max_boundary_segment_observations = max_boundary_segment_observations + self.max_partner_observations = max_partner_observations + self.max_traffic_light_observations = max_traffic_light_observations + self.max_stop_sign_observations = max_stop_sign_observations self.partner_features = binding.PARTNER_FEATURES self.road_features = binding.ROAD_FEATURES + self.traffic_light_features = binding.TRAFFIC_LIGHT_FEATURES + self.stop_sign_features = binding.STOP_SIGN_FEATURES + self.num_reward_coefs = binding.NUM_REWARD_COEFS if reward_conditioning else 0 + + # Target features based on target_type + if target_type == "static": + self.target_features = binding.STATIC_TARGET_FEATURES + else: + self.target_features = binding.DYNAMIC_TARGET_FEATURES + self.target_dim = num_target_waypoints * self.target_features self.num_obs = ( self.ego_features - + self.max_partner_objects * self.partner_features - + self.max_road_objects * self.road_features + + self.num_reward_coefs + + self.target_dim + + self.max_partner_observations * self.partner_features + + self.max_lane_segment_observations * self.road_features + + self.max_boundary_segment_observations * self.road_features + + self.max_traffic_light_observations * self.traffic_light_features + + self.max_stop_sign_observations * self.stop_sign_features ) + self.single_observation_space = gymnasium.spaces.Box(low=-1, high=1, shape=(self.num_obs,), dtype=np.float32) self.init_steps = init_steps self.init_mode_str = init_mode self.control_mode_str = control_mode + self.simulation_mode_str = simulation_mode self.map_dir = map_dir + self.map_files = sorted(os.path.join(map_dir, f) for f in os.listdir(map_dir) if f.endswith(".bin")) + + if self.simulation_mode_str == "gigaflow": + self.simulation_mode = 0 + elif self.simulation_mode_str == "replay": + self.simulation_mode = 1 + else: + raise ValueError(f"simulation_mode must be one of 'gigaflow' or 'replay'. Got: {self.simulation_mode_str}") if self.control_mode_str == "control_vehicles": self.control_mode = 0 @@ -104,11 +192,9 @@ def __init__( self.control_mode = 2 elif self.control_mode_str == "control_sdc_only": self.control_mode = 3 - elif self.control_mode_str == "control_mixed_play": - self.control_mode = 4 else: raise ValueError( - f"control_mode must be one of 'control_vehicles', 'control_wosac', 'control_agents' or 'control_mixed_play'. Got: {self.control_mode_str}" + f"control_mode must be one of 'control_vehicles', 'control_wosac', or 'control_agents'. Got: {self.control_mode_str}" ) if self.init_mode_str == "create_all_valid": self.init_mode = 0 @@ -120,6 +206,7 @@ def __init__( ) if action_type == "discrete": + self._action_type_flag = 0 if dynamics_model == "classic": # Joint action space (assume dependence) self.single_action_space = gymnasium.spaces.MultiDiscrete([7 * 13]) @@ -131,45 +218,57 @@ def __init__( else: raise ValueError(f"dynamics_model must be 'classic' or 'jerk'. Got: {dynamics_model}") elif action_type == "continuous": + self._action_type_flag = 1 self.single_action_space = gymnasium.spaces.Box(low=-1, high=1, shape=(2,), dtype=np.float32) else: raise ValueError(f"action_space must be 'discrete' or 'continuous'. Got: {action_type}") - self._action_type_flag = 0 if action_type == "discrete" else 1 - # Check if resources directory exists - binary_path = f"{map_dir}/map_000.bin" - if not os.path.exists(binary_path): + if not self.map_files: raise FileNotFoundError( - f"Required directory {binary_path} not found. Please ensure the Drive maps are downloaded and installed correctly per docs." + f"No .bin files found in {map_dir}. Please ensure the Drive maps are downloaded and installed correctly per docs." ) # Check maps availability - available_maps = len([name for name in os.listdir(map_dir) if name.endswith(".bin")]) + available_maps = len(self.map_files) if num_maps > available_maps: - raise ValueError( - f"num_maps ({num_maps}) exceeds available maps in directory ({available_maps}). Please reduce num_maps or add more maps to resources/drive/binaries." + raise ValueError(f"num_maps ({num_maps}) exceeds available maps in {map_dir} ({available_maps}).") + self.starting_map_counter = starting_map + self.starting_map_counter_init = starting_map + + # Calculate dynamic batch size for Eval + Replay mode + self.current_num_eval_scenarios = self.num_eval_scenarios + if self.eval_mode: + self.current_num_eval_scenarios = min( + self.num_eval_scenarios, + self.num_eval_scenarios + self.starting_map_counter_init - self.starting_map_counter, ) # Iterate through all maps to count total agents that can be initialized for each map agent_offsets, map_ids, num_envs = binding.shared( - map_dir=map_dir, + map_files=self.map_files, num_agents=num_agents, num_maps=num_maps, + starting_map_counter=self.starting_map_counter, + eval_mode=self.eval_mode, init_mode=self.init_mode, control_mode=self.control_mode, + simulation_mode=self.simulation_mode, init_steps=self.init_steps, - goal_behavior=self.goal_behavior, - goal_target_distance=self.goal_target_distance, - max_controlled_agents=self.max_controlled_agents, + seed=self.random_seed, + min_agents_per_env=self.min_agents_per_env, + max_agents_per_env=self.max_agents_per_env, + num_eval_scenarios=self.current_num_eval_scenarios, # Use the dynamic size here ) + # In eval mode, don't wrap counter - allows termination condition to work correctly + self.starting_map_counter = self.starting_map_counter + num_envs - self.num_agents = agent_offsets[-1] + self.num_agents = num_agents self.agent_offsets = agent_offsets self.map_ids = map_ids self.num_envs = num_envs super().__init__(buf=buf) - self.env_ids = [] + env_ids = [] for i in range(num_envs): cur = agent_offsets[i] nxt = agent_offsets[i + 1] @@ -179,125 +278,183 @@ def __init__( self.rewards[cur:nxt], self.terminals[cur:nxt], self.truncations[cur:nxt], - seed, - action_type=self._action_type_flag, - human_agent_idx=human_agent_idx, - reward_vehicle_collision=reward_vehicle_collision, - reward_offroad_collision=reward_offroad_collision, - reward_goal=reward_goal, - reward_goal_post_respawn=reward_goal_post_respawn, - goal_radius=goal_radius, - goal_speed=goal_speed, - goal_behavior=self.goal_behavior, - goal_target_distance=self.goal_target_distance, - collision_behavior=self.collision_behavior, - offroad_behavior=self.offroad_behavior, - dt=dt, - episode_length=(int(episode_length) if episode_length is not None else None), - termination_mode=(int(self.termination_mode) if self.termination_mode is not None else 0), - map_id=map_ids[i], - max_agents=nxt - cur, - ini_file="pufferlib/config/ocean/drive.ini", - init_steps=init_steps, - init_mode=self.init_mode, - control_mode=self.control_mode, - map_dir=map_dir, - max_controlled_agents=self.max_controlled_agents, - render_mode=render_mode, - ) - self.env_ids.append(env_id) - - self.c_envs = binding.vectorize(*self.env_ids) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - self.truncations[:] = 0 - return self.observations, [] - - def resample_maps(self): - """Resample environment maps.""" - self.tick = 0 - binding.vec_close(self.c_envs) - agent_offsets, map_ids, num_envs = binding.shared( - num_agents=self.num_agents, - num_maps=self.num_maps, - init_mode=self.init_mode, - control_mode=self.control_mode, - init_steps=self.init_steps, - goal_behavior=self.goal_behavior, - goal_target_distance=self.goal_target_distance, - goal_speed=self.goal_speed, - map_dir=self.map_dir, - max_controlled_agents=self.max_controlled_agents, - ) - self.agent_offsets = agent_offsets - self.map_ids = map_ids - self.num_envs = num_envs - self.env_ids = [] - seed = np.random.randint(0, 2**32 - 1) - for i in range(num_envs): - cur = agent_offsets[i] - nxt = agent_offsets[i + 1] - env_id = binding.env_init( - self.observations[cur:nxt], - self.actions[cur:nxt], - self.rewards[cur:nxt], - self.terminals[cur:nxt], - self.truncations[cur:nxt], - seed, + self.masks[cur:nxt], + self.random_seed, action_type=self._action_type_flag, + dynamics_model=self.dynamics_model_flag, human_agent_idx=self.human_agent_idx, + reward_goal=self.reward_goal, reward_vehicle_collision=self.reward_vehicle_collision, reward_offroad_collision=self.reward_offroad_collision, - reward_goal=self.reward_goal, - reward_goal_post_respawn=self.reward_goal_post_respawn, - goal_radius=self.goal_radius, - goal_behavior=self.goal_behavior, - goal_target_distance=self.goal_target_distance, - goal_speed=self.goal_speed, + reward_comfort=self.reward_comfort, + reward_lane_align=self.reward_lane_align, + reward_vel_align=self.reward_vel_align, + reward_lane_center=self.reward_lane_center, + reward_center_bias=self.reward_center_bias, + reward_velocity=self.reward_velocity, + reward_reverse=self.reward_reverse, + reward_traffic_light_violation=self.reward_traffic_light_violation, + reward_timestep=self.reward_timestep, + reward_overspeed=self.reward_overspeed, + reward_ade=self.reward_ade, collision_behavior=self.collision_behavior, offroad_behavior=self.offroad_behavior, + traffic_light_behavior=self.traffic_light_behavior, + goal_radius=self.goal_radius, + min_waypoint_spacing=self.min_waypoint_spacing, + max_waypoint_spacing=self.max_waypoint_spacing, + num_target_waypoints=self.num_target_waypoints, + target_type=self.target_type, + use_rear_axle=self.use_rear_axle, + max_lane_segment_observations=self.max_lane_segment_observations, + max_boundary_segment_observations=self.max_boundary_segment_observations, + max_partner_observations=self.max_partner_observations, + max_traffic_light_observations=self.max_traffic_light_observations, + max_stop_sign_observations=self.max_stop_sign_observations, dt=self.dt, - episode_length=(int(self.episode_length) if self.episode_length is not None else None), - map_id=map_ids[i], + spawn_initial_speed=self.spawn_initial_speed, + goal_speed_threshold=self.goal_speed_threshold, + scenario_length=(int(self.scenario_length) if self.scenario_length is not None else None), + termination_mode=int(self.termination_mode), + inactive_agent_threshold=float(self.inactive_agent_threshold), + map_file=self.map_files[map_ids[i]], max_agents=nxt - cur, + max_agents_per_env=self.max_agents_per_env, ini_file="pufferlib/config/ocean/drive.ini", init_steps=self.init_steps, init_mode=self.init_mode, control_mode=self.control_mode, - map_dir=self.map_dir, - termination_mode=(int(self.termination_mode) if self.termination_mode is not None else 0), - max_controlled_agents=self.max_controlled_agents, - render_mode=self.render_mode, + simulation_mode=self.simulation_mode, + reward_conditioning=self.reward_conditioning, + reward_randomization=self.reward_randomization, + compute_eval_metrics=self.compute_eval_metrics, + eval_mode=self.eval_mode, ) - self.env_ids.append(env_id) - self.c_envs = binding.vectorize(*self.env_ids) + env_ids.append(env_id) - binding.vec_reset(self.c_envs, seed) - self.terminals[:] = 1 - self.truncations[:] = 1 + self.c_envs = binding.vectorize(*env_ids) + binding.vec_reset(self.c_envs, self.random_seed) - def step(self, actions, per_env_logs=False): - self.terminals[:] = 0 + @property + def random_seed(self): + return int(self.rng.integers(0, 2**24)) + + def reset(self, seed=0): + binding.vec_reset(self.c_envs, seed) + self.tick = 0 self.truncations[:] = 0 + return self.observations, [] + + def step(self, actions): self.actions[:] = actions binding.vec_step(self.c_envs) self.tick += 1 info = [] if self.tick % self.report_interval == 0: - if per_env_logs: # Get the stats for every separate env - logs = self.get_env_logs() - if any(logs): - info = logs - else: # Default: Aggregate across vectorized envs - log = binding.vec_log(self.c_envs, self.num_agents) - if log: - info.append(log) - + log = binding.vec_log(self.c_envs, self.num_agents) + if log: + info.append(log) + # print(log) if self.tick > 0 and self.resample_frequency > 0 and self.tick % self.resample_frequency == 0: - self.resample_maps() + self.tick = 0 + will_resample = 1 + if will_resample: + # Calculate dynamic batch size for Eval + Replay mode + self.current_num_eval_scenarios = self.num_eval_scenarios + if self.eval_mode: + self.current_num_eval_scenarios = min( + self.num_eval_scenarios, + self.num_eval_scenarios + self.starting_map_counter_init - self.starting_map_counter, + ) + if self.current_num_eval_scenarios == 0: + return (self.observations, self.rewards, self.terminals, self.truncations, info) + binding.vec_close(self.c_envs) + agent_offsets, map_ids, num_envs = binding.shared( + num_agents=self.num_agents, + num_maps=self.num_maps, + starting_map_counter=self.starting_map_counter, + eval_mode=self.eval_mode, + init_mode=self.init_mode, + control_mode=self.control_mode, + simulation_mode=self.simulation_mode, + init_steps=self.init_steps, + map_files=self.map_files, + seed=self.random_seed, + min_agents_per_env=self.min_agents_per_env, + max_agents_per_env=self.max_agents_per_env, + num_eval_scenarios=self.current_num_eval_scenarios, # Use the dynamic size here + ) + # In eval mode, don't wrap counter - allows termination condition to work correctly + self.starting_map_counter = self.starting_map_counter + num_envs + env_ids = [] + for i in range(num_envs): + cur = agent_offsets[i] + nxt = agent_offsets[i + 1] + env_id = binding.env_init( + self.observations[cur:nxt], + self.actions[cur:nxt], + self.rewards[cur:nxt], + self.terminals[cur:nxt], + self.truncations[cur:nxt], + self.masks[cur:nxt], + self.random_seed, + action_type=self._action_type_flag, + dynamics_model=self.dynamics_model_flag, + human_agent_idx=self.human_agent_idx, + reward_goal=self.reward_goal, + reward_vehicle_collision=self.reward_vehicle_collision, + reward_offroad_collision=self.reward_offroad_collision, + reward_comfort=self.reward_comfort, + reward_lane_align=self.reward_lane_align, + reward_vel_align=self.reward_vel_align, + reward_lane_center=self.reward_lane_center, + reward_center_bias=self.reward_center_bias, + reward_velocity=self.reward_velocity, + reward_reverse=self.reward_reverse, + reward_traffic_light_violation=self.reward_traffic_light_violation, + reward_timestep=self.reward_timestep, + reward_overspeed=self.reward_overspeed, + reward_ade=self.reward_ade, + collision_behavior=self.collision_behavior, + offroad_behavior=self.offroad_behavior, + traffic_light_behavior=self.traffic_light_behavior, + goal_radius=self.goal_radius, + min_waypoint_spacing=self.min_waypoint_spacing, + max_waypoint_spacing=self.max_waypoint_spacing, + num_target_waypoints=self.num_target_waypoints, + target_type=self.target_type, + use_rear_axle=self.use_rear_axle, + max_lane_segment_observations=self.max_lane_segment_observations, + max_boundary_segment_observations=self.max_boundary_segment_observations, + max_partner_observations=self.max_partner_observations, + max_traffic_light_observations=self.max_traffic_light_observations, + max_stop_sign_observations=self.max_stop_sign_observations, + dt=self.dt, + spawn_initial_speed=self.spawn_initial_speed, + goal_speed_threshold=self.goal_speed_threshold, + scenario_length=(int(self.scenario_length) if self.scenario_length is not None else None), + termination_mode=int(self.termination_mode), + inactive_agent_threshold=float(self.inactive_agent_threshold), + map_file=self.map_files[map_ids[i]], + max_agents=nxt - cur, + max_agents_per_env=self.max_agents_per_env, + ini_file="pufferlib/config/ocean/drive.ini", + init_steps=self.init_steps, + init_mode=self.init_mode, + control_mode=self.control_mode, + simulation_mode=self.simulation_mode, + reward_conditioning=self.reward_conditioning, + reward_randomization=self.reward_randomization, + compute_eval_metrics=self.compute_eval_metrics, + eval_mode=self.eval_mode, + ) + env_ids.append(env_id) + self.c_envs = binding.vectorize(*env_ids) + + binding.vec_reset(self.c_envs, self.random_seed) + # Map resampling is an external reset boundary (dataset/map switch). Treat as truncation. + self.truncations[:] = 1 return (self.observations, self.rewards, self.terminals, self.truncations, info) def get_global_agent_state(self): @@ -341,15 +498,13 @@ def get_ground_truth_trajectories(self): num_agents = self.num_agents trajectories = { - "x": np.zeros((num_agents, self.episode_length - self.init_steps), dtype=np.float32), - "y": np.zeros((num_agents, self.episode_length - self.init_steps), dtype=np.float32), - "z": np.zeros((num_agents, self.episode_length - self.init_steps), dtype=np.float32), - "heading": np.zeros((num_agents, self.episode_length - self.init_steps), dtype=np.float32), - "valid": np.zeros((num_agents, self.episode_length - self.init_steps), dtype=np.int32), + "x": np.zeros((num_agents, self.scenario_length - self.init_steps), dtype=np.float32), + "y": np.zeros((num_agents, self.scenario_length - self.init_steps), dtype=np.float32), + "z": np.zeros((num_agents, self.scenario_length - self.init_steps), dtype=np.float32), + "heading": np.zeros((num_agents, self.scenario_length - self.init_steps), dtype=np.float32), + "valid": np.zeros((num_agents, self.scenario_length - self.init_steps), dtype=np.int32), "id": np.zeros(num_agents, dtype=np.int32), - "is_vehicle": np.zeros(num_agents, dtype=bool), - "is_track_to_predict": np.zeros(num_agents, dtype=bool), - "scenario_id": np.zeros(num_agents, dtype="S16"), + "scenario_id": np.zeros(num_agents, dtype=np.int32), } binding.vec_get_global_ground_truth_trajectories( @@ -360,16 +515,12 @@ def get_ground_truth_trajectories(self): trajectories["heading"], trajectories["valid"], trajectories["id"], - trajectories["is_vehicle"], - trajectories["is_track_to_predict"], trajectories["scenario_id"], ) for key in trajectories: trajectories[key] = trajectories[key][:, None] - trajectories["scenario_id"] = trajectories["scenario_id"].astype(str) - return trajectories def get_road_edge_polylines(self): @@ -385,7 +536,7 @@ def get_road_edge_polylines(self): "x": np.zeros(total_points, dtype=np.float32), "y": np.zeros(total_points, dtype=np.float32), "lengths": np.zeros(num_polylines, dtype=np.int32), - "scenario_id": np.zeros(num_polylines, dtype="S16"), + "scenario_id": np.zeros(num_polylines, dtype=np.int32), } binding.vec_get_road_edge_polylines( @@ -396,29 +547,19 @@ def get_road_edge_polylines(self): polylines["scenario_id"], ) - polylines["scenario_id"] = polylines["scenario_id"].astype(str) - return polylines - def render(self, view_mode: RenderView = RenderView.FULL_SIM_STATE, draw_traces: bool = True, env_id: int = 0): - binding.vec_render(self.c_envs, int(view_mode), draw_traces, env_id) + def render(self): + binding.vec_render(self.c_envs, 0) def close(self): binding.vec_close(self.c_envs) - def env_log(self, env_idx): - """Get log statistics for a single environment.""" - num_agents = self.agent_offsets[env_idx + 1] - self.agent_offsets[env_idx] - return binding.env_log(self.env_ids[env_idx], num_agents) - - def get_env_logs(self): - """Get log statistics for all environments (unaggregated).""" - return [self.env_log(i) for i in range(self.num_envs)] - - @property - def scenario_ids(self) -> list[str]: - """Return scenario ID string for each env, stripping null padding.""" - return [s.rstrip("\x00") for s in binding.vec_get_scenario_ids(self.c_envs)] + def get_state(self): + try: + return binding.vec_get(self.c_envs) + except Exception: + return binding.env_get(self.c_envs) def calculate_area(p1, p2, p3): @@ -426,13 +567,7 @@ def calculate_area(p1, p2, p3): return 0.5 * abs((p1["x"] - p3["x"]) * (p2["y"] - p1["y"]) - (p1["x"] - p2["x"]) * (p3["y"] - p1["y"])) -def dist(a, b): - dx = a["x"] - b["x"] - dy = a["y"] - b["y"] - return dx * dx + dy * dy - - -def simplify_polyline(geometry, polyline_reduction_threshold, max_segment_length): +def simplify_polyline(geometry, polyline_reduction_threshold): """Simplify the given polyline using a method inspired by Visvalingham-Whyatt, optimized for Python.""" num_points = len(geometry) if num_points < 3: @@ -461,7 +596,8 @@ def simplify_polyline(geometry, polyline_reduction_threshold, max_segment_length point2 = geometry[k_1] point3 = geometry[k_2] area = calculate_area(point1, point2, point3) - if area < polyline_reduction_threshold and dist(point1, point3) <= max_segment_length: + + if area < polyline_reduction_threshold: skip[k_1] = True skip_changed = True k = k_2 @@ -471,29 +607,13 @@ def simplify_polyline(geometry, polyline_reduction_threshold, max_segment_length return [geometry[i] for i in range(num_points) if not skip[i]] -def save_map_binary(map_data, output_file, unique_map_id): +def save_map_binary(map_data, output_file): trajectory_length = 91 """Saves map data in a binary format readable by C""" with open(output_file, "wb") as f: - # Get metadata - metadata = map_data.get("metadata", {}) - sdc_track_index = metadata.get("sdc_track_index", -1) # -1 as default if not found - tracks_to_predict = metadata.get("tracks_to_predict", []) - - # Write original scenario_id with fallback to placeholder - scenario_id = map_data.get("scenario_id", f"map_{unique_map_id:03d}") - f.write(struct.pack("16s", scenario_id.encode("utf-8"))) - - # Write sdc_track_index - f.write(struct.pack("i", sdc_track_index)) - - # Write tracks_to_predict info (indices only) - f.write(struct.pack("i", len(tracks_to_predict))) - for track in tracks_to_predict: - track_index = track.get("track_index", -1) - f.write(struct.pack("i", track_index)) - # Count total entities + print(len(map_data.get("objects", []))) + print(len(map_data.get("roads", []))) num_objects = len(map_data.get("objects", [])) num_roads = len(map_data.get("roads", [])) # num_entities = num_objects + num_roads @@ -502,9 +622,6 @@ def save_map_binary(map_data, output_file, unique_map_id): # f.write(struct.pack('i', num_entities)) # Write objects for obj in map_data.get("objects", []): - # Write unique map id - f.write(struct.pack("i", unique_map_id)) - # Write base entity data obj_type = obj.get("type", 1) if obj_type == "vehicle": @@ -514,7 +631,7 @@ def save_map_binary(map_data, output_file, unique_map_id): elif obj_type == "cyclist": obj_type = 3 f.write(struct.pack("i", obj_type)) # type - f.write(struct.pack("i", obj.get("id", 0))) # id + # f.write(struct.pack("i", obj.get("id", 0))) # id f.write(struct.pack("i", trajectory_length)) # array_size # Write position arrays positions = obj.get("position", []) @@ -564,8 +681,6 @@ def save_map_binary(map_data, output_file, unique_map_id): # Write roads for idx, road in enumerate(map_data.get("roads", [])): - f.write(struct.pack("i", unique_map_id)) - geometry = road.get("geometry", []) road_type = road.get("map_element_id", 0) road_type_word = road.get("type", 0) @@ -575,7 +690,7 @@ def save_map_binary(map_data, output_file, unique_map_id): road_type = 15 # breakpoint() if len(geometry) > 10 and road_type <= 16: - geometry = simplify_polyline(geometry, 0.1, 250) + geometry = simplify_polyline(geometry, 0.1) size = len(geometry) # breakpoint() if road_type >= 0 and road_type <= 3: @@ -594,14 +709,13 @@ def save_map_binary(map_data, output_file, unique_map_id): road_type = 10 # Write base entity data f.write(struct.pack("i", road_type)) # type - f.write(struct.pack("i", road.get("id", 0))) # id + # f.write(struct.pack("i", road.get("id", 0))) # id f.write(struct.pack("i", size)) # array_size # Write position arrays for coord in ["x", "y", "z"]: for point in geometry: f.write(struct.pack("f", float(point.get(coord, 0.0)))) - # Write scalar fields f.write(struct.pack("f", float(road.get("width", 0.0)))) f.write(struct.pack("f", float(road.get("length", 0.0)))) @@ -613,92 +727,80 @@ def save_map_binary(map_data, output_file, unique_map_id): f.write(struct.pack("i", road.get("mark_as_expert", 0))) -def load_map(map_name, unique_map_id, binary_output=None): +def load_map(map_name, binary_output=None): """Loads a JSON map and optionally saves it as binary""" with open(map_name, "r") as f: map_data = json.load(f) if binary_output: - save_map_binary(map_data, binary_output, unique_map_id) - + save_map_binary(map_data, binary_output) -def _process_single_map(args): - """Worker function to process a single map file""" - i, map_path, binary_path = args - try: - load_map(str(map_path), i, str(binary_path)) - return (i, map_path.name, True, None) - except Exception as e: - return (i, map_path.name, False, str(e)) - - -def process_all_maps( - data_folder="data/processed/training", - max_maps=50_000, - num_workers=None, -): - """Process all maps and save them as binaries using multiprocessing - - Args: - data_folder: Path to the folder containing JSON map files - max_maps: Maximum number of maps to process - num_workers: Number of parallel workers (defaults to cpu_count()) - """ - from pathlib import Path - - if num_workers is None: - num_workers = cpu_count() - - # Path to the training data - data_dir = Path(data_folder) - dataset_name = data_dir.name +def process_all_maps(dataset_path: str, max_file_to_process: int = 1000): + """Process all maps from a local path (or GCS) and save them as binaries.""" # Create the binaries directory if it doesn't exist - binary_dir = Path(f"resources/drive/binaries/{dataset_name}") + binary_dir = Path("pufferlib/resources/drive/binaries") binary_dir.mkdir(parents=True, exist_ok=True) - # Get all JSON files in the training directory - json_files = sorted(data_dir.glob("*.json")) - - # Prepare arguments for parallel processing - tasks = [] - for i, map_path in enumerate(json_files[:max_maps]): - binary_file = f"map_{i:03d}.bin" - binary_path = binary_dir / binary_file - tasks.append((i, map_path, binary_path)) - - # Process maps in parallel with progress bar - with Pool(num_workers) as pool: - results = list( - tqdm(pool.imap(_process_single_map, tasks), total=len(tasks), desc="Processing maps", unit="map") - ) - - # Collect statistics - successful = sum(1 for _, _, success, _ in results if success) - failed = sum(1 for _, _, success, _ in results if not success) - - if failed > 0: - print(f"\nFailed {failed}/{len(results)} files:") - for i, name, success, error in results: - if not success: - print(f" {name}: {error}") + # --- GCS FUSE --- + if dataset_path.startswith("gs://") and os.path.exists("/gcs/"): + print("Vertex AI GCS FUSE mount detected. Translating GCS URI to local path.") + dataset_path = dataset_path.replace("gs://", "/gcs/") + print(f"Using mounted dataset path: {dataset_path}") + + file_iterator = None + fs = None # Will hold the gcsfs filesystem object if needed + + path = Path(dataset_path) + print(f"Searching for JSON map files in local path: {path.resolve()}") + # Use rglob for recursive globbing to match the GCS '**' behavior + file_iterator = sorted(path.rglob("*.json")) + print(f"Found {len(file_iterator)} JSON files locally.") + + file_count = 0 + # Process each JSON file from the appropriate source + for i, item in enumerate(file_iterator): + if i >= max_file_to_process: + print(f"Reached file limit of {max_file_to_process}.") + break + + map_path_str = "" + try: + # if is_gcs_stream: + # # item is a path string from gcsfs.glob, e.g., "my-bucket/path/file.json" + # map_path_str = f"gs://{item}" + # # Use 'with' to ensure the stream is automatically closed + # with fs.open(item, "rt", encoding="utf-8") as stream: + # map_data = json.load(stream) + # else: + # item is a Path object from Path.rglob + map_path_str = str(item) + # Use 'with' for local files too (good practice) + with open(map_path_str, "r") as f: + map_data = json.load(f) + + map_name = Path(map_path_str).name + binary_file = f"map_{i:03d}.bin" + binary_path = binary_dir / binary_file + + print(f"Processing {map_name} -> {binary_file}") + save_map_binary(map_data, str(binary_path)) + file_count += 1 + + except Exception as e: + print(f"Error processing {map_path_str}: {e}") + continue + + print(f"Found and processed {file_count} JSON files.") def test_performance(timeout=10, atn_cache=1024, num_agents=1024): import time - env = Drive( - num_agents=num_agents, - num_maps=1, - control_mode="control_vehicles", - init_mode="create_all_valid", - init_steps=0, - episode_length=91, - ) - + env = Drive(num_agents=num_agents) env.reset() - tick = 0 + num_agents = 1024 actions = np.stack( [np.random.randint(0, space.n + 1, (atn_cache, num_agents)) for space in env.single_action_space], axis=-1 ) @@ -710,15 +812,14 @@ def test_performance(timeout=10, atn_cache=1024, num_agents=1024): tick += 1 print(f"SPS: {num_agents * tick / (time.time() - start)}") - env.close() if __name__ == "__main__": # test_performance() - # Process the train dataset - process_all_maps(data_folder="data/processed/training") - # Process the validation/test dataset - # process_all_maps(data_folder="data/processed/validation") - # # Process the validation_interactive dataset - # process_all_maps(data_folder="data/processed/validation_interactive") + parser = argparse.ArgumentParser(description="Process maps for PufferDrive.") + parser.add_argument( + "--data_dir", type=str, default="data/train", help="Path to the directory containing JSON map files." + ) + args = parser.parse_args() + process_all_maps(args.data_dir) diff --git a/pufferlib/ocean/drive/drivenet.h b/pufferlib/ocean/drive/drivenet.h index 5719081bb1..fdad05c585 100644 --- a/pufferlib/ocean/drive/drivenet.h +++ b/pufferlib/ocean/drive/drivenet.h @@ -8,271 +8,386 @@ #include #include -#define NN_INPUT_SIZE 64 -#define NN_HIDDEN_SIZE 256 +// Tanh activation (not in puffernet.h) +static inline void tanh_activation(float *data, int size) { + for (int i = 0; i < size; i++) { + data[i] = tanhf(data[i]); + } +} + +// Gigaflow-style encoder: Linear → LayerNorm → Tanh → Linear +// Weights order matches PyTorch: encoder.0 (Linear), encoder.1 (LayerNorm), encoder.4 (Linear) +typedef struct { + Linear *linear1; + LayerNorm *layernorm; + Linear *linear2; + float *ln_output; + int batch_size; + int input_size; +} Encoder; + +Encoder *make_encoder(Weights *weights, int batch_size, int in_features, int input_size) { + Encoder *enc = calloc(1, sizeof(Encoder)); + enc->batch_size = batch_size; + enc->input_size = input_size; + enc->linear1 = make_linear(weights, batch_size, in_features, input_size); + enc->layernorm = make_layernorm(weights, batch_size, input_size); + enc->ln_output = calloc(batch_size * input_size, sizeof(float)); + enc->linear2 = make_linear(weights, batch_size, input_size, input_size); + return enc; +} + +// Apply encoder to flat input (batch_size x in_features) +void encoder_forward(Encoder *enc, float *input) { + linear(enc->linear1, input); + layernorm(enc->layernorm, enc->linear1->output); + // Tanh after layernorm + memcpy(enc->ln_output, enc->layernorm->output, enc->batch_size * enc->input_size * sizeof(float)); + tanh_activation(enc->ln_output, enc->batch_size * enc->input_size); + // Second linear + linear(enc->linear2, enc->ln_output); +} + +// Apply encoder per-object: input is [batch_size * num_objects * features] +// Output is max-pooled: [batch_size * input_size] +void encoder_forward_objects(Encoder *enc, float *input, float *output, + int batch_size, int num_objects, int in_features, int input_size) { + float *obj_encoded = calloc(batch_size * num_objects * input_size, sizeof(float)); + + for (int b = 0; b < batch_size; b++) { + for (int obj = 0; obj < num_objects; obj++) { + float *obj_in = &input[b * num_objects * in_features + obj * in_features]; + float *lin1_out = &obj_encoded[b * num_objects * input_size + obj * input_size]; + + // Linear1 + _linear(obj_in, enc->linear1->weights, enc->linear1->bias, lin1_out, 1, in_features, input_size); + + // LayerNorm + float ln_out[input_size]; + _layernorm(lin1_out, enc->layernorm->weights, enc->layernorm->bias, ln_out, 1, input_size); + + // Tanh + tanh_activation(ln_out, input_size); + + // Linear2 + float *final_out = &obj_encoded[b * num_objects * input_size + obj * input_size]; + _linear(ln_out, enc->linear2->weights, enc->linear2->bias, final_out, 1, input_size, input_size); + } + } + + // Max pool over objects dimension + for (int b = 0; b < batch_size; b++) { + for (int f = 0; f < input_size; f++) { + float max_val = -1e30f; + for (int obj = 0; obj < num_objects; obj++) { + float val = obj_encoded[b * num_objects * input_size + obj * input_size + f]; + if (val > max_val) max_val = val; + } + output[b * input_size + f] = max_val; + } + } + + free(obj_encoded); +} -// Note: This C neural network implementation is designed specifically for lightweight -// browser demos and is not intended for training purposes. -// -// For development and experimentation, it is recommended to use the render structure -// defined in eval() inside pufferl.py, since it uses the torch net. This makes modifying, -// testing, and iterating on the model easier and less error-prone. +void free_encoder(Encoder *enc) { + free(enc->linear1); + free(enc->layernorm); + free(enc->linear2); + free(enc->ln_output); + free(enc); +} typedef struct DriveNet DriveNet; struct DriveNet { int num_agents; int ego_dim; - float *obs_self; - float *obs_partner; - float *obs_road; - float *partner_linear_output; - float *road_linear_output; - float *partner_layernorm_output; - float *road_layernorm_output; - float *partner_linear_output_two; - float *road_linear_output_two; - Linear *ego_encoder; - Linear *road_encoder; - Linear *partner_encoder; - LayerNorm *ego_layernorm; - LayerNorm *road_layernorm; - LayerNorm *partner_layernorm; - Linear *ego_encoder_two; - Linear *road_encoder_two; - Linear *partner_encoder_two; - MaxDim1 *partner_max; - MaxDim1 *road_max; - CatDim1 *cat1; - CatDim1 *cat2; - GELU *gelu; - Linear *shared_embedding; - ReLU *relu; - LSTM *lstm; + int input_size; + int backbone_hidden_size; + + // Observation dimensions + int max_partner_obs; + int partner_features; + int max_lane_obs; + int max_boundary_obs; + int road_features; + int max_traffic_light_obs; + int traffic_light_features_raw; + int traffic_light_features_onehot; + int conditioning_dim; + + // Encoders + Encoder *ego_encoder; + Encoder *lane_encoder; + Encoder *boundary_encoder; + Encoder *partner_encoder; + Encoder *traffic_light_encoder; + Encoder *conditioning_encoder; + + // Temp buffers for per-object encoding + max pooling + float *lane_pooled; + float *boundary_pooled; + float *partner_pooled; + float *traffic_light_pooled; + float *traffic_light_onehot_buf; + + // Backbone layers: GELU → Linear → GELU → Linear → ... → GELU + int num_backbone_layers; + GELU **backbone_gelus; + Linear **backbone_linears; + + // Heads Linear *actor; Linear *value_fn; + + // Final GELU before heads + GELU *final_gelu; + + // Action selection Multidiscrete *multidiscrete; + + // Concatenation buffer + float *concat_buf; }; DriveNet *init_drivenet(Weights *weights, int num_agents, int dynamics_model) { DriveNet *net = calloc(1, sizeof(DriveNet)); - // Use constants directly from drive.h + + // Architecture config (must match torch.py / drive.ini) + int input_size = 64; + int backbone_hidden_size = 512; + int backbone_num_layers = 4; + int ego_dim = (dynamics_model == JERK) ? EGO_FEATURES_JERK : EGO_FEATURES_CLASSIC; - int max_partners = MAX_AGENTS - 1; - int max_road_obs = MAX_ROAD_SEGMENT_OBSERVATIONS; - int partner_features = PARTNER_FEATURES; - int road_features = ROAD_FEATURES; - int input_size = NN_INPUT_SIZE; - int hidden_size = NN_HIDDEN_SIZE; - int road_feat_onehot = road_features + 6; // one-hot extra 6 features for road - - // Determine action space size based on dynamics model - int action_size, logit_sizes[2]; - int action_dim; + int partner_features = PARTNER_FEATURES; // 8 + int road_features = ROAD_FEATURES; // 7 + int traffic_light_features_raw = TRAFFIC_LIGHT_FEATURES; // 6 + int num_tl_states = 4; // NUM_TRAFFIC_LIGHT_STATES from datatypes.h + int traffic_light_features_onehot = traffic_light_features_raw - 1 + num_tl_states; // 5+4=9 + + // Observation counts (from drive.ini defaults) + int max_partner_obs = 20; + int max_lane_obs = 64; + int max_boundary_obs = 32; + int max_traffic_light_obs = 4; + + // Conditioning: target waypoints (static: 3 waypoints * 3 features = 9) + int conditioning_dim = 9; + + // Action space + int action_size, logit_sizes[1]; if (dynamics_model == CLASSIC) { - action_size = 7 * 13; // Joint action space - logit_sizes[0] = 7 * 13; - action_dim = 1; - } else { // JERK - action_size = 4 * 3; // Joint action space (4 longitudinal × 3 lateral = 12) - logit_sizes[0] = 4 * 3; - action_dim = 1; + action_size = 7 * 9; // 7 accel * 9 steer + logit_sizes[0] = action_size; + } else { // JERK + action_size = 4 * 3; // 4 longitudinal * 3 lateral = 12 + logit_sizes[0] = action_size; } net->num_agents = num_agents; net->ego_dim = ego_dim; - net->obs_self = calloc(num_agents * ego_dim, sizeof(float)); - net->obs_partner = calloc(num_agents * max_partners * partner_features, sizeof(float)); - net->obs_road = calloc(num_agents * max_road_obs * road_feat_onehot, sizeof(float)); - net->partner_linear_output = calloc(num_agents * max_partners * input_size, sizeof(float)); - net->road_linear_output = calloc(num_agents * max_road_obs * input_size, sizeof(float)); - net->partner_linear_output_two = calloc(num_agents * max_partners * input_size, sizeof(float)); - net->road_linear_output_two = calloc(num_agents * max_road_obs * input_size, sizeof(float)); - net->partner_layernorm_output = calloc(num_agents * max_partners * input_size, sizeof(float)); - net->road_layernorm_output = calloc(num_agents * max_road_obs * input_size, sizeof(float)); - - net->ego_encoder = make_linear(weights, num_agents, ego_dim, input_size); - net->ego_layernorm = make_layernorm(weights, num_agents, input_size); - net->ego_encoder_two = make_linear(weights, num_agents, input_size, input_size); - net->road_encoder = make_linear(weights, num_agents, road_feat_onehot, input_size); - net->road_layernorm = make_layernorm(weights, num_agents, input_size); - net->road_encoder_two = make_linear(weights, num_agents, input_size, input_size); - net->partner_encoder = make_linear(weights, num_agents, partner_features, input_size); - net->partner_layernorm = make_layernorm(weights, num_agents, input_size); - net->partner_encoder_two = make_linear(weights, num_agents, input_size, input_size); - net->partner_max = make_max_dim1(num_agents, max_partners, input_size); - net->road_max = make_max_dim1(num_agents, max_road_obs, input_size); - net->cat1 = make_cat_dim1(num_agents, input_size, input_size); - net->cat2 = make_cat_dim1(num_agents, input_size + input_size, input_size); - net->gelu = make_gelu(num_agents, 3 * input_size); - net->shared_embedding = make_linear(weights, num_agents, input_size * 3, hidden_size); - net->relu = make_relu(num_agents, hidden_size); - net->actor = make_linear(weights, num_agents, hidden_size, action_size); - net->value_fn = make_linear(weights, num_agents, hidden_size, 1); - net->lstm = make_lstm(weights, num_agents, hidden_size, NN_HIDDEN_SIZE); - memset(net->lstm->state_h, 0, num_agents * NN_HIDDEN_SIZE * sizeof(float)); - memset(net->lstm->state_c, 0, num_agents * NN_HIDDEN_SIZE * sizeof(float)); - net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, action_dim); + net->input_size = input_size; + net->backbone_hidden_size = backbone_hidden_size; + net->max_partner_obs = max_partner_obs; + net->partner_features = partner_features; + net->max_lane_obs = max_lane_obs; + net->max_boundary_obs = max_boundary_obs; + net->road_features = road_features; + net->max_traffic_light_obs = max_traffic_light_obs; + net->traffic_light_features_raw = traffic_light_features_raw; + net->traffic_light_features_onehot = traffic_light_features_onehot; + net->conditioning_dim = conditioning_dim; + + // Create encoders (weight order must match PyTorch export) + // actor_backbone.ego_encoder.{0,1,4} + net->ego_encoder = make_encoder(weights, num_agents, ego_dim, input_size); + // actor_backbone.lane_encoder.{0,1,4} + net->lane_encoder = make_encoder(weights, num_agents, road_features, input_size); + // actor_backbone.boundary_encoder.{0,1,4} + net->boundary_encoder = make_encoder(weights, num_agents, road_features, input_size); + // actor_backbone.partner_encoder.{0,1,4} + net->partner_encoder = make_encoder(weights, num_agents, partner_features, input_size); + // actor_backbone.traffic_light_encoder.{0,1,4} + net->traffic_light_encoder = make_encoder(weights, num_agents, traffic_light_features_onehot, input_size); + // actor_backbone.conditioning_encoder.{0,1,4} + net->conditioning_encoder = make_encoder(weights, num_agents, conditioning_dim, input_size); + + // Pooling output buffers + net->lane_pooled = calloc(num_agents * input_size, sizeof(float)); + net->boundary_pooled = calloc(num_agents * input_size, sizeof(float)); + net->partner_pooled = calloc(num_agents * input_size, sizeof(float)); + net->traffic_light_pooled = calloc(num_agents * input_size, sizeof(float)); + net->traffic_light_onehot_buf = calloc(num_agents * max_traffic_light_obs * traffic_light_features_onehot, sizeof(float)); + + // Backbone: GELU → Linear → GELU → Linear → ... → GELU + // actor_backbone.backbone.{1,3,5,7} are the Linear layers (0,2,4,6,8 are GELUs) + net->num_backbone_layers = backbone_num_layers; + net->backbone_gelus = calloc(backbone_num_layers + 1, sizeof(GELU *)); + net->backbone_linears = calloc(backbone_num_layers, sizeof(Linear *)); + + int bb_in = 6 * input_size; // 6 feature sets * 64 = 384 + for (int i = 0; i < backbone_num_layers; i++) { + net->backbone_gelus[i] = make_gelu(num_agents, bb_in); + net->backbone_linears[i] = make_linear(weights, num_agents, bb_in, backbone_hidden_size); + bb_in = backbone_hidden_size; + } + net->final_gelu = make_gelu(num_agents, backbone_hidden_size); + + // Actor and critic heads + // actor_head.0, critic_head.0 + net->actor = make_linear(weights, num_agents, backbone_hidden_size, action_size); + net->value_fn = make_linear(weights, num_agents, backbone_hidden_size, 1); + + // Concat buffer + net->concat_buf = calloc(num_agents * 6 * input_size, sizeof(float)); + + // Action selection + net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, 1); + return net; } void free_drivenet(DriveNet *net) { - free(net->obs_self); - free(net->obs_partner); - free(net->obs_road); - free(net->partner_linear_output); - free(net->road_linear_output); - free(net->partner_linear_output_two); - free(net->road_linear_output_two); - free(net->partner_layernorm_output); - free(net->road_layernorm_output); - free(net->ego_encoder); - free(net->road_encoder); - free(net->partner_encoder); - free(net->ego_layernorm); - free(net->road_layernorm); - free(net->partner_layernorm); - free(net->ego_encoder_two); - free(net->road_encoder_two); - free(net->partner_encoder_two); - free(net->partner_max); - free(net->road_max); - free(net->cat1); - free(net->cat2); - free(net->gelu); - free(net->shared_embedding); - free(net->relu); + free_encoder(net->ego_encoder); + free_encoder(net->lane_encoder); + free_encoder(net->boundary_encoder); + free_encoder(net->partner_encoder); + free_encoder(net->traffic_light_encoder); + free_encoder(net->conditioning_encoder); + free(net->lane_pooled); + free(net->boundary_pooled); + free(net->partner_pooled); + free(net->traffic_light_pooled); + free(net->traffic_light_onehot_buf); + for (int i = 0; i < net->num_backbone_layers; i++) { + free(net->backbone_gelus[i]); + free(net->backbone_linears[i]); + } + free(net->backbone_gelus); + free(net->backbone_linears); + free(net->final_gelu); + free(net->concat_buf); free(net->multidiscrete); free(net->actor); free(net->value_fn); - free(net->lstm); free(net); } void forward(DriveNet *net, float *observations, int *actions) { + int n = net->num_agents; int ego_dim = net->ego_dim; - int max_partners = MAX_AGENTS - 1; - int max_road_obs = MAX_ROAD_SEGMENT_OBSERVATIONS; - int partner_features = PARTNER_FEATURES; - int road_features = ROAD_FEATURES; - int road_feat_onehot = road_features + 6; // one-hot extra 6 features for road - - // Clear previous observations - memset(net->obs_self, 0, net->num_agents * ego_dim * sizeof(float)); - memset(net->obs_partner, 0, net->num_agents * max_partners * partner_features * sizeof(float)); - memset(net->obs_road, 0, net->num_agents * max_road_obs * road_feat_onehot * sizeof(float)); - - for (int b = 0; b < net->num_agents; b++) { - int b_offset = b * (ego_dim + max_partners * partner_features + max_road_obs * road_features); - int partner_offset = b_offset + ego_dim; - int road_offset = b_offset + ego_dim + max_partners * partner_features; - - // Process self observation - for (int i = 0; i < ego_dim; i++) { - net->obs_self[b * ego_dim + i] = observations[b_offset + i]; - } + int input_size = net->input_size; - // Process partner observation - for (int i = 0; i < max_partners; i++) { - for (int j = 0; j < partner_features; j++) { - net->obs_partner[b * max_partners * partner_features + i * partner_features + j] = - observations[partner_offset + i * partner_features + j]; - } - } + // Observation layout (from torch.py forward): + // [ego | conditioning | partners | lanes | boundaries | traffic_lights | stop_signs] + int cond_dim = net->conditioning_dim; + int partner_dim = net->max_partner_obs * net->partner_features; + int lane_dim = net->max_lane_obs * net->road_features; + int boundary_dim = net->max_boundary_obs * net->road_features; + int tl_dim = net->max_traffic_light_obs * net->traffic_light_features_raw; - // Process road observation - for (int i = 0; i < MAX_ROAD_SEGMENT_OBSERVATIONS; i++) { - for (int j = 0; j < 7; j++) { - net->obs_road[b * MAX_ROAD_SEGMENT_OBSERVATIONS * ROAD_FEATURES_ONEHOT + i * ROAD_FEATURES_ONEHOT + j] = - observations[road_offset + i * 7 + j]; - } - for (int j = 0; j < 7; j++) { - if (j == observations[road_offset + i * 7 + 6]) { - net->obs_road[b * MAX_ROAD_SEGMENT_OBSERVATIONS * ROAD_FEATURES_ONEHOT + i * ROAD_FEATURES_ONEHOT + - 6 + j] = 1.0f; - } else { - net->obs_road[b * MAX_ROAD_SEGMENT_OBSERVATIONS * ROAD_FEATURES_ONEHOT + i * ROAD_FEATURES_ONEHOT + - 6 + j] = 0.0f; - } - } - } + int obs_stride = ego_dim + cond_dim + partner_dim + lane_dim + boundary_dim + tl_dim; + + // 1. Ego encoder (flat, no pooling) + // Extract ego observations into contiguous buffer + float *ego_buf = calloc(n * ego_dim, sizeof(float)); + for (int b = 0; b < n; b++) { + memcpy(&ego_buf[b * ego_dim], &observations[b * obs_stride], ego_dim * sizeof(float)); } + encoder_forward(net->ego_encoder, ego_buf); - // Forward pass through the network - linear(net->ego_encoder, net->obs_self); - layernorm(net->ego_layernorm, net->ego_encoder->output); - linear(net->ego_encoder_two, net->ego_layernorm->output); - for (int b = 0; b < net->num_agents; b++) { - for (int obj = 0; obj < max_partners; obj++) { - // Get the 7 features for this object - float *obj_features = &net->obs_partner[b * max_partners * partner_features + obj * partner_features]; - // Apply linear layer to this object - _linear(obj_features, net->partner_encoder->weights, net->partner_encoder->bias, - &net->partner_linear_output[b * max_partners * NN_INPUT_SIZE + obj * NN_INPUT_SIZE], 1, - partner_features, NN_INPUT_SIZE); - } + // 2. Conditioning encoder (flat, no pooling) + float *cond_buf = calloc(n * cond_dim, sizeof(float)); + for (int b = 0; b < n; b++) { + memcpy(&cond_buf[b * cond_dim], &observations[b * obs_stride + ego_dim], cond_dim * sizeof(float)); } + encoder_forward(net->conditioning_encoder, cond_buf); - for (int b = 0; b < net->num_agents; b++) { - for (int obj = 0; obj < max_partners; obj++) { - float *after_first = &net->partner_linear_output[b * max_partners * NN_INPUT_SIZE + obj * NN_INPUT_SIZE]; - _layernorm(after_first, net->partner_layernorm->weights, net->partner_layernorm->bias, - &net->partner_layernorm_output[b * max_partners * NN_INPUT_SIZE + obj * NN_INPUT_SIZE], 1, - NN_INPUT_SIZE); - } + // 3. Lane encoder (per-object + max pool) + float *lane_buf = calloc(n * lane_dim, sizeof(float)); + for (int b = 0; b < n; b++) { + int offset = ego_dim + cond_dim + partner_dim; + memcpy(&lane_buf[b * lane_dim], &observations[b * obs_stride + offset], lane_dim * sizeof(float)); } - for (int b = 0; b < net->num_agents; b++) { - for (int obj = 0; obj < max_partners; obj++) { - // Get the 7 features for this object - float *obj_features = - &net->partner_layernorm_output[b * max_partners * NN_INPUT_SIZE + obj * NN_INPUT_SIZE]; - // Apply linear layer to this object - _linear(obj_features, net->partner_encoder_two->weights, net->partner_encoder_two->bias, - &net->partner_linear_output_two[b * max_partners * NN_INPUT_SIZE + obj * NN_INPUT_SIZE], 1, - NN_INPUT_SIZE, NN_INPUT_SIZE); - } + encoder_forward_objects(net->lane_encoder, lane_buf, net->lane_pooled, + n, net->max_lane_obs, net->road_features, input_size); + + // 4. Boundary encoder (per-object + max pool) + float *boundary_buf = calloc(n * boundary_dim, sizeof(float)); + for (int b = 0; b < n; b++) { + int offset = ego_dim + cond_dim + partner_dim + lane_dim; + memcpy(&boundary_buf[b * boundary_dim], &observations[b * obs_stride + offset], boundary_dim * sizeof(float)); } + encoder_forward_objects(net->boundary_encoder, boundary_buf, net->boundary_pooled, + n, net->max_boundary_obs, net->road_features, input_size); - // Process road objects: apply linear to each object individually - for (int b = 0; b < net->num_agents; b++) { - for (int obj = 0; obj < max_road_obs; obj++) { - // Get the 13 features for this object - float *obj_features = &net->obs_road[b * max_road_obs * ROAD_FEATURES_ONEHOT + obj * ROAD_FEATURES_ONEHOT]; - // Apply linear layer to this object - _linear(obj_features, net->road_encoder->weights, net->road_encoder->bias, - &net->road_linear_output[b * max_road_obs * NN_INPUT_SIZE + obj * NN_INPUT_SIZE], 1, - ROAD_FEATURES_ONEHOT, NN_INPUT_SIZE); - } + // 5. Partner encoder (per-object + max pool) + float *partner_buf = calloc(n * partner_dim, sizeof(float)); + for (int b = 0; b < n; b++) { + int offset = ego_dim + cond_dim; + memcpy(&partner_buf[b * partner_dim], &observations[b * obs_stride + offset], partner_dim * sizeof(float)); } + encoder_forward_objects(net->partner_encoder, partner_buf, net->partner_pooled, + n, net->max_partner_obs, net->partner_features, input_size); - // Apply layer norm and second linear to each road object - for (int b = 0; b < net->num_agents; b++) { - for (int obj = 0; obj < max_road_obs; obj++) { - float *after_first = &net->road_linear_output[b * max_road_obs * NN_INPUT_SIZE + obj * NN_INPUT_SIZE]; - _layernorm(after_first, net->road_layernorm->weights, net->road_layernorm->bias, - &net->road_layernorm_output[b * max_road_obs * NN_INPUT_SIZE + obj * NN_INPUT_SIZE], 1, - NN_INPUT_SIZE); + // 6. Traffic light encoder (per-object + max pool, with one-hot encoding) + // Raw: [n * max_tl * 6], need to convert last feature to one-hot → [n * max_tl * 9] + memset(net->traffic_light_onehot_buf, 0, n * net->max_traffic_light_obs * net->traffic_light_features_onehot * sizeof(float)); + for (int b = 0; b < n; b++) { + int raw_offset = ego_dim + cond_dim + partner_dim + lane_dim + boundary_dim; + for (int obj = 0; obj < net->max_traffic_light_obs; obj++) { + float *raw = &observations[b * obs_stride + raw_offset + obj * net->traffic_light_features_raw]; + float *out = &net->traffic_light_onehot_buf[(b * net->max_traffic_light_obs + obj) * net->traffic_light_features_onehot]; + // Copy continuous features (first 5) + for (int f = 0; f < net->traffic_light_features_raw - 1; f++) { + out[f] = raw[f]; + } + // One-hot encode the last feature (traffic light state) + int state = (int)raw[net->traffic_light_features_raw - 1]; + if (state >= 0 && state < 4) { + out[net->traffic_light_features_raw - 1 + state] = 1.0f; + } } } - for (int b = 0; b < net->num_agents; b++) { - for (int obj = 0; obj < max_road_obs; obj++) { - float *after_first = &net->road_layernorm_output[b * max_road_obs * NN_INPUT_SIZE + obj * NN_INPUT_SIZE]; - _linear(after_first, net->road_encoder_two->weights, net->road_encoder_two->bias, - &net->road_linear_output_two[b * max_road_obs * NN_INPUT_SIZE + obj * NN_INPUT_SIZE], 1, - NN_INPUT_SIZE, NN_INPUT_SIZE); - } + encoder_forward_objects(net->traffic_light_encoder, net->traffic_light_onehot_buf, net->traffic_light_pooled, + n, net->max_traffic_light_obs, net->traffic_light_features_onehot, input_size); + + // Concatenate all features: [ego | lane | boundary | partner | traffic_light | conditioning] + for (int b = 0; b < n; b++) { + int off = 0; + memcpy(&net->concat_buf[b * 6 * input_size + off], &net->ego_encoder->linear2->output[b * input_size], input_size * sizeof(float)); + off += input_size; + memcpy(&net->concat_buf[b * 6 * input_size + off], &net->lane_pooled[b * input_size], input_size * sizeof(float)); + off += input_size; + memcpy(&net->concat_buf[b * 6 * input_size + off], &net->boundary_pooled[b * input_size], input_size * sizeof(float)); + off += input_size; + memcpy(&net->concat_buf[b * 6 * input_size + off], &net->partner_pooled[b * input_size], input_size * sizeof(float)); + off += input_size; + memcpy(&net->concat_buf[b * 6 * input_size + off], &net->traffic_light_pooled[b * input_size], input_size * sizeof(float)); + off += input_size; + memcpy(&net->concat_buf[b * 6 * input_size + off], &net->conditioning_encoder->linear2->output[b * input_size], input_size * sizeof(float)); + } + + // Backbone: GELU → Linear → GELU → Linear → ... → GELU + float *bb_input = net->concat_buf; + for (int i = 0; i < net->num_backbone_layers; i++) { + gelu(net->backbone_gelus[i], bb_input); + linear(net->backbone_linears[i], net->backbone_gelus[i]->output); + bb_input = net->backbone_linears[i]->output; } + gelu(net->final_gelu, bb_input); - max_dim1(net->partner_max, net->partner_linear_output_two); - max_dim1(net->road_max, net->road_linear_output_two); - cat_dim1(net->cat1, net->ego_encoder_two->output, net->road_max->output); - cat_dim1(net->cat2, net->cat1->output, net->partner_max->output); - gelu(net->gelu, net->cat2->output); - linear(net->shared_embedding, net->gelu->output); - relu(net->relu, net->shared_embedding->output); - lstm(net->lstm, net->relu->output); - linear(net->actor, net->lstm->state_h); - linear(net->value_fn, net->lstm->state_h); + // Actor and critic heads + linear(net->actor, net->final_gelu->output); + linear(net->value_fn, net->final_gelu->output); // Get action by taking argmax of actor output softmax_multidiscrete(net->multidiscrete, net->actor->output, actions); + + // Cleanup temp buffers + free(ego_buf); + free(cond_buf); + free(lane_buf); + free(boundary_buf); + free(partner_buf); } diff --git a/pufferlib/ocean/drive/render.h b/pufferlib/ocean/drive/render.h new file mode 100644 index 0000000000..d3ee4bd332 --- /dev/null +++ b/pufferlib/ocean/drive/render.h @@ -0,0 +1,843 @@ +#ifndef RENDER_H +#define RENDER_H + +#include +#include "rlgl.h" + +#define MAX_AGENTS 64 + +const Color STONE_GRAY = (Color){80, 80, 80, 255}; +const Color PUFF_RED = (Color){187, 0, 0, 255}; +const Color PUFF_CYAN = (Color){0, 187, 187, 255}; +const Color PUFF_WHITE = (Color){241, 241, 241, 241}; +const Color PUFF_BACKGROUND = (Color){6, 24, 24, 255}; +const Color PUFF_BACKGROUND2 = (Color){18, 72, 72, 255}; +const Color LIGHTGREEN = (Color){152, 255, 152, 255}; + +typedef struct Client { + float width; + float height; + Texture2D puffers; + Vector3 camera_target; + float camera_zoom; + Camera3D camera; + Model cars[6]; + Model cyclist; + Model pedestrian; + ModelAnimation *cycle_anim; + int car_assignments[MAX_AGENTS]; // To keep car model assignments consistent per vehicle + Vector3 default_camera_position; + Vector3 default_camera_target; +} Client; + +Client *make_client(Drive *env) { + Client *client = (Client *)calloc(1, sizeof(Client)); + client->width = 1280; + client->height = 704; + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(client->width, client->height, "PufferLib Ray GPU Drive"); + SetTargetFPS(30); + client->puffers = LoadTexture("resources/puffers_128.png"); + client->cars[0] = LoadModel("resources/drive/RedCar.glb"); + client->cars[1] = LoadModel("resources/drive/WhiteCar.glb"); + client->cars[2] = LoadModel("resources/drive/BlueCar.glb"); + client->cars[3] = LoadModel("resources/drive/YellowCar.glb"); + client->cars[4] = LoadModel("resources/drive/GreenCar.glb"); + client->cars[5] = LoadModel("resources/drive/GreyCar.glb"); + client->cyclist = LoadModel("resources/drive/cyclist.glb"); + client->pedestrian = LoadModel("resources/drive/pedestrian.glb"); + int animCountCyc = 0; + client->cycle_anim = LoadModelAnimations("resources/drive/cyclist.glb", &animCountCyc); + for (int i = 0; i < MAX_AGENTS; i++) { + client->car_assignments[i] = (rand() % 4) + 1; + } + // Get initial target position from first active agent + Vector3 target_pos = { + 0, + 0, // Y is up + 1 // Z is depth + }; + + // Set up camera to look at target from above and behind + client->default_camera_position = (Vector3){ + 0, // Same X as target + 120.0f, // 20 units above target + 175.0f // 20 units behind target + }; + client->default_camera_target = target_pos; + client->camera.position = client->default_camera_position; + client->camera.target = client->default_camera_target; + client->camera.up = (Vector3){0.0f, -1.0f, 0.0f}; // Y is up + client->camera.fovy = 45.0f; + client->camera.projection = CAMERA_PERSPECTIVE; + client->camera_zoom = 1.0f; + return client; +} + +// Camera control functions +void handle_camera_controls(Client *client) { + static Vector2 prev_mouse_pos = {0}; + static bool is_dragging = false; + float camera_move_speed = 0.5f; + + // Handle mouse drag for camera movement + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { + prev_mouse_pos = GetMousePosition(); + is_dragging = true; + } + + if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) { + is_dragging = false; + } + + if (is_dragging) { + Vector2 current_mouse_pos = GetMousePosition(); + Vector2 delta = {(current_mouse_pos.x - prev_mouse_pos.x) * camera_move_speed, + -(current_mouse_pos.y - prev_mouse_pos.y) * camera_move_speed}; + + // Update camera position (only X and Y) + client->camera.position.x += delta.x; + client->camera.position.y += delta.y; + + // Update camera target (only X and Y) + client->camera.target.x += delta.x; + client->camera.target.y += delta.y; + + prev_mouse_pos = current_mouse_pos; + } + + // Handle mouse wheel for zoom + float wheel = GetMouseWheelMove(); + if (wheel != 0) { + float zoom_factor = 1.0f - (wheel * 0.1f); + // Calculate the current direction vector from target to position + Vector3 direction = {client->camera.position.x - client->camera.target.x, + client->camera.position.y - client->camera.target.y, + client->camera.position.z - client->camera.target.z}; + + // Scale the direction vector by the zoom factor + direction.x *= zoom_factor; + direction.y *= zoom_factor; + direction.z *= zoom_factor; + + // Update the camera position based on the scaled direction + client->camera.position.x = client->camera.target.x + direction.x; + client->camera.position.y = client->camera.target.y + direction.y; + client->camera.position.z = client->camera.target.z + direction.z; + } +} + +void draw_agent_obs(Drive *env, int agent_index, int mode, int obs_only, int lasers) { + // Diamond dimensions + float diamond_height = 3.0f; // Total height of diamond + float diamond_width = 1.5f; // Width of diamond + float diamond_z = 8.0f; // Base Z position + + // Define diamond points + Vector3 top_point = (Vector3){0.0f, 0.0f, diamond_z + diamond_height / 2}; // Top point + Vector3 bottom_point = (Vector3){0.0f, 0.0f, diamond_z - diamond_height / 2}; // Bottom point + Vector3 front_point = (Vector3){0.0f, diamond_width / 2, diamond_z}; // Front point + Vector3 back_point = (Vector3){0.0f, -diamond_width / 2, diamond_z}; // Back point + Vector3 left_point = (Vector3){-diamond_width / 2, 0.0f, diamond_z}; // Left point + Vector3 right_point = (Vector3){diamond_width / 2, 0.0f, diamond_z}; // Right point + + // Draw the diamond faces + // Top pyramid + + if (mode == 0) { + DrawTriangle3D(top_point, front_point, right_point, PUFF_CYAN); // Front-right face + DrawTriangle3D(top_point, right_point, back_point, PUFF_CYAN); // Back-right face + DrawTriangle3D(top_point, back_point, left_point, PUFF_CYAN); // Back-left face + DrawTriangle3D(top_point, left_point, front_point, PUFF_CYAN); // Front-left face + + // Bottom pyramid + DrawTriangle3D(bottom_point, right_point, front_point, PUFF_CYAN); // Front-right face + DrawTriangle3D(bottom_point, back_point, right_point, PUFF_CYAN); // Back-right face + DrawTriangle3D(bottom_point, left_point, back_point, PUFF_CYAN); // Back-left face + DrawTriangle3D(bottom_point, front_point, left_point, PUFF_CYAN); // Front-left face + } + if (!IsKeyDown(KEY_LEFT_CONTROL) && obs_only == 0) { + return; + } + + int ego_dim = (env->dynamics_model == JERK) ? EGO_FEATURES_JERK : EGO_FEATURES_CLASSIC; + if (env->max_stop_sign_observations > 0) + ego_dim += 1; + int num_reward_coefs = env->reward_conditioning ? NUM_REWARD_COEFS : 0; + int target_features = (env->target_type == TARGET_STATIC) ? env->num_target_waypoints * STATIC_TARGET_FEATURES + : env->num_target_waypoints * DYNAMIC_TARGET_FEATURES; + int max_obs = compute_observation_size(env); + float (*observations)[max_obs] = (float (*)[max_obs])env->observations; + float *agent_obs = &observations[agent_index][0]; + // self + int active_idx = env->active_agent_indices[agent_index]; + float heading_self = env->agents[active_idx].sim_heading; + float heading_self_x = cosf(heading_self); + float heading_self_y = sinf(heading_self); + float px = env->agents[active_idx].sim_x; + float py = env->agents[active_idx].sim_y; + // draw goal (first target waypoint, in ego frame) + if (env->num_target_waypoints > 0) { + int goal_obs_idx = ego_dim + num_reward_coefs; + float goal_x = agent_obs[goal_obs_idx] * MAX_GOAL_POSITION; + float goal_y = agent_obs[goal_obs_idx + 1] * MAX_GOAL_POSITION; + if (mode == 0) { + DrawSphere((Vector3){goal_x, goal_y, 1}, 0.5f, LIGHTGREEN); + DrawCircle3D((Vector3){goal_x, goal_y, 0.1f}, env->goal_radius, (Vector3){0, 0, 1}, 90.0f, + Fade(LIGHTGREEN, 0.3f)); + } + + if (mode == 1) { + float goal_x_world = px + (goal_x * heading_self_x - goal_y * heading_self_y); + float goal_y_world = py + (goal_x * heading_self_y + goal_y * heading_self_x); + DrawSphere((Vector3){goal_x_world, goal_y_world, 1}, 0.5f, LIGHTGREEN); + DrawCircle3D((Vector3){goal_x_world, goal_y_world, 0.1f}, env->goal_radius, (Vector3){0, 0, 1}, 90.0f, + Fade(LIGHTGREEN, 0.3f)); + } + } + // First draw other agent observations + int obs_idx = ego_dim + num_reward_coefs + target_features; // Start after ego, conditioning, and target obs + for (int j = 0; j < env->max_partner_observations; j++) { + if (agent_obs[obs_idx] == 0 || agent_obs[obs_idx + 1] == 0) { + obs_idx += PARTNER_FEATURES; + continue; + } + // Draw position of other agents + float x = agent_obs[obs_idx] * 50; + float y = agent_obs[obs_idx + 1] * 50; + if (lasers && mode == 0) { + DrawLine3D((Vector3){0, 0, 0}, (Vector3){x, y, 1}, ORANGE); + } + + float partner_x = px + (x * heading_self_x - y * heading_self_y); + float partner_y = py + (x * heading_self_y + y * heading_self_x); + if (lasers && mode == 1) { + DrawLine3D((Vector3){px, py, 1}, (Vector3){partner_x, partner_y, 1}, ORANGE); + } + + float half_width = 0.5 * agent_obs[obs_idx + 2] * MAX_VEH_WIDTH; + float half_len = 0.5 * agent_obs[obs_idx + 3] * MAX_VEH_LEN; + float theta_x = agent_obs[obs_idx + 4]; + float theta_y = agent_obs[obs_idx + 5]; + float partner_angle = atan2f(theta_y, theta_x); + float cos_heading = cosf(partner_angle); + float sin_heading = sinf(partner_angle); + Vector3 corners[4] = { + (Vector3){x + (half_len * cos_heading - half_width * sin_heading), + y + (half_len * sin_heading + half_width * cos_heading), 1}, + (Vector3){x + (half_len * cos_heading + half_width * sin_heading), + y + (half_len * sin_heading - half_width * cos_heading), 1}, + (Vector3){x + (-half_len * cos_heading + half_width * sin_heading), + y + (-half_len * sin_heading - half_width * cos_heading), 1}, + (Vector3){x + (-half_len * cos_heading - half_width * sin_heading), + y + (-half_len * sin_heading + half_width * cos_heading), 1}, + }; + + if (mode == 0) { + for (int j = 0; j < 4; j++) { + DrawLine3D(corners[j], corners[(j + 1) % 4], ORANGE); + } + } + + if (mode == 1) { + Vector3 world_corners[4]; + for (int j = 0; j < 4; j++) { + float lx = corners[j].x; + float ly = corners[j].y; + + world_corners[j].x = px + (lx * heading_self_x - ly * heading_self_y); + world_corners[j].y = py + (lx * heading_self_y + ly * heading_self_x); + world_corners[j].z = 1; + } + for (int j = 0; j < 4; j++) { + DrawLine3D(world_corners[j], world_corners[(j + 1) % 4], ORANGE); + } + } + + // draw an arrow above the car pointing in the direction that the partner is going + float arrow_length = 2.5f; + float arrow_x = x + arrow_length * cosf(partner_angle); + float arrow_y = y + arrow_length * sinf(partner_angle); + float arrow_x_world; + float arrow_y_world; + if (mode == 0) { + DrawLine3D((Vector3){x, y, 1}, (Vector3){arrow_x, arrow_y, 1}, PUFF_WHITE); + } + if (mode == 1) { + arrow_x_world = px + (arrow_x * heading_self_x - arrow_y * heading_self_y); + arrow_y_world = py + (arrow_x * heading_self_y + arrow_y * heading_self_x); + DrawLine3D((Vector3){partner_x, partner_y, 1}, (Vector3){arrow_x_world, arrow_y_world, 1}, PUFF_WHITE); + } + // Calculate perpendicular offsets for arrow head + float arrow_size = 0.3f; // Size of the arrow head + float dx = arrow_x - x; + float dy = arrow_y - y; + float length = sqrtf(dx * dx + dy * dy); + if (length > 0) { + // Normalize direction vector + dx /= length; + dy /= length; + + // Calculate perpendicular vector + float perp_x = -dy * arrow_size; + float perp_y = dx * arrow_size; + + float arrow_x_end1 = arrow_x - dx * arrow_size + perp_x; + float arrow_y_end1 = arrow_y - dy * arrow_size + perp_y; + float arrow_x_end2 = arrow_x - dx * arrow_size - perp_x; + float arrow_y_end2 = arrow_y - dy * arrow_size - perp_y; + + // Draw the two lines forming the arrow head + if (mode == 0) { + DrawLine3D((Vector3){arrow_x, arrow_y, 1}, (Vector3){arrow_x_end1, arrow_y_end1, 1}, PUFF_WHITE); + DrawLine3D((Vector3){arrow_x, arrow_y, 1}, (Vector3){arrow_x_end2, arrow_y_end2, 1}, PUFF_WHITE); + } + + if (mode == 1) { + float arrow_x_end1_world = px + (arrow_x_end1 * heading_self_x - arrow_y_end1 * heading_self_y); + float arrow_y_end1_world = py + (arrow_x_end1 * heading_self_y + arrow_y_end1 * heading_self_x); + float arrow_x_end2_world = px + (arrow_x_end2 * heading_self_x - arrow_y_end2 * heading_self_y); + float arrow_y_end2_world = py + (arrow_x_end2 * heading_self_y + arrow_y_end2 * heading_self_x); + DrawLine3D((Vector3){arrow_x_world, arrow_y_world, 1}, + (Vector3){arrow_x_end1_world, arrow_y_end1_world, 1}, PUFF_WHITE); + DrawLine3D((Vector3){arrow_x_world, arrow_y_world, 1}, + (Vector3){arrow_x_end2_world, arrow_y_end2_world, 1}, PUFF_WHITE); + } + } + + obs_idx += PARTNER_FEATURES; + } + // Then draw lane segment observations (obs_idx is now at lane obs start after partner loop) + int lane_obs_start = obs_idx; + for (int k = 0; k < env->max_lane_segment_observations; k++) { + int entity_idx = lane_obs_start + k * ROAD_FEATURES; + if (agent_obs[entity_idx] == 0 && agent_obs[entity_idx + 1] == 0) { + continue; + } + Color lineColor = PUFF_CYAN; + // For road segments, draw line between start and end points + float x_middle = agent_obs[entity_idx] * 50; + float y_middle = agent_obs[entity_idx + 1] * 50; + float rel_angle_x = (agent_obs[entity_idx + 4]); + float rel_angle_y = (agent_obs[entity_idx + 5]); + float rel_angle = atan2f(rel_angle_y, rel_angle_x); + float segment_length = agent_obs[entity_idx + 2] * MAX_ROAD_SEGMENT_LENGTH; + // Calculate endpoint using the relative angle directly + // Calculate endpoint directly + float x_start = x_middle - segment_length * cosf(rel_angle); + float y_start = y_middle - segment_length * sinf(rel_angle); + float x_end = x_middle + segment_length * cosf(rel_angle); + float y_end = y_middle + segment_length * sinf(rel_angle); + + if (lasers && mode == 0) { + DrawLine3D((Vector3){0, 0, 0}, (Vector3){x_middle, y_middle, 1}, lineColor); + } + + if (mode == 1) { + float x_middle_world = px + (x_middle * heading_self_x - y_middle * heading_self_y); + float y_middle_world = py + (x_middle * heading_self_y + y_middle * heading_self_x); + float x_start_world = px + (x_start * heading_self_x - y_start * heading_self_y); + float y_start_world = py + (x_start * heading_self_y + y_start * heading_self_x); + float x_end_world = px + (x_end * heading_self_x - y_end * heading_self_y); + float y_end_world = py + (x_end * heading_self_y + y_end * heading_self_x); + DrawCube((Vector3){x_middle_world, y_middle_world, 1}, 0.5f, 0.5f, 0.5f, lineColor); + DrawLine3D((Vector3){x_start_world, y_start_world, 1}, (Vector3){x_end_world, y_end_world, 1}, BLUE); + if (lasers) + DrawLine3D((Vector3){px, py, 1}, (Vector3){x_middle_world, y_middle_world, 1}, lineColor); + } + if (mode == 0) { + DrawCube((Vector3){x_middle, y_middle, 1}, 0.5f, 0.5f, 0.5f, lineColor); + DrawLine3D((Vector3){x_start, y_start, 1}, (Vector3){x_end, y_end, 1}, BLUE); + } + } +} + +void draw_road_edge(Drive *env, float start_x, float start_y, float end_x, float end_y, Color lineColor) { + Color CURB_TOP = (Color){220, 220, 220, 255}; // Top surface - lightest + Color CURB_SIDE = (Color){180, 180, 180, 255}; // Side faces - medium + Color CURB_BOTTOM = (Color){160, 160, 160, 255}; + // Calculate curb dimensions + float curb_height = 0.5f; // Height of the curb + float curb_width = 0.3f; // Width/thickness of the curb + float road_z = 0.2f; // Ensure z-level for roads is below agents + + // Calculate direction vector between start and end + Vector3 direction = {end_x - start_x, end_y - start_y, 0.0f}; + + // Calculate length of the segment + float length = sqrtf(direction.x * direction.x + direction.y * direction.y); + + // Normalize direction vector + Vector3 normalized_dir = {direction.x / length, direction.y / length, 0.0f}; + + // Calculate perpendicular vector for width + Vector3 perpendicular = {-normalized_dir.y, normalized_dir.x, 0.0f}; + + // Calculate the four bottom corners of the curb + Vector3 b1 = {start_x - perpendicular.x * curb_width / 2, start_y - perpendicular.y * curb_width / 2, road_z}; + Vector3 b2 = {start_x + perpendicular.x * curb_width / 2, start_y + perpendicular.y * curb_width / 2, road_z}; + Vector3 b3 = {end_x + perpendicular.x * curb_width / 2, end_y + perpendicular.y * curb_width / 2, road_z}; + Vector3 b4 = {end_x - perpendicular.x * curb_width / 2, end_y - perpendicular.y * curb_width / 2, road_z}; + + // Draw the curb faces + // Bottom face + DrawTriangle3D(b1, b2, b3, CURB_BOTTOM); + DrawTriangle3D(b1, b3, b4, CURB_BOTTOM); + + // Top face (raised by curb_height) + Vector3 t1 = {b1.x, b1.y, b1.z + curb_height}; + Vector3 t2 = {b2.x, b2.y, b2.z + curb_height}; + Vector3 t3 = {b3.x, b3.y, b3.z + curb_height}; + Vector3 t4 = {b4.x, b4.y, b4.z + curb_height}; + DrawTriangle3D(t1, t3, t2, CURB_TOP); + DrawTriangle3D(t1, t4, t3, CURB_TOP); + + // Side faces + DrawTriangle3D(b1, t1, b2, CURB_SIDE); + DrawTriangle3D(t1, t2, b2, CURB_SIDE); + DrawTriangle3D(b2, t2, b3, CURB_SIDE); + DrawTriangle3D(t2, t3, b3, CURB_SIDE); + DrawTriangle3D(b3, t3, b4, CURB_SIDE); + DrawTriangle3D(t3, t4, b4, CURB_SIDE); + DrawTriangle3D(b4, t4, b1, CURB_SIDE); + DrawTriangle3D(t4, t1, b1, CURB_SIDE); +} + +void draw_scene(Drive *env, Client *client, int mode, int obs_only, int lasers, int show_grid) { + // Draw a grid to help with orientation + // DrawGrid(20, 1.0f); + DrawLine3D((Vector3){env->grid_map->top_left_x, env->grid_map->top_left_y, 0}, + (Vector3){env->grid_map->bottom_right_x, env->grid_map->top_left_y, 0}, PUFF_CYAN); + DrawLine3D((Vector3){env->grid_map->top_left_x, env->grid_map->bottom_right_y, 0}, + (Vector3){env->grid_map->top_left_x, env->grid_map->top_left_y, 0}, PUFF_CYAN); + DrawLine3D((Vector3){env->grid_map->bottom_right_x, env->grid_map->bottom_right_y, 0}, + (Vector3){env->grid_map->bottom_right_x, env->grid_map->top_left_y, 0}, PUFF_CYAN); + DrawLine3D((Vector3){env->grid_map->top_left_x, env->grid_map->bottom_right_y, 0}, + (Vector3){env->grid_map->bottom_right_x, env->grid_map->bottom_right_y, 0}, PUFF_CYAN); + + // Draw road edges (collision boundaries) as red lines + rlSetLineWidth(4.0f); + for (int i = 0; i < env->num_road_elements; i++) { + RoadMapElement *elem = &env->road_elements[i]; + if (!is_road_edge(elem->type)) continue; + for (int j = 0; j < elem->segment_length - 1; j++) { + DrawLine3D( + (Vector3){elem->x[j], elem->y[j], elem->z[j] + 1.0f}, + (Vector3){elem->x[j+1], elem->y[j+1], elem->z[j+1] + 1.0f}, + RED); + } + } + // Draw drivable lanes as green lines + rlSetLineWidth(2.0f); + for (int i = 0; i < env->num_road_elements; i++) { + RoadMapElement *elem = &env->road_elements[i]; + if (!is_drivable_road_lane(elem->type)) continue; + for (int j = 0; j < elem->segment_length - 1; j++) { + DrawLine3D( + (Vector3){elem->x[j], elem->y[j], elem->z[j] + 0.5f}, + (Vector3){elem->x[j+1], elem->y[j+1], elem->z[j+1] + 0.5f}, + GREEN); + } + } + + // Draw traffic lights and stop signs + for (int i = 0; i < env->num_traffic_elements; i++) { + TrafficControlElement *tc = &env->traffic_elements[i]; + Vector3 p1 = {tc->stop_line[0], tc->stop_line[1], tc->stop_line[2] + 0.2f}; + Vector3 p2 = {tc->stop_line[3], tc->stop_line[4], tc->stop_line[5] + 0.2f}; + + if (tc->type == TRAFFIC_LIGHT) { + // Get current state + int state = TL_STATE_DISABLED; + if (tc->states && env->timestep < tc->state_length) { + state = tc->states[env->timestep]; + } + Color tl_color = GRAY; + if (is_traffic_light_red(state)) tl_color = RED; + else if (is_traffic_light_yellow(state)) tl_color = YELLOW; + else if (is_traffic_light_green(state)) tl_color = GREEN; + + rlSetLineWidth(4.0f); + DrawLine3D(p1, p2, tl_color); + // Draw a sphere at midpoint for visibility + Vector3 mid = {(p1.x + p2.x) / 2, (p1.y + p2.y) / 2, (p1.z + p2.z) / 2 + 0.5f}; + DrawSphere(mid, 0.8f, tl_color); + } else if (tc->type == STOP_SIGN) { + rlSetLineWidth(3.0f); + DrawLine3D(p1, p2, MAGENTA); + Vector3 mid = {(p1.x + p2.x) / 2, (p1.y + p2.y) / 2, (p1.z + p2.z) / 2 + 0.5f}; + DrawSphere(mid, 0.6f, MAGENTA); + } + } + + for (int i = 0; i < env->num_total_agents; i++) { + Agent *agent = &env->agents[i]; + // Draw objects + // Check if this vehicle is an active agent + bool is_active_agent = false; + bool is_static_agent = false; + int agent_index = -1; + for (int j = 0; j < env->active_agent_count; j++) { + if (env->active_agent_indices[j] == i) { + is_active_agent = true; + agent_index = j; + break; + } + } + for (int j = 0; j < env->static_agent_count; j++) { + if (env->static_agent_indices[j] == i) { + is_static_agent = true; + break; + } + } + if (!is_active_agent && !is_static_agent) { + continue; + } + Vector3 position; + float heading; + position = (Vector3){agent->sim_x, agent->sim_y, 1}; + heading = agent->sim_heading; + // Create size vector + Vector3 size = {agent->sim_length, agent->sim_width, agent->sim_height}; + + bool is_expert = (!is_active_agent) && (agent->mark_as_expert == 1); + + // Save current transform + if (mode == 1) { + float cos_heading = cosf(heading); + float sin_heading = sinf(heading); + + // Compute corners fresh from current agent state + float half_len = agent->sim_length * 0.5f; + float half_wid = agent->sim_width * 0.5f; + float ch = cosf(agent->sim_heading); + float sh = sinf(agent->sim_heading); + Vector3 corners[4] = { + {agent->sim_x + (-half_len * ch - half_wid * sh), + agent->sim_y + (-half_len * sh + half_wid * ch), position.z}, + {agent->sim_x + ( half_len * ch - half_wid * sh), + agent->sim_y + ( half_len * sh + half_wid * ch), position.z}, + {agent->sim_x + ( half_len * ch + half_wid * sh), + agent->sim_y + ( half_len * sh - half_wid * ch), position.z}, + {agent->sim_x + (-half_len * ch + half_wid * sh), + agent->sim_y + (-half_len * sh - half_wid * ch), position.z}, + }; + + if (agent_index == env->human_agent_idx && !agent->metrics_array[REACHED_GOAL_IDX]) { + draw_agent_obs(env, agent_index, mode, obs_only, lasers); + } + if ((obs_only || IsKeyDown(KEY_LEFT_CONTROL)) && agent_index != env->human_agent_idx) { + continue; + } + + // --- Draw the car --- + Color car_color = GRAY; // default for static + if (is_expert) + car_color = GOLD; // expert replay + if (is_active_agent) + car_color = BLUE; // policy-controlled + if (is_active_agent && agent->metrics_array[COLLISION_IDX] > 0) + car_color = ORANGE; // vehicle collision + if (is_active_agent && agent->metrics_array[OFFROAD_IDX] > 0) + car_color = RED; // offroad + if (is_active_agent && agent->metrics_array[RED_LIGHT_IDX] > 0) + car_color = YELLOW; // red light violation + rlSetLineWidth(3.0f); + for (int j = 0; j < 4; j++) { + DrawLine3D(corners[j], corners[(j + 1) % 4], car_color); + } + // --- Draw a heading arrow pointing forward --- + Vector3 arrowStart = position; + Vector3 arrowEnd = {position.x + agent->cos_heading * half_len * 1.5f, + position.y + agent->sin_heading * half_len * 1.5f, position.z}; + + DrawLine3D(arrowStart, arrowEnd, car_color); + DrawSphere(arrowEnd, 0.2f, car_color); // arrow tip + + } else { + rlPushMatrix(); + rlTranslatef(position.x, position.y, position.z); + rlRotatef(heading * RAD2DEG, 0.0f, 0.0f, 1.0f); // Convert radians to degrees + // Determine color based on status + Model car_model = client->cars[5]; + if (is_active_agent) { + car_model = client->cars[client->car_assignments[i % 64]]; + } + if (is_active_agent && (agent->metrics_array[COLLISION_IDX] > 0 || agent->metrics_array[OFFROAD_IDX] > 0 || + agent->metrics_array[RED_LIGHT_IDX] > 0)) { + car_model = client->cars[0]; // Collided agent + } + // Draw obs for human selected agent + if (agent_index == env->human_agent_idx && !agent->metrics_array[REACHED_GOAL_IDX]) { + draw_agent_obs(env, agent_index, mode, obs_only, lasers); + } + // Draw cube for cars static and active + // Calculate scale factors based on desired size and model dimensions + + BoundingBox bounds = GetModelBoundingBox(car_model); + Vector3 model_size = {bounds.max.x - bounds.min.x, bounds.max.y - bounds.min.y, + bounds.max.z - bounds.min.z}; + Vector3 scale = {size.x / model_size.x, size.y / model_size.y, size.z / model_size.z}; + if ((obs_only || IsKeyDown(KEY_LEFT_CONTROL)) && agent_index != env->human_agent_idx) { + rlPopMatrix(); + continue; + } + + DrawModelEx(car_model, (Vector3){0, 0, 0}, (Vector3){1, 0, 0}, 90.0f, scale, WHITE); + { + // Corners in local space — rlRotatef already applies heading rotation + float half_len = agent->sim_length * 0.5f; + float half_width = agent->sim_width * 0.5f; + Vector3 corners[4] = { + (Vector3){ half_len, half_width, 0}, + (Vector3){ half_len, -half_width, 0}, + (Vector3){-half_len, -half_width, 0}, + (Vector3){-half_len, half_width, 0}, + }; + Color wire_color = GRAY; // static + if (!is_active_agent && agent->mark_as_expert == 1) + wire_color = GOLD; // expert replay + if (is_active_agent) + wire_color = BLUE; // policy + if (is_active_agent && agent->metrics_array[COLLISION_IDX] > 0) + wire_color = ORANGE; // vehicle collision + if (is_active_agent && agent->metrics_array[OFFROAD_IDX] > 0) + wire_color = RED; // offroad + if (is_active_agent && agent->metrics_array[RED_LIGHT_IDX] > 0) + wire_color = YELLOW; // red light violation + rlSetLineWidth(2.0f); + for (int j = 0; j < 4; j++) { + DrawLine3D(corners[j], corners[(j + 1) % 4], wire_color); + } + } + rlPopMatrix(); + } + + // FPV Camera Control + if (IsKeyDown(KEY_SPACE) && env->human_agent_idx == agent_index) { + if (agent->metrics_array[REACHED_GOAL_IDX]) { + env->human_agent_idx = rand() % env->active_agent_count; + } + Vector3 camera_position = + (Vector3){position.x - (25.0f * cosf(heading)), position.y - (25.0f * sinf(heading)), position.z + 15}; + + Vector3 camera_target = + (Vector3){position.x + 40.0f * cosf(heading), position.y + 40.0f * sinf(heading), position.z - 5.0f}; + client->camera.position = camera_position; + client->camera.target = camera_target; + client->camera.up = (Vector3){0, 0, 1}; + } + if (IsKeyReleased(KEY_SPACE)) { + client->camera.position = client->default_camera_position; + client->camera.target = client->default_camera_target; + client->camera.up = (Vector3){0, 0, 1}; + } + // Draw goal position for active agents + + if (!is_active_agent || agent->sim_valid == 0) { + continue; + } + if (!IsKeyDown(KEY_LEFT_CONTROL) && obs_only == 0) { + DrawSphere((Vector3){agent->goal_position_x, agent->goal_position_y, 1}, 0.5f, DARKGREEN); + + DrawCircle3D((Vector3){agent->goal_position_x, agent->goal_position_y, 0.1f}, env->goal_radius, + (Vector3){0, 0, 1}, 90.0f, Fade(LIGHTGREEN, 0.3f)); + } + } + for (int i = 0; i < env->num_road_elements; i++) { + RoadMapElement *element = &env->road_elements[i]; + + for (int j = 0; j < element->segment_length - 1; j++) { + Vector3 start = {element->x[j], element->y[j], 1}; + Vector3 end = {element->x[j + 1], element->y[j + 1], 1}; + Color lineColor = GRAY; + + if (is_road_lane(element->type)) + lineColor = GRAY; + else if (is_road_line(element->type)) + lineColor = BLUE; + else if (is_road_edge(element->type)) + lineColor = WHITE; + else if (element->type == DRIVEWAY) + lineColor = RED; + if (!IsKeyDown(KEY_LEFT_CONTROL) && obs_only == 0) { + draw_road_edge(env, start.x, start.y, end.x, end.y, lineColor); + } + } + } + if (show_grid) { + // Draw grid cells using the stored bounds + float grid_start_x = env->grid_map->top_left_x; + float grid_start_y = env->grid_map->bottom_right_y; + for (int i = 0; i < env->grid_map->grid_cols; i++) { + for (int j = 0; j < env->grid_map->grid_rows; j++) { + float x = grid_start_x + i * GRID_CELL_SIZE; + float y = grid_start_y + j * GRID_CELL_SIZE; + DrawCubeWires((Vector3){x + GRID_CELL_SIZE / 2, y + GRID_CELL_SIZE / 2, 1}, GRID_CELL_SIZE, + GRID_CELL_SIZE, 0.1f, PUFF_BACKGROUND2); + } + } + } + + EndMode3D(); + + // Draw track indices for the tracks to predict + if (mode == 1 && env->control_mode == CONTROL_WOSAC) { + float map_height = env->grid_map->top_left_y - env->grid_map->bottom_right_y; + float pixels_per_world_unit = client->height / map_height; + + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; + int womd_track_idx = env->tracks_to_predict[i]; + + float raw_x = -env->agents[agent_idx].sim_x * pixels_per_world_unit; + float raw_y = env->agents[agent_idx].sim_y * pixels_per_world_unit; + + int screen_x = (int)raw_x + client->width / 2 + 20; + int screen_y = (int)raw_y + client->height / 2 - 25; + + if (screen_x >= 0 && screen_x <= client->width && screen_y >= 0 && screen_y <= client->height) { + char text[32]; + snprintf(text, sizeof(text), "%d", womd_track_idx); + int text_width = MeasureText(text, 20); + DrawText(text, screen_x - text_width / 2, screen_y, 20, PUFF_WHITE); + } + } + } +} + +void saveTopDownImage(Drive *env, Client *client, const char *filename, RenderTexture2D target, int map_height, int obs, + int lasers, int trajectories, int frame_count, float *path, int log_trajectories, int show_grid) { + // Top-down orthographic camera + Camera3D camera = {0}; + camera.position = (Vector3){0.0f, 0.0f, 500.0f}; // above the scene + camera.target = (Vector3){0.0f, 0.0f, 0.0f}; // look at origin + camera.up = (Vector3){0.0f, -1.0f, 0.0f}; + camera.fovy = map_height; + camera.projection = CAMERA_ORTHOGRAPHIC; + Color road = (Color){35, 35, 37, 255}; + + BeginTextureMode(target); + ClearBackground(road); + BeginMode3D(camera); + rlEnableDepthTest(); + + // Draw log trajectories FIRST (in background at lower Z-level) + if (log_trajectories) { + for (int i = 0; i < env->num_total_agents; i++) { + Agent *agent = &env->agents[i]; + for (int j = 0; j < agent->trajectory_length; j++) { + float x = agent->log_trajectory_x[j]; + float y = agent->log_trajectory_y[j]; + float valid = agent->log_valid[j]; + if (!valid) + continue; + DrawSphere((Vector3){x, y, 0.5f}, 0.3f, Fade(LIGHTGREEN, 0.6f)); + } + } + } + + // Draw current path trajectories SECOND (slightly higher than log trajectories) + if (trajectories) { + for (int i = 0; i < frame_count; i++) { + DrawSphere((Vector3){path[i * 2], path[i * 2 + 1], 0.8f}, 0.5f, YELLOW); + } + } + + // Draw main scene LAST (on top) + draw_scene(env, client, 1, obs, lasers, show_grid); + + EndMode3D(); + EndTextureMode(); + + // save to file + Image img = LoadImageFromTexture(target.texture); + ImageFlipVertical(&img); + ExportImage(img, filename); + UnloadImage(img); +} + +void saveAgentViewImage(Drive *env, Client *client, const char *filename, RenderTexture2D target, int map_height, + int obs_only, int lasers, int show_grid) { + // Agent perspective camera following the human agent + int agent_idx = env->active_agent_indices[env->human_agent_idx]; + Agent *agent = &env->agents[agent_idx]; + + Camera3D camera = {0}; + // Position camera behind and above the agent + camera.position = (Vector3){agent->sim_x - (25.0f * cosf(agent->sim_heading)), + agent->sim_y - (25.0f * sinf(agent->sim_heading)), 15.0f}; + camera.target = (Vector3){agent->sim_x + 40.0f * cosf(agent->sim_heading), + agent->sim_y + 40.0f * sinf(agent->sim_heading), 1.0f}; + camera.up = (Vector3){0.0f, 0.0f, 1.0f}; + camera.fovy = 45.0f; + camera.projection = CAMERA_PERSPECTIVE; + + Color road = (Color){35, 35, 37, 255}; + + BeginTextureMode(target); + ClearBackground(road); + BeginMode3D(camera); + rlEnableDepthTest(); + draw_scene(env, client, 0, obs_only, lasers, show_grid); // mode=0 for agent view + EndMode3D(); + EndTextureMode(); + + // Save to file + Image img = LoadImageFromTexture(target.texture); + ImageFlipVertical(&img); + ExportImage(img, filename); + UnloadImage(img); +} + +void c_render(Drive *env) { + if (env->client == NULL) { + env->client = make_client(env); + } + Client *client = env->client; + BeginDrawing(); + Color road = (Color){35, 35, 37, 255}; + ClearBackground(road); + BeginMode3D(client->camera); + handle_camera_controls(env->client); + draw_scene(env, client, 0, 0, 0, 0); + // Draw debug info + DrawText(TextFormat("Camera Position: (%.2f, %.2f, %.2f)", client->camera.position.x, client->camera.position.y, + client->camera.position.z), + 10, 10, 20, PUFF_WHITE); + DrawText(TextFormat("Camera Target: (%.2f, %.2f, %.2f)", client->camera.target.x, client->camera.target.y, + client->camera.target.z), + 10, 30, 20, PUFF_WHITE); + DrawText(TextFormat("Timestep: %d", env->timestep), 10, 50, 20, PUFF_WHITE); + // acceleration & steering + int human_idx = env->active_agent_indices[env->human_agent_idx]; + DrawText(TextFormat("Controlling Agent: %d", env->human_agent_idx), 10, 70, 20, PUFF_WHITE); + DrawText(TextFormat("Agent Index: %d", human_idx), 10, 90, 20, PUFF_WHITE); + // Controls help + DrawText("Controls: W/S - Accelerate/Brake, A/D - Steer, 1-4 - Switch Agent", 10, client->height - 30, 20, + PUFF_WHITE); + // acceleration & steering + if (env->action_type == 1) { // continuous (float) + float (*action_array_f)[2] = (float (*)[2])env->actions; + DrawText(TextFormat("Acceleration: %.2f", action_array_f[env->human_agent_idx][0]), 10, 110, 20, PUFF_WHITE); + DrawText(TextFormat("Steering: %.2f", action_array_f[env->human_agent_idx][1]), 10, 130, 20, PUFF_WHITE); + } else { // discrete (int) + int (*action_array)[2] = (int (*)[2])env->actions; + DrawText(TextFormat("Acceleration: %d", action_array[env->human_agent_idx][0]), 10, 110, 20, PUFF_WHITE); + DrawText(TextFormat("Steering: %d", action_array[env->human_agent_idx][1]), 10, 130, 20, PUFF_WHITE); + } + DrawText(TextFormat("Grid Rows: %d", env->grid_map->grid_rows), 10, 150, 20, PUFF_WHITE); + DrawText(TextFormat("Grid Cols: %d", env->grid_map->grid_cols), 10, 170, 20, PUFF_WHITE); + EndDrawing(); +} + +void close_client(Client *client) { + for (int i = 0; i < 6; i++) { + UnloadModel(client->cars[i]); + } + UnloadTexture(client->puffers); + CloseWindow(); + free(client); +} + +#endif // RENDER_H diff --git a/pufferlib/ocean/drive/visualize.c b/pufferlib/ocean/drive/visualize.c new file mode 100644 index 0000000000..616d9c8e92 --- /dev/null +++ b/pufferlib/ocean/drive/visualize.c @@ -0,0 +1,564 @@ +#include +#include +#include +#include +#include +#include +#include "rlgl.h" +#include +#include +#include +#include +#include "error.h" +#include "drive.h" +#include "drivenet.h" +#include "libgen.h" +#include "../env_config.h" +#define TRAJECTORY_LENGTH_DEFAULT 91 + +typedef struct { + int pipefd[2]; + pid_t pid; +} VideoRecorder; + +bool OpenVideo(VideoRecorder *recorder, const char *output_filename, int width, int height) { + if (pipe(recorder->pipefd) == -1) { + fprintf(stderr, "Failed to create pipe\n"); + return false; + } + + recorder->pid = fork(); + if (recorder->pid == -1) { + fprintf(stderr, "Failed to fork\n"); + return false; + } + + char size_str[64]; + snprintf(size_str, sizeof(size_str), "%dx%d", width, height); + + if (recorder->pid == 0) { // Child process: run ffmpeg + close(recorder->pipefd[1]); + dup2(recorder->pipefd[0], STDIN_FILENO); + close(recorder->pipefd[0]); + // Close all other file descriptors to prevent leaks + for (int fd = 3; fd < 256; fd++) { + close(fd); + } + execlp("ffmpeg", "ffmpeg", "-y", "-f", "rawvideo", "-pix_fmt", "rgba", "-s", size_str, "-r", "30", "-i", "-", + "-c:v", "libx264", "-pix_fmt", "yuv420p", "-preset", "ultrafast", "-crf", "23", "-loglevel", "error", + output_filename, NULL); + TraceLog(LOG_ERROR, "Failed to launch ffmpeg"); + return false; + } + + close(recorder->pipefd[0]); // Close read end in parent + return true; +} + +void WriteFrame(VideoRecorder *recorder, int width, int height) { + unsigned char *screen_data = rlReadScreenPixels(width, height); + write(recorder->pipefd[1], screen_data, width * height * 4 * sizeof(*screen_data)); + RL_FREE(screen_data); +} + +void CloseVideo(VideoRecorder *recorder) { + close(recorder->pipefd[1]); + waitpid(recorder->pid, NULL, 0); +} + +void renderTopDownView(Drive *env, Client *client, int map_height, int obs, int lasers, int trajectories, + int frame_count, float *path, int log_trajectories, int show_grid, int img_width, + int img_height) { + + BeginDrawing(); + + // Top-down orthographic camera + Camera3D camera = {0}; + camera.position = (Vector3){env->grid_map->top_left_x, env->grid_map->bottom_right_y, 500.0f}; + camera.target = (Vector3){env->grid_map->top_left_x, env->grid_map->bottom_right_y, 0.0f}; + camera.up = (Vector3){0.0f, -1.0f, 0.0f}; + camera.fovy = 2 * map_height; + camera.projection = CAMERA_ORTHOGRAPHIC; + + client->width = img_width; + client->height = img_height; + + Color road = (Color){35, 35, 37, 255}; + ClearBackground(road); + BeginMode3D(camera); + rlEnableDepthTest(); + + // Draw human replay trajectories if enabled + if (log_trajectories) { + for (int i = 0; i < env->active_agent_count; i++) { + int idx = env->active_agent_indices[i]; + Vector3 prev_point = {0}; + bool has_prev = false; + + for (int j = 0; j < env->agents[idx].trajectory_length; j++) { + float x = env->agents[idx].log_trajectory_x[j]; + float y = env->agents[idx].log_trajectory_y[j]; + float valid = env->agents[idx].log_valid[j]; + + if (!valid) { + has_prev = false; + continue; + } + + Vector3 curr_point = {x, y, 0.5f}; + + if (has_prev) { + DrawLine3D(prev_point, curr_point, Fade(LIGHTGREEN, 0.6f)); + } + + prev_point = curr_point; + has_prev = true; + } + } + } + + // Draw agent trajs + if (trajectories) { + for (int i = 0; i < frame_count; i++) { + DrawSphere((Vector3){path[i * 2], path[i * 2 + 1], 0.8f}, 0.5f, YELLOW); + } + } + + // Draw scene + draw_scene(env, client, 1, obs, lasers, show_grid); + EndMode3D(); + EndDrawing(); +} + +void renderAgentView(Drive *env, Client *client, int map_height, int obs_only, int lasers, int show_grid) { + // Agent perspective camera following the selected agent + int agent_idx = env->active_agent_indices[env->human_agent_idx]; + Agent *agent = &env->agents[agent_idx]; + + BeginDrawing(); + + Camera3D camera = {0}; + // Position camera behind and above the agent + camera.position = (Vector3){agent->sim_x - (25.0f * cosf(agent->sim_heading)), + agent->sim_y - (25.0f * sinf(agent->sim_heading)), 15.0f}; + camera.target = (Vector3){agent->sim_x + 40.0f * cosf(agent->sim_heading), + agent->sim_y + 40.0f * sinf(agent->sim_heading), 1.0f}; + camera.up = (Vector3){0.0f, 0.0f, 1.0f}; + camera.fovy = 45.0f; + camera.projection = CAMERA_PERSPECTIVE; + + Color road = (Color){35, 35, 37, 255}; + + ClearBackground(road); + BeginMode3D(camera); + rlEnableDepthTest(); + draw_scene(env, client, 0, obs_only, lasers, show_grid); // mode=0 for agent view + EndMode3D(); + EndDrawing(); +} + +static int run_cmd(const char *cmd) { + int rc = system(cmd); + if (rc != 0) { + fprintf(stderr, "[ffmpeg] command failed (%d): %s\n", rc, cmd); + } + return rc; +} + +// Make a high-quality GIF from numbered PNG frames like frame_000.png +static int make_gif_from_frames(const char *pattern, int fps, const char *palette_path, const char *out_gif) { + char cmd[1024]; + + // 1) Generate palette (no quotes needed for simple filter) + // NOTE: if your frames start at 000, you don't need -start_number. + snprintf(cmd, sizeof(cmd), "ffmpeg -y -framerate %d -i %s -vf palettegen %s", fps, pattern, palette_path); + if (run_cmd(cmd) != 0) + return -1; + + // 2) Use palette to encode the GIF + snprintf(cmd, sizeof(cmd), "ffmpeg -y -framerate %d -i %s -i %s -lavfi paletteuse -loop 0 %s", fps, pattern, + palette_path, out_gif); + if (run_cmd(cmd) != 0) + return -1; + + return 0; +} + +int eval_gif(const char *map_name, const char *policy_name, int show_grid, int obs_only, int lasers, + int log_trajectories, int frame_skip, float goal_radius, int init_steps, int max_controlled_agents, + const char *view_mode, const char *output_topdown, const char *output_agent, int num_maps, + int scenario_length_override, int init_mode, int control_mode, int goal_behavior) { + + // Parse configuration from INI file + env_init_config conf = {0}; // Initialize to zero + const char *ini_file = "pufferlib/config/ocean/drive.ini"; + int ini_result = load_env_config(ini_file, &conf); + if (ini_result != 0) { + fprintf(stderr, "Error: Could not load %s (ini_parse returned %d).\n", ini_file, ini_result); + return -1; + } + printf("Config: max_partner=%d max_lane=%d max_boundary=%d max_tl=%d target_type=%d num_waypoints=%d\n", + conf.max_partner_observations, conf.max_lane_segment_observations, + conf.max_boundary_segment_observations, conf.max_traffic_light_observations, + conf.target_type, conf.num_target_waypoints); + + char map_buffer[100]; + if (map_name == NULL) { + srand(time(NULL)); + int random_map = rand() % num_maps; + sprintf(map_buffer, "%s/map_%03d.bin", conf.map_dir, random_map); // random map file + map_name = map_buffer; + } + + if (frame_skip <= 0) { + frame_skip = 1; // Default: render every frame + } + + // Check if map file exists + FILE *map_file = fopen(map_name, "rb"); + if (map_file == NULL) { + RAISE_FILE_ERROR(map_name); + } + fclose(map_file); + + FILE *policy_file = fopen(policy_name, "rb"); + if (policy_file == NULL) { + RAISE_FILE_ERROR(policy_name); + } + fclose(policy_file); + + Drive env = { + .dynamics_model = conf.dynamics_model, + .action_type = conf.action_type, + .reward_vehicle_collision = conf.reward_vehicle_collision, + .reward_offroad_collision = conf.reward_offroad_collision, + .reward_ade = conf.reward_ade, + .reward_comfort = conf.reward_comfort, + .reward_lane_align = conf.reward_lane_align, + .reward_lane_center = conf.reward_lane_center, + .reward_velocity = conf.reward_velocity, + .reward_reverse = conf.reward_reverse, + .reward_traffic_light_violation = conf.reward_traffic_light_violation, + .reward_timestep = conf.reward_timestep, + .reward_overspeed = conf.reward_overspeed, + .reward_vel_align = conf.reward_vel_align, + .reward_center_bias = conf.reward_center_bias, + .goal_radius = conf.goal_radius, + .dt = conf.dt, + .map_name = (char *)map_name, + .init_steps = (init_steps >= 0) ? init_steps : conf.init_steps, + .num_controllable_agents = (max_controlled_agents > 0) ? max_controlled_agents : conf.max_agents_per_env, + .collision_behavior = conf.collision_behavior, + .offroad_behavior = conf.offroad_behavior, + .traffic_light_behavior = conf.traffic_light_behavior, + .compute_eval_metrics = conf.compute_eval_metrics, + .reward_randomization = conf.reward_randomization, + .reward_conditioning = conf.reward_conditioning, + .init_mode = (init_mode >= 0) ? init_mode : conf.init_mode, + .control_mode = (control_mode >= 0) ? control_mode : conf.control_mode, + .simulation_mode = conf.simulation_mode, + .num_target_waypoints = conf.num_target_waypoints, + .min_waypoint_spacing = conf.min_waypoint_spacing, + .max_waypoint_spacing = conf.max_waypoint_spacing, + .target_type = conf.target_type, + .max_partner_observations = conf.max_partner_observations, + .max_lane_segment_observations = conf.max_lane_segment_observations, + .max_boundary_segment_observations = conf.max_boundary_segment_observations, + .max_traffic_light_observations = conf.max_traffic_light_observations, + .max_stop_sign_observations = conf.max_stop_sign_observations, + .termination_mode = conf.termination_mode, + }; + + env.scenario_length = (scenario_length_override > 0) ? scenario_length_override + : (conf.scenario_length > 0) ? conf.scenario_length + : TRAJECTORY_LENGTH_DEFAULT; + allocate(&env); + + // Set which vehicle to focus on for obs mode + env.human_agent_idx = 0; + + c_reset(&env); + + // Make client for rendering + Client *client = (Client *)calloc(1, sizeof(Client)); + env.client = client; + + SetConfigFlags(FLAG_WINDOW_HIDDEN); + SetTargetFPS(6000); + + float map_width = env.grid_map->bottom_right_x - env.grid_map->top_left_x; + float map_height = env.grid_map->top_left_y - env.grid_map->bottom_right_y; + + printf("Map size: %.1fx%.1f grid: top_left=(%.1f,%.1f) bottom_right=(%.1f,%.1f)\n", + map_width, map_height, + env.grid_map->top_left_x, env.grid_map->top_left_y, + env.grid_map->bottom_right_x, env.grid_map->bottom_right_y); + float scale = 6.0f; // Can be used to increase the video quality + + // Calculate video width and height; round to nearest even number + int img_width = (int)roundf(map_width * scale / 2.0f) * 2; + int img_height = (int)roundf(map_height * scale / 2.0f) * 2; + + InitWindow(img_width, img_height, "Puffer Drive"); + SetConfigFlags(FLAG_MSAA_4X_HINT); + + // Load the textures and models + client->puffers = LoadTexture("resources/puffers_128.png"); + client->cars[0] = LoadModel("resources/drive/RedCar.glb"); + client->cars[1] = LoadModel("resources/drive/WhiteCar.glb"); + client->cars[2] = LoadModel("resources/drive/BlueCar.glb"); + client->cars[3] = LoadModel("resources/drive/YellowCar.glb"); + client->cars[4] = LoadModel("resources/drive/GreenCar.glb"); + client->cars[5] = LoadModel("resources/drive/GreyCar.glb"); + client->cyclist = LoadModel("resources/drive/cyclist.glb"); + client->pedestrian = LoadModel("resources/drive/pedestrian.glb"); + + Weights *weights = load_weights(policy_name); + printf("Active agents in map: %d\n", env.active_agent_count); + DriveNet *net = init_drivenet(weights, env.active_agent_count, env.dynamics_model); + + int frame_count = env.scenario_length > 0 ? env.scenario_length : TRAJECTORY_LENGTH_DEFAULT; + int log_trajectory = log_trajectories; + char filename_topdown[256]; + char filename_agent[256]; + + if (output_topdown != NULL && output_agent != NULL) { + strcpy(filename_topdown, output_topdown); + strcpy(filename_agent, output_agent); + } else { + char policy_base[256]; + strcpy(policy_base, policy_name); + *strrchr(policy_base, '.') = '\0'; + + char map[256]; + strcpy(map, basename((char *)map_name)); + *strrchr(map, '.') = '\0'; + + // Create video directory if it doesn't exist + char video_dir[256]; + sprintf(video_dir, "%s/video", policy_base); + char mkdir_cmd[512]; + snprintf(mkdir_cmd, sizeof(mkdir_cmd), "mkdir -p \"%s\"", video_dir); + system(mkdir_cmd); + + sprintf(filename_topdown, "%s/video/%s_topdown.mp4", policy_base, map); + sprintf(filename_agent, "%s/video/%s_agent.mp4", policy_base, map); + } + + bool render_topdown = (strcmp(view_mode, "both") == 0 || strcmp(view_mode, "topdown") == 0); + bool render_agent = (strcmp(view_mode, "both") == 0 || strcmp(view_mode, "agent") == 0); + + printf("Rendering: %s\n", view_mode); + + int rendered_frames = 0; + double startTime = GetTime(); + + VideoRecorder topdown_recorder, agent_recorder; + + if (render_topdown) { + if (!OpenVideo(&topdown_recorder, filename_topdown, img_width, img_height)) { + CloseWindow(); + return -1; + } + } + + if (render_agent) { + if (!OpenVideo(&agent_recorder, filename_agent, img_width, img_height)) { + if (render_topdown) + CloseVideo(&topdown_recorder); + CloseWindow(); + return -1; + } + } + + if (render_topdown) { + printf("Recording topdown view...\n"); + for (int i = 0; i < frame_count; i++) { + if (i % frame_skip == 0) { + renderTopDownView(&env, client, map_height, 0, 0, 0, frame_count, NULL, log_trajectories, show_grid, + img_width, img_height); + WriteFrame(&topdown_recorder, img_width, img_height); + rendered_frames++; + } + int (*actions)[2] = (int (*)[2])env.actions; + forward(net, env.observations, (int *)env.actions); + c_step(&env); + } + } + + if (render_agent) { + c_reset(&env); + printf("Recording agent view...\n"); + for (int i = 0; i < frame_count; i++) { + // Check if selected agent has reached the first goal and stop recording + int human_idx = env.active_agent_indices[env.human_agent_idx]; + if (env.agents[human_idx].reached_goal_this_episode) { + break; + } + if (i % frame_skip == 0) { + renderAgentView(&env, client, map_height, obs_only, lasers, show_grid); + WriteFrame(&agent_recorder, img_width, img_height); + rendered_frames++; + } + int (*actions)[2] = (int (*)[2])env.actions; + forward(net, env.observations, (int *)env.actions); + c_step(&env); + } + } + + double endTime = GetTime(); + double elapsedTime = endTime - startTime; + double writeFPS = (elapsedTime > 0) ? rendered_frames / elapsedTime : 0; + + printf("Wrote %d frames in %.2f seconds (%.2f FPS) to %s \n", rendered_frames, elapsedTime, writeFPS, + filename_topdown); + + if (render_topdown) { + CloseVideo(&topdown_recorder); + } + if (render_agent) { + CloseVideo(&agent_recorder); + } + CloseWindow(); + + // Clean up resources + free(client); + free_allocated(&env); + free_drivenet(net); + free(weights); + return 0; +} + +int main(int argc, char *argv[]) { + int show_grid = 0; + int obs_only = 0; + int lasers = 0; + int log_trajectories = 1; + int frame_skip = 1; + float goal_radius = 2.0f; + int init_steps = 0; + const char *map_name = NULL; + const char *policy_name = "resources/drive/puffer_drive_weights.bin"; + int max_controlled_agents = 32; + int num_maps = 1; + int scenario_length_cli = -1; + int init_mode = 0; + int control_mode = 0; + int goal_behavior = 0; + + const char *view_mode = "both"; // "both", "topdown", "agent" + const char *output_topdown = NULL; + const char *output_agent = NULL; + + // Parse command line arguments + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--show-grid") == 0) { + show_grid = 1; + } else if (strcmp(argv[i], "--obs-only") == 0) { + obs_only = 1; + } else if (strcmp(argv[i], "--lasers") == 0) { + lasers = 1; + } else if (strcmp(argv[i], "--log-trajectories") == 0) { + log_trajectories = 1; + } else if (strcmp(argv[i], "--frame-skip") == 0) { + if (i + 1 < argc) { + frame_skip = atoi(argv[i + 1]); + i++; // Skip the next argument since we consumed it + if (frame_skip <= 0) { + frame_skip = 1; // Ensure valid value + } + } + } else if (strcmp(argv[i], "--goal-radius") == 0) { + if (i + 1 < argc) { + goal_radius = atof(argv[i + 1]); + i++; + if (goal_radius <= 0) { + goal_radius = 2.0f; // Ensure valid value + } + } + } else if (strcmp(argv[i], "--map-name") == 0) { + // Check if there's a next argument for the map path + if (i + 1 < argc) { + map_name = argv[i + 1]; + i++; // Skip the next argument since we used it as map path + } else { + fprintf(stderr, "Error: --map-name option requires a map file path\n"); + return 1; + } + } else if (strcmp(argv[i], "--policy-name") == 0) { + if (i + 1 < argc) { + policy_name = argv[i + 1]; + i++; + } else { + fprintf(stderr, "Error: --policy-name option requires a policy file path\n"); + return 1; + } + } else if (strcmp(argv[i], "--view") == 0) { + if (i + 1 < argc) { + view_mode = argv[i + 1]; + i++; + if (strcmp(view_mode, "both") != 0 && strcmp(view_mode, "topdown") != 0 && + strcmp(view_mode, "agent") != 0) { + fprintf(stderr, "Error: --view must be 'both', 'topdown', or 'agent'\n"); + return 1; + } + } else { + fprintf(stderr, "Error: --view option requires a value (both/topdown/agent)\n"); + return 1; + } + } else if (strcmp(argv[i], "--output-topdown") == 0) { + if (i + 1 < argc) { + output_topdown = argv[i + 1]; + i++; + } + } else if (strcmp(argv[i], "--output-agent") == 0) { + if (i + 1 < argc) { + output_agent = argv[i + 1]; + i++; + } + } else if (strcmp(argv[i], "--init-steps") == 0) { + if (i + 1 < argc) { + init_steps = atoi(argv[i + 1]); + i++; + if (init_steps < 0) { + init_steps = 0; + } + } + } else if (strcmp(argv[i], "--init-mode") == 0) { + if (i + 1 < argc) { + init_mode = atoi(argv[i + 1]); + i++; + } + } else if (strcmp(argv[i], "--control-mode") == 0) { + if (i + 1 < argc) { + control_mode = atoi(argv[i + 1]); + i++; + } + } else if (strcmp(argv[i], "--max-controlled-agents") == 0) { + if (i + 1 < argc) { + max_controlled_agents = atoi(argv[i + 1]); + i++; + } + } else if (strcmp(argv[i], "--num-maps") == 0) { + if (i + 1 < argc) { + num_maps = atoi(argv[i + 1]); + i++; + } + } else if (strcmp(argv[i], "--scenario-length") == 0) { + if (i + 1 < argc) { + scenario_length_cli = atoi(argv[i + 1]); + i++; + } + } else if (strcmp(argv[i], "--goal-behavior") == 0) { + if (i + 1 < argc) { + goal_behavior = atoi(argv[i + 1]); + i++; + } + } + } + + eval_gif(map_name, policy_name, show_grid, obs_only, lasers, log_trajectories, frame_skip, goal_radius, init_steps, + max_controlled_agents, view_mode, output_topdown, output_agent, num_maps, scenario_length_cli, init_mode, + control_mode, goal_behavior); + return 0; +} diff --git a/pufferlib/ocean/env_binding.h b/pufferlib/ocean/env_binding.h index c2c0c10f03..5963e1dcb4 100644 --- a/pufferlib/ocean/env_binding.h +++ b/pufferlib/ocean/env_binding.h @@ -1,9 +1,8 @@ -#include "env_config.h" #include #include // Forward declarations for env-specific functions supplied by user -static int my_log(PyObject *dict, Log *log); +static int my_log(PyObject *dict, Env *env, Log *log, float n); static int my_init(Env *env, PyObject *args, PyObject *kwargs); static PyObject *my_shared(PyObject *self, PyObject *args, PyObject *kwargs); @@ -43,8 +42,8 @@ static Env *unpack_env(PyObject *args) { // Python function to initialize the environment static PyObject *env_init(PyObject *self, PyObject *args, PyObject *kwargs) { - if (PyTuple_Size(args) != 6) { - PyErr_SetString(PyExc_TypeError, "Environment requires 5 arguments"); + if (PyTuple_Size(args) != 7) { + PyErr_SetString(PyExc_TypeError, "Environment requires 7 positional arguments"); return NULL; } @@ -130,7 +129,19 @@ static PyObject *env_init(PyObject *self, PyObject *args, PyObject *kwargs) { } env->truncations = PyArray_DATA(truncations); - PyObject *seed_arg = PyTuple_GetItem(args, 5); + PyObject *msk = PyTuple_GetItem(args, 5); + if (!PyObject_TypeCheck(msk, &PyArray_Type)) { + PyErr_SetString(PyExc_TypeError, "Masks must be a NumPy array"); + return NULL; + } + PyArrayObject *masks_array = (PyArrayObject *)msk; + if (!PyArray_ISCONTIGUOUS(masks_array)) { + PyErr_SetString(PyExc_ValueError, "Masks must be contiguous"); + return NULL; + } + env->masks = PyArray_DATA(masks_array); + + PyObject *seed_arg = PyTuple_GetItem(args, 6); if (!PyObject_TypeCheck(seed_arg, &PyLong_Type)) { PyErr_SetString(PyExc_TypeError, "seed must be an integer"); return NULL; @@ -198,34 +209,13 @@ static PyObject *env_step(PyObject *self, PyObject *args) { Py_RETURN_NONE; } -// Python function to render the environment +// Python function to step the environment static PyObject *env_render(PyObject *self, PyObject *args) { - int num_args = PyTuple_Size(args); - if (num_args != 3) { - PyErr_SetString(PyExc_TypeError, "env_render requires 3 arguments (env_handle, view_mode, draw_traces)"); - return NULL; - } - Env *env = unpack_env(args); if (!env) { return NULL; } - - PyObject *view_mode_arg = PyTuple_GetItem(args, 1); - if (!PyObject_TypeCheck(view_mode_arg, &PyLong_Type)) { - PyErr_SetString(PyExc_TypeError, "view_mode must be an integer"); - return NULL; - } - int view_mode = PyLong_AsLong(view_mode_arg); - - PyObject *show_traces_arg = PyTuple_GetItem(args, 2); - if (!PyObject_TypeCheck(show_traces_arg, &PyBool_Type)) { - PyErr_SetString(PyExc_TypeError, "draw_traces must be a boolean"); - return NULL; - } - bool draw_traces = PyObject_IsTrue(show_traces_arg); - - c_render(env, view_mode, draw_traces); + c_render(env); Py_RETURN_NONE; } @@ -514,7 +504,7 @@ static PyObject *vec_reset(PyObject *self, PyObject *args) { for (int i = 0; i < vec->num_envs; i++) { // Assumes each process has the same number of environments - srand(i + seed * vec->num_envs); + srand(i + seed); c_reset(vec->envs[i]); } Py_RETURN_NONE; @@ -540,8 +530,8 @@ static PyObject *vec_step(PyObject *self, PyObject *arg) { static PyObject *vec_render(PyObject *self, PyObject *args) { int num_args = PyTuple_Size(args); - if (num_args != 4) { - PyErr_SetString(PyExc_TypeError, "vec_render requires 4 arguments"); + if (num_args != 2) { + PyErr_SetString(PyExc_TypeError, "vec_render requires 2 arguments"); return NULL; } @@ -551,23 +541,14 @@ static PyObject *vec_render(PyObject *self, PyObject *args) { return NULL; } - if (!PyObject_TypeCheck(PyTuple_GetItem(args, 1), &PyLong_Type)) { - PyErr_SetString(PyExc_TypeError, "view_mode must be an integer"); - return NULL; - } - if (!PyObject_TypeCheck(PyTuple_GetItem(args, 2), &PyBool_Type)) { - PyErr_SetString(PyExc_TypeError, "draw_traces must be a boolean"); - return NULL; - } - if (!PyObject_TypeCheck(PyTuple_GetItem(args, 3), &PyLong_Type)) { + PyObject *env_id_arg = PyTuple_GetItem(args, 1); + if (!PyObject_TypeCheck(env_id_arg, &PyLong_Type)) { PyErr_SetString(PyExc_TypeError, "env_id must be an integer"); return NULL; } - int view_mode = PyLong_AsLong(PyTuple_GetItem(args, 1)); - bool draw_traces = PyObject_IsTrue(PyTuple_GetItem(args, 2)); - int env_id = PyLong_AsLong(PyTuple_GetItem(args, 3)); + int env_id = PyLong_AsLong(env_id_arg); - c_render(vec->envs[env_id], view_mode, draw_traces); + c_render(vec->envs[env_id]); Py_RETURN_NONE; } @@ -600,83 +581,125 @@ static PyObject *vec_log(PyObject *self, PyObject *args) { // horribly if Log has non-float data. PyObject *num_agents_arg = PyTuple_GetItem(args, 1); float num_agents = (float)PyLong_AsLong(num_agents_arg); - - Log aggregate = {0}; int num_keys = sizeof(Log) / sizeof(float); - for (int i = 0; i < vec->num_envs; i++) { - Env *env = vec->envs[i]; - for (int j = 0; j < num_keys; j++) { - ((float *)&aggregate)[j] += ((float *)&env->log)[j]; - } - } - PyObject *dict = PyDict_New(); + Env *env = vec->envs[0]; + if (env->eval_mode) { + PyObject *list = PyList_New(vec->num_envs); + PyObject *dict = PyDict_New(); - // Only log if we have at least num_agents worth of data - if (aggregate.n < num_agents) { - return dict; - } - - // Got enough data. Reset logs and return metrics - for (int i = 0; i < vec->num_envs; i++) { - Env *env = vec->envs[i]; - for (int j = 0; j < num_keys; j++) { - ((float *)&env->log)[j] = 0.0f; + if (env->log.n == 0) { + return dict; } - } - float n = aggregate.n; + // Got enough data. Reset logs and return metrics + for (int i = 0; i < vec->num_envs; i++) { + PyObject *dict = PyDict_New(); + Env *env = vec->envs[i]; + float n = env->log.n; + // Average across agents + for (int i = 0; i < num_keys; i++) { + ((float *)&env->log)[i] /= n; + } + my_log(dict, env, &env->log, n); + assign_to_dict(dict, "n", n); + // Add map_name to dict + if (env->map_name) { + PyObject *s = PyUnicode_FromString(env->map_name); + if (s != NULL) { + PyDict_SetItemString(dict, "map_name", s); + Py_DECREF(s); + } + } + + PyList_SetItem(list, i, dict); + } + // Reset logs to 0 after extracting metrics (prevents accumulation across episodes) + for (int i = 0; i < vec->num_envs; i++) { + Env *env = vec->envs[i]; + for (int j = 0; j < num_keys; j++) { + ((float *)&env->log)[j] = 0.0f; + } + } + return list; + } else { + Log aggregate = {0}; + for (int i = 0; i < vec->num_envs; i++) { + Env *env = vec->envs[i]; + for (int j = 0; j < num_keys; j++) { + ((float *)&aggregate)[j] += ((float *)&env->log)[j]; + } + } - // Average across agents - for (int i = 0; i < num_keys; i++) { - ((float *)&aggregate)[i] /= n; - } + PyObject *dict = PyDict_New(); + + // Only log if we have at least num_agents worth of data + Env *env = vec->envs[0]; + if (env->eval_mode) { + if (aggregate.n == 0) { + return dict; + } + } else { + if (aggregate.n < num_agents) { + return dict; + } + } - // Compute completion_rate from aggregated counts - aggregate.completion_rate = aggregate.goals_reached_this_episode / aggregate.goals_sampled_this_episode; + // Got enough data. Reset logs and return metrics + for (int i = 0; i < vec->num_envs; i++) { + Env *env = vec->envs[i]; + for (int j = 0; j < num_keys; j++) { + ((float *)&env->log)[j] = 0.0f; + } + } - // User populates dict - my_log(dict, &aggregate); - assign_to_dict(dict, "n", n); + float n = aggregate.n; - return dict; + // Average across agents + for (int i = 0; i < num_keys; i++) { + ((float *)&aggregate)[i] /= n; + } + // User populates dict + my_log(dict, env, &aggregate, n); + assign_to_dict(dict, "n", n); + return dict; + } } -static PyObject *env_log(PyObject *self, PyObject *args) { - int num_args = PyTuple_Size(args); - if (num_args != 2) { - PyErr_SetString(PyExc_TypeError, "env_log requires 2 arguments"); +static PyObject *vec_get(PyObject *self, PyObject *args) { + VecEnv *vec = unpack_vecenv(args); + if (!vec) { + PyErr_SetString(PyExc_ValueError, "Invalid VecEnv handle"); return NULL; } - Env *env = unpack_env(args); - if (!env) { + PyObject *list = PyList_New(vec->num_envs); + if (!list) return NULL; - } - // Aggregate this env's per-agent logs (same as vec_log but for one env) - // Note: breaks horribly if you don't use floats - Log aggregate = {0}; - int num_keys = sizeof(Log) / sizeof(float); - for (int j = 0; j < num_keys; j++) { - ((float *)&aggregate)[j] += ((float *)&env->log)[j]; - } - - PyObject *dict = PyDict_New(); - if (aggregate.n == 0.0f) { - return dict; - } - - // Average across agents in env - float n = aggregate.n; - for (int i = 0; i < num_keys; i++) { - ((float *)&aggregate)[i] /= n; + for (int i = 0; i < vec->num_envs; i++) { + Env *env = vec->envs[i]; + if (!env) { + Py_INCREF(Py_None); + PyList_SetItem(list, i, Py_None); + continue; + } + PyObject *dict = PyDict_New(); + if (!dict) { + Py_DECREF(list); + return NULL; + } + PyObject *res = my_get(dict, env); + if (res == NULL) { + Py_DECREF(dict); + Py_DECREF(list); + return NULL; + } + /* my_get returns the dict (or NULL on error) */ + PyList_SetItem(list, i, dict); } - aggregate.n = (float)env->active_agent_count; - - my_log(dict, &aggregate); - return dict; + return list; } static PyObject *vec_close(PyObject *self, PyObject *args) { @@ -694,19 +717,6 @@ static PyObject *vec_close(PyObject *self, PyObject *args) { Py_RETURN_NONE; } -static PyObject *vec_get_scenario_ids(PyObject *self, PyObject *args) { - VecEnv *vec = unpack_vecenv(args); - if (!vec) - return NULL; - - PyObject *list = PyList_New(vec->num_envs); - for (int i = 0; i < vec->num_envs; i++) { - // scenario_id is char[16], may not be null-terminated at byte 16 - PyList_SET_ITEM(list, i, PyUnicode_FromStringAndSize(vec->envs[i]->scenario_id, 16)); - } - return list; -} - static PyObject *get_global_agent_state(PyObject *self, PyObject *args) { if (PyTuple_Size(args) != 7) { PyErr_SetString(PyExc_TypeError, "get_global_agent_state requires 7 arguments"); @@ -807,8 +817,8 @@ static PyObject *vec_get_global_agent_state(PyObject *self, PyObject *args) { } static PyObject *get_ground_truth_trajectories(PyObject *self, PyObject *args) { - if (PyTuple_Size(args) != 9) { - PyErr_SetString(PyExc_TypeError, "get_ground_truth_trajectories requires 9 arguments"); + if (PyTuple_Size(args) != 7) { + PyErr_SetString(PyExc_TypeError, "get_ground_truth_trajectories requires 7 arguments"); return NULL; } @@ -826,13 +836,10 @@ static PyObject *get_ground_truth_trajectories(PyObject *self, PyObject *args) { PyObject *heading_arr = PyTuple_GetItem(args, 4); PyObject *valid_arr = PyTuple_GetItem(args, 5); PyObject *id_arr = PyTuple_GetItem(args, 6); - PyObject *is_vehicle_arr = PyTuple_GetItem(args, 7); - PyObject *is_track_to_predict_arr = PyTuple_GetItem(args, 8); - PyObject *scenario_id_arr = PyTuple_GetItem(args, 9); + PyObject *scenario_id_arr = PyTuple_GetItem(args, 7); if (!PyArray_Check(x_arr) || !PyArray_Check(y_arr) || !PyArray_Check(z_arr) || !PyArray_Check(heading_arr) || - !PyArray_Check(valid_arr) || !PyArray_Check(id_arr) || !PyArray_Check(is_vehicle_arr) || - !PyArray_Check(is_track_to_predict_arr) || !PyArray_Check(scenario_id_arr)) { + !PyArray_Check(valid_arr) || !PyArray_Check(id_arr) || !PyArray_Check(scenario_id_arr)) { PyErr_SetString(PyExc_TypeError, "All output arrays must be NumPy arrays"); return NULL; } @@ -843,19 +850,17 @@ static PyObject *get_ground_truth_trajectories(PyObject *self, PyObject *args) { float *heading_data = (float *)PyArray_DATA((PyArrayObject *)heading_arr); int *valid_data = (int *)PyArray_DATA((PyArrayObject *)valid_arr); int *id_data = (int *)PyArray_DATA((PyArrayObject *)id_arr); - bool *is_vehicle_data = (bool *)PyArray_DATA((PyArrayObject *)is_vehicle_arr); - bool *is_track_to_predict_data = (bool *)PyArray_DATA((PyArrayObject *)is_track_to_predict_arr); - char *scenario_id_data = (char *)PyArray_DATA((PyArrayObject *)scenario_id_arr); + int *scenario_id_data = (int *)PyArray_DATA((PyArrayObject *)scenario_id_arr); c_get_global_ground_truth_trajectories(drive, x_data, y_data, z_data, heading_data, valid_data, id_data, - is_vehicle_data, is_track_to_predict_data, scenario_id_data); + scenario_id_data); Py_RETURN_NONE; } static PyObject *vec_get_global_ground_truth_trajectories(PyObject *self, PyObject *args) { - if (PyTuple_Size(args) != 10) { - PyErr_SetString(PyExc_TypeError, "vec_get_global_ground_truth_trajectories requires 10 arguments"); + if (PyTuple_Size(args) != 8) { + PyErr_SetString(PyExc_TypeError, "vec_get_global_ground_truth_trajectories requires 8 arguments"); return NULL; } @@ -871,13 +876,10 @@ static PyObject *vec_get_global_ground_truth_trajectories(PyObject *self, PyObje PyObject *heading_arr = PyTuple_GetItem(args, 4); PyObject *valid_arr = PyTuple_GetItem(args, 5); PyObject *id_arr = PyTuple_GetItem(args, 6); - PyObject *is_vehicle_arr = PyTuple_GetItem(args, 7); - PyObject *is_track_to_predict_arr = PyTuple_GetItem(args, 8); - PyObject *scenario_id_arr = PyTuple_GetItem(args, 9); + PyObject *scenario_id_arr = PyTuple_GetItem(args, 7); if (!PyArray_Check(x_arr) || !PyArray_Check(y_arr) || !PyArray_Check(z_arr) || !PyArray_Check(heading_arr) || - !PyArray_Check(valid_arr) || !PyArray_Check(id_arr) || !PyArray_Check(is_vehicle_arr) || - !PyArray_Check(is_track_to_predict_arr) || !PyArray_Check(scenario_id_arr)) { + !PyArray_Check(valid_arr) || !PyArray_Check(id_arr) || !PyArray_Check(scenario_id_arr)) { PyErr_SetString(PyExc_TypeError, "All output arrays must be NumPy arrays"); return NULL; } @@ -888,8 +890,6 @@ static PyObject *vec_get_global_ground_truth_trajectories(PyObject *self, PyObje PyArrayObject *heading_array = (PyArrayObject *)heading_arr; PyArrayObject *valid_array = (PyArrayObject *)valid_arr; PyArrayObject *id_array = (PyArrayObject *)id_arr; - PyArrayObject *is_vehicle_array = (PyArrayObject *)is_vehicle_arr; - PyArrayObject *is_track_to_predict_array = (PyArrayObject *)is_track_to_predict_arr; PyArrayObject *scenario_id_array = (PyArrayObject *)scenario_id_arr; // Get base pointers to the arrays @@ -899,9 +899,7 @@ static PyObject *vec_get_global_ground_truth_trajectories(PyObject *self, PyObje float *heading_base = (float *)PyArray_DATA(heading_array); int *valid_base = (int *)PyArray_DATA(valid_array); int *id_base = (int *)PyArray_DATA(id_array); - bool *is_vehicle_base = (bool *)PyArray_DATA(is_vehicle_array); - bool *is_track_to_predict_base = (bool *)PyArray_DATA(is_track_to_predict_array); - char *scenario_id_base = (char *)PyArray_DATA(scenario_id_array); + int *scenario_id_base = (int *)PyArray_DATA(scenario_id_array); // Get number of timesteps from array shape npy_intp *x_shape = PyArray_DIMS(x_array); @@ -914,10 +912,9 @@ static PyObject *vec_get_global_ground_truth_trajectories(PyObject *self, PyObje for (int i = 0; i < vec->num_envs; i++) { Drive *drive = (Drive *)vec->envs[i]; - c_get_global_ground_truth_trajectories( - drive, &x_base[traj_offset], &y_base[traj_offset], &z_base[traj_offset], &heading_base[traj_offset], - &valid_base[traj_offset], &id_base[agent_offset], &is_vehicle_base[agent_offset], - &is_track_to_predict_base[agent_offset], &scenario_id_base[agent_offset * 16]); + c_get_global_ground_truth_trajectories(drive, &x_base[traj_offset], &y_base[traj_offset], &z_base[traj_offset], + &heading_base[traj_offset], &valid_base[traj_offset], + &id_base[agent_offset], &scenario_id_base[agent_offset]); // Move offsets forward agent_offset += drive->active_agent_count; @@ -967,7 +964,7 @@ static PyObject *vec_get_road_edge_polylines(PyObject *self, PyObject *args) { float *x_base = (float *)PyArray_DATA((PyArrayObject *)x_arr); float *y_base = (float *)PyArray_DATA((PyArrayObject *)y_arr); int *lengths_base = (int *)PyArray_DATA((PyArrayObject *)lengths_arr); - char *scenario_ids_base = (char *)PyArray_DATA((PyArrayObject *)scenario_ids_arr); + int *scenario_ids_base = (int *)PyArray_DATA((PyArrayObject *)scenario_ids_arr); int poly_offset = 0, pt_offset = 0; for (int i = 0; i < vec->num_envs; i++) { @@ -975,7 +972,7 @@ static PyObject *vec_get_road_edge_polylines(PyObject *self, PyObject *args) { int np, tp; c_get_road_edge_counts(drive, &np, &tp); c_get_road_edge_polylines(drive, &x_base[pt_offset], &y_base[pt_offset], &lengths_base[poly_offset], - &scenario_ids_base[poly_offset * 16]); + &scenario_ids_base[poly_offset]); poly_offset += np; pt_offset += tp; } @@ -1046,7 +1043,6 @@ static PyMethodDef methods[] = { {"env_close", env_close, METH_VARARGS, "Close the environment"}, {"env_get", env_get, METH_VARARGS, "Get the environment state"}, {"env_put", (PyCFunction)env_put, METH_VARARGS | METH_KEYWORDS, "Put stuff into env"}, - {"env_log", env_log, METH_VARARGS, "Log stats for a single environment"}, {"vectorize", vectorize, METH_VARARGS, "Make a vector of environment handles"}, {"vec_init", (PyCFunction)vec_init, METH_VARARGS | METH_KEYWORDS, "Initialize a vector of environments"}, {"vec_reset", vec_reset, METH_VARARGS, "Reset the vector of environments"}, @@ -1054,7 +1050,7 @@ static PyMethodDef methods[] = { {"vec_log", vec_log, METH_VARARGS, "Log the vector of environments"}, {"vec_render", vec_render, METH_VARARGS, "Render the vector of environments"}, {"vec_close", vec_close, METH_VARARGS, "Close the vector of environments"}, - {"vec_get_scenario_ids", vec_get_scenario_ids, METH_VARARGS, "Get scenario IDs for all envs"}, + {"vec_get", vec_get, METH_VARARGS, "Get attributes from each env in a VecEnv"}, {"shared", (PyCFunction)my_shared, METH_VARARGS | METH_KEYWORDS, "Shared state"}, {"get_global_agent_state", get_global_agent_state, METH_VARARGS, "Get global agent state"}, {"vec_get_global_agent_state", vec_get_global_agent_state, METH_VARARGS, "Get agent state from vectorized env"}, @@ -1080,15 +1076,22 @@ PyMODINIT_FUNC PyInit_binding(void) { } // Make constants accessible from Python - PyModule_AddIntConstant(m, "MAX_ROAD_SEGMENT_OBSERVATIONS", MAX_ROAD_SEGMENT_OBSERVATIONS); - PyModule_AddIntConstant(m, "MAX_AGENTS", MAX_AGENTS); - PyModule_AddIntConstant(m, "TRAJECTORY_LENGTH", TRAJECTORY_LENGTH); PyModule_AddIntConstant(m, "MAX_ENTITIES_PER_CELL", MAX_ENTITIES_PER_CELL); - PyModule_AddIntConstant(m, "ROAD_FEATURES", ROAD_FEATURES); PyModule_AddIntConstant(m, "PARTNER_FEATURES", PARTNER_FEATURES); + PyModule_AddIntConstant(m, "TRAFFIC_LIGHT_FEATURES", TRAFFIC_LIGHT_FEATURES); + PyModule_AddIntConstant(m, "NUM_TRAFFIC_LIGHT_STATES", NUM_TRAFFIC_LIGHT_STATES); + PyModule_AddIntConstant(m, "STOP_SIGN_FEATURES", STOP_SIGN_FEATURES); PyModule_AddIntConstant(m, "EGO_FEATURES_CLASSIC", EGO_FEATURES_CLASSIC); PyModule_AddIntConstant(m, "EGO_FEATURES_JERK", EGO_FEATURES_JERK); + PyModule_AddIntConstant(m, "STATIC_TARGET_FEATURES", STATIC_TARGET_FEATURES); + PyModule_AddIntConstant(m, "DYNAMIC_TARGET_FEATURES", DYNAMIC_TARGET_FEATURES); + PyModule_AddIntConstant(m, "MAX_TARGET_WAYPOINTS", MAX_TARGET_WAYPOINTS); + PyModule_AddIntConstant(m, "NUM_REWARD_COEFS", NUM_REWARD_COEFS); + PyModule_AddIntConstant(m, "TARGET_STATIC", TARGET_STATIC); + PyModule_AddIntConstant(m, "TARGET_DYNAMIC", TARGET_DYNAMIC); + PyObject_SetAttrString(m, "MULTI_LANE_FULL_SCORE_TIME", PyFloat_FromDouble(MULTI_LANE_FULL_SCORE_TIME)); + PyObject_SetAttrString(m, "MULTI_LANE_HALF_SCORE_TIME", PyFloat_FromDouble(MULTI_LANE_HALF_SCORE_TIME)); return m; } diff --git a/pufferlib/ocean/env_config.h b/pufferlib/ocean/env_config.h index 10f592077f..dc05fa9dc6 100644 --- a/pufferlib/ocean/env_config.h +++ b/pufferlib/ocean/env_config.h @@ -8,29 +8,48 @@ // Config struct for parsing INI files - contains all environment configuration typedef struct { - int render_mode; int action_type; int dynamics_model; float reward_vehicle_collision; float reward_offroad_collision; + float reward_traffic_light_violation; float reward_goal; - float reward_goal_post_respawn; - float reward_vehicle_collision_post_respawn; + float reward_ade; + float reward_overspeed; + float reward_comfort; + float reward_velocity; + float reward_lane_align; + float reward_vel_align; + float reward_lane_center; + float reward_center_bias; + float reward_timestep; + float reward_reverse; float goal_radius; - float goal_speed; int collision_behavior; int offroad_behavior; - int spawn_immunity_timer; + int traffic_light_behavior; float dt; - int goal_behavior; - float goal_target_distance; - int episode_length; + int target_type; + int scenario_length; int termination_mode; int init_steps; int init_mode; int control_mode; - int max_controlled_agents; + int simulation_mode; char map_dir[256]; + float min_waypoint_spacing; + float max_waypoint_spacing; + int num_target_waypoints; + int reward_conditioning; + int reward_randomization; + int compute_eval_metrics; + int max_agents_per_env; + int use_rear_axle; + int max_lane_segment_observations; + int max_boundary_segment_observations; + int max_partner_observations; + int max_traffic_light_observations; + int max_stop_sign_observations; } env_init_config; // INI file parser handler - parses all environment configuration from drive.ini @@ -56,76 +75,125 @@ static int handler(void *config, const char *section, const char *name, const ch printf("Warning: Unknown dynamics_model value '%s', defaulting to JERK\n", value); env_config->dynamics_model = 1; // Default to JERK } - } else if (MATCH("env", "goal_behavior")) { - env_config->goal_behavior = atoi(value); - } else if (MATCH("env", "goal_target_distance")) { - env_config->goal_target_distance = atof(value); + } else if (MATCH("env", "collision_behavior")) { + env_config->collision_behavior = atoi(value); + } else if (MATCH("env", "offroad_behavior")) { + env_config->offroad_behavior = atoi(value); + } else if (MATCH("env", "traffic_light_behavior")) { + env_config->traffic_light_behavior = atoi(value); + } else if (MATCH("env", "target_type")) { + if (strcmp(value, "\"static\"") == 0 || strcmp(value, "static") == 0) { + env_config->target_type = 0; // TARGET_STATIC + } else if (strcmp(value, "\"dynamic\"") == 0 || strcmp(value, "dynamic") == 0) { + env_config->target_type = 1; // TARGET_DYNAMIC + } else { + printf("Warning: Unknown target_type value '%s', defaulting to static\n", value); + env_config->target_type = 0; + } } else if (MATCH("env", "reward_vehicle_collision")) { env_config->reward_vehicle_collision = atof(value); } else if (MATCH("env", "reward_offroad_collision")) { env_config->reward_offroad_collision = atof(value); + } else if (MATCH("env", "reward_traffic_light_violation")) { + env_config->reward_traffic_light_violation = atof(value); } else if (MATCH("env", "reward_goal")) { env_config->reward_goal = atof(value); - } else if (MATCH("env", "reward_goal_post_respawn")) { - env_config->reward_goal_post_respawn = atof(value); - } else if (MATCH("env", "reward_vehicle_collision_post_respawn")) { - env_config->reward_vehicle_collision_post_respawn = atof(value); + } else if (MATCH("env", "reward_ade")) { + env_config->reward_ade = atof(value); + } else if (MATCH("env", "reward_overspeed")) { + env_config->reward_overspeed = atof(value); + } else if (MATCH("env", "reward_comfort")) { + env_config->reward_comfort = atof(value); + } else if (MATCH("env", "reward_velocity")) { + env_config->reward_velocity = atof(value); + } else if (MATCH("env", "reward_lane_align")) { + env_config->reward_lane_align = atof(value); + } else if (MATCH("env", "reward_vel_align")) { + env_config->reward_vel_align = atof(value); + } else if (MATCH("env", "reward_lane_center")) { + env_config->reward_lane_center = atof(value); + } else if (MATCH("env", "reward_center_bias")) { + env_config->reward_center_bias = atof(value); + } else if (MATCH("env", "reward_timestep")) { + env_config->reward_timestep = atof(value); + } else if (MATCH("env", "reward_reverse")) { + env_config->reward_reverse = atof(value); } else if (MATCH("env", "goal_radius")) { env_config->goal_radius = atof(value); - } else if (MATCH("env", "goal_speed")) { - env_config->goal_speed = atof(value); - } else if (MATCH("env", "collision_behavior")) { - env_config->collision_behavior = atoi(value); - } else if (MATCH("env", "offroad_behavior")) { - env_config->offroad_behavior = atoi(value); - } else if (MATCH("env", "spawn_immunity_timer")) { - env_config->spawn_immunity_timer = atoi(value); } else if (MATCH("env", "dt")) { env_config->dt = atof(value); - } else if (MATCH("env", "episode_length")) { - env_config->episode_length = atoi(value); + } else if (MATCH("env", "scenario_length")) { + env_config->scenario_length = atoi(value); } else if (MATCH("env", "termination_mode")) { env_config->termination_mode = atoi(value); } else if (MATCH("env", "init_steps")) { env_config->init_steps = atoi(value); + } else if (MATCH("env", "max_agents_per_env")) { + env_config->max_agents_per_env = atoi(value); } else if (MATCH("env", "init_mode")) { - if (strcmp(value, "\"create_all_valid\"") == 0 || strcmp(value, "create_all_valid") == 0) { - env_config->init_mode = 0; - } else if (strcmp(value, "\"create_only_controlled\"") == 0 || strcmp(value, "create_only_controlled") == 0) { - env_config->init_mode = 1; - } else { - printf("Warning: Unknown init_mode value '%s', defaulting to CREATE_ALL_VALID\n", value); - env_config->init_mode = 0; // Default to CREATE_ALL_VALID - } + env_config->init_mode = atoi(value); } else if (MATCH("env", "control_mode")) { - if (strcmp(value, "\"control_vehicles\"") == 0 || strcmp(value, "control_vehicles") == 0) { - env_config->control_mode = 0; - } else if (strcmp(value, "\"control_agents\"") == 0 || strcmp(value, "control_agents") == 0) { - env_config->control_mode = 1; - } else if (strcmp(value, "\"control_wosac\"") == 0 || strcmp(value, "control_wosac") == 0) { - env_config->control_mode = 2; - } else if (strcmp(value, "\"control_sdc_only\"") == 0 || strcmp(value, "control_sdc_only") == 0) { - env_config->control_mode = 3; - } else if (strcmp(value, "\"control_mixed_play\"") == 0 || strcmp(value, "control_mixed_play") == 0) { - env_config->control_mode = 4; - } else { - printf("Warning: Unknown control_mode value '%s', defaulting to CONTROL_VEHICLES\n", value); - env_config->control_mode = 0; // Default to CONTROL_VEHICLES - } + env_config->control_mode = atoi(value); + } else if (MATCH("env", "simulation_mode")) { + env_config->simulation_mode = atoi(value); } else if (MATCH("env", "map_dir")) { if (sscanf(value, "\"%255[^\"]\"", env_config->map_dir) != 1) { strncpy(env_config->map_dir, value, sizeof(env_config->map_dir) - 1); env_config->map_dir[sizeof(env_config->map_dir) - 1] = '\0'; } - // printf("Parsed map_dir: '%s'\n", env_config->map_dir); - } else if (MATCH("env", "max_controlled_agents")) { - env_config->max_controlled_agents = atoi(value); + } else if (MATCH("env", "min_waypoint_spacing")) { + env_config->min_waypoint_spacing = atof(value); + } else if (MATCH("env", "max_waypoint_spacing")) { + env_config->max_waypoint_spacing = atof(value); + } else if (MATCH("env", "num_target_waypoints")) { + env_config->num_target_waypoints = atoi(value); + } else if (MATCH("env", "reward_conditioning")) { + if (strcmp(value, "True") == 0 || strcmp(value, "true") == 0 || strcmp(value, "1") == 0) { + env_config->reward_conditioning = 1; + } else { + env_config->reward_conditioning = 0; + } + } else if (MATCH("env", "reward_randomization")) { + if (strcmp(value, "True") == 0 || strcmp(value, "true") == 0 || strcmp(value, "1") == 0) { + env_config->reward_randomization = 1; + } else { + env_config->reward_randomization = 0; + } + } else if (MATCH("env", "compute_eval_metrics")) { + if (strcmp(value, "True") == 0 || strcmp(value, "true") == 0 || strcmp(value, "1") == 0) { + env_config->compute_eval_metrics = 1; + } else { + env_config->compute_eval_metrics = 0; + } + } else if (MATCH("env", "use_rear_axle")) { + if (strcmp(value, "True") == 0 || strcmp(value, "true") == 0 || strcmp(value, "1") == 0) { + env_config->use_rear_axle = 1; + } else { + env_config->use_rear_axle = 0; + } + } else if (MATCH("env", "max_boundary_segment_observations")) { + env_config->max_boundary_segment_observations = atoi(value); + } else if (MATCH("env", "max_lane_segment_observations")) { + env_config->max_lane_segment_observations = atoi(value); + } else if (MATCH("env", "max_partner_observations")) { + env_config->max_partner_observations = atoi(value); + } else if (MATCH("env", "max_traffic_light_observations")) { + env_config->max_traffic_light_observations = atoi(value); + } else if (MATCH("env", "max_stop_sign_observations")) { + env_config->max_stop_sign_observations = atoi(value); } else { - return 0; // Unknown section/name, indicate failure to handle + if (strcmp(section, "env") == 0) { + printf("Warning: unknown key '%s' in [env] section\n", name); + } + return 1; // Skip keys in non-env sections silently } #undef MATCH return 1; } +static int load_env_config(const char *ini_file, env_init_config *config) { + return ini_parse(ini_file, handler, config); +} + #endif // ENV_CONFIG_H diff --git a/pufferlib/ocean/environment.py b/pufferlib/ocean/environment.py index feba8bead2..a4843effcf 100644 --- a/pufferlib/ocean/environment.py +++ b/pufferlib/ocean/environment.py @@ -1,189 +1,7 @@ import importlib -import pufferlib.emulation +import pufferlib - -def lazy_import(module_path, attr): - """ - Returns a callable that, when called with any arguments, will - import the module, retrieve the attribute (usually a class or factory) - and then call it with the given arguments. - """ - return lambda *args, **kwargs: getattr(__import__(module_path, fromlist=[attr]), attr)(*args, **kwargs) - - -def make_foraging( - width=1080, height=720, num_agents=4096, horizon=512, discretize=True, food_reward=0.1, render_mode="rgb_array" -): - from .grid import grid - - init_fn = grid.init_foraging - reward_fn = grid.reward_foraging - return grid.PufferGrid( - width, - height, - num_agents, - horizon, - discretize=discretize, - food_reward=food_reward, - init_fn=init_fn, - reward_fn=reward_fn, - render_mode=render_mode, - ) - - -def make_predator_prey( - width=1080, height=720, num_agents=4096, horizon=512, discretize=True, food_reward=0.1, render_mode="rgb_array" -): - from .grid import grid - - init_fn = grid.init_predator_prey - reward_fn = grid.reward_predator_prey - return grid.PufferGrid( - width, - height, - num_agents, - horizon, - discretize=discretize, - food_reward=food_reward, - init_fn=init_fn, - reward_fn=reward_fn, - render_mode=render_mode, - ) - - -def make_group( - width=1080, height=720, num_agents=4096, horizon=512, discretize=True, food_reward=0.1, render_mode="rgb_array" -): - from .grid import grid - - init_fn = grid.init_group - reward_fn = grid.reward_group - return grid.PufferGrid( - width, - height, - num_agents, - horizon, - discretize=discretize, - food_reward=food_reward, - init_fn=init_fn, - reward_fn=reward_fn, - render_mode=render_mode, - ) - - -def make_puffer( - width=1080, height=720, num_agents=4096, horizon=512, discretize=True, food_reward=0.1, render_mode="rgb_array" -): - from .grid import grid - - init_fn = grid.init_puffer - reward_fn = grid.reward_puffer - return grid.PufferGrid( - width, - height, - num_agents, - horizon, - discretize=discretize, - food_reward=food_reward, - init_fn=init_fn, - reward_fn=reward_fn, - render_mode=render_mode, - ) - - -def make_puffergrid( - render_mode="raylib", vision_range=5, num_envs=4096, num_maps=1000, max_map_size=9, report_interval=128, buf=None -): - return PufferGrid(render_mode, vision_range, num_envs, num_maps, max_map_size, report_interval, buf) - - -def make_continuous(discretize=False, buf=None, **kwargs): - from . import sanity - - env = sanity.Continuous(discretize=discretize) - if not discretize: - env = pufferlib.ClipAction(env) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - - -def make_squared(distance_to_target=3, num_targets=1, buf=None, **kwargs): - from . import sanity - - env = sanity.Squared(distance_to_target=distance_to_target, num_targets=num_targets, **kwargs) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf, **kwargs) - - -def make_bandit(num_actions=10, reward_scale=1, reward_noise=1, buf=None): - from . import sanity - - env = sanity.Bandit(num_actions=num_actions, reward_scale=reward_scale, reward_noise=reward_noise) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - - -def make_memory(mem_length=2, mem_delay=2, buf=None, **kwargs): - from . import sanity - - env = sanity.Memory(mem_length=mem_length, mem_delay=mem_delay) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - - -def make_password(password_length=5, buf=None, **kwargs): - from . import sanity - - env = sanity.Password(password_length=password_length) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - - -def make_performance(delay_mean=0, delay_std=0, bandwidth=1, buf=None, **kwargs): - from . import sanity - - env = sanity.Performance(delay_mean=delay_mean, delay_std=delay_std, bandwidth=bandwidth) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - - -def make_performance_empiric(count_n=0, count_std=0, bandwidth=1, buf=None, **kwargs): - from . import sanity - - env = sanity.PerformanceEmpiric(count_n=count_n, count_std=count_std, bandwidth=bandwidth) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - - -def make_stochastic(p=0.7, horizon=100, buf=None, **kwargs): - from . import sanity - - env = sanity.Stochastic(p=p, horizon=100) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - - -def make_spaces(buf=None, **kwargs): - from . import sanity - - env = sanity.Spaces() - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf, **kwargs) - - -def make_multiagent(buf=None, **kwargs): - from . import sanity - - env = sanity.Multiagent() - env = pufferlib.MultiagentEpisodeStats(env) - return pufferlib.emulation.PettingZooPufferEnv(env=env, buf=buf) - - -MAKE_FUNCTIONS = { - "drive": "Drive", - "spaces": make_spaces, - "multiagent": make_multiagent, -} +MAKE_FUNCTIONS = {"drive": "Drive"} def env_creator(name="squared", *args, **kwargs): diff --git a/pufferlib/ocean/torch.py b/pufferlib/ocean/torch.py index 0d4d618cea..592e2c94ee 100644 --- a/pufferlib/ocean/torch.py +++ b/pufferlib/ocean/torch.py @@ -4,110 +4,330 @@ import pufferlib import pufferlib.models +from pufferlib.ocean.drive import binding from pufferlib.models import Default as Policy # noqa: F401 from pufferlib.models import Convolutional as Conv # noqa: F401 - Recurrent = pufferlib.models.LSTMWrapper +class DriveBackbone(nn.Module): + """ + Neural network backbone + Architecture features: + - Split Actor/Critic (configurable) + """ + + def _create_encoder(self, in_features, input_size, encoder_gigaflow, dropout=0.0): + if encoder_gigaflow: + return nn.Sequential( + pufferlib.pytorch.layer_init(nn.Linear(in_features, input_size)), + nn.LayerNorm(input_size), + nn.Tanh(), + nn.Dropout(dropout), + pufferlib.pytorch.layer_init(nn.Linear(input_size, input_size)), + ) + else: + return nn.Sequential( + pufferlib.pytorch.layer_init(nn.Linear(in_features, input_size)), + nn.LayerNorm(input_size), + pufferlib.pytorch.layer_init(nn.Linear(input_size, input_size)), + ) + + def __init__( + self, + env, + input_size, + backbone_hidden_size, + backbone_num_layers, + ego_dim, + encoder_gigaflow, + dropout, + ): + super().__init__() + + # Observation dimensions from environment config + self.max_partner_observations = env.max_partner_observations + self.partner_features_count = env.partner_features + # Road features size (lanes + boundaries) + self.max_lane_segment_observations = env.max_lane_segment_observations + self.max_boundary_segment_observations = env.max_boundary_segment_observations + self.road_features_count = env.road_features + # Traffic light size + self.max_traffic_light_observations = env.max_traffic_light_observations + self.traffic_light_features_count = env.traffic_light_features + self.traffic_light_features_after_onehot = env.traffic_light_features + (binding.NUM_TRAFFIC_LIGHT_STATES - 1) + # Stop sign size + self.max_stop_sign_observations = env.max_stop_sign_observations + self.stop_sign_features_count = env.stop_sign_features + # Conditioning size (reward coefficients + target info) + self.conditioning_dim = env.num_reward_coefs + env.target_dim + + num_feature_sets = 1 + + # 1. observations Encoders + # Each encoder projects raw features into a common input_size embedding space + self.ego_encoder = self._create_encoder(ego_dim, input_size, encoder_gigaflow) + if self.max_lane_segment_observations > 0: + self.lane_encoder = self._create_encoder( + self.road_features_count, + input_size, + encoder_gigaflow, + dropout=dropout, + ) + num_feature_sets += 1 + if self.max_boundary_segment_observations > 0: + self.boundary_encoder = self._create_encoder( + self.road_features_count, + input_size, + encoder_gigaflow, + dropout=dropout, + ) + num_feature_sets += 1 + if self.max_partner_observations > 0: + self.partner_encoder = self._create_encoder(self.partner_features_count, input_size, encoder_gigaflow) + num_feature_sets += 1 + if self.max_traffic_light_observations > 0: + self.traffic_light_encoder = self._create_encoder( + self.traffic_light_features_after_onehot, + input_size, + encoder_gigaflow, + ) + num_feature_sets += 1 + if self.max_stop_sign_observations > 0: + self.stop_sign_encoder = self._create_encoder( + self.stop_sign_features_count, + input_size, + encoder_gigaflow, + ) + num_feature_sets += 1 + if self.conditioning_dim > 0: + self.conditioning_encoder = self._create_encoder(self.conditioning_dim, input_size, encoder_gigaflow) + num_feature_sets += 1 + + # 2. Main Backbone MLP + backbone_layers = [] + bb_in = num_feature_sets * input_size + for _ in range(backbone_num_layers): + backbone_layers.append(nn.GELU()) + backbone_layers.append(pufferlib.pytorch.layer_init(nn.Linear(bb_in, backbone_hidden_size))) + bb_in = backbone_hidden_size + # Add final GELU before heads + backbone_layers.append(nn.GELU()) + self.backbone = nn.Sequential(*backbone_layers) + self.out_dim = backbone_hidden_size if backbone_num_layers > 0 else num_feature_sets * input_size + + def forward(self, observations, ego_dim): + # Extract and slice observations from the flat buffer + partner_dim = self.max_partner_observations * self.partner_features_count + lane_dim = self.max_lane_segment_observations * self.road_features_count + boundary_dim = self.max_boundary_segment_observations * self.road_features_count + traffic_light_dim = self.max_traffic_light_observations * self.traffic_light_features_count + stop_sign_dim = self.max_stop_sign_observations * self.stop_sign_features_count + + slide_idx = ego_dim + ego_observations = observations[:, :slide_idx] + + conditioning_observations = observations[:, slide_idx : slide_idx + self.conditioning_dim] + slide_idx += self.conditioning_dim + + partner_observations = observations[:, slide_idx : slide_idx + partner_dim] + slide_idx += partner_dim + + lane_observations = observations[:, slide_idx : slide_idx + lane_dim] + slide_idx += lane_dim + + boundary_observations = observations[:, slide_idx : slide_idx + boundary_dim] + slide_idx += boundary_dim + + traffic_light_observations = observations[:, slide_idx : slide_idx + traffic_light_dim] + slide_idx += traffic_light_dim + + stop_sign_observations = observations[:, slide_idx : slide_idx + stop_sign_dim] + + # Encode Ego State + ego_features = self.ego_encoder(ego_observations) + + feature_list = [ego_features] + + # Encode Lanes and Boundaries separately + if self.max_lane_segment_observations > 0: + lane_objects = lane_observations.view(-1, self.max_lane_segment_observations, self.road_features_count) + lane_features, _ = self.lane_encoder(lane_objects).max(dim=1) + feature_list.append(lane_features) + if self.max_boundary_segment_observations > 0: + boundary_objects = boundary_observations.view( + -1, self.max_boundary_segment_observations, self.road_features_count + ) + + boundary_features, _ = self.boundary_encoder(boundary_objects).max(dim=1) + feature_list.append(boundary_features) + + # Encode Partners + if self.max_partner_observations > 0: + partner_objects = partner_observations.view(-1, self.max_partner_observations, self.partner_features_count) + partner_encoded = self.partner_encoder(partner_objects) + partner_features, _ = partner_encoded.max(dim=1) + feature_list.append(partner_features) + + # Encode Traffic lights + if self.max_traffic_light_observations > 0: + traffic_light_objects = traffic_light_observations.view( + -1, self.max_traffic_light_observations, self.traffic_light_features_count + ) + traffic_light_continuous = traffic_light_objects[:, :, : self.traffic_light_features_count - 1] + traffic_light_categorical = traffic_light_objects[:, :, self.traffic_light_features_count - 1] + traffic_light_onehot = F.one_hot( + traffic_light_categorical.long(), + num_classes=binding.NUM_TRAFFIC_LIGHT_STATES, + ) + traffic_light_objects = torch.cat([traffic_light_continuous, traffic_light_onehot], dim=2) + traffic_light_features, _ = self.traffic_light_encoder(traffic_light_objects).max(dim=1) + feature_list.append(traffic_light_features) + + # Encode Stop Signs + if self.max_stop_sign_observations > 0: + stop_sign_objects = stop_sign_observations.view( + -1, self.max_stop_sign_observations, self.stop_sign_features_count + ) + stop_sign_features, _ = self.stop_sign_encoder(stop_sign_objects).max(dim=1) + feature_list.append(stop_sign_features) + + # Add optional features if enabled + if self.conditioning_dim > 0: + conditioning_features = self.conditioning_encoder(conditioning_observations) + feature_list.append(conditioning_features) + + # Concatenate all features and pass through main backbone + concat_features = torch.cat(feature_list, dim=1) + return self.backbone(concat_features) + + class Drive(nn.Module): - def __init__(self, env, input_size=128, hidden_size=128, **kwargs): + def __init__( + self, + env, + input_size: int, + backbone_hidden_size: int, + backbone_num_layers: int, + actor_hidden_size: int, + actor_num_layers: int, + critic_hidden_size: int, + critic_num_layers: int, + encoder_gigaflow: bool, + dropout: int, + split_network: bool, + ): super().__init__() - self.hidden_size = hidden_size - self.observation_size = env.single_observation_space.shape[0] - self.max_partner_objects = env.max_partner_objects - self.partner_features = env.partner_features - self.max_road_objects = env.max_road_objects - self.road_features = env.road_features - self.road_features_after_onehot = env.road_features + 6 # 6 is the number of one-hot encoded categories + + # Configuration flags from policy kwargs + self.split_network = split_network self.ego_dim = env.ego_features - self.ego_encoder = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(self.ego_dim, input_size)), - nn.LayerNorm(input_size), - # nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Linear(input_size, input_size)), - ) - - self.road_encoder = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(self.road_features_after_onehot, input_size)), - nn.LayerNorm(input_size), - # nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Linear(input_size, input_size)), - ) - - self.partner_encoder = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(self.partner_features, input_size)), - nn.LayerNorm(input_size), - # nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Linear(input_size, input_size)), - ) - - self.shared_embedding = nn.Sequential( - nn.GELU(), - pufferlib.pytorch.layer_init(nn.Linear(3 * input_size, hidden_size)), - ) - self.is_continuous = isinstance(env.single_action_space, pufferlib.spaces.Box) + # Prepare arguments for the Backbone + backbone_args = { + "env": env, + "input_size": input_size, + "backbone_hidden_size": backbone_hidden_size, + "backbone_num_layers": backbone_num_layers, + "ego_dim": self.ego_dim, + "encoder_gigaflow": encoder_gigaflow, + "dropout": dropout, + } + + # Instantiate backbones + self.actor_backbone = DriveBackbone(**backbone_args) + # If split_network is True, create a separate backbone for the critic. + # Otherwise, share the same backbone for both. + if self.split_network: + self.critic_backbone = DriveBackbone(**backbone_args) + else: + self.critic_backbone = self.actor_backbone + + # Setup action and value heads + self.is_continuous = isinstance(env.single_action_space, pufferlib.spaces.Box) if self.is_continuous: self.atn_dim = (env.single_action_space.shape[0],) * 2 else: self.atn_dim = env.single_action_space.nvec.tolist() - self.actor = pufferlib.pytorch.layer_init(nn.Linear(hidden_size, sum(self.atn_dim)), std=0.01) - self.value_fn = pufferlib.pytorch.layer_init(nn.Linear(hidden_size, 1), std=1) + # n-layer MLP for actor head (num_layers = number of hidden layers) + backbone_out_dim = self.actor_backbone.out_dim + actor_head_layers = [] + actor_in = backbone_out_dim + for _ in range(actor_num_layers): + actor_head_layers.append(pufferlib.pytorch.layer_init(nn.Linear(actor_in, actor_hidden_size))) + actor_head_layers.append(nn.ReLU()) + actor_in = actor_hidden_size + actor_head_layers.append(pufferlib.pytorch.layer_init(nn.Linear(actor_in, sum(self.atn_dim)), std=0.01)) + self.actor_head = nn.Sequential(*actor_head_layers) + + # n-layer MLP for critic head (num_layers = number of hidden layers) + critic_head_layers = [] + critic_in = backbone_out_dim + for _ in range(critic_num_layers): + critic_head_layers.append(pufferlib.pytorch.layer_init(nn.Linear(critic_in, critic_hidden_size))) + critic_head_layers.append(nn.ReLU()) + critic_in = critic_hidden_size + critic_head_layers.append(pufferlib.pytorch.layer_init(nn.Linear(critic_in, 1), std=1)) + self.critic_head = nn.Sequential(*critic_head_layers) def forward(self, observations, state=None): - hidden = self.encode_observations(observations) - actions, value = self.decode_actions(hidden) + """ + Forward pass handling both Actor and Critic inference. + """ + # Forward pass for actor + actor_hidden = self.actor_backbone(observations, self.ego_dim) + + # Forward pass for critic (may use separate backbone) + if self.split_network: + critic_hidden = self.critic_backbone(observations, self.ego_dim) + else: + critic_hidden = actor_hidden + + # Compute actions + if self.is_continuous: + params = self.actor_head(actor_hidden) + loc, scale = torch.split(params, self.atn_dim, dim=1) + std = torch.nn.functional.softplus(scale) + 1e-4 + actions = torch.distributions.Normal(loc, std) + else: + actions = torch.split(self.actor_head(actor_hidden), self.atn_dim, dim=1) + + # Compute value + value = self.critic_head(critic_hidden) + return actions, value def forward_train(self, x, state=None): return self.forward(x, state) - def forward_eval(self, observations, state=None): - hidden = self.encode_observations(observations, state=state) - logits, values = self.decode_actions(hidden) - return logits, values + def forward_eval(self, x, state=None): + return self.forward(x, state) + # Required for PufferLib recurrent wrappers def encode_observations(self, observations, state=None): - ego_dim = self.ego_dim - partner_dim = self.max_partner_objects * self.partner_features - road_dim = self.max_road_objects * self.road_features - ego_obs = observations[:, :ego_dim] - partner_obs = observations[:, ego_dim : ego_dim + partner_dim] - road_obs = observations[:, ego_dim + partner_dim : ego_dim + partner_dim + road_dim] - - partner_objects = partner_obs.view(-1, self.max_partner_objects, self.partner_features) - - road_objects = road_obs.view(-1, self.max_road_objects, self.road_features) - road_continuous = road_objects[:, :, : self.road_features - 1] - road_categorical = road_objects[:, :, self.road_features - 1] - road_onehot = F.one_hot(road_categorical.long(), num_classes=7) # Shape: [batch, ROAD_MAX_OBJECTS, 7] - road_objects = torch.cat([road_continuous, road_onehot], dim=2) - ego_features = self.ego_encoder(ego_obs) - partner_features, _ = self.partner_encoder(partner_objects).max(dim=1) - road_features, _ = self.road_encoder(road_objects).max(dim=1) - - concat_features = torch.cat([ego_features, road_features, partner_features], dim=1) - - # Pass through shared embedding - embedding = F.relu(self.shared_embedding(concat_features)) - # embedding = self.shared_embedding(concat_features) - return embedding - - def decode_actions(self, flat_hidden): + assert not self.split_network, "LSTM wrapper doesn't support split_network=True" + return self.actor_backbone(observations, self.ego_dim) + + def decode_actions(self, hidden): + """ + USE ONLY FOR LSTM WRAPPER. + Decodes actions and value from the hidden state. + Args: + hidden: The hidden state for the actor (policy). + """ if self.is_continuous: - parameters = self.actor(flat_hidden) + parameters = self.actor_head(hidden) loc, scale = torch.split(parameters, self.atn_dim, dim=1) std = torch.nn.functional.softplus(scale) + 1e-4 action = torch.distributions.Normal(loc, std) else: - action = self.actor(flat_hidden) + action = self.actor_head(hidden) action = torch.split(action, self.atn_dim, dim=1) - value = self.value_fn(flat_hidden) + value = self.critic_head(hidden) return action, value diff --git a/pufferlib/pufferl.py b/pufferlib/pufferl.py index 2712ab02d1..343bb74ee2 100644 --- a/pufferlib/pufferl.py +++ b/pufferlib/pufferl.py @@ -3,12 +3,18 @@ # Distributed example: torchrun --standalone --nnodes=1 --nproc-per-node=6 -m pufferlib.pufferl train puffer_nmmo3 import contextlib +import copy +import numbers import warnings +import pandas as pd + + warnings.filterwarnings("error", category=RuntimeWarning) import os import sys +import traceback import glob import ast import time @@ -18,9 +24,10 @@ import argparse import importlib import configparser +from datetime import datetime from threading import Thread from collections import defaultdict, deque -from pathlib import Path +import yaml import numpy as np import psutil @@ -28,15 +35,15 @@ import torch import torch.distributed from torch.distributed.elastic.multiprocessing.errors import record -import torch.utils.cpp_extension import pufferlib import pufferlib.sweep import pufferlib.vector import pufferlib.pytorch import pufferlib.utils +import pufferlib.viz -from pufferlib.ocean.benchmark.evaluator import Evaluator +import mediapy try: from pufferlib import _C @@ -50,6 +57,7 @@ from rich.table import Table from rich.console import Console from rich_argparse import RichHelpFormatter +from tqdm import tqdm rich.traceback.install(show_locals=False) @@ -57,56 +65,59 @@ signal.signal(signal.SIGINT, lambda sig, frame: os._exit(0)) -# Assume advantage kernel has been built if CUDA compiler is available -ADVANTAGE_CUDA = shutil.which("nvcc") is not None +from torch.utils.cpp_extension import CUDA_HOME, ROCM_HOME # noqa: E402 + +# Assume advantage kernel has been built if torch has been compiled with CUDA or HIP support +# and can find CUDA or HIP in the system +ADVANTAGE_CUDA = bool(CUDA_HOME or ROCM_HOME) +HIDDEN_DASHBOARD_METRICS = { + "comfort_score", + "driving_direction_score", + "making_progress_rate", + "multi_lane_score", + "multi_lane_time", + "speed_limit_compliance", + "ttc_within_bound_rate", +} class PuffeRL: - def __init__(self, config, vecenv, policy, logger=None, full_args=None): - self.full_args = full_args + def __init__(self, config, vecenv, policy, logger=None): # Backend perf optimization torch.set_float32_matmul_precision("high") torch.backends.cudnn.deterministic = config["torch_deterministic"] - torch.backends.cudnn.benchmark = True + torch.backends.cudnn.benchmark = not config["torch_deterministic"] + torch.use_deterministic_algorithms(config["torch_deterministic"], warn_only=True) # Reproducibility seed = config["seed"] - # random.seed(seed) - # np.random.seed(seed) - # torch.manual_seed(seed) # Vecenv info vecenv.async_reset(seed) obs_space = vecenv.single_observation_space atn_space = vecenv.single_action_space - # The number of concurrent agents running in the vectorized environments total_agents = vecenv.num_agents self.total_agents = total_agents # Experience - if config["batch_size"] == "auto" and config["rollout_horizon"] == "auto": - raise pufferlib.APIUsageError("Must specify batch_size or rollout_horizon") + if config["batch_size"] == "auto" and config["bptt_horizon"] == "auto": + raise pufferlib.APIUsageError("Must specify batch_size or bptt_horizon") elif config["batch_size"] == "auto": - config["batch_size"] = total_agents * config["rollout_horizon"] - elif config["rollout_horizon"] == "auto": - config["rollout_horizon"] = config["batch_size"] // total_agents + config["batch_size"] = total_agents * config["bptt_horizon"] + elif config["bptt_horizon"] == "auto": + config["bptt_horizon"] = config["batch_size"] // total_agents batch_size = config["batch_size"] - rollout_horizon = config["rollout_horizon"] - bptt_horizon = config["rollout_horizon"] # LSTM backprop horizon - config["bptt_horizon"] = bptt_horizon - segments = batch_size // rollout_horizon # Use rollout_horizon - - # Number of independent rollout sequences stored in the experience buffer + horizon = config["bptt_horizon"] + segments = batch_size // horizon self.segments = segments - if total_agents > segments: raise pufferlib.APIUsageError(f"Total agents {total_agents} <= segments {segments}") device = config["device"] self.observations = torch.zeros( segments, - rollout_horizon, + horizon, *obs_space.shape, dtype=pufferlib.pytorch.numpy_to_torch_dtype_dict[obs_space.dtype], pin_memory=device == "cuda" and config["cpu_offload"], @@ -114,21 +125,27 @@ def __init__(self, config, vecenv, policy, logger=None, full_args=None): ) self.actions = torch.zeros( segments, - rollout_horizon, + horizon, *atn_space.shape, device=device, dtype=pufferlib.pytorch.numpy_to_torch_dtype_dict[atn_space.dtype], ) - self.values = torch.zeros(segments, rollout_horizon, device=device) - self.logprobs = torch.zeros(segments, rollout_horizon, device=device) - self.rewards = torch.zeros(segments, rollout_horizon, device=device) - self.terminals = torch.zeros(segments, rollout_horizon, device=device) - self.truncations = torch.zeros(segments, rollout_horizon, device=device) - self.ratio = torch.ones(segments, rollout_horizon, device=device) - self.importance = torch.ones(segments, rollout_horizon, device=device) + self.values = torch.zeros(segments, horizon, device=device) + self.logprobs = torch.zeros(segments, horizon, device=device) + self.rewards = torch.zeros(segments, horizon, device=device) + self.terminals = torch.zeros(segments, horizon, device=device) + self.truncations = torch.zeros(segments, horizon, device=device) + self.ratio = torch.ones(segments, horizon, device=device) + self.importance = torch.ones(segments, horizon, device=device) + self.masks = torch.zeros(segments, horizon, device=device, dtype=torch.bool) self.ep_lengths = torch.zeros(total_agents, device=device, dtype=torch.int32) self.ep_indices = torch.arange(total_agents, device=device, dtype=torch.int32) self.free_idx = total_agents + self.render = config["render"] + self.render_interval = config["render_interval"] + + if self.render: + ensure_drive_binary() # LSTM if config["use_rnn"]: @@ -151,10 +168,10 @@ def __init__(self, config, vecenv, policy, logger=None, full_args=None): self.accumulate_minibatches = max(1, minibatch_size // max_minibatch_size) self.total_minibatches = int(config["update_epochs"] * batch_size / self.minibatch_size) - self.minibatch_segments = self.minibatch_size // rollout_horizon - if self.minibatch_segments * rollout_horizon != self.minibatch_size: + self.minibatch_segments = self.minibatch_size // horizon + if self.minibatch_segments * horizon != self.minibatch_size: raise pufferlib.APIUsageError( - f"minibatch_size {self.minibatch_size} must be divisible by bptt_horizon {rollout_horizon}" + f"minibatch_size {self.minibatch_size} must be divisible by bptt_horizon {horizon}" ) # Torch compile @@ -175,18 +192,32 @@ def __init__(self, config, vecenv, policy, logger=None, full_args=None): betas=(config["adam_beta1"], config["adam_beta2"]), eps=config["adam_eps"], ) + elif config["optimizer"] == "adamw": + optimizer = torch.optim.AdamW( + self.policy.parameters(), + lr=config["learning_rate"], + betas=(config["adam_beta1"], config["adam_beta2"]), + eps=config["adam_eps"], + ) elif config["optimizer"] == "muon": + import heavyball from heavyball import ForeachMuon warnings.filterwarnings(action="ignore", category=UserWarning, module=r"heavyball.*") - import heavyball.utils + heavyball.utils.compile_mode = "default" + + # # optionally a little bit better/faster alternative to newtonschulz iteration + # import heavyball.utils + # heavyball.utils.zeroth_power_mode = 'thinky_polar_express' - heavyball.utils.compile_mode = config["compile_mode"] if config["compile"] else None + # heavyball_momentum=True introduced in heavyball 2.1.1 + # recovers heavyball-1.7.2 behaviour - previously swept hyperparameters work well optimizer = ForeachMuon( self.policy.parameters(), lr=config["learning_rate"], betas=(config["adam_beta1"], config["adam_beta2"]), eps=config["adam_eps"], + heavyball_momentum=True, ) else: raise ValueError(f"Unknown optimizer: {config['optimizer']}") @@ -203,8 +234,6 @@ def __init__(self, config, vecenv, policy, logger=None, full_args=None): self.scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=epochs) self.total_epochs = epochs - self.ent_coef_initial = config["ent_coef"] - # Automatic mixed precision precision = config["precision"] self.amp_context = contextlib.nullcontext() @@ -226,6 +255,8 @@ def __init__(self, config, vecenv, policy, logger=None, full_args=None): self.stats = defaultdict(list) self.last_stats = defaultdict(list) self.losses = {} + self.best_score = -float("inf") + self.ema_max = 0.0 # Dashboard self.model_size = sum(p.numel() for p in policy.parameters() if p.requires_grad) @@ -253,8 +284,8 @@ def evaluate(self): if config["use_rnn"]: for k in self.lstm_h: - self.lstm_h[k] = torch.zeros(self.lstm_h[k].shape, device=device) - self.lstm_c[k] = torch.zeros(self.lstm_c[k].shape, device=device) + self.lstm_h[k].zero_() + self.lstm_c[k].zero_() self.full_rows = 0 while self.full_rows < self.segments: @@ -264,7 +295,8 @@ def evaluate(self): profile("eval_misc", epoch) env_id = slice(env_id[0], env_id[-1] + 1) - self.global_step += int(mask.sum()) + self.global_step += env_id.stop - env_id.start + # self.global_step += int(mask.sum()) profile("eval_copy", epoch) o = torch.as_tensor(o) @@ -272,7 +304,8 @@ def evaluate(self): r = torch.as_tensor(r).to(device) # , non_blocking=True) d = torch.as_tensor(d).to(device) # , non_blocking=True) t = torch.as_tensor(t).to(device) # , non_blocking=True) - done_mask = (d + t).clamp(max=1) + done_mask = (d + t).clamp(max=1.0) + m = torch.as_tensor(mask).to(device) # , non_blocking=True) profile("eval_forward", epoch) with torch.no_grad(), self.amp_context: @@ -289,7 +322,8 @@ def evaluate(self): logits, value = self.policy.forward_eval(o_device, state) action, logprob, _ = pufferlib.pytorch.sample_logits(logits) - r = torch.clamp(r, -1, 1) + if config.get("symlog_rewards", False): + r = torch.sign(r) * torch.log1p(torch.abs(r)) profile("eval_copy", epoch) with torch.no_grad(): @@ -319,6 +353,7 @@ def evaluate(self): self.terminals[batch_rows, l] = done_mask.float() self.truncations[batch_rows, l] = t.float() self.values[batch_rows, l] = value.flatten() + self.masks[batch_rows, l] = m # Note: We are not yet handling masks in this version self.ep_lengths[env_id] += 1 @@ -358,7 +393,213 @@ def train(self): profile = self.profile epoch = self.epoch profile("train", epoch) + profile("train_misc", epoch, nest=True) losses = defaultdict(float) + config = self.config + ppo_granularity = config["ppo_granularity"] + if ppo_granularity == "auto": + ppo_granularity = "trajectory" if config["use_rnn"] else "transition" + if config["use_rnn"] and ppo_granularity == "transition": + raise ValueError("RNN requires trajectory-level training") + + if ppo_granularity == "trajectory": + explained_var = self._train_ppo_trajectory(losses, profile, epoch) + else: + explained_var = self._train_ppo_transition(losses, profile, epoch) + + profile("train_misc", epoch) + if config["anneal_lr"]: + self.scheduler.step() + + losses["explained_variance"] = explained_var + + profile.end() + logs = None + self.epoch += 1 + done_training = self.global_step >= config["total_timesteps"] + if done_training or self.global_step == 0 or time.time() > self.last_log_time + 0.25: + self.losses = losses + logs = self.mean_and_log() + self.print_dashboard() + self.stats = defaultdict(list) + self.last_log_time = time.time() + self.last_log_step = self.global_step + profile.clear() + + if self.epoch % config["checkpoint_interval"] == 0 or done_training: + self.save_checkpoint() + self.msg = f"Checkpoint saved at update {self.epoch}" + + if self.render and self.epoch % self.render_interval == 0: + model_dir = os.path.join(self.config["data_dir"], f"{self.config['env']}_{self.logger.run_id}") + model_files = glob.glob(os.path.join(model_dir, "models", "model_*.pt")) + + if model_files: + # Take the latest checkpoint + latest_cpt = max(model_files, key=os.path.getctime) + bin_path = f"{model_dir}.bin" + + # Export to .bin for rendering with raylib + try: + export_args = {"env_name": self.config["env"], "load_model_path": latest_cpt, **self.config} + + export( + args=export_args, + env_name=self.config["env"], + vecenv=self.vecenv, + policy=self.uncompiled_policy, + path=bin_path, + silent=True, + ) + pufferlib.utils.render_videos( + self.config, self.vecenv, self.logger, self.epoch, self.global_step, bin_path + ) + + except Exception as e: + print(f"Failed to export model weights: {e}") + + if self.config["eval"]["wosac_realism_eval"] and ( + self.epoch % self.config["eval"]["eval_interval"] == 0 or done_training + ): + pufferlib.utils.run_wosac_eval_in_subprocess(self.config, self.logger, self.global_step) + + if self.config["eval"]["human_replay_eval"] and ( + self.epoch % self.config["eval"]["eval_interval"] == 0 or done_training + ): + pufferlib.utils.run_human_replay_eval_in_subprocess(self.config, self.logger, self.global_step) + + if self.config["eval"]["wosac_realism_eval"] and ( + self.epoch % self.config["eval"]["eval_interval"] == 0 or done_training + ): + pufferlib.utils.run_wosac_eval_in_subprocess(self.config, self.logger, self.global_step) + + if self.config["eval"]["human_replay_eval"] and ( + self.epoch % self.config["eval"]["eval_interval"] == 0 or done_training + ): + pufferlib.utils.run_human_replay_eval_in_subprocess(self.config, self.logger, self.global_step) + + if self.config["eval"]["multi_scenario_eval"] and ( + self.epoch % self.config["eval"]["eval_interval"] == 0 or done_training + ): + # Get evaluation settings from config + eval_simulation_mode = self.config["eval"]["multi_scenario_simulation_mode"] + num_agents_eval = self.config["eval"]["num_agents"] + map_dir = self.config["eval"]["map_dir"] + + # Build eval_overrides using helper function + eval_overrides = build_eval_overrides( + simulation_mode=eval_simulation_mode, + num_agents=num_agents_eval, + num_scenarios=self.config["eval"]["multi_scenario_num_scenarios"], + map_dir=map_dir, + num_carla_maps=self.config["eval"].get("num_carla_maps", 8), + ) + + # Build eval args by applying overrides to training config + eval_args = load_eval_multi_scenarios_config( + env_name=self.config["env"], + model_path=None, # No saved model - using current policy in memory + eval_overrides=eval_overrides, + ) + # Add inline-specific settings + eval_args["global_step"] = self.global_step # Log by global step for TensorBoard + eval_args["num_scenarios"] = self.config["eval"]["multi_scenario_num_scenarios"] + eval_args["eval_simulation"] = eval_simulation_mode + + # Mark this as inline evaluation and set results folder in experiments + eval_args["inline_eval"] = True # Flag to indicate inline evaluation during training + experiment_name = f"{self.config['env']}_{self.logger.run_id}" + eval_args["load_model_path"] = os.path.join( + self.config["data_dir"], experiment_name, "models", f"inline_epoch_{self.epoch}.pt" + ) + # For inline eval, results go in experiments folder instead of benchmark + eval_args["eval_results_dir"] = os.path.join( + self.config["data_dir"], + experiment_name, + "validation", + f"epoch_{self.epoch}", + self.config["eval"]["multi_scenario_simulation_mode"], + ) + + # Call eval_multi_scenarios inline with current policy and logger + print(f"\n🔄 Running multi-scenario evaluation at step {self.global_step}...") + eval_multi_scenarios( + env_name=self.config["env"], + args=eval_args, + vecenv=None, # Let it create its own eval environment + policy=self.uncompiled_policy, # Pass current policy + logger=self.logger, # Pass logger for TensorBoard logging + metric_prefix="validation", # Use validation_ prefix + quiet=True, # Suppress verbose output during inline eval + ) + + return logs + + def _ppo_minibatch_obs(self, obs, idx): + obs_idx = idx.cpu() if obs.device.type == "cpu" and idx.device.type != "cpu" else idx + mb_obs = obs[obs_idx] + device = torch.device(self.config["device"]) + if mb_obs.device != device: + mb_obs = mb_obs.to(device, non_blocking=self.config["cpu_offload"]) + return mb_obs + + def _ppo_loss( + self, + mb_obs, + mb_actions, + mb_logprobs, + mb_values, + mb_returns, + mb_adv, + clip_coef, + vf_clip, + adv_weights=None, + unbiased_std=False, + ): + state = dict(action=mb_actions, lstm_h=None, lstm_c=None) + logits, newvalue = self.policy(mb_obs, state) + _, newlogprob, entropy = pufferlib.pytorch.sample_logits(logits, action=mb_actions) + + newlogprob = newlogprob.view_as(mb_logprobs) + newvalue = newvalue.view_as(mb_returns) + logratio = newlogprob - mb_logprobs + ratio = logratio.exp() + + with torch.no_grad(): + old_approx_kl = (-logratio).mean() + approx_kl = ((ratio - 1) - logratio).mean() + clipfrac = ((ratio - 1.0).abs() > clip_coef).float().mean() + + mb_adv = (mb_adv - mb_adv.mean()) / (mb_adv.std(unbiased=unbiased_std) + 1e-8) + if adv_weights is not None: + mb_adv = adv_weights * mb_adv + + pg_loss1 = -mb_adv * ratio + pg_loss2 = -mb_adv * torch.clamp(ratio, 1 - clip_coef, 1 + clip_coef) + pg_loss = torch.max(pg_loss1, pg_loss2).mean() + + v_clipped = mb_values + torch.clamp(newvalue - mb_values, -vf_clip, vf_clip) + v_loss_unclipped = (newvalue - mb_returns) ** 2 + v_loss_clipped = (v_clipped - mb_returns) ** 2 + v_loss = 0.5 * torch.max(v_loss_unclipped, v_loss_clipped).mean() + entropy_loss = entropy.mean() + loss = pg_loss + self.config["vf_coef"] * v_loss - self.config["ent_coef"] * entropy_loss + + return ( + loss, + newvalue, + ratio, + { + "policy_loss": pg_loss.item(), + "value_loss": v_loss.item(), + "entropy": entropy_loss.item(), + "old_approx_kl": old_approx_kl.item(), + "approx_kl": approx_kl.item(), + "clipfrac": clipfrac.item(), + }, + ) + + def _train_ppo_trajectory(self, losses, profile, epoch): config = self.config device = config["device"] @@ -370,7 +611,7 @@ def train(self): self.ratio[:] = 1 for mb in range(self.total_minibatches): - profile("train_misc", epoch, nest=True) + profile("train_misc", epoch) self.amp_context.__enter__() shape = self.values.shape @@ -387,100 +628,43 @@ def train(self): config["vtrace_c_clip"], ) - profile("train_copy", epoch) adv = advantages.abs().sum(axis=1) prio_weights = torch.nan_to_num(adv**a, 0, 0, 0) prio_probs = (prio_weights + 1e-6) / (prio_weights.sum() + 1e-6) idx = torch.multinomial(prio_probs, self.minibatch_segments) mb_prio = (self.segments * prio_probs[idx, None]) ** -anneal_beta - mb_obs = self.observations[idx] + + profile("train_copy", epoch) + mb_obs = self._ppo_minibatch_obs(self.observations, idx) mb_actions = self.actions[idx] mb_logprobs = self.logprobs[idx] - mb_rewards = self.rewards[idx] - mb_terminals = self.terminals[idx] - mb_truncations = self.truncations[idx] - mb_ratio = self.ratio[idx] mb_values = self.values[idx] mb_returns = advantages[idx] + mb_values - mb_advantages = advantages[idx] + mb_adv = advantages[idx] profile("train_forward", epoch) - if not config["use_rnn"]: - mb_obs = mb_obs.reshape(-1, *self.vecenv.single_observation_space.shape) - - state = dict( - action=mb_actions, - lstm_h=None, - lstm_c=None, - ) - - logits, newvalue = self.policy(mb_obs, state) - actions, newlogprob, entropy = pufferlib.pytorch.sample_logits(logits, action=mb_actions) - - profile("train_misc", epoch) - newlogprob = newlogprob.reshape(mb_logprobs.shape) - logratio = newlogprob - mb_logprobs - ratio = logratio.exp() - self.ratio[idx] = ratio.detach() - - with torch.no_grad(): - old_approx_kl = (-logratio).mean() - approx_kl = ((ratio - 1) - logratio).mean() - clipfrac = ((ratio - 1.0).abs() > config["clip_coef"]).float().mean() - - adv = advantages[idx] - adv = compute_puff_advantage( + loss, newvalue, ratio, stats = self._ppo_loss( + mb_obs, + mb_actions, + mb_logprobs, mb_values, - mb_rewards, - mb_terminals, - ratio, - adv, - config["gamma"], - config["gae_lambda"], - config["vtrace_rho_clip"], - config["vtrace_c_clip"], + mb_returns, + mb_adv, + clip_coef, + vf_clip, + adv_weights=mb_prio, + unbiased_std=True, ) - adv = mb_advantages - adv = mb_prio * (adv - adv.mean()) / (adv.std() + 1e-8) - - # Losses - pg_loss1 = -adv * ratio - pg_loss2 = -adv * torch.clamp(ratio, 1 - clip_coef, 1 + clip_coef) - pg_loss = torch.max(pg_loss1, pg_loss2).mean() - - newvalue = newvalue.view(mb_returns.shape) - v_clipped = mb_values + torch.clamp(newvalue - mb_values, -vf_clip, vf_clip) - v_loss_unclipped = (newvalue - mb_returns) ** 2 - v_loss_clipped = (v_clipped - mb_returns) ** 2 - v_loss = 0.5 * torch.max(v_loss_unclipped, v_loss_clipped).mean() - - entropy_loss = entropy.mean() - - # Get current entropy coefficient - if config["anneal_entropy"]: - # Cosine annealing from initial to 0.0 - current_ent_coef = 0.5 * self.ent_coef_initial * (1 + np.cos(np.pi * self.epoch / self.total_epochs)) - else: - current_ent_coef = config["ent_coef"] - - loss = pg_loss + config["vf_coef"] * v_loss - current_ent_coef * entropy_loss - + self.ratio[idx] = ratio.detach() self.amp_context.__enter__() # TODO: AMP needs some debugging - # This breaks vloss clipping? self.values[idx] = newvalue.detach().float() - # Logging profile("train_misc", epoch) - losses["policy_loss"] += pg_loss.item() / self.total_minibatches - losses["value_loss"] += v_loss.item() / self.total_minibatches - losses["entropy"] += entropy_loss.item() / self.total_minibatches - losses["old_approx_kl"] += old_approx_kl.item() / self.total_minibatches - losses["approx_kl"] += approx_kl.item() / self.total_minibatches - losses["clipfrac"] += clipfrac.item() / self.total_minibatches + for key, value in stats.items(): + losses[key] += value / self.total_minibatches losses["importance"] += ratio.mean().item() / self.total_minibatches - # Learn on accumulated minibatches profile("learn", epoch) loss.backward() if (mb + 1) % self.accumulate_minibatches == 0: @@ -488,56 +672,129 @@ def train(self): self.optimizer.step() self.optimizer.zero_grad() - # Reprioritize experience - profile("train_misc", epoch) - if config["anneal_lr"]: - self.scheduler.step() - y_pred = self.values.flatten() y_true = advantages.flatten() + self.values.flatten() var_y = y_true.var() - explained_var = torch.nan if var_y == 0 else 1 - (y_true - y_pred).var() / var_y - losses["explained_variance"] = explained_var.item() + return float("nan") if var_y == 0 else (1 - (y_true - y_pred).var() / var_y).item() - profile.end() - logs = None - self.epoch += 1 - done_training = self.global_step >= config["total_timesteps"] - if done_training or self.global_step == 0 or time.time() > self.last_log_time + 0.25: - logs = self.mean_and_log() - self.losses = losses - self.print_dashboard() - self.stats = defaultdict(list) - self.last_log_time = time.time() - self.last_log_step = self.global_step - profile.clear() + def _train_ppo_transition(self, losses, profile, epoch): + config = self.config + device = config["device"] - if self.epoch % config["checkpoint_interval"] == 0 or done_training: - self.save_checkpoint() - self.msg = f"Checkpoint saved at update {self.epoch}" + clip_coef = config["clip_coef"] + vf_clip = config["vf_clip_coef"] - if (self.epoch - 1) % self.config["eval"]["eval_interval"] == 0 or done_training: - human_replay_eval = self.config["eval"]["human_replay_eval"] - self_play_eval = self.config["eval"]["self_play_eval"] - - self.evaluator = Evaluator(self.full_args, self.logger) - if human_replay_eval: - self.evaluator.hr_env = load_env("puffer_drive", self.evaluator.hr_eval_config) - self.evaluator.rollout(self.uncompiled_policy, mode="human_replay") - self.evaluator.hr_env.close() - self.evaluator.log_videos(eval_mode="human_replay", epoch=self.epoch) - if self_play_eval: - self.evaluator.sp_env = load_env("puffer_drive", self.evaluator.sp_eval_config) - self.evaluator.rollout(self.uncompiled_policy, mode="self_play") - self.evaluator.sp_env.close() - self.evaluator.log_videos(eval_mode="self_play", epoch=self.epoch) - if human_replay_eval or self_play_eval: - self.evaluator.log_stats() - - del self.evaluator - - if self.config["eval"]["wosac_realism_eval"]: - pufferlib.utils.run_wosac_eval_in_subprocess(self.config, self.logger, self.global_step) + masks = self.masks.bool() + terminals = torch.maximum(self.terminals, (~masks).float()) + advantages = compute_puff_advantage( + self.values, + self.rewards, + terminals, + torch.ones_like(self.values, device=device), + torch.zeros_like(self.values, device=device), + config["gamma"], + config["gae_lambda"], + 1.0, + 1.0, + ) + advantages = advantages.masked_fill(~masks, 0.0) + returns = advantages + self.values + + flat_advantages_f = advantages.reshape(-1) + flat_masks_f = masks.reshape(-1).bool() + total_transitions = flat_masks_f.numel() + valid_idx = torch.nonzero(flat_masks_f, as_tuple=False).flatten() + + filter_metrics = { + "masked_fraction": 1.0 - (valid_idx.numel() / max(total_transitions, 1)), + "kept_fraction": 0.0, + "filtered_fraction": 1.0, + } + + ewma_beta = config["adv_filter_ewma_beta"] + threshold_scale = config["adv_filter_threshold_scale"] + valid_abs_adv = flat_advantages_f[valid_idx].abs() + current_max = valid_abs_adv.max().item() if valid_abs_adv.numel() > 0 else 0.0 + self.ema_max = current_max if epoch == 0 else ewma_beta * current_max + (1 - ewma_beta) * self.ema_max + threshold = threshold_scale * self.ema_max + + keep_mask = valid_abs_adv >= threshold + keep_idx = valid_idx[keep_mask] + num_valid, num_kept = valid_idx.numel(), keep_idx.numel() + + filter_metrics["kept_fraction"] = num_kept / max(num_valid, 1) + filter_metrics["filtered_fraction"] = 1.0 - filter_metrics["kept_fraction"] + + losses["filter_threshold"] = threshold + losses["ema_max"] = self.ema_max + losses.update(filter_metrics) + + obs_shape = self.vecenv.single_observation_space.shape + flat_obs = self.observations.reshape(-1, *obs_shape) + flat_actions = self.actions.reshape(-1, *self.actions.shape[2:]) + flat_logprobs = self.logprobs.reshape(-1) + flat_values = self.values.reshape(-1) + flat_returns = returns.reshape(-1) + flat_advantages = advantages.reshape(-1) + + self.optimizer.zero_grad() + total_minibatches = 0 + pending_minibatches = 0 + + for _ in range(config["update_epochs"]): + permutation = keep_idx[torch.randperm(keep_idx.numel(), device=keep_idx.device)] + for start in range(0, permutation.numel(), self.minibatch_size): + profile("train_copy", epoch) + mb_idx = permutation[start : start + self.minibatch_size] + mb_obs = self._ppo_minibatch_obs(flat_obs, mb_idx) + mb_actions = flat_actions[mb_idx] + mb_logprobs = flat_logprobs[mb_idx] + mb_values = flat_values[mb_idx] + mb_returns = flat_returns[mb_idx] + mb_adv = flat_advantages[mb_idx] + + profile("train_forward", epoch) + loss, _, _, stats = self._ppo_loss( + mb_obs, + mb_actions, + mb_logprobs, + mb_values, + mb_returns, + mb_adv, + clip_coef, + vf_clip, + unbiased_std=False, + ) + self.amp_context.__enter__() # TODO: AMP needs some debugging + + profile("train_misc", epoch) + for key, value in stats.items(): + losses[key] += value + + profile("learn", epoch) + loss.backward() + total_minibatches += 1 + pending_minibatches += 1 + + if pending_minibatches >= self.accumulate_minibatches: + torch.nn.utils.clip_grad_norm_(self.policy.parameters(), config["max_grad_norm"]) + self.optimizer.step() + self.optimizer.zero_grad() + pending_minibatches = 0 + + if pending_minibatches > 0: + torch.nn.utils.clip_grad_norm_(self.policy.parameters(), config["max_grad_norm"]) + self.optimizer.step() + self.optimizer.zero_grad() + + if total_minibatches > 0: + for key in ("policy_loss", "value_loss", "entropy", "old_approx_kl", "approx_kl", "clipfrac"): + losses[key] /= total_minibatches + + y_pred = flat_values[valid_idx] + y_true = flat_returns[valid_idx] + var_y = y_true.var(unbiased=False) + return float("nan") if var_y == 0 else (1 - (y_true - y_pred).var(unbiased=False) / var_y).item() def mean_and_log(self): config = self.config @@ -556,24 +813,18 @@ def mean_and_log(self): "SPS": dist_sum(self.sps, device), "agent_steps": agent_steps, "uptime": time.time() - self.start_time, - "epoch": int(dist_sum(self.epoch, device)), + "epoch": int(dist_sum(self.epoch, device)), # VB Why it is a sum ? "learning_rate": self.optimizer.param_groups[0]["lr"], - "ent_coef": ( - 0.5 * self.ent_coef_initial * (1 + np.cos(np.pi * self.epoch / self.total_epochs)) - if config["anneal_entropy"] - else config["ent_coef"] - ), **{f"environment/{k}": v for k, v in self.stats.items()}, **{f"losses/{k}": v for k, v in self.losses.items()}, **{f"performance/{k}": v["elapsed"] for k, v in self.profile}, + # **{f'environment/{k}': dist_mean(v, device) for k, v in self.stats.items()}, + # **{f'losses/{k}': dist_mean(v, device) for k, v in self.losses.items()}, + # **{f'performance/{k}': dist_sum(v['elapsed'], device) for k, v in self.profile}, } - if torch.distributed.is_initialized(): - if torch.distributed.get_rank() != 0: - self.logger.log(logs, agent_steps) - return logs - else: - return None + if torch.distributed.is_initialized() and torch.distributed.get_rank() != 0: + return None self.logger.log(logs, agent_steps) return logs @@ -581,24 +832,28 @@ def mean_and_log(self): def close(self): self.vecenv.close() self.utilization.stop() + if torch.distributed.is_initialized() and torch.distributed.get_rank() != 0: + return model_path = self.save_checkpoint() run_id = self.logger.run_id - path = os.path.join(self.config["data_dir"], f"{self.config['env']}_{run_id}.pt") + run_dir = os.path.join(self.config["data_dir"], f"{self.config['env']}_{run_id}") + path = os.path.join(run_dir, f"{self.config['env']}_{run_id}.pt") shutil.copy(model_path, path) return path def save_checkpoint(self): - if torch.distributed.is_initialized(): - if torch.distributed.get_rank() != 0: - return + if torch.distributed.is_initialized() and torch.distributed.get_rank() != 0: + return run_id = self.logger.run_id path = os.path.join(self.config["data_dir"], f"{self.config['env']}_{run_id}") if not os.path.exists(path): os.makedirs(path) + models_dir = os.path.join(path, "models") + os.makedirs(models_dir, exist_ok=True) model_name = f"model_{self.config['env']}_{self.epoch:06d}.pt" - model_path = os.path.join(path, model_name) + model_path = os.path.join(models_dir, model_name) if os.path.exists(model_path): return model_path @@ -615,15 +870,27 @@ def save_checkpoint(self): state_path = os.path.join(path, "trainer_state.pt") torch.save(state, state_path + ".tmp") os.rename(state_path + ".tmp", state_path) + + current_score = self.last_stats.get("puffer_score", self.last_stats.get("score", -float("inf"))) + + if current_score > self.best_score: + self.best_score = current_score + + best_state_file = os.path.join(path, f"best_models/best_trainer_state_{self.epoch:06d}.pt") + os.makedirs(os.path.dirname(best_state_file), exist_ok=True) + shutil.copy(model_path, best_state_file) + print(f"New best model saved at epoch {self.epoch} with puffer_score {self.best_score:.4f}") + return model_path - def print_dashboard(self, clear=False, idx=[0], c1="[cyan]", c2="[white]", b1="[bright_cyan]", b2="[bright_white]"): + def print_dashboard( + self, clear=False, idx=[0], c1="[cyan]", c2="[dim default]", b1="[bright_cyan]", b2="[default]" + ): config = self.config sps = dist_sum(self.sps, config["device"]) agent_steps = dist_sum(self.global_step, config["device"]) - if torch.distributed.is_initialized(): - if torch.distributed.get_rank() != 0: - return + if torch.distributed.is_initialized() and torch.distributed.get_rank() != 0: + return profile = self.profile console = Console() @@ -647,19 +914,19 @@ def print_dashboard(self, clear=False, idx=[0], c1="[cyan]", c2="[white]", b1="[ idx[0] = (idx[0] - 1) % 10 s = Table(box=None, expand=True) - remaining = "A hair past a freckle" + remaining = f"{b2}A hair past a freckle{c2}" if sps != 0: remaining = duration((config["total_timesteps"] - agent_steps) / sps, b2, c2) s.add_column(f"{c1}Summary", justify="left", vertical="top", width=10) s.add_column(f"{c1}Value", justify="right", vertical="top", width=14) - s.add_row(f"{c2}Env", f"{b2}{config['env']}") - s.add_row(f"{c2}Params", abbreviate(self.model_size, b2, c2)) - s.add_row(f"{c2}Steps", abbreviate(agent_steps, b2, c2)) - s.add_row(f"{c2}SPS", abbreviate(sps, b2, c2)) - s.add_row(f"{c2}Epoch", f"{b2}{self.epoch}") - s.add_row(f"{c2}Uptime", duration(self.uptime, b2, c2)) - s.add_row(f"{c2}Remaining", remaining) + s.add_row(f"{b2}Env", f"{b2}{config['env']}") + s.add_row(f"{b2}Params", abbreviate(self.model_size, b2, c2)) + s.add_row(f"{b2}Steps", abbreviate(agent_steps, b2, c2)) + s.add_row(f"{b2}SPS", abbreviate(sps, b2, c2)) + s.add_row(f"{b2}Epoch", f"{b2}{self.epoch}") + s.add_row(f"{b2}Uptime", duration(self.uptime, b2, c2)) + s.add_row(f"{b2}Remaining", remaining) delta = profile.eval["buffer"] + profile.train["buffer"] p = Table(box=None, expand=True, show_header=False) @@ -667,15 +934,15 @@ def print_dashboard(self, clear=False, idx=[0], c1="[cyan]", c2="[white]", b1="[ p.add_column(f"{c1}Time", justify="right", width=8) p.add_column(f"{c1}%", justify="right", width=4) p.add_row(*fmt_perf("Evaluate", b1, delta, profile.eval, b2, c2)) - p.add_row(*fmt_perf(" Forward", c2, delta, profile.eval_forward, b2, c2)) - p.add_row(*fmt_perf(" Env", c2, delta, profile.env, b2, c2)) - p.add_row(*fmt_perf(" Copy", c2, delta, profile.eval_copy, b2, c2)) - p.add_row(*fmt_perf(" Misc", c2, delta, profile.eval_misc, b2, c2)) + p.add_row(*fmt_perf(" Forward", b2, delta, profile.eval_forward, b2, c2)) + p.add_row(*fmt_perf(" Env", b2, delta, profile.env, b2, c2)) + p.add_row(*fmt_perf(" Copy", b2, delta, profile.eval_copy, b2, c2)) + p.add_row(*fmt_perf(" Misc", b2, delta, profile.eval_misc, b2, c2)) p.add_row(*fmt_perf("Train", b1, delta, profile.train, b2, c2)) - p.add_row(*fmt_perf(" Forward", c2, delta, profile.train_forward, b2, c2)) - p.add_row(*fmt_perf(" Learn", c2, delta, profile.learn, b2, c2)) - p.add_row(*fmt_perf(" Copy", c2, delta, profile.train_copy, b2, c2)) - p.add_row(*fmt_perf(" Misc", c2, delta, profile.train_misc, b2, c2)) + p.add_row(*fmt_perf(" Forward", b2, delta, profile.train_forward, b2, c2)) + p.add_row(*fmt_perf(" Learn", b2, delta, profile.learn, b2, c2)) + p.add_row(*fmt_perf(" Copy", b2, delta, profile.train_copy, b2, c2)) + p.add_row(*fmt_perf(" Misc", b2, delta, profile.train_misc, b2, c2)) l = Table( box=None, @@ -684,7 +951,7 @@ def print_dashboard(self, clear=False, idx=[0], c1="[cyan]", c2="[white]", b1="[ l.add_column(f"{c1}Losses", justify="left", width=16) l.add_column(f"{c1}Value", justify="right", width=8) for metric, value in self.losses.items(): - l.add_row(f"{c2}{metric}", f"{b2}{value:.3f}") + l.add_row(f"{b2}{metric}", f"{b2}{value:.3f}") monitor = Table(box=None, expand=True, pad_edge=False) monitor.add_row(s, p, l) @@ -705,13 +972,16 @@ def print_dashboard(self, clear=False, idx=[0], c1="[cyan]", c2="[white]", b1="[ self.last_stats = self.stats for metric, value in (self.stats or self.last_stats).items(): + if metric in HIDDEN_DASHBOARD_METRICS: + continue + try: # Discard non-numeric values int(value) except: continue u = left if i % 2 == 0 else right - u.add_row(f"{c2}{metric}", f"{b2}{value:.3f}") + u.add_row(f"{b2}{metric}", f"{b2}{value:.3f}") i += 1 if i == 30: break @@ -752,15 +1022,15 @@ def compute_puff_advantage( def abbreviate(num, b2, c2): if num < 1e3: - return str(num) + return f"{b2}{num}{c2}" elif num < 1e6: - return f"{num / 1e3:.1f}K" + return f"{b2}{num / 1e3:.1f}{c2}K" elif num < 1e9: - return f"{num / 1e6:.1f}M" + return f"{b2}{num / 1e6:.1f}{c2}M" elif num < 1e12: - return f"{num / 1e9:.1f}B" + return f"{b2}{num / 1e9:.1f}{c2}B" else: - return f"{num / 1e12:.2f}T" + return f"{b2}{num / 1e12:.2f}{c2}T" def duration(seconds, b2, c2): @@ -807,11 +1077,12 @@ def __getattr__(self, name): return self.profiles[name] def __call__(self, name, epoch, nest=False): - if epoch % self.frequency != 0: + # Skip profiling the first few epochs, which are noisy due to setup + if (epoch + 1) % self.frequency != 0: return - # if torch.cuda.is_available(): - # torch.cuda.synchronize() + if torch.cuda.is_available(): + torch.cuda.synchronize() tick = time.time() if len(self.stack) != 0 and not nest: @@ -823,12 +1094,13 @@ def __call__(self, name, epoch, nest=False): def pop(self, end): profile = self.profiles[self.stack.pop()] delta = end - profile["start"] - profile["elapsed"] += delta profile["delta"] += delta + # Multiply delta by freq to account for skipped epochs + profile["elapsed"] += delta * self.frequency def end(self): - # if torch.cuda.is_available(): - # torch.cuda.synchronize() + if torch.cuda.is_available(): + torch.cuda.synchronize() end = time.time() for i in range(len(self.stack)): @@ -863,9 +1135,13 @@ def run(self): time.sleep(self.delay) continue - self.gpu_util.append(torch.cuda.utilization()) - free, total = torch.cuda.mem_get_info() - self.gpu_mem.append(100 * (total - free) / total) + try: + self.gpu_util.append(torch.cuda.utilization()) + free, total = torch.cuda.mem_get_info() + self.gpu_mem.append(100 * (total - free) / total) + except (ModuleNotFoundError, RuntimeError): + self.gpu_util.append(0) + self.gpu_mem.append(0) else: self.gpu_util.append(0) self.gpu_mem.append(0) @@ -876,32 +1152,35 @@ def stop(self): self.stopped = True -def downsample(arr, m): - if len(arr) < m: - return arr +def downsample(data_list, num_points): + if not data_list or num_points <= 0: + return [] + if num_points == 1: + return [data_list[-1]] + if len(data_list) <= num_points: + return data_list + + last = data_list[-1] + data_list = data_list[:-1] - if m == 0: - return [arr[-1]] + data_np = np.array(data_list) + num_points -= 1 # one down for the last one - orig_arr = arr - last = arr[-1] - arr = arr[:-1] - arr = np.array(arr) - n = len(arr) - n = (n // m) * m - arr = arr[-n:] - downsampled = arr.reshape(m, -1).mean(axis=1) - return np.concatenate([downsampled, [last]]) + n = (len(data_np) // num_points) * num_points + data_np = data_np[-n:] if n > 0 else data_np + downsampled = data_np.reshape(num_points, -1).mean(axis=1) + + return downsampled.tolist() + [last] class NoLogger: - def __init__(self, args): - self.run_id = str(int(100 * time.time())) + def __init__(self, args, run_id=None): + self.run_id = run_id or str(int(time.time())) def log(self, logs, step): pass - def close(self, model_path): + def close(self, model_path, early_stop): pass @@ -925,13 +1204,19 @@ def __init__(self, args, load_id=None, mode="async"): self.neptune = neptune for k, v in pufferlib.unroll_nested_dict(args): neptune[k].append(v) + self.should_upload_model = not args["no_model_upload"] def log(self, logs, step): for k, v in logs.items(): self.neptune[k].append(v, step=step) - def close(self, model_path): + def upload_model(self, model_path): self.neptune["model"].track_files(model_path) + + def close(self, model_path, early_stop): + self.neptune["early_stop"] = early_stop + if self.should_upload_model: + self.upload_model(model_path) self.neptune.stop() def download(self): @@ -947,23 +1232,30 @@ def __init__(self, args, load_id=None, resume="allow"): id=load_id or wandb.util.generate_id(), project=args["wandb_project"], group=args["wandb_group"], + name=args.get("wandb_name"), allow_val_change=True, save_code=False, resume=resume, config=args, - name=args.get("wandb_name"), tags=[args["tag"]] if args["tag"] is not None else [], + settings=wandb.Settings(console="off"), # stop sending dashboard to wandb ) self.wandb = wandb self.run_id = wandb.run.id + self.should_upload_model = not args["no_model_upload"] def log(self, logs, step): self.wandb.log(logs, step=step) - def close(self, model_path): + def upload_model(self, model_path): artifact = self.wandb.Artifact(self.run_id, type="model") artifact.add_file(model_path) self.wandb.run.log_artifact(artifact) + + def close(self, model_path, early_stop): + self.wandb.run.summary["early_stop"] = early_stop + if self.should_upload_model: + self.upload_model(model_path) self.wandb.finish() def download(self): @@ -973,9 +1265,118 @@ def download(self): return f"{data_dir}/{model_file}" -def train(env_name, args=None, vecenv=None, policy=None, logger=None): +class TensorBoardLogger: + def __init__(self, run_id, experiment_dir): + try: + from torch.utils.tensorboard import SummaryWriter + except ImportError: + raise ImportError("TensorBoardLogger requires tensorboard.") + + self.run_id = run_id + local_log_dir = experiment_dir + os.makedirs(local_log_dir, exist_ok=True) + print(f"[TensorBoardLogger] Logging locally to: {local_log_dir}") + self.local_writer = SummaryWriter(log_dir=local_log_dir) + + def log(self, logs, step): + for key, value in logs.items(): + if isinstance(value, (int, float)): + self.local_writer.add_scalar(key, value, step) + + def close(self, model_path, early_stop): + self.local_writer.close() + + +def _get_git_metadata(): + git_metadata = { + "commit_hash": None, + "commit_message": None, + "is_dirty": None, + } + + try: + repo_root = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + git_metadata["commit_hash"] = subprocess.check_output( + ["git", "rev-parse", "HEAD"], + cwd=repo_root, + stderr=subprocess.DEVNULL, + text=True, + ).strip() + git_metadata["commit_message"] = subprocess.check_output( + ["git", "log", "-1", "--pretty=%s"], + cwd=repo_root, + stderr=subprocess.DEVNULL, + text=True, + ).strip() + git_metadata["is_dirty"] = bool( + subprocess.check_output( + ["git", "status", "--porcelain", "--untracked-files=no"], + cwd=repo_root, + stderr=subprocess.DEVNULL, + text=True, + ).strip() + ) + except (OSError, subprocess.SubprocessError): + pass + + return git_metadata + + +def _save_experiment_config(args, path): + import yaml + import json + + experiment_dir = path + os.makedirs(experiment_dir, exist_ok=True) + + # Save config as yaml + config_yaml_path = os.path.join(experiment_dir, "config.yaml") + with open(config_yaml_path, "w") as f: + # Convert defaultdict to dict for cleaner output + config = json.loads(json.dumps(args)) + config["git"] = _get_git_metadata() + yaml.dump(config, f) + + +def train(env_name, args=None, vecenv=None, policy=None, logger=None, early_stop_fn=None): args = args or load_config(env_name) + # Fine-tuning: reload network, observation configuration from config.yaml and override the args --> only change new reward / new maps / new simulation mode + if args["load_model_path"]: + experiment_dir = os.path.dirname(args["load_model_path"]) + config_yaml_path = os.path.join(experiment_dir, "config.yaml") + KEYS_OF_INTEREST = { + "action_type", + "dynamics_model", + "target_type", + "num_target_waypoints", + "reward_conditioning", + "reward_randomization", + "trajectory_prediction_length", + "num_trajectory_scaling_factors", + "trajectory_scaling_factors", + "max_boundary_segment_observations", + "max_lane_segment_observations", + "max_partner_observations", + "max_traffic_light_observations", + "max_stop_sign_observations", + } + if os.path.exists(config_yaml_path): + print(f"Found config.yaml at {config_yaml_path}. Merging with defaults...") + with open(config_yaml_path, "r") as f: + yaml_config = yaml.safe_load(f) + + # Override Policy and RNN dimensions from model config + for section in ["policy", "rnn"]: + if section in yaml_config and isinstance(yaml_config[section], dict): + for k, v in yaml_config[section].items(): + args[section][k] = v + # Override ENV parameters for observation size from model config + if "env" in yaml_config and isinstance(yaml_config["env"], dict): + for k, v in yaml_config["env"].items(): + if k in KEYS_OF_INTEREST: + args["env"][k] = v + # Assume TorchRun DDP is used if LOCAL_RANK is set if "LOCAL_RANK" in os.environ: world_size = int(os.environ.get("WORLD_SIZE", 1)) @@ -987,6 +1388,10 @@ def train(env_name, args=None, vecenv=None, policy=None, logger=None): torch.cuda.set_device(local_rank) os.environ["CUDA_VISIBLE_DEVICES"] = str(local_rank) + train_seed = args["train"]["seed"] + if train_seed is None: + train_seed = time.time_ns() & 0xFFFFFFFF + torch.manual_seed(train_seed) vecenv = vecenv or load_env(env_name, args) policy = policy or load_policy(args, vecenv, env_name) @@ -1006,31 +1411,72 @@ def train(env_name, args=None, vecenv=None, policy=None, logger=None): logger = NeptuneLogger(args) elif args["wandb"]: logger = WandbLogger(args) + elif args["tb"]: + date_time = datetime.now().strftime("%Y%m%d-%H%M%S") + experiment_dir = os.path.join(args["train"]["data_dir"], rf"{env_name}_" + date_time) + logger = TensorBoardLogger( + run_id=date_time, + experiment_dir=experiment_dir, + ) train_config = dict(**args["train"], env=env_name, eval=args.get("eval", {})) - pufferl = PuffeRL(train_config, vecenv, policy, logger, full_args=args) + pufferl = PuffeRL(train_config, vecenv, policy, logger) + + path = os.path.join(args["train"]["data_dir"], f"{env_name}_{pufferl.logger.run_id}") + _save_experiment_config(args, path) + # Sweep needs data for early stopped runs, so send data when steps > 100M + logging_threshold = min(0.20 * train_config["total_timesteps"], 100_000_000) all_logs = [] + while pufferl.global_step < train_config["total_timesteps"]: if train_config["device"] == "cuda": torch.compiler.cudagraph_mark_step_begin() - pufferl.evaluate() + try: + pufferl.evaluate() + except Exception: + pufferl.vecenv.close() + pufferl.utilization.stop() + if torch.distributed.is_initialized(): + torch.distributed.destroy_process_group() + raise if train_config["device"] == "cuda": torch.compiler.cudagraph_mark_step_begin() - logs = pufferl.train() + try: + logs = pufferl.train() + except Exception: + pufferl.vecenv.close() + pufferl.utilization.stop() + if torch.distributed.is_initialized(): + torch.distributed.destroy_process_group() + raise if logs is not None: - if pufferl.global_step > 0.20 * train_config["total_timesteps"]: + should_stop_early = False + if early_stop_fn is not None: + should_stop_early = early_stop_fn(logs) + # This is hacky, but need to see if threshold looks reasonable + if "early_stop_threshold" in logs: + pufferl.logger.log( + {"environment/early_stop_threshold": logs["early_stop_threshold"]}, logs["agent_steps"] + ) + + if pufferl.global_step > logging_threshold: all_logs.append(logs) + if should_stop_early: + model_path = pufferl.close() + pufferl.logger.close(model_path, early_stop=True) + return all_logs + # Final eval. You can reset the env here, but depending on # your env, this can skew data (i.e. you only collect the shortest # rollouts within a fixed number of epochs) - i = 0 - stats = {} - while i < 32 or not stats: - stats = pufferl.evaluate() - i += 1 + # i = 0 + # stats = {} + # while i < 32 or not stats: + # stats = pufferl.evaluate() + # i += 1 logs = pufferl.mean_and_log() if logs is not None: @@ -1038,7 +1484,7 @@ def train(env_name, args=None, vecenv=None, policy=None, logger=None): pufferl.print_dashboard() model_path = pufferl.close() - pufferl.logger.close(model_path) + pufferl.logger.close(model_path, early_stop=False) return all_logs @@ -1099,18 +1545,47 @@ def eval(env_name, args=None, vecenv=None, policy=None): vecenv.close() return results_dict + elif human_replay_enabled: + args["env"]["map_dir"] = args["eval"]["map_dir"] + dataset_name = args["env"]["map_dir"].split("/")[-1] + print(f"Running human replay evaluation with {dataset_name} dataset.\n") + from pufferlib.ocean.benchmark.evaluator import HumanReplayEvaluator + + backend = args["eval"].get("backend", "PufferEnv") + args["env"]["map_dir"] = args["eval"]["map_dir"] + args["env"]["num_agents"] = args["eval"]["human_replay_num_agents"] + + args["vec"] = dict(backend=backend, num_envs=1) + args["env"]["control_mode"] = args["eval"]["human_replay_control_mode"] + args["env"]["episode_length"] = 91 # WOMD scenario length + + vecenv = vecenv or load_env(env_name, args) + policy = policy or load_policy(args, vecenv, env_name) + + print(f"Effective number of scenarios used: {len(vecenv.driver_env.agent_offsets) - 1}") + + evaluator = HumanReplayEvaluator(args) + + # Run rollouts with human replays + results = evaluator.rollout(args, vecenv, policy) + + import json + + print("HUMAN_REPLAY_METRICS_START") + print(json.dumps(results)) + print("HUMAN_REPLAY_METRICS_END") + + return results + else: # Standard evaluation: Render backend = args["vec"]["backend"] if backend != "PufferEnv": backend = "Serial" args["vec"] = dict(backend=backend, num_envs=1) - - # Create environment and policy vecenv = vecenv or load_env(env_name, args) policy = policy or load_policy(args, vecenv, env_name) - # Reset environment ob, info = vecenv.reset() driver = vecenv.driver_env num_agents = vecenv.observation_space.shape[0] @@ -1123,12 +1598,23 @@ def eval(env_name, args=None, vecenv=None, policy=None): lstm_c=torch.zeros(num_agents, policy.hidden_size, device=device), ) - if driver.render_mode == 1: - max_frames = 91 - frame_count = 0 - + frames = [] while True: - driver.render() + render = driver.render() + if len(frames) < args["save_frames"]: + frames.append(render) + + # Screenshot Ocean envs with F12, gifs with control + F12 + if driver.render_mode == "ansi": + print("\033[0;0H" + render + "\n") + time.sleep(1 / args["fps"]) + elif driver.render_mode == "rgb_array": + pass + # import cv2 + # render = cv2.cvtColor(render, cv2.COLOR_RGB2BGR) + # cv2.imshow('frame', render) + # cv2.waitKey(1) + # time.sleep(1/args['fps']) with torch.no_grad(): ob = torch.as_tensor(ob).to(device) @@ -1139,20 +1625,623 @@ def eval(env_name, args=None, vecenv=None, policy=None): if isinstance(logits, torch.distributions.Normal): action = np.clip(action, vecenv.action_space.low, vecenv.action_space.high) - ob, reward, done, truncated, info = vecenv.step(action) + step_result = vecenv.step(action) + ob = step_result[0] + step_info = step_result[4] if len(step_result) > 4 else [] + for info_item in step_info: + if isinstance(info_item, dict): + print("\n=== Episode Metrics ===") + for k, v in sorted(info_item.items()): + if isinstance(v, (int, float)): + print(f" {k}: {v:.4f}") + print("=======================\n") + + if len(frames) > 0 and len(frames) == args["save_frames"]: + import imageio + + imageio.mimsave(args["gif_path"], frames, fps=args["fps"], loop=0) + frames.append("Done") + + +def load_eval_multi_scenarios_config(env_name, model_path=None, eval_overrides=None): + """Load config for evaluation, merging experiment YAML with defaults.""" + args = load_config(env_name) + if model_path: + experiment_dir = os.path.dirname(os.path.dirname(model_path)) + config_yaml_path = os.path.join(experiment_dir, "config.yaml") + EXCLUDE_KEYS = eval_overrides["env"].keys() + # Override Policy and RNN dimensions from training config + if os.path.exists(config_yaml_path): + print(f"Found config.yaml at {config_yaml_path}. Merging with defaults...") + with open(config_yaml_path, "r") as f: + yaml_config = yaml.safe_load(f) + + for section in ["env", "policy", "rnn"]: + if section in yaml_config and isinstance(yaml_config[section], dict): + for k, v in yaml_config[section].items(): + if k not in EXCLUDE_KEYS: + args[section][k] = v + + # Also copy root-level keys like rnn_name, policy_name + for key in ["rnn_name", "policy_name"]: + if key in yaml_config: + args[key] = yaml_config[key] + + # Update use_rnn based on rnn_name + args["train"]["use_rnn"] = args["rnn_name"] is not None + + # Override env parameters from evaluation config + if eval_overrides: + for section, section_overrides in eval_overrides.items(): + if isinstance(section_overrides, dict): + for k, v in section_overrides.items(): + args[section][k] = v + else: + args[section] = section_overrides + + return args - if driver.render_mode == 1: - frame_count += 1 - if frame_count >= max_frames or done.all() or truncated.all(): - break - vecenv.close() +def build_eval_overrides(simulation_mode, num_agents, num_scenarios, map_dir=None, num_carla_maps=6): + """Build evaluation overrides for a given simulation mode. + + Args: + simulation_mode: "gigaflow" or "replay" + num_agents: agent slot budget for evaluation + map_dir: optional map directory, uses config value if not provided + """ + # Common reward coefficients (same for both modes) + common_env = { + "eval_mode": 1, + "collision_behavior": 1, + "offroad_behavior": 1, + "reward_randomization": False, + "min_agents_per_env": 30, + "max_agents_per_env": 30, + "reward_vehicle_collision": 3.0, + "reward_offroad_collision": 3.0, + "reward_ade": 0.0, + "reward_goal": 1.0, + "reward_overspeed": 0.05, + "reward_comfort": 0.05, + "reward_velocity": 0.0025, + "reward_lane_align": 0.025, + "reward_lane_center": 0.0038, + "reward_timestep": 0.000025, + } + + if simulation_mode == "gigaflow": + eval_overrides = { + "env": { + **common_env, + "simulation_mode": "gigaflow", + "resample_frequency": 500, + "scenario_length": 500, + "map_dir": "pufferlib/resources/drive/binaries/carla", + "num_maps": num_carla_maps, + "num_agents": num_agents, + "termination_mode": 0.0, + } + } + elif simulation_mode == "replay": + eval_overrides = { + "env": { + **common_env, + "simulation_mode": "replay", + "resample_frequency": 91, + "scenario_length": 91, + "map_dir": "pufferlib/resources/drive/binaries/eval", + "num_maps": num_scenarios, + "num_agents": num_agents, + "reward_traffic_light_violation": 1.0, + "termination_mode": 0.0, + } + } + else: + raise ValueError(f"Invalid simulation_mode: {simulation_mode}. Must be 'gigaflow' or 'replay'.") + + return eval_overrides + + +def verify_scenario_coverage(csv_path: str, num_scenarios: int) -> dict: + """ + Verify that episode_metrics.csv contains all expected scenarios. + + Args: + csv_path: Path to episode_metrics.csv + num_scenarios: Expected number of scenarios (e.g., 1000) + + Returns: + dict with keys: + - complete: bool - True if all scenarios present + - expected_count: number of expected scenarios + - found_count: number of unique scenarios found + - missing: sorted list of missing map names + - extra: sorted list of unexpected map names + - duplicates: dict mapping map_name -> count (if >1) + """ + df = pd.read_csv(csv_path) + + # Expected: map_000, map_001, ..., map_{num_scenarios-1} + expected = {f"map_{i:03d}" for i in range(num_scenarios)} + found = set(df["map_name"].unique()) + + missing = expected - found + extra = found - expected + + # Check for duplicates + counts = df["map_name"].value_counts() + duplicates = {name: count for name, count in counts.items() if count > 1} + + complete = len(missing) == 0 + + return { + "complete": complete, + "expected_count": num_scenarios, + "found_count": len(found), + "missing": sorted(missing), + "extra": sorted(extra), + "duplicates": duplicates, + } + + +def verify_scenario_coverage_gigaflow(csv_path: str, num_scenarios: int) -> dict: + """ + Verify gigaflow evaluation CSV: maps repeat across scenarios, so check total + row count rather than unique map names. + """ + df = pd.read_csv(csv_path) + total_rows = len(df) + complete = total_rows == num_scenarios + return { + "complete": complete, + "expected_count": num_scenarios, + "found_count": total_rows, + } + + +# Helper functions for eval_multi_scenarios and eval_multi_scenarios_render +def _export_metrics(global_infos, eval_folder, num_scenarios, quiet, verify_coverage=False, simulation_mode="replay"): + """Export episode and summary CSVs, return avg_infos dict.""" + # Episode Metrics + try: + df_episodes = pd.DataFrame(global_infos) + first_cols = ["episode_id", "map_name"] + other_cols = [col for col in df_episodes.columns if col not in first_cols] + new_col_order = first_cols + other_cols + df_episodes = df_episodes[new_col_order] + + if verify_coverage: + df_episodes = df_episodes.sort_values(by=["map_name", "episode_id"]) + + episode_csv_path = os.path.join(eval_folder, "episode_metrics.csv") + df_episodes.to_csv(episode_csv_path, index=False) + if not quiet: + print(f"\n✅ Per-episode metrics exported to {episode_csv_path}") + + if verify_coverage: + if simulation_mode == "gigaflow": + result = verify_scenario_coverage_gigaflow(episode_csv_path, num_scenarios) + if not quiet: + if result["complete"]: + print(f"✅ All {num_scenarios} episodes present in CSV") + else: + print( + f"⚠️ Episode count mismatch: expected {result['expected_count']}, found {result['found_count']}" + ) + else: + result = verify_scenario_coverage(episode_csv_path, num_scenarios) + if not quiet: + if result["complete"]: + print(f"✅ All {num_scenarios} scenarios present in CSV") + else: + print(f"⚠️ Scenario coverage incomplete:") + print(f" Expected: {result['expected_count']}, Found: {result['found_count']}") + if result["missing"]: + print(f" Missing ({len(result['missing'])}): {result['missing']}") + if result["extra"]: + print(f" Extra: {result['extra'][:10]}...") + if result["duplicates"]: + print(f" Duplicates: {len(result['duplicates'])} scenarios have multiple entries") + for name, count in sorted(result["duplicates"].items()): + print(f" {name}: {count} entries") + except Exception as e: + print(f"\n⚠️ Could not export per-episode CSV. Error: {e}") + print("Global infos data:", global_infos) + + # Evaluation average metrics + avg_infos = {} + for k, v in global_infos.items(): + if k == "num_scenarios": + avg_infos[k] = np.sum(v) + elif v and isinstance(v[0], numbers.Number): + avg_infos[k] = np.mean(v) + df_summary = pd.DataFrame(list(avg_infos.items()), columns=["Metric", "Average"]) + summary_csv_path = os.path.join(eval_folder, "evaluation_summary.csv") + df_summary.to_csv(summary_csv_path, index=False) + if not quiet: + print(f"\n✅ Average results exported to {summary_csv_path}") + print(df_summary.to_string(index=False)) + + return avg_infos + + +def _log_eval_metrics(logger, avg_infos, args, metric_prefix, quiet): + """Log metrics to TensorBoard/wandb if logger is provided.""" + if logger is None or args.get("global_step") is None: + return + + global_step = args["global_step"] + + # Create log dict with metric prefix (use / for TensorBoard grouping) + log_dict = {} + for metric_key, metric_value in avg_infos.items(): + if isinstance(metric_value, (int, float)): + log_dict[f"{metric_prefix}/{metric_key}"] = float(metric_value) + + # Log to TensorBoard if available + if hasattr(logger, "local_writer") and logger.local_writer: + for key, value in log_dict.items(): + logger.local_writer.add_scalar(key, value, global_step) + if not quiet: + print(f"✅ Logged {len(log_dict)} validation metrics to TensorBoard at step {global_step}") + + # Also log to wandb/neptune if available + if hasattr(logger, "log"): + logger.log(log_dict, global_step) + + +def eval_multi_scenarios( + env_name, args=None, vecenv=None, policy=None, logger=None, metric_prefix="validation", quiet=False +): + t0 = time.time() + + if args is None: + tmp_args = load_config(env_name) + model_path = tmp_args.get("load_model_path") + num_agents_eval = tmp_args["eval"]["num_agents"] + map_dir = tmp_args["eval"]["map_dir"] + + eval_overrides = build_eval_overrides( + tmp_args["eval_simulation"], + num_agents_eval, + tmp_args["num_scenarios"], + map_dir, + num_carla_maps=tmp_args.get("num_carla_maps", 6), + ) + args = load_eval_multi_scenarios_config(env_name, model_path, eval_overrides) + + # Reproducibility — same approach as training + seed = args["train"]["seed"] or 42 + np.random.seed(seed) + torch.manual_seed(seed) + + backend = args["vec"]["backend"] + num_scenarios = args["num_scenarios"] + + num_workers = min(args["vec"]["num_envs"], num_scenarios) + + # Distribute scenarios across workers + scenarios_per_worker = num_scenarios // num_workers + remainder = num_scenarios % num_workers + current_start = 0 + env_kwargs_list = [] + for j in range(num_workers): + worker_kwargs = copy.deepcopy(args["env"]) + worker_num_scenario = scenarios_per_worker + (1 if j < remainder else 0) + worker_kwargs["starting_map"] = current_start + worker_kwargs["num_eval_scenarios"] = worker_num_scenario + env_kwargs_list.append(worker_kwargs) + current_start += worker_num_scenario + + print(f"Distributing {num_scenarios} scenarios across {num_workers} workers:") + for j, w in enumerate(env_kwargs_list): + start = w["starting_map"] + count = w["num_eval_scenarios"] + print(f" Worker {j}: maps {start}-{start + count - 1} ({count} scenarios)") + + args["vec"] = dict(backend=backend, num_envs=num_workers, num_workers=num_workers, batch_size=num_workers) + + if vecenv is None: + package = args["package"] + module_name = "pufferlib.ocean" if package == "ocean" else f"pufferlib.environments.{package}" + env_module = importlib.import_module(module_name) + make_env = env_module.env_creator(env_name) + # Pass as lists to preserve per-worker env_kwargs + env_creators = [make_env] * num_workers + env_args = [[]] * num_workers + vecenv = pufferlib.vector.make(env_creators, env_args=env_args, env_kwargs=env_kwargs_list, **args["vec"]) + + policy = policy or load_policy(args, vecenv, env_name) + num_agents = vecenv.observation_space.shape[0] + device = args["train"]["device"] + + state = {} + if args["train"]["use_rnn"]: + state = dict( + lstm_h=torch.zeros(num_agents, policy.hidden_size, device=device), + lstm_c=torch.zeros(num_agents, policy.hidden_size, device=device), + ) + + # Folder for evaluation results + # For inline evaluation during training, use eval_results_dir in experiments folder + # For standalone evaluation, use benchmark folder + if "inline_eval" in args and args["inline_eval"] and "eval_results_dir" in args: + eval_folder = args["eval_results_dir"] + else: + # Standalone evaluation path (in benchmark folder) + model_path = args["load_model_path"] + model_filename_with_ext = os.path.basename(model_path) + model_name = os.path.splitext(model_filename_with_ext)[0] + models_dir = os.path.dirname(model_path) + experiment_dir = os.path.dirname(models_dir) + experiment_name = os.path.basename(experiment_dir) + eval_folder = os.path.join("benchmark", experiment_name, model_name, args["eval_simulation"]) + os.makedirs(eval_folder, exist_ok=True) + + global_infos = {} + scenarios_processed = 0 + vecenv.async_reset(42) + + ob, _, _, _, infos, _, _ = vecenv.recv() + with tqdm(total=num_scenarios, desc="Processing scenarios", disable=quiet) as pbar: + while scenarios_processed < num_scenarios: + # Reset LSTM + if args["train"]["use_rnn"]: + state = dict( + lstm_h=torch.zeros(num_agents, policy.hidden_size, device=device), + lstm_c=torch.zeros(num_agents, policy.hidden_size, device=device), + ) + + for _ in range(args["env"]["scenario_length"]): + with torch.no_grad(): + ob = torch.as_tensor(ob).to(device) + logits, _ = policy.forward_eval(ob, state) + action, _, _ = pufferlib.pytorch.sample_logits(logits, deterministic=True) + action = action.cpu().numpy().reshape(vecenv.action_space.shape) + + if isinstance(logits, torch.distributions.Normal): + action = np.clip(action, vecenv.action_space.low, vecenv.action_space.high) + + ob, _, _, _, infos = vecenv.step(action) + + # Multi-worker backend returns infos as list of lists (one per worker) + if infos and infos[0]: + for sub_env in infos: + for env_idx, summary in enumerate(sub_env): + env_map_name = summary["map_name"].split("/")[-1].split(".")[0] + summary["episode_id"] = env_idx + summary["map_name"] = env_map_name + scenarios_processed += 1 + pbar.update(1) + + for k, v in summary.items(): + if k not in global_infos: + global_infos[k] = [] + global_infos[k].append(v) + + avg_infos = _export_metrics( + global_infos, + eval_folder, + num_scenarios, + quiet, + verify_coverage=True, + simulation_mode=args["env"]["simulation_mode"], + ) + print(f"\nTotal evaluation time: {time.time() - t0:.2f} seconds for {num_scenarios} scenarios.") + _log_eval_metrics(logger, avg_infos, args, metric_prefix, quiet) + + # Close vectorized environment to avoid file descriptor leaks + vecenv.close() + + +def eval_multi_scenarios_render( + env_name, args=None, vecenv=None, policy=None, logger=None, metric_prefix="validation", quiet=False +): + # Set fixed seed for reproducible evaluation + np.random.seed(42) + torch.manual_seed(42) + + if args is None: + tmp_args = load_config(env_name) + model_path = tmp_args.get("load_model_path") + num_agents_eval = tmp_args["eval"]["num_agents"] + map_dir = tmp_args["eval"]["map_dir"] + eval_overrides = build_eval_overrides( + tmp_args["eval_simulation"], + num_agents_eval, + tmp_args["num_scenarios"], + map_dir, + num_carla_maps=tmp_args.get("num_carla_maps", 6), + ) + args = load_eval_multi_scenarios_config(env_name, model_path, eval_overrides) + + backend = args["vec"]["backend"] + if backend != "PufferEnv": + backend = "Serial" + + args["vec"] = dict(backend=backend, num_envs=1) + args["env"]["num_eval_scenarios"] = args["num_scenarios"] # first batch: fill as many scenarios as fit + + vecenv = vecenv or load_env(env_name, args) + + policy = policy or load_policy(args, vecenv, env_name) + num_agents = vecenv.observation_space.shape[0] + device = args["train"]["device"] + + state = {} + if args["train"]["use_rnn"]: + state = dict( + lstm_h=torch.zeros(num_agents, policy.hidden_size, device=device), + lstm_c=torch.zeros(num_agents, policy.hidden_size, device=device), + ) + + # Folder for evaluation results + # For inline evaluation during training, use eval_results_dir in experiments folder + # For standalone evaluation, use benchmark folder + if "inline_eval" in args and args["inline_eval"] and "eval_results_dir" in args: + eval_folder = args["eval_results_dir"] + else: + # Standalone evaluation path (in benchmark folder) + model_path = args["load_model_path"] + model_filename_with_ext = os.path.basename(model_path) + model_name = os.path.splitext(model_filename_with_ext)[0] + models_dir = os.path.dirname(model_path) + experiment_dir = os.path.dirname(models_dir) + experiment_name = os.path.basename(experiment_dir) + eval_folder = os.path.join("benchmark", experiment_name, model_name, args["eval_simulation"]) + os.makedirs(eval_folder, exist_ok=True) + + if args["render"]: + gif_folder = eval_folder + "/gif" + os.makedirs(gif_folder, exist_ok=True) + + global_infos = {} + num_scenarios = args["num_scenarios"] + + scenarios_processed = 0 + with tqdm(total=num_scenarios, desc="Processing scenarios", disable=quiet) as pbar: + while scenarios_processed < num_scenarios: + ob, _ = vecenv.reset() + + # Get initial states for all environments in the batch + scenarios = vecenv.get_state() + num_envs_in_batch = len(scenarios) + batch_start = scenarios_processed + + # Prepare batch_size_eval for the resample that fires at end of the step loop. + # That resample will load the NEXT batch, so cap it at remaining_after_this. + remaining_after_this = num_scenarios - scenarios_processed - num_envs_in_batch + vecenv.envs[0].batch_size_eval = max(1, remaining_after_this) + + map_names = [] + for env_idx in range(num_envs_in_batch): + map_names.append(scenarios[env_idx]["map_name"].split("/")[-1].split(".")[0]) + + # Reset LSTM + if args["train"]["use_rnn"]: + state = dict( + lstm_h=torch.zeros(num_agents, policy.hidden_size, device=device), + lstm_c=torch.zeros(num_agents, policy.hidden_size, device=device), + ) + + # Initialize histories as lists of lists (one list per environment) + if args["render"]: + agent_histories = [[] for _ in range(num_envs_in_batch)] + traffic_histories = [[] for _ in range(num_envs_in_batch)] + trajectory_histories = [[] for _ in range(num_envs_in_batch)] + all_agents_obs_histories = [[] for _ in range(num_envs_in_batch)] + + for t in range(args["env"]["scenario_length"]): + if args["render"]: + current_scenarios = vecenv.get_state() + start_obs_index = 0 + + # Loop through every environment in the batch to record its history + for env_idx in range(num_envs_in_batch): + env_scenario = current_scenarios[env_idx] + + agent_histories[env_idx].append( + pufferlib.viz.fill_agents_state( + env_scenario, use_trajectory="trajectory" in args["env"]["action_type"] + ) + ) + traffic_histories[env_idx].append(pufferlib.viz.fill_traffics_state(env_scenario, t)) + + if "trajectory" in args["env"]["action_type"]: + trajectory_histories[env_idx].append(pufferlib.viz.fill_trajectories(env_scenario, t)) + + # Collect observation dictionaries for ALL active agents in THIS environment at timestep t + if args["render_obs"]: + step_obs_dict = {} + if env_idx > 0: + start_obs_index += current_scenarios[env_idx - 1]["active_agent_count"] + for agent_idx in range(env_scenario["active_agent_count"]): + agent_id = env_scenario["active_agent_indices"][agent_idx] + step_obs_dict[int(agent_id)] = pufferlib.viz.extract_obs_frame( + ob, + env_scenario, + args, + timestep=t, + obs_index=start_obs_index + agent_idx, + agent_idx=agent_idx, + head_north=True, + ) + all_agents_obs_histories[env_idx].append(step_obs_dict) + + with torch.no_grad(): + ob = torch.as_tensor(ob).to(device) + logits, _ = policy.forward_eval(ob, state) + action, _, _ = pufferlib.pytorch.sample_logits(logits, deterministic=True) + action = action.cpu().numpy().reshape(vecenv.action_space.shape) + + if isinstance(logits, torch.distributions.Normal): + action = np.clip(action, vecenv.action_space.low, vecenv.action_space.high) + + ob, _, _, _, infos = vecenv.step(action) + + # Serial backend returns infos as single list (infos[0] is the env's info list) + if infos and infos[0]: + for env_idx, summary in enumerate(infos[0]): + env_map_name = summary["map_name"].split("/")[-1].split(".")[0] + summary["episode_id"] = batch_start + env_idx + summary["env_id"] = env_idx + summary["map_name"] = env_map_name + + for k, v in summary.items(): + if k not in global_infos: + global_infos[k] = [] + global_infos[k].append(v) + + if args["render"]: + # Loop through every environment to generate its specific HTML replay + for env_idx in range(num_envs_in_batch): + global_episode_id = batch_start + env_idx + # Ensure we don't render padding environments if num_scenarios isn't perfectly divisible by batch_size + if global_episode_id >= num_scenarios: + break + env_map_name = map_names[env_idx] + + pufferlib.viz.generate_interactive_replay( + current_scenarios[env_idx], + agent_histories[env_idx], + traffic_histories[env_idx], + trajectory_histories[env_idx], + all_agents_obs_histories[env_idx], + f"{gif_folder}/{env_map_name}_{global_episode_id:03d}.html", + head_north=True, + use_rear_axle=args["env"]["use_rear_axle"], + ) + + scenarios_processed += num_envs_in_batch + pbar.update(num_envs_in_batch) + + if args["render"]: + pufferlib.viz.build_gallery_index(gif_folder) + + avg_infos = _export_metrics(global_infos, eval_folder, num_scenarios, quiet, verify_coverage=False) + _log_eval_metrics(logger, avg_infos, args, metric_prefix, quiet) + + # Close vectorized environment to avoid file descriptor leaks + vecenv.close() + + +def dict_to_args(d, prefix=""): + args = [] + for k, v in d.items(): + key_str = f"{prefix}.{k}" if prefix else k + if isinstance(v, dict): + args.extend(dict_to_args(v, key_str)) + else: + args.append(f"--{key_str.replace('_', '-')}") + args.append(str(v)) + return args def sweep(args=None, env_name=None): args = args or load_config(env_name) - if not args["wandb"] and not args["neptune"]: - raise pufferlib.APIUsageError("Sweeps require either wandb or neptune") + if not args["wandb"] and not args["neptune"] and not args["tb"]: + raise pufferlib.APIUsageError("Sweeps require either wandb, neptune, or tb") method = args["sweep"].pop("method") try: @@ -1163,6 +2252,7 @@ def sweep(args=None, env_name=None): sweep = sweep_cls(args["sweep"]) points_per_run = args["sweep"]["downsample"] target_key = f"environment/{args['sweep']['metric']}" + for i in range(args["max_runs"]): seed = time.time_ns() & 0xFFFFFFFF random.seed(seed) @@ -1230,71 +2320,6 @@ def controlled_exp(env_name, args=None): print(f"\n✓ Completed all {len(combinations)} experiments") -def sanity(env_name, args=None): - args = args or load_config(env_name) - base_dir = Path(__file__).resolve().parent / "resources" / "drive" / "sanity" - json_dir = base_dir / "sanity_jsons" - binary_dir = base_dir / "sanity_binaries" - - available_maps = {p.stem: p for p in json_dir.glob("*.json")} - selected = args.get("sanity_maps") - if isinstance(selected, str): - selected = [selected] - - if selected: - missing = [name for name in selected if name not in available_maps] - if missing: - raise pufferlib.APIUsageError(f"Unknown sanity maps: {', '.join(sorted(missing))}") - chosen = [(name, available_maps[name]) for name in selected] - else: - chosen = sorted(available_maps.items()) - - if not chosen: - raise pufferlib.APIUsageError(f"No sanity maps found in {json_dir}") - - from pufferlib.ocean.drive.drive import load_map - - binary_dir.mkdir(parents=True, exist_ok=True) - binaries = [] - for idx, (name, json_path) in enumerate(chosen): - output_path = binary_dir / f"{name}.bin" - load_map(str(json_path), idx, str(output_path)) - binaries.append((name, output_path)) - - runs = [] - for name, binary in binaries: - map_zero = binary_dir / "map_000.bin" - shutil.copy2(binary, map_zero) - - run_args = { - **args, - "env": {**args["env"], "num_maps": 1, "map_dir": str(binary_dir)}, - "train": {**args["train"], "render_map": str(map_zero)}, - } - if run_args.get("wandb"): - run_args["wandb_name"] = name - - print(f"Running sanity map '{name}' from {binary.name}") - run_logs = train(env_name=env_name, args=run_args) - runs.append({"map": name, "logs": run_logs}) - - print("Sanity checklist:") - for entry in runs: - name = entry["map"] - logs = entry.get("logs") or [] - final = logs[-1] if logs else {} - score = final.get("environment/score") - if score is None: - status = "unknown (no score)" - elif score >= 0.95: - status = "✅ Solved" - else: - status = "❌ unsolved" - print(f" - {name}: {status} (score={score})") - - return runs - - def profile(args=None, env_name=None, vecenv=None, policy=None): args = load_config() vecenv = vecenv or load_env(env_name, args) @@ -1336,6 +2361,31 @@ def export(args=None, env_name=None, vecenv=None, policy=None, path=None, silent print(f"Saved {len(weights)} weights to {path}") +def ensure_drive_binary(): + """Delete existing visualize binary and rebuild it. This ensures the + binary is always up-to-date with the latest code changes. + """ + if os.path.exists("./visualize"): + print("Removing existing visualize binary...") + os.remove("./visualize") + + print("Building visualize binary...") + try: + result = subprocess.run( + ["bash", "scripts/build_ocean.sh", "visualize", "fast"], capture_output=True, text=True, timeout=300 + ) + + if result.returncode == 0: + print("Successfully built visualize binary") + else: + print(f"Build failed: {result.stderr}") + raise RuntimeError("Failed to build visualize binary for rendering") + except subprocess.TimeoutExpired: + raise RuntimeError("Build timed out") + except Exception as e: + raise RuntimeError(f"Build error: {e}") + + def autotune(args=None, env_name=None, vecenv=None, policy=None): package = args["package"] module_name = "pufferlib.ocean" if package == "ocean" else f"pufferlib.environments.{package}" @@ -1359,6 +2409,8 @@ def load_policy(args, vecenv, env_name=""): env_module = importlib.import_module(module_name) device = args["train"]["device"] + if isinstance(device, int): + device = torch.device("cuda", device) if torch.cuda.is_available() else torch.device("cpu") policy_cls = getattr(env_module.torch, args["policy_name"]) policy = policy_cls(vecenv.driver_env, **args["policy"]) @@ -1409,8 +2461,21 @@ def load_config(env_name, config_dir=None): "--load-id", type=str, default=None, help="Kickstart/eval from from a finished Wandb/Neptune run" ) parser.add_argument( - "--render-mode", type=str, default="auto", choices=["auto", "human", "ansi", "rgb_array", "raylib", "None"] + "--render-mode", + type=str, + default="matplotlib", + choices=["auto", "human", "ansi", "rgb_array", "raylib", "matplotlib", "None"], + ) + parser.add_argument("--video-path", type=str, default="videos", help="Path to save videos") + parser.add_argument("--num_scenarios", type=int, default=3, help="Number of scenarios to eval") + parser.add_argument( + "--num_carla_maps", type=int, default=6, help="Number of CARLA maps to use in gigaflow mode (max 6)" + ) + parser.add_argument("--render", type=int, default=0, help="Rendering the evaluation") + parser.add_argument( + "--render_obs", type=int, default=0, help="Rendering the observation of first agent in evaluation" ) + parser.add_argument("--agent_index", nargs="*", type=int, default=None, help="Agent index to plot the observation") parser.add_argument("--save-frames", type=int, default=0) parser.add_argument("--gif-path", type=str, default="eval.gif") parser.add_argument("--fps", type=float, default=15) @@ -1418,12 +2483,16 @@ def load_config(env_name, config_dir=None): parser.add_argument("--wandb", action="store_true", help="Use wandb for logging") parser.add_argument("--wandb-project", type=str, default="pufferlib") parser.add_argument("--wandb-group", type=str, default="debug") + parser.add_argument("--wandb-name", type=str, default=None, help="Wandb run name") parser.add_argument("--neptune", action="store_true", help="Use neptune for logging") parser.add_argument("--neptune-name", type=str, default="pufferai") parser.add_argument("--neptune-project", type=str, default="ablations") + parser.add_argument("--tb", action="store_true", help="Use tensorboard for logging") parser.add_argument("--local-rank", type=int, default=0, help="Used by torchrun for DDP") parser.add_argument("--tag", type=str, default=None, help="Tag for experiment") - parser.add_argument("--sanity-maps", nargs="*", default=None, help="Optional list of sanity map base names to run") + parser.add_argument( + "--eval_simulation", type=str, default=None, help="Simulation mode for evaluation - gigaflow/replay" + ) args = parser.parse_known_args()[0] if config_dir is None: @@ -1475,11 +2544,20 @@ def puffer_type(value): prev[subkey] = value args["train"]["use_rnn"] = args["rnn_name"] is not None + + # Use World size to divide Num_Agents / minibatch size in DDP + if "LOCAL_RANK" in os.environ: + world_size = int(os.environ.get("WORLD_SIZE", 1)) + args["env"]["num_agents"] = args["env"]["num_agents"] // world_size + args["train"]["minibatch_size"] = args["train"]["minibatch_size"] // world_size + args["train"]["max_minibatch_size"] = args["train"]["max_minibatch_size"] // world_size + args["train"]["total_timesteps"] = args["train"]["total_timesteps"] // world_size + return args def main(): - err = "Usage: puffer [train, eval, sweep, controlled_exp, autotune, profile, export, sanity] [env_name] [optional args]. --help for more info" + err = "Usage: puffer [train, eval, sweep, controlled_exp, autotune, profile, export] [env_name] [optional args]. --help for more info" if len(sys.argv) < 3: raise pufferlib.APIUsageError(err) @@ -1489,6 +2567,11 @@ def main(): train(env_name=env_name) elif mode == "eval": eval(env_name=env_name) + elif mode == "eval_multi_scenarios": + eval_multi_scenarios(env_name=env_name) + elif mode == "eval_multi_scenarios_render": + eval_multi_scenarios_render(env_name=env_name) + print("") elif mode == "sweep": sweep(env_name=env_name) elif mode == "controlled_exp": @@ -1499,11 +2582,13 @@ def main(): profile(env_name=env_name) elif mode == "export": export(env_name=env_name) - elif mode == "sanity": - sanity(env_name=env_name) else: raise pufferlib.APIUsageError(err) if __name__ == "__main__": - main() + try: + main() + except Exception: + traceback.print_exc() + sys.exit(1) diff --git a/pufferlib/pytorch.py b/pufferlib/pytorch.py index 92d4af77a6..2ec10a5c5f 100644 --- a/pufferlib/pytorch.py +++ b/pufferlib/pytorch.py @@ -187,12 +187,14 @@ def entropy_probs(logits, probs): return -p_log_p.sum(-1) -def sample_logits(logits, action=None): +def sample_logits(logits, action=None, deterministic=False): is_discrete = isinstance(logits, torch.Tensor) if isinstance(logits, torch.distributions.Normal): batch = logits.loc.shape[0] if action is None: action = logits.sample().view(batch, -1) + if deterministic: + action = logits.loc.view(batch, -1) # TODO - DETERMINISTIC use mean action for eval log_probs = logits.log_prob(action.view(batch, -1)).sum(1) logits_entropy = logits.entropy().view(batch, -1).sum(1) @@ -210,9 +212,12 @@ def sample_logits(logits, action=None): probs = logits_to_probs(logits) if action is None: - probs = torch.nan_to_num(probs, 1e-8, 1e-8, 1e-8) - action = torch.multinomial(probs.reshape(-1, probs.shape[-1]), 1, replacement=True).int() - action = action.reshape(probs.shape[:-1]) + if deterministic: + action = torch.argmax(probs, -1) + else: + probs = torch.nan_to_num(probs, 1e-8, 1e-8, 1e-8) + action = torch.multinomial(probs.reshape(-1, probs.shape[-1]), 1, replacement=True).int() + action = action.reshape(probs.shape[:-1]) else: batch = logits[0].shape[0] action = action.view(batch, -1).T diff --git a/pufferlib/resources/drive/binaries/carla/opendrive__Town01.bin b/pufferlib/resources/drive/binaries/carla/opendrive__Town01.bin new file mode 100644 index 0000000000..7b05f6a185 Binary files /dev/null and b/pufferlib/resources/drive/binaries/carla/opendrive__Town01.bin differ diff --git a/pufferlib/resources/drive/binaries/carla/opendrive__Town02.bin b/pufferlib/resources/drive/binaries/carla/opendrive__Town02.bin new file mode 100644 index 0000000000..96cf31ede3 Binary files /dev/null and b/pufferlib/resources/drive/binaries/carla/opendrive__Town02.bin differ diff --git a/pufferlib/resources/drive/binaries/carla/opendrive__Town03.bin b/pufferlib/resources/drive/binaries/carla/opendrive__Town03.bin new file mode 100644 index 0000000000..280bedb614 Binary files /dev/null and b/pufferlib/resources/drive/binaries/carla/opendrive__Town03.bin differ diff --git a/pufferlib/resources/drive/binaries/carla/opendrive__Town04.bin b/pufferlib/resources/drive/binaries/carla/opendrive__Town04.bin new file mode 100644 index 0000000000..fd16fc4a00 Binary files /dev/null and b/pufferlib/resources/drive/binaries/carla/opendrive__Town04.bin differ diff --git a/pufferlib/resources/drive/binaries/carla/opendrive__Town05.bin b/pufferlib/resources/drive/binaries/carla/opendrive__Town05.bin new file mode 100644 index 0000000000..ba5b9cdefa Binary files /dev/null and b/pufferlib/resources/drive/binaries/carla/opendrive__Town05.bin differ diff --git a/pufferlib/resources/drive/binaries/carla/opendrive__Town06.bin b/pufferlib/resources/drive/binaries/carla/opendrive__Town06.bin new file mode 100644 index 0000000000..51b6cd5ad3 Binary files /dev/null and b/pufferlib/resources/drive/binaries/carla/opendrive__Town06.bin differ diff --git a/pufferlib/resources/drive/binaries/carla/opendrive__Town07.bin b/pufferlib/resources/drive/binaries/carla/opendrive__Town07.bin new file mode 100644 index 0000000000..ef43c74beb Binary files /dev/null and b/pufferlib/resources/drive/binaries/carla/opendrive__Town07.bin differ diff --git a/pufferlib/resources/drive/binaries/carla/opendrive__Town10HD.bin b/pufferlib/resources/drive/binaries/carla/opendrive__Town10HD.bin new file mode 100644 index 0000000000..ba78031e84 Binary files /dev/null and b/pufferlib/resources/drive/binaries/carla/opendrive__Town10HD.bin differ diff --git a/pufferlib/resources/drive/puffer_drive_weights.bin b/pufferlib/resources/drive/puffer_drive_weights.bin index 87c1254ba4..4a5b30e74b 100644 Binary files a/pufferlib/resources/drive/puffer_drive_weights.bin and b/pufferlib/resources/drive/puffer_drive_weights.bin differ diff --git a/pufferlib/spaces.py b/pufferlib/spaces.py index 800f93ab8a..5949344963 100644 --- a/pufferlib/spaces.py +++ b/pufferlib/spaces.py @@ -1,13 +1,12 @@ import numpy as np -import gym import gymnasium -Box = (gym.spaces.Box, gymnasium.spaces.Box) -Dict = (gym.spaces.Dict, gymnasium.spaces.Dict) -Discrete = (gym.spaces.Discrete, gymnasium.spaces.Discrete) -MultiBinary = (gym.spaces.MultiBinary, gymnasium.spaces.MultiBinary) -MultiDiscrete = (gym.spaces.MultiDiscrete, gymnasium.spaces.MultiDiscrete) -Tuple = (gym.spaces.Tuple, gymnasium.spaces.Tuple) +Box = gymnasium.spaces.Box +Dict = gymnasium.spaces.Dict +Discrete = gymnasium.spaces.Discrete +MultiBinary = gymnasium.spaces.MultiBinary +MultiDiscrete = gymnasium.spaces.MultiDiscrete +Tuple = gymnasium.spaces.Tuple def joint_space(space, n): diff --git a/pufferlib/sweep.py b/pufferlib/sweep.py index fa405f73ea..a3db50d8ab 100644 --- a/pufferlib/sweep.py +++ b/pufferlib/sweep.py @@ -121,6 +121,27 @@ def unnormalize(self, value): return 1 - self.base**log_spaced +class Categorical(Space): + def __init__(self, values, scale, mean): + if scale == "auto": + scale = 1.0 # full range so all values are reachable + self.values = list(values) + self._n = len(self.values) + super().__init__(min=self.values[0], max=self.values[-1], scale=scale, mean=mean) + + def normalize(self, value): + idx = self.values.index(value) + if self._n == 1: + return 0.0 + return -1.0 + 2.0 * idx / (self._n - 1) + + def unnormalize(self, value): + zero_one = (value + 1) / 2 + idx = round(zero_one * (self._n - 1)) + idx = max(0, min(self._n - 1, idx)) + return self.values[idx] + + def _params_from_puffer_sweep(sweep_config): param_spaces = {} for name, param in sweep_config.items(): @@ -134,6 +155,15 @@ def _params_from_puffer_sweep(sweep_config): assert "distribution" in param distribution = param["distribution"] + + if distribution == "categorical": + values = param["values"] + mean = param.get("mean", values[len(values) // 2]) + scale = param.get("scale", "auto") + space = Categorical(values=values, scale=scale, mean=mean) + param_spaces[name] = space + continue + search_center = param["mean"] kwargs = dict( min=param["min"], diff --git a/pufferlib/utils.py b/pufferlib/utils.py index e66a37165d..30316f0eb9 100644 --- a/pufferlib/utils.py +++ b/pufferlib/utils.py @@ -6,6 +6,73 @@ import json +def run_human_replay_eval_in_subprocess(config, logger, global_step): + """ + Run human replay evaluation in a subprocess and log metrics to wandb. + + """ + try: + run_id = logger.run_id + model_dir = os.path.join(config["data_dir"], f"{config['env']}_{run_id}") + model_files = glob.glob(os.path.join(model_dir, "model_*.pt")) + + if not model_files: + print("No model files found for human replay evaluation") + return + + latest_cpt = max(model_files, key=os.path.getctime) + + # Prepare evaluation command + eval_config = config["eval"] + cmd = [ + sys.executable, + "-m", + "pufferlib.pufferl", + "eval", + config["env"], + "--load-model-path", + latest_cpt, + "--eval.wosac-realism-eval", + "False", + "--eval.human-replay-eval", + "True", + "--eval.human-replay-num-agents", + str(eval_config["human_replay_num_agents"]), + "--eval.human-replay-control-mode", + str(eval_config["human_replay_control_mode"]), + ] + + # Run human replay evaluation in subprocess + result = subprocess.run(cmd, capture_output=True, text=True, timeout=600, cwd=os.getcwd()) + + if result.returncode == 0: + # Extract JSON from stdout between markers + stdout = result.stdout + if "HUMAN_REPLAY_METRICS_START" in stdout and "HUMAN_REPLAY_METRICS_END" in stdout: + start = stdout.find("HUMAN_REPLAY_METRICS_START") + len("HUMAN_REPLAY_METRICS_START") + end = stdout.find("HUMAN_REPLAY_METRICS_END") + json_str = stdout[start:end].strip() + human_replay_metrics = json.loads(json_str) + + # Log to wandb if available + if hasattr(logger, "wandb") and logger.wandb: + logger.wandb.log( + { + "eval/human_replay_collision_rate": human_replay_metrics["collision_rate"], + "eval/human_replay_offroad_rate": human_replay_metrics["offroad_rate"], + "eval/human_replay_completion_rate": human_replay_metrics["completion_rate"], + }, + step=global_step, + ) + else: + print(f"Human replay evaluation failed with exit code {result.returncode}: {result.stderr}") + + except subprocess.TimeoutExpired: + print("Human replay evaluation timed out") + except Exception as e: + print(f"Failed to run human replay evaluation: {e}") + + def run_wosac_eval_in_subprocess(config, logger, global_step): """ Run WOSAC evaluation in a subprocess and log metrics to wandb. @@ -24,6 +91,12 @@ def run_wosac_eval_in_subprocess(config, logger, global_step): model_dir = os.path.join(config["data_dir"], f"{config['env']}_{run_id}") model_files = glob.glob(os.path.join(model_dir, "model_*.pt")) + if not model_files: + print("No model files found for WOSAC evaluation") + return + + latest_cpt = max(model_files, key=os.path.getctime) + # Prepare evaluation command eval_config = config.get("eval", {}) cmd = [ @@ -32,34 +105,26 @@ def run_wosac_eval_in_subprocess(config, logger, global_step): "pufferlib.pufferl", "eval", config["env"], + "--load-model-path", + latest_cpt, "--eval.wosac-realism-eval", "True", - "--eval.wosac-batch-size", - str(eval_config.get("wosac_batch_size", 32)), - "--eval.wosac-target-scenarios", - str(eval_config.get("wosac_target_scenarios", 64)), - "--eval.wosac-scenario-pool-size", - str(eval_config.get("wosac_scenario_pool_size", 10_000)), + "--eval.wosac-num-agents", + str(eval_config.get("wosac_num_agents", 256)), "--eval.wosac-init-mode", str(eval_config.get("wosac_init_mode", "create_all_valid")), "--eval.wosac-control-mode", str(eval_config.get("wosac_control_mode", "control_wosac")), "--eval.wosac-init-steps", str(eval_config.get("wosac_init_steps", 10)), - "--eval.wosac-goal-behavior", - str(eval_config.get("wosac_goal_behavior", 2)), "--eval.wosac-goal-radius", str(eval_config.get("wosac_goal_radius", 2.0)), "--eval.wosac-sanity-check", str(eval_config.get("wosac_sanity_check", False)), + "--eval.wosac-aggregate-results", + str(eval_config.get("wosac_aggregate_results", True)), ] - if not model_files: - print("No model files found for WOSAC evaluation. Running WOSAC with random policy.") - elif len(model_files) > 0: - latest_cpt = max(model_files, key=os.path.getctime) - cmd.extend(["--load-model-path", latest_cpt]) - # Run WOSAC evaluation in subprocess result = subprocess.run(cmd, capture_output=True, text=True, timeout=600, cwd=os.getcwd()) @@ -77,10 +142,6 @@ def run_wosac_eval_in_subprocess(config, logger, global_step): logger.wandb.log( { "eval/wosac_realism_meta_score": wosac_metrics["realism_meta_score"], - "eval/realism_meta_score_std": wosac_metrics["realism_meta_score_std"], - "eval/wosac_kinematic_metrics": wosac_metrics["kinematic_metrics"], - "eval/wosac_interactive_metrics": wosac_metrics["interactive_metrics"], - "eval/wosac_map_based_metrics": wosac_metrics["map_based_metrics"], "eval/wosac_ade": wosac_metrics["ade"], "eval/wosac_min_ade": wosac_metrics["min_ade"], "eval/wosac_total_num_agents": wosac_metrics["total_num_agents"], @@ -102,3 +163,176 @@ def run_wosac_eval_in_subprocess(config, logger, global_step): print(f"WOSAC evaluation ran out of memory. Skipping this evaluation: {e}") except Exception as e: print(f"Failed to run WOSAC evaluation: {type(e).__name__}: {e}") + + +def render_videos(config, vecenv, logger, epoch, global_step, bin_path): + """ + Generate and log training videos using C-based rendering. + + Args: + config: Configuration dictionary containing data_dir, env, and render settings + vecenv: Vectorized environment with driver_env attribute + logger: Logger object with run_id and optional wandb attribute + epoch: Current training epoch + global_step: Current global training step + bin_path: Path to the exported .bin model weights file + + Returns: + None. Prints error messages if rendering fails. + """ + if not os.path.exists(bin_path): + print(f"Binary weights file does not exist: {bin_path}") + return + + run_id = logger.run_id + model_dir = os.path.join(config["data_dir"], f"{config['env']}_{run_id}") + + # Now call the C rendering function + try: + # Create output directory for videos + video_output_dir = os.path.join(model_dir, "videos") + os.makedirs(video_output_dir, exist_ok=True) + + # TODO: Fix memory leaks so that this is not needed + # Suppress AddressSanitizer exit code (temp) + env_vars = os.environ.copy() + env_vars["ASAN_OPTIONS"] = "exitcode=0" + + # Base command — pass policy weights directly via --policy-name + base_cmd = ["xvfb-run", "-a", "-s", "-screen 0 1280x720x24", "./visualize", + "--policy-name", bin_path] + + # Render config flags + if config.get("show_grid", False): + base_cmd.append("--show-grid") + if config.get("obs_only", False): + base_cmd.append("--obs-only") + if config.get("show_lasers", False): + base_cmd.append("--lasers") + if config.get("show_human_logs", False): + base_cmd.append("--log-trajectories") + + env_cfg = getattr(vecenv, "driver_env", None) + if env_cfg is not None: + if getattr(env_cfg, "goal_radius", None) is not None: + base_cmd.extend(["--goal-radius", str(env_cfg.goal_radius)]) + if getattr(env_cfg, "init_steps", 0) > 0: + base_cmd.extend(["--init-steps", str(env_cfg.init_steps)]) + if getattr(env_cfg, "init_mode", None) is not None: + base_cmd.extend(["--init-mode", str(env_cfg.init_mode)]) + if getattr(env_cfg, "control_mode", None) is not None: + base_cmd.extend(["--control-mode", str(env_cfg.control_mode)]) + if getattr(env_cfg, "control_all_agents", False): + base_cmd.append("--pure-self-play") + if getattr(env_cfg, "deterministic_agent_selection", False): + base_cmd.append("--deterministic-selection") + + # Policy-controlled agents (prefer num_policy_controlled_agents, fallback to max_controlled_agents) + n_policy = getattr(env_cfg, "num_policy_controlled_agents", getattr(env_cfg, "max_controlled_agents", -1)) + try: + n_policy = int(n_policy) + except (TypeError, ValueError): + n_policy = -1 + if n_policy > 0: + base_cmd += ["--num-policy-controlled-agents", str(n_policy)] + + if getattr(env_cfg, "num_maps", False): + base_cmd.extend(["--num-maps", str(env_cfg.num_maps)]) + if getattr(env_cfg, "scenario_length", None): + base_cmd.extend(["--scenario-length", str(env_cfg.scenario_length)]) + + # Handle single or multiple map rendering + render_maps = config.get("render_map", None) + if render_maps is None or render_maps == "none": + # Auto-discover maps from the env's map_dir + map_dir = ( + config.get("env", {}).get("map_dir", None) + if isinstance(config.get("env"), dict) + else getattr(env_cfg, "map_dir", None) + ) + if map_dir and os.path.isdir(map_dir): + render_maps = sorted(os.path.join(map_dir, f) for f in os.listdir(map_dir) if f.endswith(".bin")) + if not render_maps: + render_maps = [None] + elif isinstance(render_maps, (str, os.PathLike)): + render_maps = [render_maps] + else: + # Ensure list-like + render_maps = list(render_maps) + + # Collect videos to log as lists so W&B shows all in the same step + videos_to_log_world = [] + videos_to_log_agent = [] + + for i, map_path in enumerate(render_maps): + cmd = list(base_cmd) # copy + if map_path is not None and os.path.exists(map_path): + cmd.extend(["--map-name", str(map_path)]) + + # Output paths — use absolute paths in the video output dir + topdown_tmp = os.path.join(video_output_dir, "output_topdown.mp4") + agent_tmp = os.path.join(video_output_dir, "output_agent.mp4") + cmd.extend(["--output-topdown", topdown_tmp]) + cmd.extend(["--output-agent", agent_tmp]) + + result = subprocess.run(cmd, cwd=os.getcwd(), capture_output=True, text=True, timeout=600, env=env_vars) + + vids_exist = os.path.exists(topdown_tmp) and os.path.exists(agent_tmp) + + if not vids_exist and result.stderr: + print(f"Visualize stderr: {result.stderr[:500]}") + if not vids_exist and result.stdout: + print(f"Visualize stdout: {result.stdout[:500]}") + + if result.returncode != 0: + print(f"Visualize exited with code {result.returncode} (map index {i})") + if result.stdout: + print(f" stdout: {result.stdout[:500]}") + if result.stderr: + print(f" stderr: {result.stderr[:500]}") + + if vids_exist: + videos = [ + ( + topdown_tmp, + f"epoch_{epoch:06d}_map{i:02d}_topdown.mp4" if map_path else f"epoch_{epoch:06d}_topdown.mp4", + ), + ( + agent_tmp, + f"epoch_{epoch:06d}_map{i:02d}_agent.mp4" if map_path else f"epoch_{epoch:06d}_agent.mp4", + ), + ] + + for source_vid, target_filename in videos: + if os.path.exists(source_vid): + target_path = os.path.join(video_output_dir, target_filename) + shutil.move(source_vid, target_path) + # Accumulate for a single wandb.log call + if hasattr(logger, "wandb") and logger.wandb: + import wandb + + if "topdown" in target_filename: + videos_to_log_world.append(wandb.Video(target_path, format="mp4")) + else: + videos_to_log_agent.append(wandb.Video(target_path, format="mp4")) + else: + print(f"Video generation completed but {source_vid} not found") + else: + print(f"C rendering failed (map index {i}) with exit code {result.returncode}: {result.stdout}\nstderr: {result.stderr}") + + # Log all videos at once so W&B keeps all of them under the same step + if hasattr(logger, "wandb") and logger.wandb and (videos_to_log_world or videos_to_log_agent): + payload = {} + if videos_to_log_world: + payload["render/world_state"] = videos_to_log_world + if videos_to_log_agent: + payload["render/agent_view"] = videos_to_log_agent + logger.wandb.log(payload, step=global_step) + + except subprocess.TimeoutExpired: + print("C rendering timed out") + except Exception as e: + print(f"Failed to generate GIF: {e}") + + finally: + pass diff --git a/pufferlib/vector.py b/pufferlib/vector.py index bf5dc7460e..0df30f7ba3 100644 --- a/pufferlib/vector.py +++ b/pufferlib/vector.py @@ -5,7 +5,6 @@ import time import psutil -from pufferlib.emulation import GymnasiumPufferEnv, PettingZooPufferEnv from pufferlib import PufferEnv, set_buffers import pufferlib.spaces @@ -62,6 +61,7 @@ def num_envs(self): def __init__(self, env_creators, env_args, env_kwargs, num_envs, buf=None, seed=0, **kwargs): self.driver_env = env_creators[0](*env_args[0], **env_kwargs[0]) + self.driver_env.starting_map_counter = 0 # reset map counter for serial envs - only used in evaluation self.agents_per_batch = self.driver_env.num_agents * num_envs self.num_agents = self.agents_per_batch @@ -74,6 +74,7 @@ def __init__(self, env_creators, env_args, env_kwargs, num_envs, buf=None, seed= self.envs = [] ptr = 0 + child_seeds = np.random.SeedSequence(seed).spawn(len(env_creators)) if seed is not None else None for i in range(num_envs): end = ptr + self.driver_env.num_agents buf_i = dict( @@ -85,10 +86,15 @@ def __init__(self, env_creators, env_args, env_kwargs, num_envs, buf=None, seed= actions=self.actions[ptr:end], ) ptr = end - seed_i = seed + i if seed is not None else None + if seed is not None: + seed_i = int(child_seeds[i].generate_state(1)[0]) & 0x7FFFFFFF + else: + seed_i = None env = env_creators[i](*env_args[i], buf=buf_i, seed=seed_i, **env_kwargs[i]) self.envs.append(env) + # Close the initial driver_env used only for configuration (it's not in self.envs) + self.driver_env.close() self.driver_env = driver = self.envs[0] self.emulated = self.driver_env.emulated check_envs(self.envs, self.driver_env) @@ -119,11 +125,12 @@ def _avg_infos(self): def async_reset(self, seed=None): self.flag = RECV infos = [] + child_seeds = np.random.SeedSequence(seed).spawn(len(self.envs)) if seed is not None else None for i, env in enumerate(self.envs): if seed is None: ob, i = env.reset() else: - ob, i = env.reset(seed=seed + i) + ob, i = env.reset(seed=int(child_seeds[i].generate_state(1)[0]) & 0x7FFFFFFF) if isinstance(i, list): infos.extend(i) @@ -174,6 +181,9 @@ def recv(self): self.masks, ) + def get_state(self): + return [env.get_state() for env in self.envs][0] + def close(self): for env in self.envs: env.close() @@ -213,7 +223,7 @@ def _worker_process( if is_native and num_envs == 1: envs = env_creators[0](*env_args[0], **env_kwargs[0], buf=buf, seed=seed) else: - envs = Serial(env_creators, env_args, env_kwargs, num_envs, buf=buf, seed=seed * num_envs) + envs = Serial(env_creators, env_args, env_kwargs, num_envs, buf=buf, seed=seed) semaphores = np.ndarray(num_workers, dtype=np.uint8, buffer=shm["semaphores"]) notify = np.ndarray(num_workers, dtype=bool, buffer=shm["notify"]) @@ -369,11 +379,13 @@ def __init__( w_send_pipes, self.recv_pipes = zip(*[Pipe() for _ in range(num_workers)]) self.recv_pipe_dict = {p: i for i, p in enumerate(self.recv_pipes)} + worker_ss = np.random.SeedSequence(seed).spawn(num_workers) if seed is not None else [None] * num_workers + worker_seeds = [int(ss.generate_state(1)[0]) & 0x7FFFFFFF if ss is not None else None for ss in worker_ss] + self.processes = [] for i in range(num_workers): start = i * envs_per_worker end = start + envs_per_worker - seed_i = seed + i if seed is not None else None p = Process( target=_worker_process, args=( @@ -392,7 +404,7 @@ def __init__( w_recv_pipes[i], self.shm, is_native, - seed_i, + worker_seeds[i], ), ) p.start() @@ -525,10 +537,12 @@ def async_reset(self, seed=0): self.infos = [[] for _ in range(self.num_workers)] self.buf["semaphores"][:] = RESET + worker_ss = ( + np.random.SeedSequence(seed).spawn(self.num_workers) if seed is not None else [None] * self.num_workers + ) for i in range(self.num_workers): - start = i * self.envs_per_worker - end = (i + 1) * self.envs_per_worker - self.send_pipes[i].send(seed + i) + s = int(worker_ss[i].generate_state(1)[0]) & 0x7FFFFFFF if worker_ss[i] is not None else None + self.send_pipes[i].send(s) def notify(self): self.buf["notify"][:] = True @@ -775,15 +789,14 @@ def make_seeds(seed, num_envs): def check_envs(envs, driver): - valid = (PufferEnv, GymnasiumPufferEnv, PettingZooPufferEnv) - if not isinstance(driver, valid): - raise pufferlib.APIUsageError(f"env_creator must be {valid}") + if not isinstance(driver, PufferEnv): + raise pufferlib.APIUsageError("env_creator must be PufferEnv") driver_obs = driver.single_observation_space driver_atn = driver.single_action_space for env in envs: - if not isinstance(env, valid): - raise pufferlib.APIUsageError(f"env_creators must be {valid}") + if not isinstance(env, PufferEnv): + raise pufferlib.APIUsageError("env_creators must be PufferEnv") obs_space = env.single_observation_space if obs_space != driver_obs: raise pufferlib.APIUsageError(f"\n{obs_space}\n{driver_obs} obs space mismatch") diff --git a/pufferlib/viz.py b/pufferlib/viz.py new file mode 100644 index 0000000000..bcfe83c9d4 --- /dev/null +++ b/pufferlib/viz.py @@ -0,0 +1,2174 @@ +"""Bird's Eye View visualization for PufferDrive scenarios using Matplotlib.""" + +import dataclasses +import weakref +from typing import Optional, Tuple + +import math +import matplotlib.figure +import matplotlib.patches as mpatches +import matplotlib.pyplot as plt +import numpy as np +from matplotlib.collections import LineCollection, PatchCollection, PolyCollection +from matplotlib.patches import Circle, Polygon +import os +import json +import zlib +import base64 + +from pufferlib.ocean.drive import binding + + +COLORS = { + "pedestrian": "#2E8B57", + "cyclist": "#FF8C00", + "road_line": "#808080", + "road_edge": "#000000", + "lane": "#D3D3D3", + "crosswalk": "#E6C200", + "speed_bump": "#C90000", + "stop_sign": "#FF0000", + "inactive_agent": "#808080", + "background": "#F5F5F5", +} + +TRAFFIC_LIGHT_COLORS = { + 0: "#808080", + 1: "#FF0000", + 2: "#FFFF00", + 3: "#00FF00", + 4: "#FF0000", + 5: "#FFFF00", + 6: "#00FF00", + 7: "#FF6600", + 8: "#FFFF00", +} + +VEHICLE_COLORS = [ + "#681D00", + "#1F77B4", + "#FF7F0E", + "#2CA02C", + "#9467BD", + "#8C564B", + "#D47CBA", + "#BCBD22", + "#17BECF", + "#AEC7E8", + "#FFBB78", + "#98DF8A", + "#FF9896", + "#C5B0D5", + "#C49C94", + "#F7B6D2", + "#DBDB8D", + "#9EDAE5", +] + +_figure_cache: weakref.WeakValueDictionary = weakref.WeakValueDictionary() +_map_cache = {} + +MULTI_LANE_FULL_SCORE_TIME = binding.MULTI_LANE_FULL_SCORE_TIME +MULTI_LANE_HALF_SCORE_TIME = binding.MULTI_LANE_HALF_SCORE_TIME + +METRIC_LABELS = [ + "collision", + "offroad", + "red_light", + "stop_sign", + "reached_goal", + "lane_dist", + "lane_angle", + "comfort_violation", + "velocity_progress", + "speed_limit", + "ADE", + "progression", + "at_fault_collision", + "ttc", + "ttc_tfl", + "progress_ratio", + "multi_lane_time", + "multi_lane_score", +] + + +@dataclasses.dataclass +class VizConfig: + """Visualization config using radius and center for view bounds.""" + + center: Optional[Tuple[float, float]] = None + radius: Optional[float] = None + figsize: Tuple[float, float] = (20.0, 20.0) + dpi: int = 100 + show_agent_id: bool = True + show_routes: bool = False + show_goal: bool = True + show_sdc_paths: bool = False + show_trajectories: bool = False + goal_radius: float = 2.0 + follow_ego: bool = False + debug_metrics: bool = False + reuse_figure: bool = True + + def get_bounds(self, scenario) -> Tuple[float, float, float, float]: + map_corners = scenario.get("map_corners") + + if self.follow_ego: + ego_agent = scenario.get("agents")[-1] + cx, cy = ego_agent["sim_x"], ego_agent["sim_y"] + elif self.center is not None: + cx, cy = self.center + elif map_corners and len(map_corners) >= 4: + cx, cy = (map_corners[0] + map_corners[2]) / 2, (map_corners[1] + map_corners[3]) / 2 + else: + cx, cy = 0.0, 0.0 + + if self.radius is not None: + r = self.radius + elif map_corners and len(map_corners) >= 4: + r = max(map_corners[2] - map_corners[0], map_corners[3] - map_corners[1]) / 2 * 1.02 + else: + r = 100.0 + return (cx - r, cx + r, cy - r, cy + r) + + +def get_agent_color(agent_id, is_active=True): + return COLORS["inactive_agent"] if not is_active else VEHICLE_COLORS[agent_id % len(VEHICLE_COLORS)] + + +def _init_fig_ax(config: VizConfig, reuse_key: str = None, with_metrics: bool = False): + cache_key = f"{reuse_key}_{'metrics' if with_metrics else 'single'}" if reuse_key else None + + if config.reuse_figure and cache_key and cache_key in _figure_cache: + fig = _figure_cache[cache_key] + if fig and plt.fignum_exists(fig.number): + for ax in fig.axes: + ax.clear() + ax.set_facecolor(COLORS["background"]) + if with_metrics: + return fig, fig.axes[0], fig.axes[1] + return fig, fig.axes[0] + + if with_metrics: + fig, (ax_main, ax_metrics) = plt.subplots( + 1, 2, figsize=(config.figsize[0] * 1.5, config.figsize[1]), gridspec_kw={"width_ratios": [2, 1]} + ) + else: + fig, ax_main = plt.subplots() + fig.set_size_inches(config.figsize) + ax_metrics = None + + fig.set_dpi(config.dpi) + fig.set_facecolor(COLORS["background"]) + ax_main.set_facecolor(COLORS["background"]) + if ax_metrics: + ax_metrics.set_facecolor(COLORS["background"]) + + if config.reuse_figure and cache_key: + _figure_cache[cache_key] = fig + + if with_metrics: + return fig, ax_main, ax_metrics + return fig, ax_main + + +def _build_road_cache(road_elements): + lanes, lines, edges = [], [], [] + lane_dict = {} + for elem in road_elements or []: + if not isinstance(elem, dict): + continue + x, y, t = elem.get("x"), elem.get("y"), elem.get("type", 0) + if not x or not y: + continue + pts = np.column_stack((np.asarray(x), np.asarray(y))) + if 1 <= t <= 3: + lanes.append(pts) + lid = elem.get("id") + if lid is not None: + lane_dict[lid] = pts + elif 11 <= t <= 18: + lines.append(pts) + elif 21 <= t <= 23: + edges.append(pts) + return { + "lanes": lanes, + "lines": lines, + "edges": edges, + "lane_dict": lane_dict, + "collections": None, + } + + +def _render_roads(ax, road_cache): + if not road_cache: + return + collections = road_cache.get("collections") + if collections is None: + collections = [] + lanes = road_cache.get("lanes") or [] + lines = road_cache.get("lines") or [] + edges = road_cache.get("edges") or [] + if lanes: + collections.append(LineCollection(lanes, colors=COLORS["lane"], linewidths=0.8, alpha=0.7, zorder=1)) + if lines: + collections.append( + LineCollection( + lines, + colors=COLORS["road_line"], + linewidths=0.8, + alpha=0.6, + linestyles=(0, (5, 5)), + zorder=2, + ) + ) + if edges: + collections.append(LineCollection(edges, colors=COLORS["road_edge"], linewidths=0.8, alpha=0.8, zorder=2)) + road_cache["collections"] = collections + for collection in collections: + ax.add_collection(collection) + + +def _build_traffic_cache(traffic_elements): + traffic_lights = [] # (stop_line, states) + stop_signs = [] # stop_line endpoints + yield_signs = [] # stop_line endpoints + for elem in traffic_elements or []: + if not isinstance(elem, dict): + continue + t_type = elem.get("type", 1) + sl = elem.get("stop_line") + if sl is None or len(sl) < 4: + continue + if t_type == 1: + traffic_lights.append({"stop_line": sl, "states": elem.get("states", [])}) + elif t_type == 2: + stop_signs.append(sl) + elif t_type == 3: + yield_signs.append(sl) + return { + "traffic_lights": traffic_lights, + "stop_signs": stop_signs, + "yield_signs": yield_signs, + } + + +def _render_traffic(ax, traffic_cache, timestep): + if not traffic_cache: + return + # Traffic lights — colored by state + for light in traffic_cache.get("traffic_lights", []): + sl = light["stop_line"] + states = light["states"] + state = int(states[timestep]) if states and len(states) > timestep else 0 + color = TRAFFIC_LIGHT_COLORS.get(state, "#808080") + ax.plot([sl[0], sl[3]], [sl[1], sl[4]], color=color, linewidth=3, solid_capstyle="butt", alpha=0.9, zorder=15) + + # Stop signs — red/black striped + for sl in traffic_cache.get("stop_signs", []): + ax.plot([sl[0], sl[3]], [sl[1], sl[4]], color="black", linewidth=4, solid_capstyle="butt", alpha=0.9, zorder=15) + ax.plot( + [sl[0], sl[3]], + [sl[1], sl[4]], + color="#FF0000", + linewidth=2.5, + solid_capstyle="butt", + alpha=0.9, + zorder=15, + linestyle=(0, (3, 2)), + ) + + # Yield signs — yellow/black striped + for sl in traffic_cache.get("yield_signs", []): + ax.plot([sl[0], sl[3]], [sl[1], sl[4]], color="black", linewidth=4, solid_capstyle="butt", alpha=0.9, zorder=15) + ax.plot( + [sl[0], sl[3]], + [sl[1], sl[4]], + color="#FFD700", + linewidth=2.5, + solid_capstyle="butt", + alpha=0.9, + zorder=15, + linestyle=(0, (3, 2)), + ) + + +def _render_routes(ax, agents, lane_dict, active_indices): + if not agents or not lane_dict: + return + + active_set = set(active_indices or []) + segments_by_color = {} + for idx, agent in enumerate(agents): + if not isinstance(agent, dict) or idx not in active_set: + continue + route = agent.get("route", []) + if not route: + continue + color = get_agent_color(agent.get("id", idx)) + segs = segments_by_color.setdefault(color, []) + for lid in route: + if lid in lane_dict: + segs.append(lane_dict[lid]) + + for color, segs in segments_by_color.items(): + if segs: + ax.add_collection(LineCollection(segs, colors=color, linewidths=2.0, alpha=0.6, linestyles="--", zorder=5)) + + +def _render_agents(ax, agents, active_indices, static_indices, config, px_per_meter, use_rear_axle=False): + if not agents: + return + active_set, static_set = set(active_indices or []), set(static_indices or []) + vehicles = [] + vehicle_lengths = [] + vehicle_widths = [] + vehicle_headings = [] + vehicle_colors = [] + vehicle_edges = [] + text_items = [] + goal_points = [] + goal_colors = [] + ped_patches = [] + cyclist_patches = [] + font_size = max(12, int(px_per_meter / 5)) + + for idx, agent in enumerate(agents): + if idx not in active_set and idx not in static_set: + continue + if not agent.get("sim_valid"): + continue + x, y = agent.get("sim_x"), agent.get("sim_y") + if x is None or y is None: + continue + + agent_type = agent.get("type", 1) + agent_id = agent.get("id", idx) + is_active = idx in active_set + color = get_agent_color(agent_id, is_active) + edge = "black" if is_active else COLORS["inactive_agent"] + + if agent_type == 1: + if agent.get("stopped"): + color = "red" + length = agent.get("sim_length", 4) + width = agent.get("sim_width", 2) + heading = agent.get("sim_heading", 0) + + vehicles.append((x, y)) + vehicle_lengths.append(length) + vehicle_widths.append(width) + vehicle_headings.append(heading) + vehicle_colors.append(color) + vehicle_edges.append(edge) + + if config.show_agent_id: + text_items.append((x, y + width, str(agent_id))) + + if config.show_goal and is_active: + gx, gy = agent.get("goal_position_x"), agent.get("goal_position_y") + if gx is not None and gy is not None: + goal_points.append((gx, gy)) + goal_colors.append(color) + elif agent_type == 2: + ped_patches.append( + Circle( + (x, y), + radius=0.5, + facecolor=COLORS["pedestrian"], + edgecolor="black", + linewidth=0.7, + alpha=0.85, + zorder=10, + ) + ) + elif agent_type == 3: + cyclist_patches.append( + Circle( + (x, y), + radius=0.8, + facecolor=COLORS["cyclist"], + edgecolor="black", + linewidth=1.5, + alpha=0.85, + zorder=10, + ) + ) + + if vehicles: + centers = np.asarray(vehicles, dtype=float) + lengths = np.asarray(vehicle_lengths, dtype=float) + widths = np.asarray(vehicle_widths, dtype=float) + headings = np.asarray(vehicle_headings, dtype=float) + cos_h = np.cos(headings) + sin_h = np.sin(headings) + half_l = lengths / 2.0 + half_w = widths / 2.0 + base = np.stack( + ( + np.stack((half_l, half_w), axis=1), + np.stack((half_l, -half_w), axis=1), + np.stack((-half_l, -half_w), axis=1), + np.stack((-half_l, half_w), axis=1), + ), + axis=1, + ) + rot_x = base[:, :, 0] * cos_h[:, None] - base[:, :, 1] * sin_h[:, None] + rot_y = base[:, :, 0] * sin_h[:, None] + base[:, :, 1] * cos_h[:, None] + polys = np.stack((rot_x, rot_y), axis=2) + centers[:, None, :] + + ax.add_collection( + PolyCollection( + polys, + facecolors=vehicle_colors, + edgecolors=vehicle_edges, + linewidths=0.7, + alpha=0.8, + zorder=10, + ) + ) + + dx = lengths * 0.6 * cos_h + dy = lengths * 0.6 * sin_h + segments = np.stack((centers, centers + np.stack((dx, dy), axis=1)), axis=1) + ax.add_collection(LineCollection(segments, colors=vehicle_colors, linewidths=0.7, zorder=11)) + + head_len = widths * 0.25 + head_half_width = widths * 0.2 + tip = centers + np.stack((dx, dy), axis=1) + dir_vec = np.stack((cos_h, sin_h), axis=1) + perp_vec = np.stack((-sin_h, cos_h), axis=1) + base_center = tip - dir_vec * head_len[:, None] + left = base_center + perp_vec * head_half_width[:, None] + right = base_center - perp_vec * head_half_width[:, None] + arrows = np.stack((tip, left, right), axis=1) + ax.add_collection( + PolyCollection( + arrows, + facecolors=vehicle_colors, + edgecolors="black", + linewidths=0.3, + zorder=12, + ) + ) + + if text_items: + for x, y, text in text_items: + ax.text( + x, + y, + text, + fontsize=font_size, + color="black", + ha="center", + va="bottom", + fontweight="bold", + zorder=12, + ) + + if goal_points: + gx, gy = zip(*goal_points) + ax.scatter(gx, gy, s=20, c=goal_colors, marker="o", zorder=13) + goal_patches = [Circle((x, y), radius=config.goal_radius) for x, y in goal_points] + ax.add_collection( + PatchCollection( + goal_patches, + facecolors="none", + edgecolors=goal_colors, + linewidths=1.0, + linestyles="--", + zorder=13, + ) + ) + + if ped_patches: + ax.add_collection(PatchCollection(ped_patches, match_original=True)) + if cyclist_patches: + ax.add_collection(PatchCollection(cyclist_patches, match_original=True)) + + +def _render_paths(ax, scenario): + """Render SDC planned paths.""" + for idx in range(scenario["active_agent_count"]): + x = np.array([item["x"] for item in scenario["sdc_paths"][idx]["waypoints"]]) + y = np.array([item["y"] for item in scenario["sdc_paths"][idx]["waypoints"]]) + init_idx = scenario["agents"][scenario["active_agent_indices"][idx]]["closest_path_idx_wp"] + end_idx = min(init_idx + 20, scenario["sdc_paths"][idx]["num_waypoints"] - 1) + agent_id = scenario["agents"][scenario["active_agent_indices"][idx]]["id"] + color = get_agent_color(agent_id, is_active=True) + ax.scatter(x[init_idx:end_idx], y[init_idx:end_idx], color=color, s=20) + + +def _render_trajectories(ax, scenario): + for idx in range(scenario["active_agent_count"]): + wps = scenario["trajectory_waypoints_global"][idx]["waypoints"] + x = np.array([item["x"] for item in wps]) + y = np.array([item["y"] for item in wps]) + heading = np.array([item["heading"] for item in wps]) + ax.scatter(x, y, color=np.array([0, 100, 0]) / 255.0, s=20) + ax.quiver( + x, + y, + np.cos(heading), + np.sin(heading), + color=np.array([0, 100, 0]) / 255.0, + scale_units="xy", # Use data coordinates for scaling + scale=1.0, # A scale of 1.0 means arrows of length (U,V) are plotted as such + width=0.005, + ) + + +def _render_debug_metrics_table(ax, agents, active_agent_indices, px_per_meter=10.0): + """Render a table of per-agent metrics for debugging.""" + font_size = max(10, int(px_per_meter / 5)) + + if not agents or not active_agent_indices: + ax.text(0.5, 0.5, "No active agents", ha="center", va="center", fontsize=font_size) + ax.axis("off") + return + + active_set = set(active_agent_indices) + + # Gather metrics for active agents + metrics_data = [] + for idx, agent in enumerate(agents): + if idx not in active_set: + continue + agent_id = agent["id"] + vx, vy = agent.get("sim_vx", 0), agent.get("sim_vy", 0) + speed = np.sqrt(vx**2 + vy**2) + current_lane_id = agent.get("current_lane_index", -1) + metrics = agent.get("metrics_array", [0.0] * len(METRIC_LABELS)) + metrics_data.append( + { + "id": agent_id, + "current_lane": current_lane_id, + "speed": speed, + "lane_dist": metrics[5], + "lane_head": metrics[6], + "offroad": metrics[1], + "collision": metrics[0], + "comfort": metrics[7], + "red_light": metrics[2], + "at_fault": metrics[12], + "ttc": metrics[13], + "ttc_tfl": metrics[14], + "progress": metrics[15], + "ml_time": metrics[16] if len(metrics) > 16 else 0.0, + "color": get_agent_color(agent_id, is_active=True), + } + ) + + if not metrics_data: + ax.text(0.5, 0.5, "No active agents", ha="center", va="center", fontsize=font_size) + ax.axis("off") + return + + ax.axis("off") + ax.set_xlim(0, 1) + ax.set_ylim(0, 1) + + # Remove margins + ax.margins(0) + + # Table headers + headers = [ + "ID", + "Lane", + "LDist", + "LHead", + "Spd", + "Cmft", + "Off", + "Col", + "Red", + "AF", + "TTC", + "TTC_TFL", + "Prog", + "MLt", + ] + num_agents = len(metrics_data) + y_start, y_end = 0.95, 0.05 + row_height = min(0.06, (y_start - y_end) / (num_agents + 2)) + x_positions = np.linspace(0.02, 0.96, len(headers)) + for i, header in enumerate(headers): + ax.text(x_positions[i], y_start, header, fontsize=font_size + 2, fontweight="bold", va="top") + + for row_idx, data in enumerate(metrics_data): + y_pos = y_start - (row_idx + 1) * row_height + ax.text( + x_positions[0], y_pos, str(data["id"]), fontsize=font_size, color=data["color"], fontweight="bold", va="top" + ) + ax.text(x_positions[1], y_pos, f"{data['current_lane']:.0f}", fontsize=font_size, va="top") + ax.text(x_positions[2], y_pos, f"{data['lane_dist']:.2f}", fontsize=font_size, va="top") + ax.text(x_positions[3], y_pos, f"{data['lane_head']:.2f}", fontsize=font_size, va="top") + ax.text(x_positions[4], y_pos, f"{data['speed']:.1f}", fontsize=font_size, va="top") + ax.text( + x_positions[5], + y_pos, + f"{data['comfort']:.1f}", + fontsize=font_size, + color="red" if data["comfort"] > 0 else "green", + va="top", + ) + ax.text( + x_positions[6], + y_pos, + "+" if data["offroad"] else "-", + fontsize=font_size, + color="red" if data["offroad"] else "green", + va="top", + ) + ax.text( + x_positions[7], + y_pos, + "+" if data["collision"] else "-", + fontsize=font_size, + color="red" if data["collision"] else "green", + va="top", + ) + ax.text( + x_positions[8], + y_pos, + "+" if data["red_light"] else "-", + fontsize=font_size, + color="red" if data["red_light"] else "green", + va="top", + ) + ax.text( + x_positions[9], + y_pos, + "+" if data["at_fault"] else "-", + fontsize=font_size, + color="red" if data["at_fault"] else "green", + va="top", + ) + ax.text( + x_positions[10], + y_pos, + f"{data['ttc']:.2f}", + fontsize=font_size, + color="red" if data["ttc"] < 0.95 else "green", + va="top", + ) + ax.text( + x_positions[11], + y_pos, + f"{data['ttc_tfl']:.2f}", + fontsize=font_size, + color="red" if data["ttc_tfl"] < 0.95 else "green", + va="top", + ) + ax.text( + x_positions[12], + y_pos, + f"{data['progress']:.2f}", + fontsize=font_size, + color="green" if data["progress"] > 0.2 else "red", + va="top", + ) + ax.text( + x_positions[13], + y_pos, + f"{data['ml_time']:.1f}", + fontsize=font_size, + color="red" if data["ml_time"] > MULTI_LANE_FULL_SCORE_TIME else "green", + va="top", + ) + + ax.set_title("Active Agent Metrics + V-Max", fontsize=font_size + 4, fontweight="bold", pad=10) + + +def _get_cache_key(reuse_key): + return reuse_key + + +def _get_or_build_map_cache(cache_key, scenario): + if cache_key: + cache = _map_cache.get(cache_key) + map_name = scenario.get("map_name") + if cache and cache.get("map_name") == map_name: + return cache + road_cache = _build_road_cache(scenario.get("road_elements", [])) + traffic_cache = _build_traffic_cache(scenario.get("traffic_elements", [])) + cache = { + "map_name": map_name, + "road": road_cache, + "traffic": traffic_cache, + } + _map_cache[cache_key] = cache + return cache + + return { + "map_name": scenario.get("map_name"), + "road": _build_road_cache(scenario.get("road_elements", [])), + "traffic": _build_traffic_cache(scenario.get("traffic_elements", [])), + } + + +def plot_simulator_state( + scenario, + timestep: int = 0, + show_trajectories: bool = False, + simulation_mode: str = None, + reuse_key: str = None, + use_rear_axle: bool = False, +) -> np.ndarray: + """Render simulator state to RGB image array.""" + vis_radius = None if simulation_mode == "gigaflow" or simulation_mode is None else 75.0 + vis_config = VizConfig(radius=vis_radius, show_trajectories=show_trajectories) + + cache_key = _get_cache_key(reuse_key) + map_cache = _get_or_build_map_cache(cache_key, scenario) + + bounds = vis_config.get_bounds(scenario) + x_min, x_max, y_min, y_max = bounds + + px_per_meter = min( + vis_config.figsize[0] * vis_config.dpi / (x_max - x_min), + vis_config.figsize[1] * vis_config.dpi / (y_max - y_min), + ) + + if vis_config.debug_metrics: + fig, ax, ax_metrics = _init_fig_ax(vis_config, cache_key, with_metrics=True) + else: + fig, ax = _init_fig_ax(vis_config, cache_key, with_metrics=False) + ax_metrics = None + + ax.set_aspect("equal") + ax.set_title( + f"PufferDrive | {scenario.get('dataset_name', '')} | {scenario.get('scenario_id', '')} | t={timestep}", + fontsize=max(14, int(px_per_meter / 8)), + fontweight="bold", + ) + + _render_roads(ax, map_cache.get("road")) + _render_traffic(ax, map_cache.get("traffic"), timestep) + if vis_config.show_routes: + _render_routes( + ax, + scenario.get("agents", []), + map_cache.get("road", {}).get("lane_dict"), + scenario.get("active_agent_indices", []), + ) + if vis_config.show_sdc_paths: + _render_paths(ax, scenario) + if vis_config.show_trajectories and timestep > 0: + _render_trajectories(ax, scenario) + + _render_agents( + ax, + scenario.get("agents", []), + scenario.get("active_agent_indices", []), + scenario.get("static_agent_indices", []), + vis_config, + px_per_meter, + use_rear_axle, + ) + + ax.set_xlim(x_min, x_max) + ax.set_ylim(y_min, y_max) + + if vis_config.debug_metrics and ax_metrics: + _render_debug_metrics_table( + ax_metrics, + scenario.get("agents", []), + scenario.get("active_agent_indices", []), + px_per_meter=px_per_meter, + ) + + close_fig = not (vis_config.reuse_figure and cache_key) + return _img_from_fig(fig, close=close_fig) + + +def _img_from_fig(fig: matplotlib.figure.Figure, close: bool = True) -> np.ndarray: + fig.subplots_adjust(left=0.01, bottom=0.02, right=1.00, top=0.96) + fig.canvas.draw() + data = np.frombuffer(fig.canvas.tostring_argb(), dtype=np.uint8) + img = data.reshape(fig.canvas.get_width_height()[::-1] + (4,))[:, :, 1:] + if close: + plt.close(fig) + return img + + +def close_figure(reuse_key: str): + if not reuse_key: + return + for suffix in ("single", "metrics"): + cache_key = f"{reuse_key}_{suffix}" + fig = _figure_cache.pop(cache_key, None) + if fig and plt.fignum_exists(fig.number): + plt.close(fig) + _map_cache.pop(reuse_key, None) + + +def unpack_obs( + obs_flat, + dynamics_model: int = 0, + target_type: str = "static", + reward_conditioning: bool = False, + num_target_waypoints: int = 5, + max_partners: int = 16, + max_lane_segments: int = 16, + max_boundary_segments: int = 16, + max_traffic_lights: int = 16, + max_stop_signs: int = 10, + agent_idx: int = 0, +): + """ + Unpack the flattened observation into the ego state and visible state. + Args: + obs_flat: flattened observation tensor of shape (batch_size, obs_dim) + dynamics_model: 0 for CLASSIC, 1 for JERK + target_type: 0 for goal only, 1 for waypoints only, 2 for both + Return: + ego_state, partners_obs, lane_obs, boundary_obs, traffic_obs, gps_obs, include_goal, include_waypoints + """ + ego_dim = binding.EGO_FEATURES_JERK if dynamics_model == "jerk" else binding.EGO_FEATURES_CLASSIC + + # Partner obs + partner_feature_size = binding.PARTNER_FEATURES + # Road obs + road_feature_size = binding.ROAD_FEATURES + # Traffic light obs + traffic_feature_size = binding.TRAFFIC_LIGHT_FEATURES + # Stop sign obs + stop_sign_feature_size = binding.STOP_SIGN_FEATURES + + # Target obs + target_features = binding.STATIC_TARGET_FEATURES if target_type == "static" else binding.DYNAMIC_TARGET_FEATURES + target_dim = num_target_waypoints * target_features + + if max_stop_signs > 0: + ego_dim += 1 + + # Extract ego state + ego_state = obs_flat[:, :ego_dim] + + target_start = ego_dim + if reward_conditioning: + target_start += binding.NUM_REWARD_COEFS + + target_end = target_start + target_dim + target_obs = obs_flat[:, target_start:target_end] + target_obs = target_obs.reshape(-1, num_target_waypoints, target_features) + + # Extract partners + partners_start = target_end + partners_end = partners_start + max_partners * partner_feature_size + partners_obs = obs_flat[:, partners_start:partners_end] + partners_obs = partners_obs.reshape(-1, max_partners, partner_feature_size) + + # Extract lane elements + lane_start = partners_end + lane_end = lane_start + max_lane_segments * road_feature_size + lane_obs = obs_flat[:, lane_start:lane_end] + lane_obs = lane_obs.reshape(-1, max_lane_segments, road_feature_size) + + # Extract boundary elements + boundary_start = lane_end + boundary_end = boundary_start + max_boundary_segments * road_feature_size + boundary_obs = obs_flat[:, boundary_start:boundary_end] + boundary_obs = boundary_obs.reshape(-1, max_boundary_segments, road_feature_size) + + # Extract traffic lights + traffic_start = boundary_end + traffic_end = traffic_start + max_traffic_lights * traffic_feature_size + if max_traffic_lights > 0: + traffic_obs = obs_flat[:, traffic_start:traffic_end] + traffic_obs = traffic_obs.reshape(-1, max_traffic_lights, traffic_feature_size) + else: + traffic_obs = np.zeros((obs_flat.shape[0], 0, traffic_feature_size)) + + # Extract stop signs + stop_sign_start = traffic_end + stop_sign_end = stop_sign_start + max_stop_signs * stop_sign_feature_size + if max_stop_signs > 0: + stop_sign_obs = obs_flat[:, stop_sign_start:stop_sign_end] + stop_sign_obs = stop_sign_obs.reshape(-1, max_stop_signs, stop_sign_feature_size) + else: + stop_sign_obs = np.zeros((obs_flat.shape[0], 0, stop_sign_feature_size)) + + return ( + ego_state[agent_idx], + target_obs[agent_idx], + partners_obs[agent_idx], + lane_obs[agent_idx], + boundary_obs[agent_idx], + traffic_obs[agent_idx], + stop_sign_obs[agent_idx], + ) + + +def plot_observation( + obs, + dynamics_model="classic", + target_type="static", + reward_conditioning=False, + num_target_waypoints=10, + max_partners=16, + max_lane_segments=32, + max_boundary_segments=32, + max_traffic_lights=4, + max_stop_signs=4, + agent_idx=0, + use_rear_axle=False, +) -> np.ndarray: + """Plot observation in ego-centric frame. + + Args: + obs: flattened observation tensor + dynamics_model: 0 for CLASSIC, 1 for JERK + target_type: 0 for goal only, 1 for waypoints only, 2 for both + """ + fig, ax = plt.subplots(figsize=(20, 20)) + + ego_state, target_obs, partners_obs, lane_obs, boundary_obs, traffic_obs, stop_sign_obs = unpack_obs( + obs, + dynamics_model, + target_type, + reward_conditioning, + num_target_waypoints, + max_partners, + max_lane_segments, + max_boundary_segments, + max_traffic_lights, + max_stop_signs, + agent_idx, + ) + + if dynamics_model == "jerk": + ego_speed, ego_width, ego_length, steering_angle, a_long, a_lat, lcenter, lalign, speed_limit = ego_state + else: + ego_speed, ego_width, ego_length, lcenter, lalign, speed_limit = ego_state + + # Ego vehicle at origin + ax.add_patch( + mpatches.Rectangle( + (-ego_length / 2, -ego_width / 2), + ego_length, + ego_width, + facecolor="blue", + edgecolor="black", + linewidth=2, + alpha=0.7, + zorder=10, + ) + ) + + # Draw target waypoints + for i in range(target_obs.shape[0]): + if np.all(target_obs[i] == 0): + continue + wp_x, wp_y = target_obs[i][0], target_obs[i][1] + if target_type == "static": + color = "red" if i == 0 else "orange" + marker = "*" if i == 0 else "o" + s = 200 if i == 0 else 80 + else: + color = "magenta" + marker = "o" + s = 100 + ax.scatter(wp_x, wp_y, color=color, marker=marker, s=s, zorder=15) + + # Add dynamics info text for JERK model + ego_info = f"Speed: {ego_speed:.2f}\nLane Centering: {lcenter:.2f}\nLane Align: {lalign:.2f}\nSpeed Limit: {speed_limit:.2f}" + + if dynamics_model == "jerk": + ego_info += f"\nSteering: {steering_angle:.3f}\na_long: {a_long:.2f}\na_lat: {a_lat:.2f}" + + ax.text( + 0.02, + 0.98, + ego_info, + transform=ax.transAxes, + fontsize=10, + verticalalignment="top", + bbox=dict(boxstyle="round", facecolor="wheat", alpha=0.8), + ) + + # Partner agents + for i in range(partners_obs.shape[0]): + if np.all(partners_obs[i] == 0): + continue + rel_x, rel_y, width, length, heading_cos, heading_sin, speed = partners_obs[i] + heading = np.arctan2(heading_sin, heading_cos) + + rect = mpatches.Rectangle( + (-length / 2, -width / 2), + length, + width, + facecolor="gray", + edgecolor="black", + linewidth=1, + alpha=0.6, + zorder=9, + ) + rect.set_transform(plt.matplotlib.transforms.Affine2D().rotate(heading).translate(rel_x, rel_y) + ax.transData) + ax.add_patch(rect) + + # Road elements + count_lane = 0 + for i in range(lane_obs.shape[0]): + if np.all(lane_obs[i] == 0): + continue + count_lane += 1 + rel_x, rel_y, length, width, dir_cos, dir_sin = lane_obs[i] + color = "lightgrey" + ax.scatter(rel_x, rel_y, color=color, s=10, zorder=1) + ax.plot( + [rel_x + dir_cos * length / 2, rel_x - dir_cos * length / 2], + [rel_y + dir_sin * length / 2, rel_y - dir_sin * length / 2], + color=color, + linewidth=1, + zorder=1, + ) + + count_boundary = 0 + for i in range(boundary_obs.shape[0]): + if np.all(boundary_obs[i] == 0): + continue + count_boundary += 1 + rel_x, rel_y, length, width, dir_cos, dir_sin = boundary_obs[i] + color = "black" + ax.scatter(rel_x, rel_y, color=color, s=10, zorder=1) + ax.plot( + [rel_x + dir_cos * length / 2, rel_x - dir_cos * length / 2], + [rel_y + dir_sin * length / 2, rel_y - dir_sin * length / 2], + color=color, + linewidth=1, + zorder=1, + ) + + ax.text( + 0.12, + 0.95, + f"Lanes: {count_lane}\nBoundaries: {count_boundary}", + transform=ax.transAxes, + fontsize=10, + verticalalignment="top", + bbox=dict(boxstyle="round", facecolor="wheat", alpha=0.8), + ) + + # Traffic lights (stop lines) + for i in range(traffic_obs.shape[0]): + if np.all(traffic_obs[i] == 0): + continue + rel_x1, rel_y1, rel_x2, rel_y2, state_normalized = traffic_obs[i] + + if state_normalized == 0: + state = 4 + elif state_normalized == 1: + state = 2 + elif state_normalized == 2: + state = 6 + else: + state = 0 + + ax.plot( + [rel_x1, rel_x2], + [rel_y1, rel_y2], + color=TRAFFIC_LIGHT_COLORS[state], + linewidth=2.5, + solid_capstyle="round", + alpha=0.9, + zorder=12, + ) + + # Stop signs + for i in range(stop_sign_obs.shape[0]): + if np.all(stop_sign_obs[i] == 0): + continue + rel_x, rel_y, _ = stop_sign_obs[i] + + radius = 0.02 + angles = np.linspace(0, 2 * np.pi, 9) + octagon_x = rel_x + radius * np.cos(angles + np.pi / 8) + octagon_y = rel_y + radius * np.sin(angles + np.pi / 8) + octagon_points = np.column_stack((octagon_x, octagon_y)) + ax.add_patch( + plt.Polygon( + xy=octagon_points, + alpha=0.9, + facecolor=COLORS.get("stop_sign", "#808080"), + edgecolor="red", + linewidth=1, + zorder=12, + ) + ) + + ax.axis((-1, 1, -1, 1)) + ax.set_aspect("equal", adjustable="box") + ax.set_xlabel("X (ego frame)", fontsize=16) + ax.set_ylabel("Y (ego frame)", fontsize=16) + ax.set_title("Observation (Ego-Centric View)", fontsize=18, fontweight="bold") + # ax.grid(True, alpha=0.3) + return _img_from_fig(fig) + + +# HTML INTERACTIVE REPLAY +def fill_agents_state(scenario, use_trajectory=False): + current_agents_data = [] + active_indices = scenario.get("active_agent_indices", []) + + # Actions + if use_trajectory: + raw_actions = scenario.get("ctrl_trajectory_actions", []) + else: + raw_actions = scenario.get("actions", []) + action_map = {} + if raw_actions and len(raw_actions) == len(active_indices): + for i, agent_idx in enumerate(active_indices): + action_map[agent_idx] = raw_actions[i] + + for idx, agent in enumerate(scenario.get("agents", [])): + if not agent.get("sim_valid"): + continue + + agent_id = agent.get("id", idx) + is_active = idx in active_indices + + # Couleur + if agent.get("stopped", False): + color = "red" + else: + color = get_agent_color(agent_id, is_active) + req_acc = float(action_map[idx][0]) if idx in action_map else 0.0 + req_str = float(action_map[idx][1]) if idx in action_map else 0.0 + + # On arrondit tout pour alléger le JSON final + current_agents_data.append( + { + "id": int(agent_id), + "x": round(float(agent["sim_x"]), 2), + "y": round(float(agent["sim_y"]), 2), + "h": round(float(agent["sim_heading"]), 3), + "l": round(float(agent["sim_length"]), 2), + "w": round(float(agent["sim_width"]), 2), + "s": round(float(agent.get("sim_speed", 0)), 2), + "st": round(float(agent.get("sim_steering", 0)), 3), + "c": color, + # Commandes + "ra": round(req_acc, 2), + "rs": round(req_str, 2), + # Compact metrics array (M1..M18) + "m": [round(float(m), 2) for m in agent.get("metrics_array")], + } + ) + + return current_agents_data + + +def fill_traffics_state(scenario, timestep): + current_traffic_data = [] + traffic_elements = scenario.get("traffic_elements", []) + for elem in traffic_elements or []: + if not isinstance(elem, dict): + continue + + t_type = elem.get("type", 1) + sl = elem.get("stop_line") + if sl is None or len(sl) < 4: + continue + + if t_type == 1: + states = elem.get("states", []) + state = int(states[timestep]) if states and len(states) > timestep else 0 + color = TRAFFIC_LIGHT_COLORS.get(state, "#808080") + current_traffic_data.append({"type": "light", "stop_line": sl, "c": color}) + elif t_type == 2: + current_traffic_data.append({"type": "stop", "stop_line": sl, "c": "#FF0000", "c2": "#000000"}) + elif t_type == 3: + current_traffic_data.append({"type": "yield", "stop_line": sl, "c": "#FFD700", "c2": "#000000"}) + + return current_traffic_data + + +def fill_trajectories(scenario, timestep): + current_trajectories = [] + if timestep > 0: + traj_data = scenario.get("trajectory_waypoints_global", []) + active_count = scenario.get("active_agent_count", 0) + + # On itère seulement sur les agents actifs qui ont des trajectoires + for idx in range(min(len(traj_data), active_count)): + waypoints = traj_data[idx].get("waypoints", []) + pts = [] + for wp in waypoints: + pts.append([float(wp["x"]), float(wp["y"]), float(wp["heading"])]) + + current_trajectories.append(pts) + return current_trajectories + + +def extract_obs_frame(obs, scenario, args, timestep, obs_index=0, agent_idx=0, head_north=False): + ego_state, target_obs, partners_obs, lane_obs, boundary_obs, traffic_obs, stop_sign_obs = unpack_obs( + obs, + dynamics_model=args["env"]["dynamics_model"], + target_type=args["env"]["target_type"], + reward_conditioning=args["env"]["reward_conditioning"], + num_target_waypoints=args["env"]["num_target_waypoints"], + max_partners=args["env"]["max_partner_observations"], + max_lane_segments=args["env"]["max_lane_segment_observations"], + max_boundary_segments=args["env"]["max_boundary_segment_observations"], + max_traffic_lights=args["env"]["max_traffic_light_observations"], + max_stop_signs=args["env"]["max_stop_sign_observations"], + agent_idx=obs_index, + ) + + # --- Rotation Helper --- + def _rot(x, y): + """Rotates coordinates 90 degrees CCW if head_north is True.""" + return (-y, x) if head_north else (x, y) + + # --- Parse Ego --- + if args["env"]["dynamics_model"] == "jerk": + ego_speed, ego_width, ego_length, steering_angle, a_long, a_lat = ego_state[:6] + else: + ego_speed, ego_width, ego_length = ego_state[:3] + steering_angle, a_long, a_lat = 0.0, 0.0, 0.0 + + ego_data = { + "s": round(float(ego_speed), 3), + "w": round(float(ego_width), 3), + "l": round(float(ego_length), 3), + "st": round(float(steering_angle), 3), + "al": round(float(a_long), 3), + "alat": round(float(a_lat), 3), + } + + # --- Parse Road Segments --- + def parse_roads(roads): + res = [] + for r in roads: + if np.all(r == 0): + continue + x, y = r[0], r[1] + length, width = r[2], r[3] + cos_a, sin_a = r[4], r[5] + if head_north: + x_rot, y_rot = _rot(x, y) + cos_rot, sin_rot = _rot(cos_a, sin_a) + else: + x_rot, y_rot = x, y + cos_rot, sin_rot = cos_a, sin_a + res.append( + [ + round(float(x_rot), 4), + round(float(y_rot), 4), + round(float(length), 4), + round(float(width), 4), + round(float(cos_rot), 4), + round(float(sin_rot), 4), + ] + ) + return res + + # --- Parse Partners --- + parsed_partners = [] + for p in partners_obs: + if np.all(p == 0): + continue + + px, py = _rot(p[0], p[1]) + h = math.atan2(p[5], p[4]) + + if head_north: + h += math.pi / 2 + h = (h + math.pi) % (2 * math.pi) - math.pi + + parsed_partners.append( + { + "x": round(float(px), 3), + "y": round(float(py), 3), + "w": round(float(p[2]), 3), + "l": round(float(p[3]), 3), + "h": round(float(h), 3), + "s": round(float(p[6]), 3), + } + ) + + # --- Parse Traffic Lights --- + parsed_lights = [] + for t in traffic_obs: + if np.all(t == 0): + continue + lx, ly = _rot(t[0], t[1]) + parsed_lights.append({"x": round(float(lx), 3), "y": round(float(ly), 3), "state": int(t[-1])}) + + # --- Parse Stop Signs --- + parsed_stops = [] + for s in stop_sign_obs: + if np.all(s == 0): + continue + sx, sy = _rot(s[0], s[1]) + parsed_stops.append({"x": round(float(sx), 3), "y": round(float(sy), 3)}) + + # --- Parse Trajectory & GPS --- + traj_data = [] + if ("trajectory" in args["env"]["action_type"] or args.get("show_trajectories")) and timestep > 0: + wps = scenario["trajectory_waypoints_local"][agent_idx]["waypoints"] + for wp in wps: + wx, wy = _rot(float(wp["x"]) / 70.0, float(wp["y"]) / 70.0) + traj_data.append({"x": round(wx, 4), "y": round(wy, 4)}) + + gps_data = [] + for g in target_obs: + if np.all(g == 0): + continue + gx, gy = _rot(g[0], g[1]) + gps_data.append([round(float(gx), 3), round(float(gy), 3)]) + + return { + "ego": ego_data, + "partners": parsed_partners, + "lanes": parse_roads(lane_obs), + "bounds": parse_roads(boundary_obs), + "lights": parsed_lights, + "stops": parsed_stops, + "traj": traj_data, + "gps": gps_data, + } + + +def generate_interactive_replay( + scenario, + agent_history, + traffic_history, + trajectory_history, + all_agents_obs_history, + filename="replay.html", + head_north=False, + use_rear_axle=False, +): + # --- 0. COMPRESSION HELPER --- + def pack_and_compress_data(data, decimals=3): + # Recursively round all floats to save string space + def round_floats(o): + if isinstance(o, float): + return round(o, decimals) + if isinstance(o, dict): + return {k: round_floats(v) for k, v in o.items()} + if isinstance(o, (list, tuple)): + return [round_floats(v) for v in o] + return o + + # Dump without whitespace + compact_json = json.dumps(round_floats(data), separators=(",", ":")) + + # Compress using zlib (deflate) + compressed_bytes = zlib.compress(compact_json.encode("utf-8")) + + # Return as Base64 string for safe HTML embedding + return base64.b64encode(compressed_bytes).decode("ascii") + + # --- 1. METADATA --- + raw_dyn = scenario.get("dynamics_model", 0) + dyn_str = "Jerk" if raw_dyn == 1 else "Classic" + + metadata = { + "map_name": scenario.get("map_name", "Unknown"), + "scenario_id": scenario.get("scenario_id", "Unknown"), + "dynamics_model": dyn_str, + "target_type": scenario.get("target_type", "static"), + "active_indices": str(scenario.get("active_agent_indices", [])), + } + + # --- 2. MAP DATA --- + map_data = {"lanes": [], "lines": [], "edges": []} + for elem in scenario.get("road_elements", []): + if not isinstance(elem, dict): + continue + t = elem.get("type", 0) + if "x" in elem and "y" in elem: + pts = [[float(x), float(y)] for x, y in zip(elem["x"], elem["y"])] + if 1 <= t <= 3: + map_data["lanes"].append(pts) + elif 11 <= t <= 18: + map_data["lines"].append(pts) + elif 21 <= t <= 23: + map_data["edges"].append(pts) + + # --- 3. TEMPLATE HTML --- + html_template = """ + + + + PufferDrive Replay XXL + + + +
Unpacking Replay Data...
+
+
SPACE: Play | ARROWS: Step | ESC: Free | CLICK: Follow | ENTER: Search
+ +
+
+

Scenario Info

+
Map
-
+
ID
-
+
+
Step
0
+
Camera Mode
+
Free Roam
+ +
+ +
+
⚠ COLLISION ⚠
+

☰ DRAG | Agent ?

+ +
+
+
Speed
+
0.0 km/h
+
+
+
Req Acc/Str
+
0.0 / 0.0
+
+
+ + + +
Metrics Table
+
+ +
Position (X/Y)
+
0 , 0
+
+ +
+
☰ DRAG TO MOVE | EGO-CENTRIC NN OBS
+ +
+ + + +
+ + + +
+
+ + + + + + + """ + + # --- 4. PACKAGE, COMPRESS, AND INJECT --- + master_payload = { + "map": map_data, + "agents": agent_history, + "traffic": traffic_history, + "traj": trajectory_history, + "meta": metadata, + "obs": all_agents_obs_history, + "head_north": head_north, + "use_rear_axle": use_rear_axle, + } + + print("Compressing replay data, this might take a second...") + compressed_payload = pack_and_compress_data(master_payload, decimals=3) + + try: + final_html = html_template.replace("__COMPRESSED_PAYLOAD__", compressed_payload) + with open(filename, "w") as f: + f.write(final_html) + print(f"Success! Saved optimized replay to {filename}") + except Exception as e: + print(f"Error: {e}") + + +def build_gallery_index(folder_path="."): + # Assuming files still start with "map_" based on your example + files = [f for f in os.listdir(folder_path) if f.startswith("map_") and f.endswith(".html")] + + if not files: + print("No matching .html files found in this directory.") + return + + def sort_key(filename): + # 1. Strip the '.html' extension + name_no_ext = filename[:-5] + + # 2. Split from the right exactly once + # e.g., "map_000_000" -> ["map_000", "000"] + parts = name_no_ext.rsplit("_", 1) + + env_map_name = parts[0] + global_episode_id = int(parts[1]) + + # 3. Sort first by episode ID, then by map name + return (global_episode_id, env_map_name) + + files.sort(key=sort_key) + + # 3. Build the HTML template + html_content = """ + + + + + PufferDrive Replay Gallery + + + +
+
PUFFERDRIVE GALLERY
+ + + +
+ + + + + + + """ + + # 4. Inject the options into the dropdown + options_html = "\n".join( + [f'' for f in files] + ) + + final_html = html_content.replace("__OPTIONS__", options_html).replace("__FIRST__", files[0]) + + # 5. Save the file + index_path = os.path.join(folder_path, "index.html") + with open(index_path, "w") as f: + f.write(final_html) diff --git a/scripts/build_ocean.sh b/scripts/build_ocean.sh index f090291120..ea9c2322f2 100755 --- a/scripts/build_ocean.sh +++ b/scripts/build_ocean.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Usage: ./build_env.sh pong [local|fast|web] +# Usage: ./build_ocean.sh visualize [local|fast] ENV=$1 MODE=${2:-local} @@ -11,72 +11,13 @@ if [ "$ENV" = "visualize" ]; then else SRC_DIR="pufferlib/ocean/$ENV" fi -WEB_OUTPUT_DIR="build_web/$ENV" + RAYLIB_NAME='raylib-5.5_macos' -BOX2D_NAME='box2d-macos-arm64' if [ "$PLATFORM" = "Linux" ]; then RAYLIB_NAME='raylib-5.5_linux_amd64' - BOX2D_NAME='box2d-linux-amd64' -fi -if [ "$MODE" = "web" ]; then - RAYLIB_NAME='raylib-5.5_webassembly' - BOX2D_NAME='box2d-web' -fi - -LINK_ARCHIVES="./$RAYLIB_NAME/lib/libraylib.a" -if [ "$ENV" = "impulse_wars" ]; then - LINK_ARCHIVES="$LINK_ARCHIVES ./$BOX2D_NAME/libbox2d.a" fi -# Create build output directory -mkdir -p "$WEB_OUTPUT_DIR" - -if [ "$MODE" = "web" ]; then - echo "Building $ENV for web deployment..." - - # Add MAX_AGENTS override for drive environment - EXTRA_FLAGS="" - if [ "$ENV" = "drive" ]; then - EXTRA_FLAGS="-DMAX_AGENTS=10" - echo "Setting MAX_AGENTS=10 for drive web build" - fi - - emcc \ - -o "$WEB_OUTPUT_DIR/game.html" \ - "$SRC_DIR/$ENV.c" \ - -O3 \ - -Wall \ - $LINK_ARCHIVES \ - -I./$RAYLIB_NAME/include \ - -I./$BOX2D_NAME/include \ - -I./$BOX2D_NAME/src \ - -I./pufferlib/extensions \ - -I./pufferlib \ - -L. \ - -L./$RAYLIB_NAME/lib \ - -sASSERTIONS=2 \ - -gsource-map \ - -s USE_GLFW=3 \ - -s USE_WEBGL2=1 \ - -s ASYNCIFY \ - -sFILESYSTEM \ - -s FORCE_FILESYSTEM=1 \ - --shell-file ./scripts/minshell.html \ - -sINITIAL_MEMORY=512MB \ - -sALLOW_MEMORY_GROWTH \ - -sSTACK_SIZE=512KB \ - -DNDEBUG \ - -DPLATFORM_WEB \ - -DGRAPHICS_API_OPENGL_ES3 \ - $EXTRA_FLAGS \ - --preload-file pufferlib/resources/$1@resources/$1 \ - #--preload-file pufferlib/resources/shared@resources/shared - echo "Web build completed: $WEB_OUTPUT_DIR/game.html" - echo "Preloaded files:" - echo " pufferlib/resources/$1@resources$1" - echo " pufferlib/resources/shared@resources/shared" - exit 0 -fi +LINK_ARCHIVES="./extern/$RAYLIB_NAME/lib/libraylib.a" # Detect available compiler and set compiler-specific flags if command -v clang >/dev/null 2>&1; then @@ -91,13 +32,11 @@ fi FLAGS=( -Wall - -I./$RAYLIB_NAME/include - -I./$BOX2D_NAME/include - -I./$BOX2D_NAME/src + -I./extern/$RAYLIB_NAME/include -I./pufferlib/extensions - -I./inih-r62 + -I./extern/inih-r62 "$SRC_DIR/$ENV.c" -o "$ENV" - ./inih-r62/ini.c + ./extern/inih-r62/ini.c $LINK_ARCHIVES -lm -lpthread @@ -105,7 +44,6 @@ FLAGS=( -DPLATFORM_DESKTOP ) - if [ "$PLATFORM" = "Darwin" ]; then FLAGS+=( -framework Cocoa @@ -119,18 +57,21 @@ echo ${FLAGS[@]} if [ "$MODE" = "local" ]; then echo "Building $ENV for local testing..." if [ "$PLATFORM" = "Linux" ]; then - # These important debug flags don't work on macos FLAGS+=( -fsanitize=address,undefined,bounds,pointer-overflow,leak -fno-omit-frame-pointer ) fi $COMPILER -g -O0 ${FLAGS[@]} +elif [ "$MODE" = "profile-debug" ]; then + echo "Building profiling-enabled $ENV (no inlining, perf-friendly)..." + $COMPILER -g -O1 -fno-inline -fno-omit-frame-pointer -DNDEBUG ${FLAGS[@]} + echo "Built to: $ENV" elif [ "$MODE" = "fast" ]; then echo "Building optimized $ENV for local testing..." - $COMPILER -pg -O2 -DNDEBUG ${FLAGS[@]} + $COMPILER -O2 -DNDEBUG ${FLAGS[@]} echo "Built to: $ENV" else - echo "Invalid mode specified: local|fast|web" + echo "Invalid mode: $MODE (use local|fast|profile-debug)" exit 1 fi diff --git a/scripts/cluster_configs/nyu_greene.yaml b/scripts/cluster_configs/nyu_greene.yaml new file mode 100644 index 0000000000..fc537c5c3d --- /dev/null +++ b/scripts/cluster_configs/nyu_greene.yaml @@ -0,0 +1,10 @@ +# NYU Greene cluster compute configuration +account: torch_pr_355_general # Set your account/allocation +nodes: 1 +gpus: 1 +cpus: 16 +mem: 32gb +time: 360 # minutes +gpu_type: null # rtx8000, a100, v100 (optional, uses partition default) +exclude: null +nodelist: null diff --git a/scripts/cluster_configs/train_base.yaml b/scripts/cluster_configs/train_base.yaml new file mode 100644 index 0000000000..921beeb681 --- /dev/null +++ b/scripts/cluster_configs/train_base.yaml @@ -0,0 +1,23 @@ +# Base training configuration for PufferDrive cluster jobs +# These args are passed to `puffer train puffer_drive` + +# Vectorization +vec.num_workers: 16 +vec.num_envs: 16 + +# Environment +env.num_agents: 1024 +env.map_dir: "pufferlib/resources/drive/binaries/carla" +env.num_maps: 8 + +# Training +train.total_timesteps: 2_000_000_000 +train.checkpoint_interval: 1000 + +# Rendering +train.render: True + +# W&B logging +wandb: True +wandb_project: pufferdrive +wandb_group: cluster diff --git a/scripts/eval/benchmark_comparison.py b/scripts/eval/benchmark_comparison.py new file mode 100644 index 0000000000..0928b10dfe --- /dev/null +++ b/scripts/eval/benchmark_comparison.py @@ -0,0 +1,57 @@ +import pandas as pd +from pathlib import Path + +BENCHMARK_DIR = Path("benchmark") +SUMMARY_FILE = "evaluation_summary.csv" + +DROP_METRICS = {"episode_id", "dnf_rate", "episode_return"} +META_COLS = [ + "model_name", + "xp", + "eval_mode", + "score", + "collision_rate", + "offroad_rate", + "red_light_violation_rate", + # "stop_sign_violation_rate", + "num_goals_reached", + "avg_speed_per_agent", +] + +rows = [] + +for model_dir in BENCHMARK_DIR.iterdir(): + if not model_dir.is_dir(): + continue + + for summary_path in model_dir.rglob(SUMMARY_FILE): + # model/xp/eval_mode/evaluation_summary.csv + try: + xp = summary_path.parents[1].name + eval_mode = summary_path.parent.name + except IndexError: + continue + + df = pd.read_csv(summary_path) # Metric | Average + + metrics = {metric: value for metric, value in zip(df["Metric"], df["Average"]) if metric not in DROP_METRICS} + + row = { + "model_name": model_dir.name, + "xp": xp, + "eval_mode": eval_mode, + **metrics, + } + rows.append(row) + +# Build dataframe +out_df = pd.DataFrame(rows) +out_df = out_df.round(3) + +# Enforce column order +metric_cols = [c for c in out_df.columns if c not in META_COLS] +out_df = out_df[META_COLS + metric_cols] + +out_df.to_csv("benchmark/benchmark_summary.csv", index=False) + +print("✅ Saved benchmark_all_summaries.csv") diff --git a/scripts/eval/run_all_eval.sh b/scripts/eval/run_all_eval.sh new file mode 100755 index 0000000000..b2e425a84e --- /dev/null +++ b/scripts/eval/run_all_eval.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +BASE_DIR="experiments" +COMMAND_PREFIX="puffer eval_multi_scenarios puffer_drive" + +# Defaults +NUM_SCENARIOS=50 +RENDER=0 +RENDER_OBS=0 +EVAL_SIMULATION="replay" + +# Parse command-line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --num_scenarios) + NUM_SCENARIOS="$2" + shift 2 + ;; + --eval_simulation) + EVAL_SIMULATION="$2" + shift 2 + ;; + --render) + RENDER="$2" + shift 2 + ;; + --render_obs) + RENDER_OBS="$2" + shift 2 + ;; + *) + echo "❌ Unknown argument: $1" + exit 1 + ;; + esac +done + +COMMAND_SUFFIX="--num_scenarios ${NUM_SCENARIOS} --render ${RENDER} --render_obs ${RENDER_OBS} --eval_simulation ${EVAL_SIMULATION}" + +if [ ! -d "$BASE_DIR" ]; then + echo "Error: Directory '$BASE_DIR' not found." + echo "Please run this script from the directory containing '$BASE_DIR/'" + exit 1 +fi + +echo "🚀 Starting evaluation for all experiments in '$BASE_DIR'..." +echo " num_scenarios = ${NUM_SCENARIOS}" +echo " eval_simulation = ${EVAL_SIMULATION}" +echo "---" + +for exp_path in ${BASE_DIR}/*/; do + MODELS_DIR="${exp_path}/models/" + echo "Processing experiment: ${exp_path}" + + LATEST_MODEL=$(ls -1 ${MODELS_DIR}*.pt 2>/dev/null | grep -v "trainer_state.pt" | sort -V | tail -n 1) + + if [ -z "${LATEST_MODEL}" ]; then + echo " [SKIP] No '.pt' model files found in ${MODELS_DIR}." + echo "---" + continue + fi + + echo " ✅ Found latest model: ${LATEST_MODEL}" + FULL_COMMAND="${COMMAND_PREFIX} --load-model-path ${LATEST_MODEL} ${COMMAND_SUFFIX}" + echo " ▶️ Executing:" + echo " ${FULL_COMMAND}" + + ${FULL_COMMAND} + echo "---" +done + +echo "🎉 All experiments processed." diff --git a/scripts/eval/run_all_latest_eval.py b/scripts/eval/run_all_latest_eval.py new file mode 100644 index 0000000000..b130183c3f --- /dev/null +++ b/scripts/eval/run_all_latest_eval.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 + +import argparse +import shlex +import shutil +import subprocess +from pathlib import Path + + +def parse_args(): + parser = argparse.ArgumentParser( + description="Run `puffer eval puffer_drive` on the latest model from each run folder." + ) + parser.add_argument("--runs-dir", default="runs", help="Directory containing run folders") + parser.add_argument("--num_scenarios", type=int, default=20, help="Number of scenarios for eval") + parser.add_argument( + "--command-prefix", + default="puffer eval_multi_scenarios_render puffer_drive --eval_simulation gigaflow --render 1 --render_obs 1 --num_carla_maps 2", + help="Full base command to run before --load-model-path and --num_scenarios are appended", + ) + parser.add_argument("--dry-run", action="store_true", help="Print commands without executing") + parser.add_argument( + "--stop-on-error", + action="store_true", + help="Stop execution when one evaluation fails", + ) + return parser.parse_args() + + +def latest_model_in_run(run_dir): + models_dir = run_dir / "models" + if not models_dir.is_dir(): + return None + + candidates = [path for path in models_dir.glob("*.pt") if path.is_file() and "trainer_state" not in path.name] + if not candidates: + return None + + return max(candidates, key=lambda path: path.stat().st_mtime) + + +def list_run_dirs(runs_dir): + return sorted([path for path in runs_dir.iterdir() if path.is_dir()]) + + +def build_command(prefix, model_path, num_scenarios): + return [*shlex.split(prefix), "--load-model-path", str(model_path), "--num_scenarios", str(num_scenarios)] + + +def move_videos_to_run(run_dir, workspace_dir): + source = workspace_dir / "videos" + if not source.is_dir(): + print(" -> no videos directory found to move") + return + + target = run_dir / "videos" + if target.exists(): + shutil.rmtree(target) + + shutil.move(str(source), str(target)) + print(f" -> moved videos to {target}") + + +def main(): + args = parse_args() + runs_dir = Path(args.runs_dir) + + if not runs_dir.is_dir(): + raise SystemExit(f"Error: runs directory not found: {runs_dir}") + + run_dirs = list_run_dirs(runs_dir) + if not run_dirs: + raise SystemExit(f"Error: no run directories found in {runs_dir}") + + selected = [(run_dir, latest_model_in_run(run_dir)) for run_dir in run_dirs] + + selected = [(run_dir, model_path) for run_dir, model_path in selected if model_path is not None] + + if not selected: + raise SystemExit(f"Error: no model files found under {runs_dir}/*/models") + + print(f"Found {len(selected)} runs with models in {runs_dir}\n") + + failures = [] + for run_dir, model_path in selected: + cmd = build_command(args.command_prefix, model_path, args.num_scenarios) + cmd_str = " ".join(shlex.quote(part) for part in cmd) + print(f"[{run_dir.name}] {cmd_str}") + + if args.dry_run: + continue + + result = subprocess.run(cmd, cwd=Path.cwd()) + if result.returncode != 0: + failures.append((run_dir.name, model_path, result.returncode)) + print(f" -> failed with exit code {result.returncode}\n") + if args.stop_on_error: + break + else: + move_videos_to_run(run_dir, Path.cwd()) + print(" -> done\n") + + if failures: + print("Failures:") + for run_name, model_path, code in failures: + print(f"- {run_name}: {model_path} (exit={code})") + raise SystemExit(1) + + print("All evaluations completed.") + + +if __name__ == "__main__": + main() diff --git a/scripts/eval/run_failure_scenarios.py b/scripts/eval/run_failure_scenarios.py new file mode 100644 index 0000000000..dab3296016 --- /dev/null +++ b/scripts/eval/run_failure_scenarios.py @@ -0,0 +1,101 @@ +import pandas as pd +import subprocess + +# --- Configuration --- +# Set the path to your CSV file +CSV_FILE_PATH = "benchmark/puffer_drive_0jb42gn1/model_puffer_drive_000700/episode_metrics.csv" + +# Base command components +BASE_COMMAND_PREFIX = "puffer eval_multi_scenarios puffer_drive --load-model-path experiments/puffer_drive_0jb42gn1/best_models/model_puffer_drive_000700.pt --num_scenarios 500 --render 1 --render_obs 1" +BASE_COMMAND_SUFFIX = "" # Can be used for extra args if needed + + +def get_failed_scenario_indices(csv_path): + """ + Reads the episode metrics CSV and returns a list of scenario indices + (episode_id) where a failure (collision, offroad, or traffic light violation) occurred. + """ + try: + # 1. Read the CSV file + df = pd.read_csv(csv_path) + except FileNotFoundError: + print(f"Error: File not found at {csv_path}") + return None + except Exception as e: + print(f"Error reading CSV: {e}") + return None + + # Ensure required columns exist + required_columns = ["episode_id", "offroad_rate", "collision_rate", "red_light_violation_rate"] + + # Check if all necessary columns are present + if not all(col in df.columns for col in required_columns if col != "traffic_light_rate"): + print( + f"Error: CSV is missing one or more required columns: {', '.join(col for col in ['episode_id', 'offroad_rate', 'collision_rate', 'traffic_light_rate'] if col not in df.columns)}" + ) + return [] + + # 2. Define the failure condition + # Check if any of the specified rates is greater than 0 + failure_condition = (df["collision_rate"] > 0) | (df["offroad_rate"] > 0) + + if "traffic_light_rate" in df.columns: + failure_condition = failure_condition | (df["traffic_light_rate"] > 0) + + # 3. Filter and extract the episode_id (which acts as the map index) + failed_indices = df[failure_condition]["episode_id"].tolist() + + # The map indices for the command should be an integer list (or a list of strings of integers) + # The 'episode_id' column in the screenshot is an integer index starting from 0. + return [str(int(i)) for i in failed_indices] + + +def execute_puffer_command(indices): + """ + Constructs and executes the puffer eval command. + """ + if not indices: + print("\n✅ No failed scenarios found. Nothing to render.") + return + + # Join the indices with a space + indices_str = " ".join(indices) + + # Construct the final command string + final_command = f"{BASE_COMMAND_PREFIX} --map_indices {indices_str}" + + print("\n--- 🔨 Command to be executed ---") + print(final_command) + print("---------------------------------") + + # Execute the command + try: + print("\n🚀 Executing command via subprocess...") + # Use shell=True for convenience, but it's generally safer to pass a list + # For simplicity with a complex string command, we use shell=True here. + process = subprocess.run(final_command, shell=True, check=True, text=True, capture_output=True) + + print("\n✅ Command execution finished.") + print("--- Subprocess Output (Stdout) ---") + print(process.stdout) + + if process.stderr: + print("--- Subprocess Errors (Stderr) ---") + print(process.stderr) + + except subprocess.CalledProcessError as e: + print(f"\n❌ ERROR: Command failed with exit code {e.returncode}") + print("--- Subprocess Errors (Stderr) ---") + print(e.stderr) + except FileNotFoundError: + print("\n❌ ERROR: 'puffer' or related command not found. Ensure your environment is correctly set up.") + except Exception as e: + print(f"\n❌ An unexpected error occurred during command execution: {e}") + + +if __name__ == "__main__": + failed_scenario_indices = get_failed_scenario_indices(CSV_FILE_PATH) + + if failed_scenario_indices is not None: + print(f"\nFound {len(failed_scenario_indices)} failed scenarios: {', '.join(failed_scenario_indices)}") + execute_puffer_command(failed_scenario_indices) diff --git a/scripts/render_maps.py b/scripts/render_maps.py new file mode 100644 index 0000000000..3a80d1e172 --- /dev/null +++ b/scripts/render_maps.py @@ -0,0 +1,105 @@ +"""Render all maps showing road discretization: lanes, edges, and grid cells.""" +import os +import shutil +import tempfile +import matplotlib +matplotlib.use('Agg') +import matplotlib.pyplot as plt +import numpy as np +from collections import Counter +from pufferlib.ocean.drive import drive + +map_dir = "pufferlib/resources/drive/binaries/carla" +maps = sorted(f for f in os.listdir(map_dir) if f.endswith(".bin")) + +for map_file in maps: + map_path = os.path.join(map_dir, map_file) + map_name = map_file.replace(".bin", "") + print(f"Rendering {map_name}...") + + tmpdir = tempfile.mkdtemp() + shutil.copy(map_path, os.path.join(tmpdir, map_file)) + + try: + env = drive.Drive( + num_agents=32, + num_maps=1, + map_dir=tmpdir, + dynamics_model="jerk", + simulation_mode="gigaflow", + min_agents_per_env=1, + max_agents_per_env=32, + scenario_length=1024, + ) + env.reset() + state = env.get_state() + if isinstance(state, list): + state = state[0] + + road_elements = state.get("road_elements", []) + type_counts = Counter() + for elem in road_elements: + type_counts[elem.get("type", -1)] += 1 + print(f" Road element types: {dict(type_counts)}") + + fig, ax = plt.subplots(1, 1, figsize=(20, 20)) + ax.set_facecolor('#1a1a1a') + ax.set_aspect('equal') + ax.set_title(f"{map_name} — Road Discretization", fontsize=16, color='white') + + # Color by type + type_colors = { + # Lanes (drivable) + 1: ('green', 'Drivable Lane', 0.6), + 2: ('limegreen', 'Lane Type 2', 0.6), + 3: ('darkgreen', 'Lane Type 3', 0.6), + # Lines + 11: ('yellow', 'Road Line', 0.4), + 12: ('gold', 'Line Type 12', 0.4), + 13: ('orange', 'Line Type 13', 0.4), + 14: ('darkorange', 'Line Type 14', 0.4), + 15: ('khaki', 'Line Type 15', 0.4), + 16: ('wheat', 'Line Type 16', 0.4), + 17: ('lightyellow', 'Line Type 17', 0.4), + 18: ('palegoldenrod', 'Line Type 18', 0.4), + # Edges + 21: ('red', 'Road Edge', 0.8), + 22: ('orangered', 'Edge Type 22', 0.8), + 23: ('darkred', 'Edge Type 23', 0.8), + } + + plotted_types = set() + for elem in road_elements: + x = elem.get("x", []) + y = elem.get("y", []) + t = elem.get("type", 0) + if not x or not y: + continue + + color, label, lw = type_colors.get(t, ('gray', f'Type {t}', 0.3)) + show_label = t not in plotted_types + plotted_types.add(t) + ax.plot(x, y, color=color, linewidth=lw, alpha=0.7, + label=label if show_label else None) + + ax.legend(loc='upper right', fontsize=10, facecolor='#333', labelcolor='white') + ax.tick_params(colors='white') + for spine in ax.spines.values(): + spine.set_color('white') + + out_path = f"/tmp/map_{map_name}_discretized.png" + fig.savefig(out_path, dpi=150, bbox_inches='tight', facecolor='#1a1a1a') + plt.close(fig) + print(f" Saved to {out_path}") + env.close() + except Exception as e: + import traceback + traceback.print_exc() + print(f" ERROR: {e}") + finally: + shutil.rmtree(tmpdir) + +print("\nDone! Opening all maps...") +for map_file in maps: + map_name = map_file.replace(".bin", "") + os.system(f"open /tmp/map_{map_name}_discretized.png") diff --git a/scripts/submit_cluster.py b/scripts/submit_cluster.py new file mode 100644 index 0000000000..377f0b7b2d --- /dev/null +++ b/scripts/submit_cluster.py @@ -0,0 +1,451 @@ +""" +Submitit script for launching PufferDrive training jobs on SLURM clusters. + +Example usage: + # Single job with config file + python scripts/submit_cluster.py \ + --save_dir /path/to/experiments \ + --compute_config scripts/cluster_configs/nyu_greene.yaml \ + --program_config scripts/cluster_configs/train_base.yaml + + # Sweep over learning rates + python scripts/submit_cluster.py \ + --save_dir /path/to/experiments \ + --compute_config scripts/cluster_configs/nyu_greene.yaml \ + --args learning_rate=1e-4:3e-4:1e-3 + + # Override compute settings + python scripts/submit_cluster.py \ + --save_dir /path/to/experiments \ + --compute_config scripts/cluster_configs/nyu_greene.yaml \ + --gpus 4 --time 120 + + # Dry run (preview commands without submitting) + python scripts/submit_cluster.py \ + --save_dir /path/to/experiments \ + --compute_config scripts/cluster_configs/nyu_greene.yaml \ + --dry + + # Run inside Singularity container (for glibc compatibility) + python scripts/submit_cluster.py \ + --save_dir /path/to/experiments \ + --compute_config scripts/cluster_configs/nyu_greene.yaml \ + --program_config scripts/cluster_configs/train_base.yaml \ + --container +""" + +import argparse +import hashlib +import json +import os +import pprint +import time +from typing import List, Optional, Tuple, Dict + +import yaml +import submitit + + +def parse_args(): + parser = argparse.ArgumentParser(description="Submit PufferDrive training jobs to SLURM cluster") + + # Job management + parser.add_argument("--save_dir", type=str, required=True, help="Base directory for experiment outputs") + parser.add_argument("--prefix", type=str, default=None, help="Prefix for job names and wandb run name") + parser.add_argument("--wandb-name", type=str, default=None, help="Wandb run name (defaults to --prefix)") + parser.add_argument("--wandb-group", type=str, default=None, help="Wandb group name (overrides program config)") + parser.add_argument("--wandb-project", type=str, default=None, help="Wandb project name (overrides program config)") + parser.add_argument("--dry", action="store_true", help="Dry run (don't submit, just print commands)") + + # Config files + parser.add_argument("--compute_config", type=str, default=None, help="YAML file with SLURM settings") + parser.add_argument("--program_config", type=str, default=None, help="YAML file with training args") + + # SLURM settings (override compute_config) + parser.add_argument("--account", type=str, help="SLURM account") + parser.add_argument("--partition", type=str, help="SLURM partition") + parser.add_argument("--cpus", type=int, default=None, help="CPUs per task") + parser.add_argument("--gpus", type=int, default=None, help="GPUs per node") + parser.add_argument("--nodes", type=int, default=None, help="Number of nodes") + parser.add_argument("--gpu_type", type=str, default=None, help="GPU type (a100/v100/etc)") + parser.add_argument("--nodelist", type=str, default=None, help="Specific nodes to use") + parser.add_argument("--mem", type=str, default=None, help="Memory per node (e.g., 32gb)") + parser.add_argument("--exclude", type=str, default="", help="Nodes to exclude") + parser.add_argument("--time", type=int, default=None, help="Time limit in minutes") + parser.add_argument("--task_per_node", type=int, default=1, help="Tasks per node") + parser.add_argument("--max_pjob", type=int, default=None, help="Max parallel jobs") + + # Program settings + parser.add_argument( + "--main", type=str, default="-m pufferlib.pufferl train puffer_drive", help="Main command to run" + ) + parser.add_argument( + "--args", type=str, nargs="+", default=None, help="Args to override/sweep (e.g., learning_rate=1e-4:3e-4)" + ) + + # Container settings + parser.add_argument("--container", action="store_true", help="Run inside Singularity container") + parser.add_argument( + "--container_image", + type=str, + default="/share/apps/images/cuda12.8.1-cudnn9.8.0-ubuntu24.04.2.sif", + help="Singularity image path", + ) + parser.add_argument( + "--container_overlay", + type=str, + default="/scratch/ev2237/containers/pufferdrive/overlay.ext3", + help="Singularity overlay path", + ) + + args = parser.parse_args() + return args + + +def process_main_args(main_args: Optional[List[str]], program_config: Optional[str]) -> Tuple[List[Dict], List[str]]: + """Process arguments and expand sweep syntax (colon-separated values).""" + from_config = {} + if program_config is not None: + from_config = yaml.safe_load(open(program_config, "r")) + print("Loaded base config:") + pprint.pprint(from_config) + + full_args = [from_config] + if main_args is None: + return full_args, [] + + override_keys = [] + for arg in main_args: + new_full_args = [] + if "=" not in arg: + raise ValueError(f"Invalid argument format: '{arg}'. Expected 'key=value' or 'key=val1:val2'") + key, vals = arg.split("=", 1) + override_keys.append(key) + vals = vals.split(":") + for val in vals: + for args in full_args: + new_args = args.copy() + new_args[key] = val + new_full_args.append(new_args) + full_args = new_full_args + + return full_args, override_keys + + +def generate_dict_hash(params_dict: Dict, hash_len: int = 7) -> str: + """Generate a short hash of the params dict for unique job naming.""" + hash_obj = hashlib.sha1(json.dumps(params_dict, sort_keys=True).encode()) + return hash_obj.hexdigest()[:hash_len] + + +def get_all_commands(args) -> Dict[str, Tuple[List[str], str]]: + """Generate all commands to run (expanding sweeps).""" + all_main_args, overrides = process_main_args(args.args, args.program_config) + name2commands = {} + + # Keys to exclude from auto-generated job name (paths, wandb config, common overrides) + name_skip_keys = { + "config", + "config_path", + "map_dir", + "env.map_dir", + "init_mode", + "env.init_mode", + "total_timesteps", + "train.total_timesteps", + "wandb_project", + "wandb_group", + "wandb_name", + } + # Boolean flags that don't take values (store_true) + boolean_flags = {"wandb", "neptune"} + + for main_args in all_main_args: + cmd = [] + name_entries = [] + + if args.program_config is not None: + name_entries.append(args.program_config.split("/")[-1].rsplit(".", 1)[0]) + + for key, val in main_args.items(): + # Convert underscores to dashes for CLI compatibility + cli_key = key.replace("_", "-") + + # Handle boolean flags that don't take values + if key in boolean_flags: + if val in (True, "True", "true", "1"): + cmd.append(f"--{cli_key}") + # Skip if False - don't add the flag at all + else: + cmd.append(f"--{cli_key}") + cmd.append(str(val)) + + if key in overrides and key not in name_skip_keys: + display_key = key.split(".")[-1] if "." in key else key + name_entries.append(f"{display_key}{val}") + + job_name = "_".join(name_entries) if name_entries else "pufferdrive" + # Sanitize job name + job_name = ( + job_name[:128] + .replace("{", "") + .replace("}", "") + .replace("'", "") + .replace('"', "") + .replace(":", "") + .replace("/", "") + ) + job_name += "_" + generate_dict_hash(main_args) + + if args.prefix is not None: + job_name = f"{args.prefix}_{job_name}" + + # Wandb overrides: explicit flags take priority, then prefix for name + wandb_name = args.wandb_name or args.prefix + if wandb_name is not None: + cmd.extend(["--wandb-name", wandb_name]) + if args.wandb_group is not None: + cmd.extend(["--wandb-group", args.wandb_group]) + if args.wandb_project is not None: + cmd.extend(["--wandb-project", args.wandb_project]) + + save_dir = os.path.join(args.save_dir, job_name) + name2commands[job_name] = (cmd, save_dir) + + return name2commands + + +def submit(args, job_name: str, command: List[str], save_dir: str, dry: bool): + """Submit a single job to SLURM via submitit.""" + # Load compute config + from_config = {} + if args.compute_config is not None: + from_config = yaml.safe_load(open(args.compute_config, "r")) + from_config = {k: v for k, v in from_config.items() if v is not None} + + # Override with CLI args + for key in ["account", "partition", "cpus", "gpus", "gpu_type", "mem", "nodes", "time", "nodelist", "exclude"]: + if vars(args)[key] is not None: + from_config[key] = vars(args)[key] + + print(">>> Compute config:") + pprint.pprint(from_config) + + # Set up executor + executor = submitit.AutoExecutor(folder=os.path.join(save_dir, "submitit")) + + # Build GRES string for GPUs + if from_config.get("gpu_type") is not None: + gres = f"gpu:{from_config['gpu_type']}:{from_config['gpus']}" + elif from_config.get("gpus") is not None: + gres = f"gpu:{from_config['gpus']}" + else: + gres = None + + if not os.path.exists(save_dir): + os.makedirs(save_dir) + + additional_parameters = {} + if from_config.get("nodelist") is not None: + additional_parameters["nodelist"] = from_config["nodelist"] + + executor.update_parameters( + slurm_account=from_config.get("account"), + slurm_partition=from_config.get("partition"), + cpus_per_task=from_config.get("cpus", 8) // args.task_per_node, + tasks_per_node=args.task_per_node, + nodes=from_config.get("nodes", 1), + slurm_gres=gres, + slurm_exclude=from_config.get("exclude") or None, + slurm_mem=from_config.get("mem"), + slurm_time=from_config.get("time", 60), + slurm_job_name=job_name, + slurm_additional_parameters=additional_parameters, + ) + + def launch_training(args, from_config, cmd, save_dir, project_root, container_config=None): + """Runs inside the SLURM allocation.""" + import glob + import os + import shutil + import subprocess + import sys + import submitit + + # Code isolation: symlink top-level entries, hard copy pufferlib/ source + # (symlink resources/ to avoid copying 3.7GB of maps/models). + isolated_root = os.path.join(save_dir, "code") + if os.path.exists(isolated_root): + version = 1 + while os.path.exists(f"{isolated_root}_v{version}"): + version += 1 + isolated_root = f"{isolated_root}_v{version}" + os.makedirs(isolated_root, exist_ok=True) + # Symlink each top-level entry (instant, avoids deep-copying data/) + for entry in os.listdir(project_root): + src = os.path.join(project_root, entry) + dst = os.path.join(isolated_root, entry) + if os.path.exists(dst) or os.path.islink(dst): + if os.path.isdir(dst) and not os.path.islink(dst): + shutil.rmtree(dst) + else: + os.remove(dst) + os.symlink(src, dst) + # Hard copy pufferlib/ so branch switches don't break running jobs. + # Previously used `cp -rs` (symlinks) which meant switching branches + # after submission would silently change the code running jobs use. + # We symlink resources/ (3.7GB of maps/models) to avoid slow copies, + # but hard copy everything else (source code, .so files). + pufferlib_dst = os.path.join(isolated_root, "pufferlib") + if os.path.islink(pufferlib_dst): + os.remove(pufferlib_dst) + elif os.path.isdir(pufferlib_dst): + shutil.rmtree(pufferlib_dst) + pufferlib_src = os.path.join(project_root, "pufferlib") + shutil.copytree( + pufferlib_src, + pufferlib_dst, + symlinks=False, + ignore=shutil.ignore_patterns("resources"), + ) + # Symlink resources/ (large static data, safe to share) + resources_src = os.path.join(pufferlib_src, "resources") + resources_dst = os.path.join(pufferlib_dst, "resources") + if os.path.isdir(resources_src): + os.symlink(resources_src, resources_dst) + project_root = isolated_root + + # Change to project directory and set up environment + os.chdir(project_root) + os.environ["PYTHONPATH"] = project_root + ":" + os.environ.get("PYTHONPATH", "") + + nodes = from_config.get("nodes", 1) + gpus = from_config.get("gpus", 1) + + # Parse the main command + main_parts = args.main.split() + + if nodes == 1: + base_cmd = [ + "torchrun", + "--standalone", + "--nproc_per_node", + str(gpus), + ] + main_parts + else: + env = submitit.JobEnvironment() + master_addr = env.hostnames[0] + os.environ["MASTER_ADDR"] = master_addr + os.environ["MASTER_PORT"] = "29500" + + base_cmd = [ + "torchrun", + "--nnodes", + str(nodes), + "--nproc_per_node", + str(gpus), + "--rdzv-backend", + "c10d", + "--rdzv-id", + str(env.job_id), + "--rdzv-endpoint", + f"{master_addr}:29500", + ] + main_parts + + # Add save_dir to command + full_cmd = base_cmd + cmd + ["--train.data-dir", save_dir] + + # Wrap with singularity if container mode is enabled + if container_config is not None: + env_setup = "source /ext3/env.sh" + # Redirect caches to scratch to avoid home quota issues + scratch_dir = os.environ.get("SCRATCH_DIR", "/scratch/" + os.environ.get("USER", "")) + cache_exports = ( + f"export XDG_CACHE_HOME={scratch_dir}/cache && " + f"export MPLCONFIGDIR={scratch_dir}/cache/matplotlib && " + f"export WANDB_CACHE_DIR={scratch_dir}/wandb_cache && " + f"export WANDB_CONFIG_DIR={scratch_dir}/wandb_config && " + f"export WANDB_DATA_DIR={scratch_dir}/wandb_data && " + f"export WANDB_DIR={scratch_dir}/wandb_data && " + f"mkdir -p {scratch_dir}/cache/matplotlib" + ) + inner_cmd = f"{env_setup} && {cache_exports} && cd {project_root} && " + " ".join(full_cmd) + full_cmd = [ + "singularity", + "exec", + "--nv", + "--overlay", + container_config["overlay"] + ":ro", # Read-only overlay for running + ] + # Bind mount SSL certificates for TLS verification (wandb, etc.) + for cert_path in ["/etc/ssl/certs", "/etc/pki"]: + if os.path.exists(cert_path): + full_cmd.extend(["--bind", f"{cert_path}:{cert_path}:ro"]) + full_cmd.extend( + [ + container_config["image"], + "bash", + "-c", + inner_cmd, + ] + ) + + print(f">>> Job: {job_name}") + print(f">>> Working directory: {project_root}") + print(f">>> Container: {container_config is not None}") + print(f">>> Command: {' '.join(full_cmd)}") + subprocess.run(full_cmd, check=True) + + # Get project root (directory containing this script's parent) + project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + # Build container config if enabled + container_config = None + if args.container: + container_config = { + "image": args.container_image, + "overlay": args.container_overlay, + } + print(f">>> Container mode enabled: {container_config['image']}") + + if not dry: + job = executor.submit(launch_training, args, from_config, command, save_dir, project_root, container_config) + print(f"Submitted job {job.job_id}: {job_name}") + return job + else: + print(f"[DRY RUN] Would submit: {job_name}") + return None + + +def wait_if_full(jobs: List, max_pjob: Optional[int]): + """Wait if we've hit the max parallel job limit.""" + + def remove_done_jobs(jobs): + for i in range(len(jobs) - 1, -1, -1): + if jobs[i].done(): + jobs.pop(i) + return len(jobs) + + if max_pjob is None: + return + + while remove_done_jobs(jobs) >= max_pjob and len(jobs) > 0: + print(f"Reached max jobs ({len(jobs)}), waiting...") + time.sleep(120) + + print(f"{len(jobs)} jobs remaining, launching new job") + + +if __name__ == "__main__": + args = parse_args() + name2commands = get_all_commands(args) + + print(f">>> Will submit {len(name2commands)} job(s)") + jobs = [] + for name, (cmd, save_dir) in name2commands.items(): + job = submit(args, name, cmd, save_dir, args.dry) + if job is not None: + jobs.append(job) + wait_if_full(jobs, args.max_pjob) + + print("All jobs launched!") diff --git a/setup.py b/setup.py index ea1692af66..c63db150cc 100644 --- a/setup.py +++ b/setup.py @@ -1,114 +1,77 @@ # Debug command: # DEBUG=1 python setup.py build_ext --inplace --force -# CUDA_VISIBLE_DEVICES=None LD_PRELOAD=$(gcc -print-file-name=libasan.so) python3.12 -m pufferlib.clean_pufferl eval --train.device cpu from setuptools import find_packages, find_namespace_packages, setup, Extension import numpy import os -import glob import urllib.request import zipfile import tarfile import platform -import shutil import sys from setuptools.command.build_ext import build_ext from torch.utils import cpp_extension -from torch.utils.cpp_extension import ( - CppExtension, - CUDAExtension, -) +from torch.utils.cpp_extension import CppExtension, CUDAExtension, CUDA_HOME, ROCM_HOME + +# build cuda extension if torch can find CUDA or HIP/ROCM in the system +# may require `uv pip install --no-build-isolation` or `python setup.py build_ext --inplace` +BUILD_CUDA_EXT = bool(CUDA_HOME or ROCM_HOME) # Build with DEBUG=1 to enable debug symbols DEBUG = os.getenv("DEBUG", "0") == "1" NO_OCEAN = os.getenv("NO_OCEAN", "0") == "1" NO_TRAIN = os.getenv("NO_TRAIN", "0") == "1" -# Build raylib for your platform +EXTERNAL_LIB_DIR = "extern" +os.makedirs(EXTERNAL_LIB_DIR, exist_ok=True) + RAYLIB_URL = "https://github.com/raysan5/raylib/releases/download/5.5/" RAYLIB_NAME = "raylib-5.5_macos" if platform.system() == "Darwin" else "raylib-5.5_linux_amd64" RLIGHTS_URL = "https://raw.githubusercontent.com/raysan5/raylib/refs/heads/master/examples/shaders/rlights.h" - -# Fetch inih library INIH_URL = "https://github.com/benhoyt/inih/archive/refs/tags/{tag}.{ext}" -def download_raylib(platform, ext): - if not os.path.exists(platform): - print(f"Downloading Raylib {platform}") - urllib.request.urlretrieve(RAYLIB_URL + platform + ext, platform + ext) - if ext == ".zip": - with zipfile.ZipFile(platform + ext, "r") as zip_ref: - zip_ref.extractall() - else: - with tarfile.open(platform + ext, "r") as tar_ref: - if sys.version_info >= (3, 12): # Use secure call when python version >= 3.12 - tar_ref.extractall(filter="data") - else: - tar_ref.extractall() - - os.remove(platform + ext) - urllib.request.urlretrieve(RLIGHTS_URL, platform + "/include/rlights.h") - - -def download_library(url: str, name: str, tag: str, ext: str = "tar.gz", files_to_extract: list = None): - library_folder = name + "-" + tag - archive_file = library_folder + "." + ext - if not os.path.exists(library_folder): - filled_url = url.format(tag=tag, ext=ext) - print(f"Downloading {name}-{tag}") - urllib.request.urlretrieve(filled_url, archive_file) - if ext == "zip": - with zipfile.ZipFile(archive_file, "r") as zip_ref: - if files_to_extract: - members = [ - member_info.filename - for member_info in zip_ref.infolist() - if os.path.basename(member_info.filename) in files_to_extract - ] - zip_ref.extractall(members=members) - else: - zip_ref.extractall() - else: - with tarfile.open(archive_file, "r") as tar_ref: - kwargs = {} - if sys.version_info >= (3, 12): - kwargs["filter"] = "data" - if files_to_extract: - kwargs["members"] = [ - member for member in tar_ref.getmembers() if os.path.basename(member.name) in files_to_extract - ] - tar_ref.extractall(**kwargs) - os.remove(archive_file) +def download_raylib(name, ext): + dest = os.path.join(EXTERNAL_LIB_DIR, name) + if os.path.exists(dest): + return + print(f"Downloading Raylib {name}") + archive = name + ext + urllib.request.urlretrieve(RAYLIB_URL + archive, archive) + if ext == ".zip": + with zipfile.ZipFile(archive, "r") as zf: + zf.extractall(EXTERNAL_LIB_DIR) + else: + with tarfile.open(archive, "r") as tf: + tf.extractall(EXTERNAL_LIB_DIR, filter="data") if sys.version_info >= (3, 12) else tf.extractall( + EXTERNAL_LIB_DIR + ) + os.remove(archive) + urllib.request.urlretrieve(RLIGHTS_URL, os.path.join(dest, "include", "rlights.h")) + + +def download_inih(): + dest = os.path.join(EXTERNAL_LIB_DIR, "inih-r62") + if os.path.exists(dest): + return + print("Downloading inih") + url = INIH_URL.format(tag="r62", ext="tar.gz") + archive = "inih-r62.tar.gz" + urllib.request.urlretrieve(url, archive) + with tarfile.open(archive, "r") as tf: + members = [m for m in tf.getmembers() if os.path.basename(m.name) in ["ini.c", "ini.h"]] + tf.extractall(EXTERNAL_LIB_DIR, members=members, filter="data") if sys.version_info >= ( + 3, + 12, + ) else tf.extractall(EXTERNAL_LIB_DIR, members=members) + os.remove(archive) if not NO_OCEAN: - download_library(INIH_URL, "inih", "r62", files_to_extract=["ini.c", "ini.h"]) - download_raylib("raylib-5.5_webassembly", ".zip") - -BOX2D_URL = "https://github.com/capnspacehook/box2d/releases/latest/download/" -BOX2D_NAME = "box2d-macos-arm64" if platform.system() == "Darwin" else "box2d-linux-amd64" - - -def download_box2d(platform): - if not os.path.exists(platform): - ext = ".tar.gz" - - print(f"Downloading Box2D {platform}") - urllib.request.urlretrieve(BOX2D_URL + platform + ext, platform + ext) - with tarfile.open(platform + ext, "r") as tar_ref: - if sys.version_info >= (3, 12): - tar_ref.extractall(filter="data") - else: - tar_ref.extractall() - - os.remove(platform + ext) + download_inih() -if not NO_OCEAN: - download_box2d("box2d-web") - # Shared compile args for all platforms extra_compile_args = [ "-DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION", @@ -165,7 +128,7 @@ def download_box2d(platform): "-Bsymbolic-functions", ] if not NO_OCEAN: - download_raylib("raylib-5.5_linux_amd64", ".tar.gz") + download_raylib(RAYLIB_NAME, ".tar.gz") elif system == "Darwin": extra_compile_args += [ "-Wno-error=int-conversion", @@ -181,25 +144,11 @@ def download_box2d(platform): "IOKit", ] if not NO_OCEAN: - download_raylib("raylib-5.5_macos", ".tar.gz") + download_raylib(RAYLIB_NAME, ".tar.gz") else: raise ValueError(f"Unsupported system: {system}") -if not NO_OCEAN: - download_box2d(BOX2D_NAME) - -# Default Gym/Gymnasium/PettingZoo versions -# Gym: -# - 0.26 still has deprecation warnings and is the last version of the package -# - 0.25 adds a breaking API change to reset, step, and render_modes -# - 0.24 is broken -# - 0.22-0.23 triggers deprecation warnings by calling its own functions -# - 0.21 is the most stable version -# - <= 0.20 is missing dict methods for gym.spaces.Dict -# - 0.18-0.21 require setuptools<=65.5.0 - -# Extensions class BuildExt(build_ext): def run(self): # Propagate any build_ext options (e.g., --inplace, --force) to subcommands @@ -226,47 +175,29 @@ def run(self): super().run() -RAYLIB_A = f"{RAYLIB_NAME}/lib/libraylib.a" -INCLUDE = [numpy.get_include(), "raylib/include", f"{BOX2D_NAME}/include", f"{BOX2D_NAME}/src"] -extension_kwargs = dict( - include_dirs=INCLUDE, - extra_compile_args=extra_compile_args, - extra_link_args=extra_link_args, - extra_objects=[RAYLIB_A], -) +RAYLIB_DIR = os.path.join(EXTERNAL_LIB_DIR, RAYLIB_NAME) +RAYLIB_A = os.path.join(RAYLIB_DIR, "lib", "libraylib.a") +INIH_DIR = os.path.join(EXTERNAL_LIB_DIR, "inih-r62") -# Find C extensions c_extensions = [] +c_extension_paths = [] if not NO_OCEAN: - c_extension_paths = glob.glob("pufferlib/ocean/**/binding.c", recursive=True) + c_extension_paths = ["pufferlib/ocean/drive"] c_extensions = [ Extension( - path.rstrip(".c").replace("/", "."), - sources=[path], - **extension_kwargs, + "pufferlib.ocean.drive.binding", + sources=["pufferlib/ocean/drive/binding.c", os.path.join(INIH_DIR, "ini.c")], + include_dirs=[numpy.get_include(), os.path.join(RAYLIB_DIR, "include")], + extra_compile_args=extra_compile_args + + [ + '-DINI_START_COMMENT_PREFIXES="#"', + '-DINI_INLINE_COMMENT_PREFIXES="#"', + ], + extra_link_args=extra_link_args, + extra_objects=[RAYLIB_A], ) - for path in c_extension_paths - if "matsci" not in path ] - c_extension_paths = [os.path.join(*path.split("/")[:-1]) for path in c_extension_paths] - - for c_ext in c_extensions: - if "drive" in c_ext.name: - c_ext.sources.append("inih-r62/ini.c") - c_ext.extra_compile_args.extend( - [ - '-DINI_START_COMMENT_PREFIXES="#"', - '-DINI_INLINE_COMMENT_PREFIXES="#"', - ] - ) - - if "impulse_wars" in c_ext.name: - print(f"Adding {c_ext.name} to extra objects") - c_ext.extra_objects.append(f"{BOX2D_NAME}/libbox2d.a") - if "matsci" in c_ext.name: - c_ext.include_dirs.append("/usr/local/include") - c_ext.extra_link_args.extend(["-L/usr/local/lib", "-llammps"]) # Check if CUDA compiler is available. You need cuda dev, not just runtime. torch_extensions = [] @@ -274,7 +205,7 @@ def run(self): torch_sources = [ "pufferlib/extensions/pufferlib.cpp", ] - if shutil.which("nvcc"): + if BUILD_CUDA_EXT: extension = CUDAExtension torch_sources.append("pufferlib/extensions/cuda/pufferlib.cu") else: @@ -292,7 +223,7 @@ def run(self): ] # Prevent Conda from injecting garbage compile flags -from distutils.sysconfig import get_config_vars +from distutils.sysconfig import get_config_vars # noqa: E402 cfg_vars = get_config_vars() for key in ("CC", "CXX", "LDSHARED"): @@ -306,34 +237,34 @@ def run(self): cfg_vars[key] = value.replace("-fno-strict-overflow", "") install_requires = [ - "setuptools", - "numpy<2.0", - "shimmy[gym-v21]", - "gym==0.23", + "setuptools<81", + "numpy", "gymnasium==0.29.1", - "pettingzoo==1.24.1", + "pyyaml", ] if not NO_TRAIN: install_requires += [ "torch", "psutil", - "nvidia-ml-py", "rich", "rich_argparse", + "pandas", + "tqdm", + "matplotlib>=3.8", "imageio", "pyro-ppl", - "heavyball<2.0.0", + "mediapy", + "heavyball", "neptune", "wandb", - "matplotlib", - "tqdm", + "tensorboard", + "google-cloud-aiplatform", ] setup( version="3.0.0", packages=find_namespace_packages() + find_packages() + c_extension_paths + ["pufferlib/extensions"], - package_data={"pufferlib": [RAYLIB_NAME + "/lib/libraylib.a"]}, include_package_data=True, install_requires=install_requires, ext_modules=c_extensions + torch_extensions, @@ -342,5 +273,5 @@ def run(self): "build_torch": TorchBuildExt, "build_c": CBuildExt, }, - include_dirs=[numpy.get_include(), RAYLIB_NAME + "/include"], + include_dirs=[numpy.get_include(), os.path.join(RAYLIB_DIR, "include")], ) diff --git a/tests/test_drive_config.py b/tests/test_drive_config.py index dfb9a8e3df..43b30916f8 100644 --- a/tests/test_drive_config.py +++ b/tests/test_drive_config.py @@ -77,21 +77,22 @@ def test_drive_ini_config(self): # --- Tunable hyperparameters (tested at high strictness) --- if ASSERTION_LEVEL >= 3: - self.assertEqual(args["train"]["total_timesteps"], 2_000_000_000) - self.assertEqual(args["train"]["batch_size"], 524288) - self.assertEqual(args["train"]["rollout_horizon"], 32) - self.assertEqual(args["train"]["minibatch_size"], 32768) - self.assertEqual(args["train"]["learning_rate"], 0.003) + self.assertEqual(args["train"]["total_timesteps"], 3_000_000_000) + self.assertEqual(args["train"]["batch_size"], "auto") + self.assertEqual(args["train"]["bptt_horizon"], 91) + self.assertEqual(args["train"]["minibatch_size"], 11648) + self.assertEqual(args["train"]["learning_rate"], 0.001) self.assertEqual(args["train"]["gamma"], 0.98) self.assertEqual(args["train"]["gae_lambda"], 0.95) - self.assertEqual(args["train"]["ent_coef"], 0.005) + self.assertEqual(args["train"]["ent_coef"], 0.001) self.assertEqual(args["env"]["reward_vehicle_collision"], -0.5) - self.assertEqual(args["env"]["reward_offroad_collision"], -0.5) - self.assertEqual(args["env"]["num_maps"], 10000) + self.assertEqual(args["env"]["reward_offroad_collision"], -0.2) + self.assertEqual(args["env"]["num_maps"], 1) @patch("sys.argv", ["pufferl.py", "--train.learning-rate=0.5"]) def test_cli_override(self): """Test that command-line arguments override INI file values.""" + # learning_rate is 0.001 in drive.ini, but we override it to 0.5 here args = load_config("puffer_drive") self.assertEqual(args["train"]["learning_rate"], 0.5) diff --git a/tests/test_drive_render.py b/tests/test_drive_render.py new file mode 100644 index 0000000000..75ea9c3746 --- /dev/null +++ b/tests/test_drive_render.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +""" +Test script for PufferDrive raylib rendering functionality. +""" + +import os +import subprocess +import sys +import numpy as np + + +def test_drive_render(): + """Test that PufferDrive renderer runs successfully (exit code 0).""" + print("Testing PufferDrive rendering...") + + # Check if drive binary exists + if not os.path.exists("./visualize"): + print("Drive binary not found, attempting to build...") + try: + result = subprocess.run( + ["bash", "scripts/build_ocean.sh", "visualize", "local"], capture_output=True, text=True, timeout=600 + ) + if result.returncode != 0 or not os.path.exists("./visualize"): + print(f"Build failed: {result.stderr}") + return False + except Exception as e: + print(f"Build error: {e}") + return False + + # Backup existing weights file if it exists + weights_path = "resources/drive/puffer_drive_weights.bin" + backup_path = "resources/drive/puffer_drive_weights.bin.backup" + weights_existed = False + + if os.path.exists(weights_path): + weights_existed = True + os.rename(weights_path, backup_path) + + # Create dummy weights file + os.makedirs("resources/drive", exist_ok=True) + dummy_weights = np.random.randn(700000).astype(np.float32) + dummy_weights.tofile(weights_path) + + try: + # Set up environment to suppress AddressSanitizer exit code (needed due to current memory leaks) + env = os.environ.copy() + env["ASAN_OPTIONS"] = "exitcode=0" + + # Run the renderer with xvfb and frame skip for faster testing + print("Running renderer.") + result = subprocess.run( + [ + "xvfb-run", + "-a", + "-s", + "-screen 0 1280x720x24", + "./visualize", + "--frame-skip", + "10", + "--map-name", + "resources/drive/binaries/map_000.bin", + "--output-topdown", + "resources/drive/output_topdown.mp4", + "--output-agent", + "resources/drive/output_agent.mp4", + "--view", + "topdown", + ], + capture_output=True, + text=True, + timeout=600, + env=env, + ) + + print(f"Renderer exit code: {result.returncode}") + + # Show output for debugging if needed + if result.stdout: + print(f"stdout: {result.stdout}") + if result.stderr: + print(f"stderr: {result.stderr}") + + if result.returncode == 0: + print("Renderer completed successfully!") + return True + else: + print(f"Renderer failed with exit code {result.returncode}") + return False + + except subprocess.TimeoutExpired: + print("Renderer timed out") + return False + except Exception as e: + print(f"Render test failed: {e}") + return False + finally: + # Cleanup: remove test outputs and restore original weights if they existed + if os.path.exists(weights_path): + os.remove(weights_path) + + if weights_existed and os.path.exists(backup_path): + os.rename(backup_path, weights_path) + + # Clean up generated outputs + for output_file in ["resources/drive/output_topdown.mp4", "resources/drive/output_agent.mp4"]: + if os.path.exists(output_file): + os.remove(output_file) + + +if __name__ == "__main__": + if test_drive_render(): + print("Render test passed!") + sys.exit(0) + else: + print("Render test failed") + sys.exit(1) diff --git a/tests/test_drive_scenario_length.py b/tests/test_drive_scenario_length.py index 3e2949fdc2..e6ff3ff39b 100644 --- a/tests/test_drive_scenario_length.py +++ b/tests/test_drive_scenario_length.py @@ -4,14 +4,14 @@ from pufferlib.ocean.drive.drive import Drive -def test_drive_emits_log_after_custom_episode_length(): +def test_drive_emits_log_after_custom_scenario_length(): """Ensure the engine produces an episode log once the custom horizon elapses.""" try: env = Drive( num_agents=32, num_maps=1, - episode_length=5, + scenario_length=5, resample_frequency=0, report_interval=1, ) @@ -28,5 +28,5 @@ def test_drive_emits_log_after_custom_episode_length(): env.close() - assert logs, "Drive never flushed its log; episode_length may be ignored" + assert logs, "Drive never flushed its log; scenario_length may be ignored" assert pytest.approx(logs[-1]["episode_length"], rel=0.0, abs=1e-6) == 5 diff --git a/tests/test_drive_train.py b/tests/test_drive_train.py index 8271fb8be8..7027299674 100644 --- a/tests/test_drive_train.py +++ b/tests/test_drive_train.py @@ -27,7 +27,7 @@ def test_drive_training(): "compile": False, "total_timesteps": 100000, "batch_size": 128, - "rollout_horizon": 8, + "bptt_horizon": 8, "minibatch_size": 128, "max_minibatch_size": 128, "update_epochs": 1, @@ -51,8 +51,6 @@ def test_drive_training(): "action_type": "discrete", "num_maps": 1, "map_dir": "resources/drive/binaries", - "init_mode": "create_all_valid", - "control_mode": "control_agents", } ) @@ -73,14 +71,10 @@ def test_drive_training(): args["neptune"] = False args["eval"] = { "eval_interval": 10000, - "self_play_eval": False, + "num_episodes": 4, "wosac_realism_eval": False, - "human_replay_eval": False, - "render_self_play_eval": False, - "render_human_replay_eval": False, - "num_eval_agents": 8, - "map_dir": "resources/drive/binaries", - "render_select_mode": "fixed", + "human_replay_eval": True, + "human_replay_num_agents": 8, } # Load components @@ -90,7 +84,7 @@ def test_drive_training(): # Initialize training train_config = dict(**args["train"], env=env_name, eval=args.get("eval", {})) - pufferl = PuffeRL(train_config, vecenv, policy, logger=None, full_args=args) + pufferl = PuffeRL(train_config, vecenv, policy, logger=None) # Train until reaching 50K steps target_steps = 50000 diff --git a/tests/test_simulator_perf.py b/tests/test_simulator_perf.py index 36fe5ab2f7..18d761014d 100644 --- a/tests/test_simulator_perf.py +++ b/tests/test_simulator_perf.py @@ -14,7 +14,7 @@ def test_simulator_raw(): num_agents = 32 # ---- Run simulation ---- - env = Drive(num_agents=num_agents, num_maps=1, episode_length=91, map_dir="resources/drive/binaries") + env = Drive(num_agents=num_agents, num_maps=1, scenario_length=91, map_dir="resources/drive/binaries") obs, _ = env.reset() tick = 0