# raquelmotzfeldttirach/imu_and_markers_ik_opensim architecture

> Architecture diagram of the GitHub repository raquelmotzfeldttirach/imu_and_markers_ik_opensim, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-15). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim
- Repository: https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim

## Overview

1. **Repository purpose**
   - This is a batch-processing pipeline for **human motion analysis with OpenSim**, centered on **sensor fusion** between IMU orientation data and optical marker tracking from **webcam**, **stereocamera**, and optionally **Vicon** reference recordings.
   - It is not a service or UI app; the architecture is a set of scripts that preprocess data, run OpenSim workflows, tune parameters, and compute error metrics.

2. **Primary data boundary**
   - Raw inputs live under a `recordings/SubjectXX/...` structure described in the README.
   - The pipeline consumes:
     - IMU `.txt` logs
     - Optical `.trc` marker files from webcam/stereocamera
     - Vicon `.trc` reference files
   - Outputs and optimization results are intended for `analytics/`, making the repo split into **raw data**, **processing scripts**, and **results**.

3. **Core biomechanics model asset**
   - `OpenSim/Models/Rajagopal/Rajagopal_2015.osim` is the central human musculoskeletal model.
   - The large `Geometry/` folder contains `.vtp` meshes for bones and body segments used by the OpenSim model.
   - Marker definition files (`vicon_markers.xml`, `webcam_markers.xml`, `stereocamera_markers.xml`) define modality-specific observation sets against the same underlying model.

4. **OpenSim/OpenSense ingestion layer**
   - `OpenSense_IMUDataConverter.py` converts raw IMU data into OpenSim-friendly orientation inputs.
   - `OpenSense_CalibrateModel.py` calibrates the model using IMU data.
   - `OpenSense_OrientationTracking.py` runs the orientation tracking workflow.
   - `OpenSense_PostProcessing.py` appears to summarize or transform OpenSim outputs after tracking.
   - These scripts form the **IMU/OpenSense branch** of the pipeline.

5. **Optical tracking preprocessing layer**
   - `TRCcorrector.py` suggests cleanup or normalization of `.trc` marker trajectories.
   - `TimeSynchronization.py` aligns modalities in time, which is essential before fusing IMU and optical data.
   - `webcam_ref_frame_correction.py`, `stereocamera_ref_frame_correction.py`, and `vicon_ref_frame_correction.py` handle coordinate-frame alignment so the different capture systems share a common spatial convention.
   - This preprocessing boundary is what makes heterogeneous recordings comparable.

6. **Model scaling and marker setup**
   - `modelScalingWebcam.py`, `modelScalingStereocamera.py`, and `modelScalingVicon.py` indicate separate scaling workflows per capture modality.
   - `scaling_setup_template*.xml` files are OpenSim setup templates used to parameterize scaling runs for each source.
   - `model_add_markers.py` likely inserts or configures model markers to match the selected recording modality.
   - This layer bridges raw measurements to a subject-specific OpenSim model.

7. **Sensor fusion and weighted IK**
   - `SensorFusion.py`, `SensorFusion_automatic.py`, and `SensorFusion_setWeights_AST.py` are the main fusion/optimization scripts.
   - The README explicitly says the project performs **weighted inverse kinematics**, adjusting sensor weights to minimize a defined cost function.
   - This is the central algorithmic subsystem: it combines IMU orientation constraints with optical position constraints rather than treating either as fully independent.

8. **Optimization loop**
   - `run_optimization.py` and `WeightsTuningModule.py` suggest an iterative search over weight settings.
   - The README lists `optuna` and `cma` as dependencies, so the weight tuning is likely driven by numerical optimization rather than manual configuration.
   - `run_ik_and_rmse_AST.py` ties together IK execution and objective evaluation, likely to support automated tuning.

9. **Evaluation and diagnostics**
   - `RMSECalculationModuleCameraAlone.py` and `run_rmse_calculation.py` compute error metrics, likely against Vicon or another reference solution.
   - `ViconIK.py` provides a Vicon-only inverse kinematics baseline.
   - `diff_check_mot.py` indicates file-level comparison of OpenSim `.mot` outputs, useful for regression checks or optimization scoring.

10. **Automation entrypoint**
   - `script.sh` is the main user-facing orchestration entrypoint described in the README.
   - It likely prompts for a subject ID and dispatches the appropriate preprocessing, scaling, fusion, IK, and evaluation scripts.
   - The architecture is therefore a scripted pipeline rather than a single monolithic executable.

11. **Dependencies and runtime context**
   - The repo is designed for **Linux** with a **Conda** environment and the **OpenSim** package installed.
   - `simbody`, `numpy`, `pandas`, `cma`, and `optuna` materially shape the architecture: OpenSim provides biomechanical simulation/IK, while Python libraries handle data wrangling and optimization.
   - The repo’s runtime boundary is an analysis workstation, not a deployed cloud system.

