--- title: "OpenSim Tool Pipeline: IK to ID to SO" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{OpenSim Tool Pipeline: IK to ID to SO} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") ``` ## Overview A common OpenSim workflow chains multiple tools in sequence: 1. **Inverse Kinematics (IK)** -- Compute joint angles from marker data 2. **Inverse Dynamics (ID)** -- Compute joint moments from kinematics + forces 3. **Static Optimization (SO)** -- Estimate muscle forces from joint moments PhysioOpenSim's template system and tool runners make it straightforward to script this pipeline entirely in R. ## Prerequisites This vignette assumes you have: - An OpenSim model file (`.osim`) - Marker trajectory data (`.trc`) - External forces data (`.mot` or `.xml`) - Template XML files for each tool ## Step 1: Inverse Kinematics Generate the IK setup from a template, then run it. ```{r ik-template} library(PhysioOpenSim) # Create dummy files for demonstration model_file <- tempfile(fileext = ".osim") marker_file <- tempfile(fileext = ".trc") writeLines("dummy", model_file) writeLines("dummy", marker_file) # Create an IK template ik_tpl <- tempfile(fileext = ".xml") writeLines(c( '', '', ' ', ' Unassigned', ' Unassigned', ' Unassigned', ' 0 1', ' ./', ' ', '' ), ik_tpl) ik_output <- tempfile(fileext = ".mot") ik_setup <- tempfile(fileext = ".xml") ik_result <- opensimWriteIKSetupFromTemplate( template_file = ik_tpl, output_file = ik_setup, model_file = model_file, marker_file = marker_file, output_motion_file = ik_output, time_range = c(0.5, 2.0), results_directory = tempdir() ) cat("Applied tags:", paste(ik_result$applied_tags, collapse = ", "), "\n") ``` ```{r ik-run, eval = FALSE} # Execute IK (requires OpenSim) ik_run <- opensimRunIK(ik_setup) cat("IK exit status:", ik_run$status, "\n") cat("IK elapsed:", round(ik_run$elapsed_sec, 2), "sec\n") ``` ## Step 2: Inverse Dynamics ID uses the IK output as input coordinates. ```{r id-template} # Create an ID template id_tpl <- tempfile(fileext = ".xml") writeLines(c( '', '', ' ', ' Unassigned', ' Unassigned', ' Unassigned', ' 0 1', ' -1', ' ./', ' ', '' ), id_tpl) # IK output becomes ID input -- create a dummy for the demo ik_output_file <- tempfile(fileext = ".mot") writeLines("dummy", ik_output_file) id_output <- tempfile(fileext = ".sto") id_setup <- tempfile(fileext = ".xml") id_result <- opensimWriteIDSetupFromTemplate( template_file = id_tpl, output_file = id_setup, model_file = model_file, coordinates_file = ik_output_file, output_gen_force_file = id_output, time_range = c(0.5, 2.0), lowpass_cutoff_frequency_for_coordinates = 6 ) cat("Applied tags:", paste(id_result$applied_tags, collapse = ", "), "\n") ``` ```{r id-run, eval = FALSE} # Execute ID id_run <- opensimRunID(id_setup) cat("ID exit status:", id_run$status, "\n") ``` ## Step 3: Static Optimization SO uses the same coordinates as ID. ```{r so-template} # Create an SO template so_tpl <- tempfile(fileext = ".xml") writeLines(c( '', '', ' ', ' Unassigned', ' Unassigned', ' 0 1', ' ./', ' ', '' ), so_tpl) so_setup <- tempfile(fileext = ".xml") so_result <- opensimWriteSOSetupFromTemplate( template_file = so_tpl, output_file = so_setup, model_file = model_file, coordinates_file = ik_output_file, time_range = c(0.5, 2.0), results_directory = tempdir() ) cat("Applied tags:", paste(so_result$applied_tags, collapse = ", "), "\n") ``` ```{r so-run, eval = FALSE} # Execute SO so_run <- opensimRunSO(so_setup) cat("SO exit status:", so_run$status, "\n") ``` ## Running the Full Pipeline In practice you would run all three steps sequentially. ```{r pipeline, eval = FALSE} # Full pipeline ik <- opensimRunIK(ik_setup) stopifnot(ik$status == 0) id <- opensimRunID(id_setup) stopifnot(id$status == 0) so <- opensimRunSO(so_setup) stopifnot(so$status == 0) cat("Pipeline complete.\n") ``` ## Inspecting Results Tool execution returns a list with useful metadata: ```{r result-structure, eval = FALSE} str(ik) # List of 9 # $ execution : chr "cli" # $ command : chr "/usr/local/bin/opensim-cmd" # $ args : chr [1:2] "run-tool" "/path/to/ik_setup.xml" # $ setup_file : chr "/path/to/ik_setup.xml" # $ workdir : chr "/path/to/workdir" # $ status : int 0 # $ stdout : chr [1:..] "..." # $ stderr : chr [1:..] "..." # $ elapsed_sec: num 3.45 ``` ## Backend Selection The `execution` parameter controls which backend is used: | Value | Behavior | |-------|----------| | `"auto"` (default) | Native if available and tool_type is specific; CLI otherwise | | `"native"` | Force native; errors if not compiled with OpenSim | | `"cli"` | Force CLI; errors if `opensim-cmd` is not found | Native execution is faster but does not support `extra_args` or the generic `tool_type = "tool"` token.