Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
d33ab05
feat(core): tire Pacejka MF96 + combined slip + Mz + camber thrust
Onlyti May 29, 2026
e0afc61
feat(core): params + scenario YAML I/O + 4 vehicles / tires / solvers…
Onlyti May 29, 2026
6e6a30a
feat(core): Ld1-Bicycle full update
Onlyti May 29, 2026
e240d32
feat(core): Ld2-SevenDOF dynamics + Ackerman + differential + aero + …
Onlyti May 29, 2026
92698ee
feat(core): Ld3-FourteenDOF dynamics (sprung 3 DOF + unsprung 4 DOF) …
Onlyti May 29, 2026
c30b543
feat(control): Lc5-AxTarget / Lc6-VTarget / Lc7-PathCurvature / Lc8-W…
Onlyti May 29, 2026
1e032ad
feat(integ): CARLA plugin skeleton (RaycastContactProvider + mock test)
Onlyti May 29, 2026
5322208
feat(python): pybind11 vdsim module + sweep_runner + CSV / .tir impor…
Onlyti May 29, 2026
d62414d
feat(multibody): Ld4-MultibodyKinematic / Ld5-MultibodyCompliant M0 stub
Onlyti May 29, 2026
e967024
feat(examples): 10 CLI demo binaries covering the Lc / Ld ladder matrix
Onlyti May 29, 2026
74b2056
build: top-level CMake (Python / CARLA options) + third_party PIC + R…
Onlyti May 29, 2026
360933a
docs: 45+ task reports + figures + PoC summaries (v1/v2/v3) + competi…
Onlyti May 29, 2026
d12e207
feat(viewer): Three.js 3D viewer (PoC v1) — CSV replay + WebSocket re…
Onlyti May 29, 2026
732e5a2
feat(viewer): add figure-8 reference course + cones + center posts
Onlyti May 29, 2026
6261179
docs(theory): textbook-grade reference — chapters 01-07 (frames → con…
Onlyti May 29, 2026
5abe7af
docs(theory): chapters 08-13 + README update (full reference complete)
Onlyti May 29, 2026
a4cadfd
docs(wiki): MkDocs Material + Mermaid + mike versioning + GitHub Page…
Onlyti May 30, 2026
797b478
feat(carla): Python bridge — drive a CARLA actor with VDSim dynamics
Onlyti May 30, 2026
896a501
feat(carla): record + telemetry plot + sync-mode tick fix
Onlyti May 31, 2026
0bd1858
feat(jump-demo): 14-DOF world-z + 3D turning jump simulators
Onlyti May 31, 2026
7d3ec06
feat(tire): load sensitivity + relaxation length + camber path (Ld2/Ld3)
Onlyti May 31, 2026
716229b
feat(tire): Ld1-Bicycle transient α + Pacejka camber Mz contribution
Onlyti May 31, 2026
120431e
feat(ld4): Stage A — double-wishbone hardpoint analyzer (2D side-view)
Onlyti May 31, 2026
34552fb
feat(ld4): Stages B–D — 3D DW solver + ISuspensionKinematics + L3 wire
Onlyti May 31, 2026
6a46b84
feat(ld4): toe forwarding (bump-steer) + Python binding for kinematics
Onlyti May 31, 2026
13de230
feat(ld4): MacPherson strut analyzer (Stage E) — 2nd suspension type
Onlyti May 31, 2026
dc943c5
fix(ld4-mp): replace strut sphere with cylindrical-joint constraint
Onlyti May 31, 2026
db6bcc5
fix(ld4): DW + MP solvers — Newton on TRUE wheel z (not small-angle a…
Onlyti May 31, 2026
cf82abf
feat(ld4): trailing arm + 5-link analyzers + diagnostic + Adams importer
Onlyti May 31, 2026
8d92973
feat(carla+ld3): wire Ld4 kinematics into CARLA bridge + branch SUMMARY
Onlyti May 31, 2026
ca34df8
feat(ld4): C++ native DW kinematics solver + matplotlib GUI editor
Onlyti May 31, 2026
dd6e2e1
feat(ld4): native C++ solvers for TA/MP/5-link + web-based hardpoint …
Onlyti May 31, 2026
ea69b14
feat(doe): parameter sweep / DOE runner for design-validation workflow
Onlyti Jun 1, 2026
4d693f7
feat(validation): ISO 7401 + ISO 4138 standard maneuver suite
Onlyti Jun 1, 2026
b3a3106
feat(fmi): export L2 SevenDOF as FMI 2.0 Co-Simulation FMU
Onlyti Jun 1, 2026
f2402c9
feat(fmi): generic FMI 2.0 CS master in pure Python + round-trip test
Onlyti Jun 1, 2026
1fbcbbb
feat: L3 FMU + ISO 3888-2 DLC + comprehensive README rewrite
Onlyti Jun 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
63 changes: 63 additions & 0 deletions .github/workflows/docs-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Deploy docs (release version)

on:
push:
tags:
- 'v*.*' # e.g. v0.95, v1.0
workflow_dispatch:
inputs:
version:
description: 'Version label (e.g. v0.95-PoC)'
required: true
alias:
description: 'Optional alias (e.g. latest, stable)'
required: false

permissions:
contents: write

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install MkDocs Material + mike
run: |
python -m pip install --upgrade pip
pip install mkdocs-material pymdown-extensions mike

- name: Configure git for mike
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Pick version from tag or input
id: vsn
run: |
if [ "${{ github.event_name }}" = "push" ]; then
echo "version=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
echo "alias=stable" >> "$GITHUB_OUTPUT"
else
echo "version=${{ inputs.version }}" >> "$GITHUB_OUTPUT"
echo "alias=${{ inputs.alias }}" >> "$GITHUB_OUTPUT"
fi

- name: Fetch gh-pages branch
run: |
git fetch origin gh-pages --depth=1 || true

- name: Deploy with mike
run: |
if [ -n "${{ steps.vsn.outputs.alias }}" ]; then
mike deploy --push --update-aliases \
"${{ steps.vsn.outputs.version }}" "${{ steps.vsn.outputs.alias }}"
else
mike deploy --push "${{ steps.vsn.outputs.version }}"
fi
47 changes: 47 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: Deploy docs

on:
push:
branches:
- main
workflow_dispatch:

# Allow mike to push to gh-pages
permissions:
contents: write

# Cancel any in-progress deploy if a new one starts
concurrency:
group: docs-${{ github.ref }}
cancel-in-progress: true

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # mike needs full history of gh-pages

- uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install MkDocs Material + mike
run: |
python -m pip install --upgrade pip
pip install mkdocs-material pymdown-extensions mike

- name: Configure git for mike
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Fetch gh-pages branch
run: |
git fetch origin gh-pages --depth=1 || true

- name: Deploy "main" version with mike
run: |
mike deploy --push --update-aliases main latest
mike set-default --push latest
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,10 @@ logs/

# CTest output
Testing/

# MkDocs build output
site/

# Animation raw frames (mp4 is committed instead)
carla_integration/results/*/frames/
apps/jump_demo/*/frames/
8 changes: 7 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

option(VDSIM_BUILD_TESTS "Build unit/integration tests" ON)
option(VDSIM_BUILD_EXAMPLES "Build CLI examples" ON)
option(VDSIM_BUILD_PYTHON "Build Python bindings" OFF)
option(VDSIM_BUILD_CARLA_PLUGIN "Build CARLA integration" OFF)
option(VDSIM_BUILD_CARLA_PLUGIN "Build CARLA integration" ON)
option(VDSIM_WITH_ERGACCESS "Build with CarMaker ERGAccess" OFF)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
Expand All @@ -32,6 +33,10 @@ if(VDSIM_BUILD_TESTS)
add_subdirectory(tests)
endif()

if(VDSIM_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()

if(VDSIM_BUILD_PYTHON)
add_subdirectory(python)
endif()
Expand All @@ -44,6 +49,7 @@ message(STATUS "VDSim version : ${PROJECT_VERSION}")
message(STATUS "Build type : ${CMAKE_BUILD_TYPE}")
message(STATUS "C++ compiler : ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
message(STATUS "Build tests : ${VDSIM_BUILD_TESTS}")
message(STATUS "Build examples : ${VDSIM_BUILD_EXAMPLES}")
message(STATUS "Build Python : ${VDSIM_BUILD_PYTHON}")
message(STATUS "Build CARLA plugin : ${VDSIM_BUILD_CARLA_PLUGIN}")
message(STATUS "ERGAccess : ${VDSIM_WITH_ERGACCESS}")
173 changes: 154 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,116 @@

차량 설계와 자율주행 평가를 잇는 오픈코어 차량 동역학 시뮬레이션 플랫폼.

> *Positioning*: 외부 시각화/센서 (CARLA 등) 의존, 그 대비 정확하고 검증된
> 차량 동역학 + 하드포인트 기반 설계 검증 + FMI 양방향 통합.

## Layout

| Directory | Contents |
|---|---|
| `core/` | `libvdsim_core` — C++17 standalone library. Bicycle / 7-DOF / 14-DOF dynamics + Pacejka MF tire. ISO 8855 RH convention |
| `python/` | pybind11 bindings (Phase 2) |
| `carla_integration/` | CARLA `UVDSimMovementComponent` + RPC patches (W7+) |
| `third_party/` | FetchContent-managed Eigen / yaml-cpp / spdlog / gtest |
| `tests/` | `unit/`, `integration/`, `validation/{analytical,carmaker}/` |
| `scripts/` | Build / sync / deployment helpers |
| `docs/` | Specs and design notes |
| `core/` | `libvdsim_core` — C++17 standalone library. Ld1 Bicycle / Ld2 7-DOF / Ld3 14-DOF dynamics + Pacejka MF96 tire (with load sensitivity + relaxation length + camber thrust/Mz) + Lc5-Lc8 control converters. Ld4 hardpoint kinematics (DW/MP/TA/5-link, lookup + native solvers). ISO 8855 RH. |
| `python/` | pybind11 bindings (`vdsim` module): VehicleParams / TireParams / SolverParams, ITireModel, ISuspensionKinematics + attach helpers, all dynamics + Lc controllers. |
| `tools/kinematics/` | Offline hardpoint solvers (DW 2D/3D, MacPherson, trailing arm, 5-link), diagnostic + Adams CSV importer + matplotlib GUI. |
| `viewer/` | Three.js 3D viewer + WebSocket realtime · web-based suspension editor with live kinematic curves. |
| `carla_integration/` | Python bridge — drives a CARLA actor with VDSim dynamics; raycast contacts; supports Ld4 kinematics attach. |
| `apps/jump_demo/` | T23/T24 — 2D + 3D turning-jump simulators (Phase-2 14-DOF prototype with world-z + airborne + Pacejka). |
| `apps/doe/` | Design-of-Experiments runner — multi-parameter × multi-scenario sweeps → CSV + heatmaps. |
| `apps/validation/` | ISO 7401 (step steer), ISO 4138 (steady-state circular), ISO 3888-2 (double lane change) — automated metric extraction + report. |
| `fmi_export/` | FMI 2.0 Co-Simulation export (L2 + L3 FMUs) and import (`fmu_master.py` — load any FMI 2.0 CS FMU via ctypes). |
| `configs/` | `vehicles/`, `tires/`, `suspensions/` (DW/MP/TA/5-link YAML), `scenarios/`. |
| `tests/` | `unit/` + `integration/` (165 tests). |

## Build

```bash
cmake -G Ninja -B build -DCMAKE_BUILD_TYPE=Debug
cmake -G Ninja -B build -DCMAKE_BUILD_TYPE=Release \
-DVDSIM_BUILD_PYTHON=ON -DVDSIM_BUILD_CARLA_PLUGIN=ON
cmake --build build -j
(cd build && ctest --output-on-failure)
```

First configure pulls Eigen / yaml-cpp / spdlog / gtest via FetchContent (~5 min).
Requires cmake ≥ 3.16, ninja, g++ ≥ 9 / clang ≥ 8, python3 + pybind11.

## Quick tour

### 1. Dynamics + control (C++)
```bash
bin/vdsim_scenario_run configs/vehicles/sports.yaml \
configs/tires/default_pacejka.yaml \
configs/scenarios/double_lane_change.yaml /tmp/out.csv
```

### 2. Hardpoint suspension design (Python)
```bash
# Compute hardpoint kinematic curves
python3 tools/kinematics/dw_3d_solver.py \
--config configs/suspensions/dw_front_sports.yaml

# Diagnostic check
python3 tools/kinematics/diagnose.py \
--config configs/suspensions/dw_front_sports.yaml

# Interactive web editor
python3 viewer/suspension_editor_server.py &
( cd viewer && python3 -m http.server 8090 )
# Browser → http://localhost:8090/suspension_editor.html
```

### 3. Parameter sweep / design exploration
```bash
python3 apps/doe/sweep_runner.py --config apps/doe/example_sweep.yaml
# → CSV + 1-D plots / 2-D heatmaps / sensitivity bars
```

### 4. ISO maneuver validation
```bash
python3 apps/validation/run_validation.py \
--vehicle configs/vehicles/sports.yaml \
--tire configs/tires/default_pacejka.yaml \
--level L3 \
--out /tmp/validation_report
# → REPORT.md + ISO 7401 + ISO 4138 + ISO 3888-2 metrics + plots
```

### 5. FMI export (industrial co-simulation)
```bash
# Build L2 FMU
bash fmi_export/build_fmu.sh
# Output: build/fmi_export/vdsim_l2.fmu

# Build L3 FMU with Ld4 kinematics
FRONT_KIN_CSV=docs/tasks/T27_ld4_dw/run3d/sweep_3d.csv \
REAR_KIN_CSV=docs/tasks/T30_ld4_5link/run01/sweep_3d.csv \
bash fmi_export/build_l3_fmu.sh
# Output: build/fmi_export/vdsim_l3.fmu (4.6 MB)

# Round-trip equivalence check (vs native VDSim)
python3 fmi_export/test_roundtrip.py
# → max |Δvx| = 0.000e+00 (numerical precision)
```

### 6. FMI import (load any FMU via ctypes)
```python
from fmi_export.fmu_master import FMUMaster
fmu = FMUMaster.load("any_compliant.fmu")
fmu.initialize(0.0)
fmu.set("throttle", 0.3); fmu.set("steer_angle_wheel", 0.05)
fmu.do_step(0.0, 0.02)
print(fmu.get("vx"), fmu.get("yaw_rate"))
```
→ Works with our `vdsim_l2.fmu`, `vdsim_l3.fmu`, Chrono Vehicle FMU, CarMaker FMU export, Modelica-generated FMUs, etc.

Requires: cmake ≥ 3.16, ninja, g++ ≥ 9 (or clang ≥ 8), git. C++17.
### 7. CARLA + VDSim bridge
```bash
# Start CARLA server (~ /path/to/CarlaUE4.sh)
python3 carla_integration/python/run_demo.py \
--vehicle configs/vehicles/sports.yaml \
--tire configs/tires/default_pacejka.yaml \
--level L3 \
--kinematics_front docs/tasks/T27_ld4_dw/run3d/sweep_3d.csv \
--kinematics_rear docs/tasks/T30_ld4_5link/run01/sweep_3d.csv \
--driver --duration 15 --v_target 10
```

## Conventions

Expand All @@ -35,17 +122,65 @@ Requires: cmake ≥ 3.16, ninja, g++ ≥ 9 (or clang ≥ 8), git. C++17.
- Euler: ZYX intrinsic (yaw → pitch → roll).
- Wheel index: FL = 0, FR = 1, RL = 2, RR = 3.

## Targets
## Architecture

```
┌──────────────────────────────────────────────────────────────┐
│ External tools │
│ · CARLA (sensors + rendering + scenarios) │
│ · CarMaker / dSPACE / Modelica (via FMI 2.0) │
│ · Chrono Vehicle (via FMI 2.0) │
└──────────────────┬─────────────────────────────┬─────────────┘
FMI import │ CARLA │
(fmu_master)│ bridge │ FMI export
▼ ▼ (build_fmu.sh)
┌──────────────────────────────────────────────────────────────┐
│ VDSim core (C++17) │
│ · Ld1 Bicycle / Ld2 7-DOF / Ld3 14-DOF │
│ · Pacejka MF96 (load sens + relaxation + camber) │
│ · Ld4 hardpoint kinematics (DW / MP / TA / 5-link) │
│ · Lc5-Lc8 control cascade (pure pursuit, vx PID, ax PID) │
└──────────────────┬─────────────────────────────┬─────────────┘
│ │
▼ ▼
Python bindings Validation + DOE
(pybind11) (ISO 7401/4138/3888-2)
Web GUI editor
```

## Validation status (sports.yaml @ L3)

| Test | Result |
|---|---|
| ISO 7401 step-steer (6°, 80 km/h) | U = 1.21 (20.6% overshoot), T_ψ̇ = 0.20 s |
| ISO 4138 understeer gradient | K = +9.69 mrad/g (UNDERSTEER, sports-typical) |
| ISO 3888-2 DLC @ 60 km/h | FAIL (excursion 1.3 m, speed loss 5.5 km/h) |
| ISO 3888-2 DLC @ 40 km/h | PASS (excursion 0.3 m, speed loss 1.0 km/h) |
| FMU export round-trip | max \|Δoutput\| = 0 (numerical precision) |
| ctest | **165 / 165 passing** |

## Status

| Phase | Milestone | Weeks |
| Phase | Milestone | Status |
|---|---|---|
| 0 | Skeleton + build sanity | W1 |
| 1 | Core interfaces + bicycle | W2–W6 |
| 2 | CARLA integration RPC | W7–W8 |
| 3 | 7-DOF + raycast contact | W9–W10 |
| 4 | 14-DOF + validation | W11–W12 |
| 0 | Skeleton + build sanity | ✅ |
| 1 | Core interfaces + bicycle | ✅ |
| 2 | CARLA integration | ✅ Python bridge + raycast |
| 3 | 7-DOF + raycast contact | ✅ |
| 4 | 14-DOF + ride dynamics | ✅ Sprung 3 + Unsprung 4 DOF |
| 5 | Control cascade L4-L8 | ✅ Pure pursuit, vx/ax PID, Driver |
| 6 | Pybind11 module | ✅ |
| 7 | Tire upgrades | ✅ Load sens + relaxation + camber Mz |
| 8 | Ld4 hardpoint framework | ✅ 4 suspension types + native solvers |
| 9 | DOE / parameter sweep | ✅ |
| 10 | ISO validation (7401/4138/3888-2) | ✅ |
| 11 | FMI 2.0 export (L2 + L3) | ✅ |
| 12 | FMI 2.0 import (generic master) | ✅ |
| 13 | SMPC / MPC controller | Phase 2 (HPIPM integration) |
| 14 | Ld5 compliance (bushings) | Phase 2 |

## License

- Core (`core/`, `python/`, `tests/`): Apache-2.0.
- Integration / plugin (`carla_integration/`): separate commercial.
- Core / kinematics / tools / validation / FMI export (this repo): Apache-2.0.
- FMI 2.0 headers (`fmi_export/fmi2/`): BSD-2-Clause (Modelica Association).
- Third-party (Eigen / yaml-cpp / spdlog / gtest): respective open-source licenses, vendored via FetchContent.
34 changes: 34 additions & 0 deletions apps/doe/example_sweep.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Example DOE / parameter sweep: how does cornering stiffness and CG height
# affect step-steer yaw response of a sports-trim vehicle at 25 m/s ?
#
# Run:
# python3 apps/doe/sweep_runner.py --config apps/doe/example_sweep.yaml

base:
vehicle: configs/vehicles/sports.yaml
tire: configs/tires/default_pacejka.yaml
level: L2

parameters:
vehicle.cg_height: [0.35, 0.42, 0.50, 0.58]
tire.D_lat: [0.8, 0.95, 1.05, 1.20] # Pacejka MF96 lateral peak factor
# tire.mu_nominal: [0.8, 1.0, 1.2] # uniform surface mu
# vehicle.mass: [1200, 1320, 1450]

scenarios:
step_30deg_at_25:
type: step_steer
params: {v_target: 25.0, steer_deg: 30.0, t_pre: 0.5, t_post: 4.0, dt: 0.005}
step_15deg_at_30:
type: step_steer
params: {v_target: 30.0, steer_deg: 15.0, t_pre: 0.5, t_post: 4.0, dt: 0.005}

metrics:
- peak_yaw_rate
- steady_state_yaw_rate
- yaw_overshoot
- yaw_settling_time
- peak_lateral_g

output:
csv: sweep_results.csv
Loading
Loading