12. **Overall data flow**
   - A typical flow is: raw recordings → modality-specific cleanup and frame alignment → model scaling and marker setup → OpenSim/OpenSense calibration or IK → sensor-fusion weight optimization → RMSE/diagnostic output → analytics artifacts.
   - The key architectural distinction is between **input normalization**, **OpenSim model execution**, and **result scoring/optimization**.

Main entry points: [`script.sh`](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/script.sh) (script.sh), [`OpenSim/SensorFusion.py`](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/SensorFusion.py) (Sensor fusion), [`OpenSim/OpenSense_IMUDataConverter.py`](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/OpenSense_IMUDataConverter.py) (IMU convert), [`OpenSim/run_optimization.py`](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/run_optimization.py) (Optimize weights)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_grp_raw["Raw data"]
  node_n_raw_recordings[("Recordings<br/>raw data")]
  node_n_trc["TRC data<br/>optical markers"]
  node_n_imu["IMU logs<br/>orientation data"]
end

subgraph group_grp_model["OpenSim model"]
  node_n_model["Rajagopal model<br/>osim model"]
  node_n_geometry["Geometry<br/>mesh assets"]
  node_n_markers["Markers<br/>marker sets"]
end

subgraph group_grp_pipeline["Processing pipeline"]
  node_n_script["script.sh<br/>orchestrator<br/>[script.sh]"]
  node_n_imu_convert["IMU convert<br/>OpenSense ingest"]
  node_n_calibrate["Calibrate model<br/>OpenSense calibrate"]
  node_n_tracking["Orientation tracking<br/>OpenSense IK"]
  node_n_post["Post process<br/>OpenSense output"]
  node_n_trc_correct["TRC corrector<br/>optical cleanup<br/>[TRCcorrector.py]"]
  node_n_sync["Time sync<br/>alignment"]
  node_n_ref_frames["Frame correction<br/>coordinate transform"]
  node_n_scaling["Model scaling<br/>subject scaling"]
  node_n_add_markers["Add markers<br/>model setup"]
  node_n_sensor_fusion["Sensor fusion<br/>weighted IK<br/>[SensorFusion.py]"]
  node_n_auto_fusion["Auto fusion<br/>fusion run"]
  node_n_weights["Weight setup<br/>objective tuning"]
  node_n_optimize["Optimize weights<br/>search loop"]
  node_n_tuning["Tuning module<br/>optimizer support"]
  node_n_ik_rmse["IK + RMSE<br/>evaluation loop"]
end

subgraph group_grp_results["Evaluation"]
  node_n_rmse["RMSE calc<br/>metrics"]
  node_n_rmse_cam["Camera RMSE<br/>metrics"]
  node_n_viconik["Vicon IK<br/>baseline<br/>[ViconIK.py]"]
  node_n_diff["Diff check<br/>regression check<br/>[diff_check_mot.py]"]
end

node_n_script -->|"dispatches"| node_n_imu_convert
node_n_script -->|"dispatches"| node_n_trc_correct
node_n_script -->|"dispatches"| node_n_scaling
node_n_script -->|"dispatches"| node_n_sensor_fusion
node_n_script -->|"dispatches"| node_n_rmse
node_n_raw_recordings -->|"contains"| node_n_imu
node_n_raw_recordings -->|"contains"| node_n_trc
node_n_imu -->|"feeds"| node_n_imu_convert
node_n_imu_convert -->|"prepares"| node_n_calibrate
node_n_trc -->|"feeds"| node_n_trc_correct
node_n_trc_correct -->|"aligns"| node_n_sync
node_n_imu_convert -->|"aligns"| node_n_sync
node_n_sync -->|"normalizes"| node_n_ref_frames
node_n_ref_frames -->|"prepares"| node_n_scaling
node_n_model -->|"basis"| node_n_scaling
node_n_geometry -->|"supports"| node_n_model
node_n_markers -->|"defines"| node_n_add_markers
node_n_scaling -->|"produces"| node_n_add_markers
node_n_add_markers -->|"configures"| node_n_sensor_fusion
node_n_calibrate -->|"enables"| node_n_tracking
node_n_tracking -->|"outputs"| node_n_post
node_n_sensor_fusion -->|"uses"| node_n_weights
node_n_weights -->|"tuned by"| node_n_optimize
node_n_tuning -->|"supports"| node_n_optimize
node_n_optimize -->|"evaluates"| node_n_ik_rmse
node_n_ik_rmse -->|"computes"| node_n_rmse
node_n_ik_rmse -->|"computes"| node_n_rmse_cam
node_n_viconik -->|"baseline for"| node_n_rmse
node_n_diff -->|"checks"| node_n_optimize
node_n_auto_fusion -->|"automates"| node_n_sensor_fusion
node_n_sensor_fusion -->|"feeds"| node_n_tracking

click node_n_script "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/script.sh"
click node_n_model "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/Models/Rajagopal/Rajagopal_2015.osim"
click node_n_geometry "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/tree/main/OpenSim/Models/Rajagopal/Geometry"
click node_n_imu_convert "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/OpenSense_IMUDataConverter.py"
click node_n_calibrate "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/OpenSense_CalibrateModel.py"
click node_n_tracking "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/OpenSense_OrientationTracking.py"
click node_n_post "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/OpenSense_PostProcessing.py"
click node_n_trc_correct "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/TRCcorrector.py"
click node_n_sync "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/TimeSynchronization.py"
click node_n_add_markers "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/model_add_markers.py"
click node_n_sensor_fusion "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/SensorFusion.py"
click node_n_auto_fusion "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/SensorFusion_automatic.py"
click node_n_weights "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/SensorFusion_setWeights_AST.py"
click node_n_optimize "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/run_optimization.py"
click node_n_tuning "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/WeightsTuningModule.py"
click node_n_ik_rmse "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/run_ik_and_rmse_AST.py"
click node_n_rmse "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/run_rmse_calculation.py"
click node_n_rmse_cam "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/RMSECalculationModuleCameraAlone.py"
click node_n_viconik "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/ViconIK.py"
click node_n_diff "https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/diff_check_mot.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_n_raw_recordings,node_n_trc,node_n_imu toneBlue
class node_n_model,node_n_geometry,node_n_markers toneAmber
class node_n_script,node_n_imu_convert,node_n_calibrate,node_n_tracking,node_n_post,node_n_trc_correct,node_n_sync,node_n_ref_frames,node_n_scaling,node_n_add_markers,node_n_sensor_fusion,node_n_auto_fusion,node_n_weights,node_n_optimize,node_n_tuning,node_n_ik_rmse toneMint
class node_n_rmse,node_n_rmse_cam,node_n_viconik,node_n_diff toneRose
```

## Components

### Raw data

Recorded IMU and optical inputs plus reference captures.

- **Recordings**: raw data · Subject recordings directory containing IMU logs and optical marker files.
- **TRC data**: optical markers · Webcam, stereocamera, and Vicon marker trajectories.
- **IMU logs**: orientation data · Raw inertial sensor logs used for OpenSense conversion.

### OpenSim model

Biomechanics model assets and modality-specific marker definitions.

- [Rajagopal model](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/Models/Rajagopal/Rajagopal_2015.osim): osim model · Central musculoskeletal model used across scaling, IK, and tracking. · `OpenSim/Models/Rajagopal/Rajagopal_2015.osim`
- [Geometry](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/tree/main/OpenSim/Models/Rajagopal/Geometry): mesh assets · Body-segment meshes referenced by the OpenSim model. · `OpenSim/Models/Rajagopal/Geometry`
- **Markers**: marker sets · Modality-specific observation sets for model fitting.

### Processing pipeline

Preprocessing, scaling, OpenSense, fusion, and optimization scripts.

- [script.sh](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/script.sh): orchestrator · Main entrypoint that dispatches the batch pipeline. · `script.sh`
- [IMU convert](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/OpenSense_IMUDataConverter.py): OpenSense ingest · Converts raw IMU logs into OpenSim-friendly orientation inputs. · `OpenSim/OpenSense_IMUDataConverter.py`
- [Calibrate model](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/OpenSense_CalibrateModel.py): OpenSense calibrate · Calibrates the model using IMU data before tracking. · `OpenSim/OpenSense_CalibrateModel.py`
- [Orientation tracking](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/OpenSense_OrientationTracking.py): OpenSense IK · Runs OpenSense orientation tracking against the calibrated model. · `OpenSim/OpenSense_OrientationTracking.py`
- [Post process](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/OpenSense_PostProcessing.py): OpenSense output · Summarizes or transforms tracking outputs for downstream use. · `OpenSim/OpenSense_PostProcessing.py`
- [TRC corrector](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/TRCcorrector.py): optical cleanup · Normalizes or cleans marker trajectories before scaling and fusion. · `OpenSim/TRCcorrector.py`
- [Time sync](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/TimeSynchronization.py): alignment · Aligns IMU and optical recordings in time. · `OpenSim/TimeSynchronization.py`
- **Frame correction**: coordinate transform · Aligns webcam, stereocamera, and Vicon reference frames to a common convention.
- **Model scaling**: subject scaling · Modality-specific scaling workflows that adapt the model to each recording source.
- [Add markers](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/model_add_markers.py): model setup · Configures or inserts markers to match the selected modality. · `OpenSim/model_add_markers.py`
- [Sensor fusion](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/SensorFusion.py): weighted IK · Combines IMU orientation constraints with optical position constraints. · `OpenSim/SensorFusion.py`
- [Auto fusion](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/SensorFusion_automatic.py): fusion run · Automated sensor-fusion workflow for batch execution. · `OpenSim/SensorFusion_automatic.py`
- [Weight setup](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/SensorFusion_setWeights_AST.py): objective tuning · Defines or updates sensor weights for the fusion cost function. · `OpenSim/SensorFusion_setWeights_AST.py`
- [Optimize weights](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/run_optimization.py): search loop · Iterative weight tuning using numerical optimizers. · `OpenSim/run_optimization.py`
- [Tuning module](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/WeightsTuningModule.py): optimizer support · Shared logic for exploring and scoring weight configurations. · `OpenSim/WeightsTuningModule.py`
- [IK + RMSE](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/run_ik_and_rmse_AST.py): evaluation loop · Runs inverse kinematics and evaluates objective error for tuning. · `OpenSim/run_ik_and_rmse_AST.py`

### Evaluation

Error metrics, baselines, and output comparison.

- [RMSE calc](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/run_rmse_calculation.py): metrics · Computes error metrics, likely against reference motion. · `OpenSim/run_rmse_calculation.py`
- [Camera RMSE](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/RMSECalculationModuleCameraAlone.py): metrics · Computes RMSE for camera-only comparisons or baselines. · `OpenSim/RMSECalculationModuleCameraAlone.py`
- [Vicon IK](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/ViconIK.py): baseline · Reference inverse-kinematics workflow using Vicon data. · `OpenSim/ViconIK.py`
- [Diff check](https://github.com/raquelmotzfeldttirach/imu_and_markers_ik_opensim/blob/main/OpenSim/diff_check_mot.py): regression check · Compares OpenSim .mot outputs for consistency or scoring. · `OpenSim/diff_check_mot.py`

## Connections

- script.sh → IMU convert: dispatches · Starts the IMU/OpenSense branch.
- script.sh → TRC corrector: dispatches · Starts optical preprocessing.
- script.sh → Model scaling: dispatches · Runs modality-specific scaling.
- script.sh → Sensor fusion: dispatches · Launches fusion and IK workflow.
- script.sh → RMSE calc: dispatches · Triggers evaluation outputs.
- Recordings → IMU logs: contains · Raw subject recordings include IMU logs.
- Recordings → TRC data: contains · Raw subject recordings include marker trajectories.
- IMU logs → IMU convert: feeds · IMU logs are converted for OpenSim.
- IMU convert → Calibrate model: prepares · Converted orientations feed model calibration.
- TRC data → TRC corrector: feeds · Marker trajectories are cleaned before use.
- TRC corrector → Time sync: aligns · Cleaned optical data is time-aligned.
- IMU convert → Time sync: aligns · IMU data is synchronized with optical streams.
- Time sync → Frame correction: normalizes · Aligned streams share a common spatial convention.
- Frame correction → Model scaling: prepares · Frame-aligned data supports modality-specific scaling.
- Rajagopal model → Model scaling: basis · Scaling adapts the core musculoskeletal model.
- Geometry → Rajagopal model: supports · Meshes provide model visualization and anatomy context.
- Markers → Add markers: defines · Marker sets drive modality-specific setup.
- Model scaling → Add markers: produces · Scaled subject model is prepared for marker setup.
- Add markers → Sensor fusion: configures · Marker-configured model enters fusion.
- Calibrate model → Orientation tracking: enables · Calibrated model is tracked in OpenSense.
- Orientation tracking → Post process: outputs · Tracking results are summarized downstream.
- Sensor fusion → Weight setup: uses · Fusion depends on sensor weight definitions.
- Weight setup → Optimize weights: tuned by · Weights are explored by optimization routines.
- Tuning module → Optimize weights: supports · Shared tuning logic drives the search loop.
- Optimize weights → IK + RMSE: evaluates · Candidate weights are scored via IK and RMSE.
- IK + RMSE → RMSE calc: computes · Evaluation writes RMSE metrics.
- IK + RMSE → Camera RMSE: computes · Camera-only error metrics can be produced.
- Vicon IK → RMSE calc: baseline for · Vicon IK provides a reference for error analysis.
- Diff check → Optimize weights: checks · Output comparisons can support regression or scoring.
- Auto fusion → Sensor fusion: automates · Batch fusion wrapper around the core fusion script.
- Sensor fusion → Orientation tracking: feeds · Fusion results inform downstream motion tracking.
