<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.2 20190208//EN" "http://jats.nlm.nih.gov/publishing/1.2/JATS-journalpublishing1.dtd"><article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" article-type="other" dtd-version="1.2" xml:lang="en">
    <front>
        <journal-meta>
            <journal-id journal-id-type="pmc">F1000Research</journal-id>
            <journal-title-group>
                <journal-title>F1000Research</journal-title>
            </journal-title-group>
            <issn pub-type="epub">2046-1402</issn>
            <publisher>
                <publisher-name>F1000 Research Limited</publisher-name>
                <publisher-loc>London, UK</publisher-loc>
            </publisher>
        </journal-meta>
        <article-meta>
            <article-id pub-id-type="doi">10.12688/f1000research.179162.1</article-id>
            <article-categories>
                <subj-group subj-group-type="heading">
                    <subject>Software Tool Article</subject>
                </subj-group>
                <subj-group>
                    <subject>Articles</subject>
                </subj-group>
            </article-categories>
            <title-group>
                <article-title>OpenMBD: An Open-Source Multibody Dynamics Simulator for Biomechanics Research and Education</article-title>
                <fn-group content-type="pub-status">
                    <fn>
                        <p>[version 1; peer review: awaiting peer review]</p>
                    </fn>
                </fn-group>
            </title-group>
            <contrib-group>
                <contrib contrib-type="author" corresp="yes">
                    <name>
                        <surname>Tierney</surname>
                        <given-names>Gregory</given-names>
                    </name>
                    <role content-type="http://credit.niso.org/">Conceptualization</role>
                    <role content-type="http://credit.niso.org/">Investigation</role>
                    <role content-type="http://credit.niso.org/">Methodology</role>
                    <role content-type="http://credit.niso.org/">Project Administration</role>
                    <role content-type="http://credit.niso.org/">Software</role>
                    <role content-type="http://credit.niso.org/">Visualization</role>
                    <role content-type="http://credit.niso.org/">Writing &#x2013; Original Draft Preparation</role>
                    <role content-type="http://credit.niso.org/">Writing &#x2013; Review &amp; Editing</role>
                    <uri content-type="orcid">https://orcid.org/0000-0002-4666-4473</uri>
                    <xref ref-type="corresp" rid="c1">a</xref>
                    <xref ref-type="aff" rid="a1">1</xref>
                </contrib>
                <aff id="a1">
                    <label>1</label>Ulster University School of Engineering, Belfast, Northern Ireland, UK</aff>
            </contrib-group>
            <author-notes>
                <corresp id="c1">
                    <label>a</label>
                    <email xlink:href="mailto:g.tierney@ulster.ac.uk">g.tierney@ulster.ac.uk</email>
                </corresp>
                <fn fn-type="conflict">
                    <p>No competing interests were disclosed.</p>
                </fn>
            </author-notes>
            <pub-date pub-type="epub">
                <day>20</day>
                <month>4</month>
                <year>2026</year>
            </pub-date>
            <pub-date pub-type="collection">
                <year>2026</year>
            </pub-date>
            <volume>15</volume>
            <elocation-id>601</elocation-id>
            <history>
                <date date-type="accepted">
                    <day>24</day>
                    <month>3</month>
                    <year>2026</year>
                </date>
            </history>
            <permissions>
                <copyright-statement>Copyright: &#x00a9; 2026 Tierney G</copyright-statement>
                <copyright-year>2026</copyright-year>
                <license xlink:href="https://creativecommons.org/licenses/by/4.0/">
                    <license-p>This is an open access article distributed under the terms of the Creative Commons Attribution Licence, which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited.</license-p>
                </license>
            </permissions>
            <self-uri content-type="pdf" xlink:href="https://f1000research.com/articles/15-601/pdf"/>
            <abstract>
                <sec>
                    <title>Background</title>
                    <p>Multibody dynamics simulation is a core technique in computational biomechanics and mechanical systems research. Existing open-source platforms are either poorly suited to biomechanics researchers or lack contact mechanics and graphical user interfaces. No single lightweight Python-native package provides forward dynamics, penalty contact, physiological joint constraints, and a graphical interface in combination.</p>
                </sec>
                <sec>
                    <title>Methods</title>
                    <p>OpenMBD is implemented in Python 3 with three external dependencies (NumPy, Matplotlib, Pillow). The dynamics engine applies the Principle of Virtual Power with analytic ZYX-Euler Jacobians and a Recursive Newton-Euler algorithm to assemble and solve the equations of motion with minimal coordinates. Contact mechanics use a penalty-based nonlinear viscoelastic model with hysteresis, applied to ellipsoid body geometry. Physiological joint range-of-motion limits for all major joints of the human body are enforced by continuous penalty spring-dampers parameterised from normative data. Numerical integration uses the Symplectic Euler scheme at a set time step. A Tkinter graphical user interface and a standalone browser-based JSON model editor are provided.</p>
                </sec>
                <sec>
                    <title>Results</title>
                    <p>OpenMBD is distributed with model files: an adult male, an adult female, a car and a bicycle, defined in an open JSON format. Use cases are presented covering fall, sport collisions and custom model definition using the JSON format and browser-based editor. Three output files are automatically generated per simulation run: an output CSV, a summary text file, and a GIF animation.</p>
                </sec>
                <sec>
                    <title>Conclusions</title>
                    <p>OpenMBD addresses a genuine gap in the open-source biomechanics software landscape by providing a Python-native forward dynamics simulator that is installation-trivial, GUI-accessible, and biomechanically parameterised. The software is released under the MIT licence and is available at 
                        <uri xlink:href="https://gtbiomech.github.io/OpenMBD/">https://gtbiomech.github.io/OpenMBD/</uri>.</p>
                </sec>
            </abstract>
            <kwd-group kwd-group-type="author">
                <kwd>forward dynamics</kwd>
                <kwd>rigid body simulation</kwd>
                <kwd>contact mechanics</kwd>
                <kwd>injury biomechanics</kwd>
                <kwd>human body model</kwd>
                <kwd>falls</kwd>
                <kwd>sport</kwd>
                <kwd>automotive</kwd>
            </kwd-group>
            <funding-group>
                <funding-statement>The author(s) declared that no grants were involved in supporting this work.</funding-statement>
            </funding-group>
        </article-meta>
    </front>
    <body>
        <sec id="sec5" sec-type="intro">
            <title>Introduction</title>
            <p>Multibody dynamics simulation is a cornerstone of computational biomechanics and mechanical systems research. By representing a physical system as an assembly of rigid bodies connected by kinematic joints, forward dynamics simulation enables investigators to predict the time-evolution of body positions, velocities, and contact forces under the action of gravity, applied loads, and surface contact, information that is often inaccessible through experimental measurement alone. Applications span human movement science,
                <sup>
                    <xref ref-type="bibr" rid="ref1">1</xref>,
                    <xref ref-type="bibr" rid="ref2">2</xref>
                </sup> injury biomechanics, prosthetics design, sports performance analysis, robotics,
                <sup>
                    <xref ref-type="bibr" rid="ref3">3</xref>
                </sup> and equipment dynamics and design. Across these domains there is a persistent demand for simulation tools that are simultaneously physically rigorous, computationally accessible, and straightforwardly adaptable to novel model geometries and research questions.</p>
            <p>A number of established software platforms exist for multibody dynamics simulation. Commercial packages such as MADYMO
                <sup>
                    <xref ref-type="bibr" rid="ref4">4</xref>
                </sup> and AnyBody Modelling System
                <sup>
                    <xref ref-type="bibr" rid="ref5">5</xref>
                </sup> offer comprehensive feature sets but impose significant licensing costs, generally challenging access for independent researchers and smaller institutions. OpenSim,
                <sup>
                    <xref ref-type="bibr" rid="ref1">1</xref>
                </sup> built on the Simbody multibody library,
                <sup>
                    <xref ref-type="bibr" rid="ref6">6</xref>
                </sup> is a widely adopted open-source platform for musculoskeletal modelling, providing mature tools for inverse kinematics, inverse dynamics, and muscle force estimation. However, OpenSim&#x2019;s emphasis on musculoskeletal analyses with motion-capture-driven kinematics makes it less suited to forward dynamics scenarios where contact with the environment plays a central role. MuJoCo, now open-source under Google DeepMind, excels at high-speed simulation for robotics and control.
                <sup>
                    <xref ref-type="bibr" rid="ref3">3</xref>
                </sup> PyDy provides a Python-based symbolic multibody modelling workflow leveraging SymPy but requires users to derive equations of motion manually and does not include a contact model or graphical user interface.
                <sup>
                    <xref ref-type="bibr" rid="ref7">7</xref>
                </sup> General-purpose physics engines such as PyBullet
                <sup>
                    <xref ref-type="bibr" rid="ref8">8</xref>
                </sup> and the Rigid Body Dynamics Library (RBDL)
                <sup>
                    <xref ref-type="bibr" rid="ref9">9</xref>
                </sup> are primarily oriented towards robotics simulation and do not provide biomechanics-specific features such as physiological joint range-of-motion enforcement or anatomically defined body segment inertia.</p>
            <p>A gap therefore exists for a Python-native forward dynamics simulator that (i) requires no compilation or specialised build environment, (ii) provides a graphical user interface accessible to researchers without programming expertise, (iii) enforces physiologically realistic joint constraints derived from normative clinical data, (iv) uses a smooth, differentiable contact geometry representation appropriate for biological body segments, (v) supports user-defined model geometries via a human-readable open file format, and (vi) automatically exports structured simulation output suitable for downstream analysis. Satisfying these requirements collectively in a single, lightweight, open-source package has not previously been achieved.</p>
            <p>OpenMBD is an open-source Python package to address this gap. It implements a constrained rigid body forward dynamics engine based on the Principle of Virtual Power, with analytic ZYX-Euler Jacobians and a Recursive Newton-Euler algorithm for efficient assembly of the equations of motion. Contact mechanics are handled by a penalty-based nonlinear viscoelastic model with hysteresis, applied to ellipsoid geometry representing body segments. Physiological joint range-of-motion limits for all major joints of the human body are enforced by continuous penalty spring-dampers parameterised from normative values. The simulator is distributed with model files: adult male, adult female, car and bicycle defined in an open JSON format that can be inspected and modified using a standalone browser-based model editor requiring no installation. A Tkinter graphical user interface provides complete control over model loading, initial conditions, and simulation parameters, and three output files are automatically generated on completion of each run.</p>
            <p>OpenMBD is intended primarily for biomechanics researchers, sports scientists, and engineers who require a transparent, modifiable forward dynamics simulation capability without the overhead of commercial licensing or compiled-language toolchains. The minimal dependency footprint, three third-party Python packages, and the absence of any compilation step lower the barrier to adoption substantially compared with C++&#x00a0;&#x2212;&#x00a0;based alternatives. The open JSON model format and browser-based editor allow users to define novel rigid body systems without writing code. By making the full source code, model files, and documentation freely available under the MIT licence, OpenMBD supports reproducible and extensible research in the spirit of open science.</p>
        </sec>
        <sec id="sec6" sec-type="methods">
            <title>Methods</title>
            <p>This section describes the implementation of OpenMBD, covering the mathematical foundations of the multibody dynamics engine, the contact and joint constraint formulations, the rigid body model representation, physiological range-of-motion enforcement, numerical integration, and the operational workflow required to configure and execute a simulation.
                <sup>
                    <xref ref-type="bibr" rid="ref10">10</xref>
                </sup>
            </p>
            <sec id="sec7">
                <title>Implementation</title>
                <p>

                    <italic toggle="yes">System architecture</italic>
                </p>
                <p>OpenMBD is implemented in Python 3 and structured as a modular collection of sixteen source files, each with a clearly defined responsibility. The package has three external dependencies: NumPy
                    <sup>
                        <xref ref-type="bibr" rid="ref11">11</xref>
                    </sup> for all numerical linear algebra; Matplotlib
                    <sup>
                        <xref ref-type="bibr" rid="ref12">12</xref>
                    </sup> for three-dimensional visualisation and analysis plotting; and Pillow,
                    <sup>
                        <xref ref-type="bibr" rid="ref13">13</xref>
                    </sup> used exclusively for GIF animation export. The graphical user interface is built on Tkinter, which is distributed as part of the Python standard library. All remaining imports are standard library modules. A browser-based model editor (openmbd_model_editor.html) is provided as a standalone HTML5/Three.js application requiring no installation.</p>
                <p>The codebase is divided into four functional layers: (i) physics - the dynamics engine (physics_engine.py), rigid body representation (physics_rigid_body.py), contact mechanics (physics_constraints.py), joint limit enforcement (physics_joint_limits.py), and utility mathematics (physics_utils.py); (ii) models - the JSON parser (models_parser.py), kinematic multibody tree (models_multibody.py), and simulation configuration (models_config.py); (iii) geometry - ellipsoid geometry (geometry_ellipsoid.py) and mesh generation (geometry_mesh_generator.py); and (iv) user interface - the main window, setup, run, analysis, and controls modules (
                    <xref ref-type="fig" rid="f1">
Figure 1</xref>).</p>
                <fig fig-type="figure" id="f1" orientation="portrait" position="float">
                    <label>
Figure 1. </label>
                    <caption>
                        <title>OpenMBD model editor.</title>
                    </caption>
                    <graphic id="gr1" orientation="portrait" position="float" xlink:href="https://f1000research-files.f1000.com/manuscripts/197643/6fd687b0-1bcd-46bf-be39-d323591b7dc7_figure1.gif"/>
                </fig>
                <p>
Equations of motion</p>
                <p>The dynamics of the multibody system are formulated using the Principle of Virtual Power (PVP). For a system of N rigid bodies connected by kinematic joints, the generalised equations of motion take the matrix form (
                    <xref ref-type="disp-formula" rid="e1">
Equation 1</xref>).
                    <disp-formula id="e1">

                        <mml:math display="block">
                            <mml:mi mathvariant="normal">M</mml:mi>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mi mathvariant="normal">q</mml:mi>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                            <mml:mo>&#x00b7;</mml:mo>
                            <mml:mover accent="true">
                                <mml:mi mathvariant="normal">q</mml:mi>
                                <mml:mo>&#x00a8;</mml:mo>
                            </mml:mover>
                            <mml:mo>=</mml:mo>
                            <mml:mi mathvariant="normal">Q</mml:mi>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mi mathvariant="normal">q</mml:mi>
                                <mml:mo>,</mml:mo>
                                <mml:mspace width="0.25em"/>
                                <mml:mover accent="true">
                                    <mml:mi mathvariant="normal">q</mml:mi>
                                    <mml:mo>&#x0307;</mml:mo>
                                </mml:mover>
                                <mml:mo>,</mml:mo>
                                <mml:mi mathvariant="normal">t</mml:mi>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                        </mml:math>

                        <label>[1]</label>
</disp-formula>where 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:mi mathvariant="normal">M</mml:mi>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mi mathvariant="normal">q</mml:mi>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                        </mml:math>
</inline-formula> is the generalised mass matrix, 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:mi mathvariant="normal">q</mml:mi>
                            <mml:mo>,</mml:mo>
                            <mml:mspace width="0.25em"/>
                            <mml:mover accent="true">
                                <mml:mi mathvariant="normal">q</mml:mi>
                                <mml:mo>&#x00a8;</mml:mo>
                            </mml:mover>
                        </mml:math>
</inline-formula> is the vector of generalised coordinates and accelerations, respectively, and 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:mi mathvariant="normal">Q</mml:mi>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mi mathvariant="normal">q</mml:mi>
                                <mml:mo>,</mml:mo>
                                <mml:mover accent="true">
                                    <mml:mi mathvariant="normal">q</mml:mi>
                                    <mml:mo>&#x0307;</mml:mo>
                                </mml:mover>
                                <mml:mo>,</mml:mo>
                                <mml:mi mathvariant="normal">t</mml:mi>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                        </mml:math>
</inline-formula> is the generalised force vector incorporating gravity, contact forces, Coulomb friction, joint limit penalties, and passive joint damping. The system is formulated in minimal coordinates, joint angles and root translation so no explicit constraint stabilisation (e.g. Baumgarte) is required. The generalised mass matrix is assembled using analytic virtual-power Jacobians computed for each rigid body in the kinematic tree (
                    <xref ref-type="disp-formula" rid="e2">
Equation 2</xref>).
                    <disp-formula id="e2">

                        <mml:math display="block">
                            <mml:mi mathvariant="normal">M</mml:mi>
                            <mml:mo>=</mml:mo>
                            <mml:msub>
                                <mml:mo>&#x2211;</mml:mo>
                                <mml:mi mathvariant="normal">i</mml:mi>
                            </mml:msub>
                            <mml:mrow>
                                <mml:mo stretchy="true">[</mml:mo>
                                <mml:msub>
                                    <mml:mi mathvariant="normal">m</mml:mi>
                                    <mml:mi mathvariant="normal">i</mml:mi>
                                </mml:msub>
                                <mml:mo>&#x00b7;</mml:mo>
                                <mml:msubsup>
                                    <mml:mi mathvariant="normal">A</mml:mi>
                                    <mml:mrow>
                                        <mml:mn>1</mml:mn>
                                        <mml:mi mathvariant="normal">i</mml:mi>
                                    </mml:mrow>
                                    <mml:mi mathvariant="normal">T</mml:mi>
                                </mml:msubsup>
                                <mml:msub>
                                    <mml:mi mathvariant="normal">A</mml:mi>
                                    <mml:mrow>
                                        <mml:mn>1</mml:mn>
                                        <mml:mi mathvariant="normal">i</mml:mi>
                                    </mml:mrow>
                                </mml:msub>
                                <mml:mo>+</mml:mo>
                                <mml:msubsup>
                                    <mml:mi mathvariant="normal">A</mml:mi>
                                    <mml:mrow>
                                        <mml:mn>2</mml:mn>
                                        <mml:mi mathvariant="normal">i</mml:mi>
                                    </mml:mrow>
                                    <mml:mi mathvariant="normal">T</mml:mi>
                                </mml:msubsup>
                                <mml:msub>
                                    <mml:mi mathvariant="normal">I</mml:mi>
                                    <mml:mrow>
                                        <mml:mi mathvariant="normal">i</mml:mi>
                                        <mml:mo>,</mml:mo>
                                        <mml:mtext>world</mml:mtext>
                                    </mml:mrow>
                                </mml:msub>
                                <mml:msub>
                                    <mml:mi mathvariant="normal">A</mml:mi>
                                    <mml:mrow>
                                        <mml:mn>2</mml:mn>
                                        <mml:mi mathvariant="normal">i</mml:mi>
                                    </mml:mrow>
                                </mml:msub>
                                <mml:mo stretchy="true">]</mml:mo>
                            </mml:mrow>
                        </mml:math>

                        <label>[2]</label>
</disp-formula>where 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">m</mml:mi>
                                <mml:mi mathvariant="normal">i</mml:mi>
                            </mml:msub>
                        </mml:math>
</inline-formula> is the mass of body I, 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">A</mml:mi>
                                <mml:mrow>
                                    <mml:mn>1</mml:mn>
                                    <mml:mi mathvariant="normal">i</mml:mi>
                                </mml:mrow>
                            </mml:msub>
                        </mml:math>
</inline-formula> is the linear velocity Jacobian (3&#x00a0;&#x00d7;&#x00a0;nq), 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">A</mml:mi>
                                <mml:mrow>
                                    <mml:mn>2</mml:mn>
                                    <mml:mi mathvariant="normal">i</mml:mi>
                                </mml:mrow>
                            </mml:msub>
                        </mml:math>
</inline-formula> is the angular velocity Jacobian (3&#x00a0;&#x00d7;&#x00a0;nq) and 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">I</mml:mi>
                                <mml:mrow>
                                    <mml:mi mathvariant="normal">i</mml:mi>
                                    <mml:mo>,</mml:mo>
                                    <mml:mtext>world</mml:mtext>
                                </mml:mrow>
                            </mml:msub>
                        </mml:math>
</inline-formula> is the world-frame inertia tensor of body i. The Jacobians are computed analytically using ZYX Euler angle parameterisation.</p>
                <p>Generalised coordinate parameterisation</p>
                <p>Joint rotations are parameterised using ZYX Euler angles [&#x03b1;, &#x03b2;, &#x03b3;] stored in radians in the state vector. The angular velocity mapping from Euler rate vector to body angular velocity is given by the analytic Jacobian in the child body&#x2019;s local frame (
                    <xref ref-type="disp-formula" rid="e3">
Equation 3</xref>).
                    <disp-formula id="e3">

                        <mml:math display="block">
                            <mml:msub>
                                <mml:mi mathvariant="normal">&#x03c9;</mml:mi>
                                <mml:mtext>local</mml:mtext>
                            </mml:msub>
                            <mml:mo>=</mml:mo>
                            <mml:msub>
                                <mml:mi mathvariant="normal">E</mml:mi>
                                <mml:mtext>body</mml:mtext>
                            </mml:msub>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mi mathvariant="normal">&#x03b2;</mml:mi>
                                <mml:mo>,</mml:mo>
                                <mml:mi mathvariant="normal">&#x03b3;</mml:mi>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                            <mml:mo>&#x00b7;</mml:mo>
                            <mml:msup>
                                <mml:mrow>
                                    <mml:mo stretchy="true">[</mml:mo>
                                    <mml:mover accent="true">
                                        <mml:mi mathvariant="normal">&#x03b1;</mml:mi>
                                        <mml:mo>&#x0307;</mml:mo>
                                    </mml:mover>
                                    <mml:mo>,</mml:mo>
                                    <mml:mover accent="true">
                                        <mml:mi mathvariant="normal">&#x03b2;</mml:mi>
                                        <mml:mo>&#x0307;</mml:mo>
                                    </mml:mover>
                                    <mml:mo>,</mml:mo>
                                    <mml:mover accent="true">
                                        <mml:mi mathvariant="normal">&#x03b3;</mml:mi>
                                        <mml:mo>&#x0307;</mml:mo>
                                    </mml:mover>
                                    <mml:mo stretchy="true">]</mml:mo>
                                </mml:mrow>
                                <mml:mi mathvariant="normal">T</mml:mi>
                            </mml:msup>
                        </mml:math>

                        <label>[3]</label>
</disp-formula>where 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">&#x03c9;</mml:mi>
                                <mml:mtext>local</mml:mtext>
                            </mml:msub>
                        </mml:math>
</inline-formula> is the body angular velocity in the child body&#x2019;s local frame, 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">E</mml:mi>
                                <mml:mtext>body</mml:mtext>
                            </mml:msub>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mi mathvariant="normal">&#x03b2;</mml:mi>
                                <mml:mo>,</mml:mo>
                                <mml:mi mathvariant="normal">&#x03b3;</mml:mi>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                        </mml:math>
</inline-formula> is the analytic Jacobian based on ZYX Euler angles and 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msup>
                                <mml:mrow>
                                    <mml:mo stretchy="true">[</mml:mo>
                                    <mml:mover accent="true">
                                        <mml:mi mathvariant="normal">&#x03b1;</mml:mi>
                                        <mml:mo>&#x0307;</mml:mo>
                                    </mml:mover>
                                    <mml:mo>,</mml:mo>
                                    <mml:mover accent="true">
                                        <mml:mi mathvariant="normal">&#x03b2;</mml:mi>
                                        <mml:mo>&#x0307;</mml:mo>
                                    </mml:mover>
                                    <mml:mo>,</mml:mo>
                                    <mml:mover accent="true">
                                        <mml:mi mathvariant="normal">&#x03b3;</mml:mi>
                                        <mml:mo>&#x0307;</mml:mo>
                                    </mml:mover>
                                    <mml:mo stretchy="true">]</mml:mo>
                                </mml:mrow>
                                <mml:mi mathvariant="normal">T</mml:mi>
                            </mml:msup>
                        </mml:math>
</inline-formula>is the Euler rate vector. The angular acceleration bias term 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">E</mml:mi>
                                <mml:mtext>body</mml:mtext>
                            </mml:msub>
                        </mml:math>
</inline-formula>&#x00b7; 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mover accent="true">
                                    <mml:mi mathvariant="normal">q</mml:mi>
                                    <mml:mo>&#x0307;</mml:mo>
                                </mml:mover>
                                <mml:mtext>joint</mml:mtext>
                            </mml:msub>
                        </mml:math>
</inline-formula> is computed analytically following Wittenburg,
                    <sup>
                        <xref ref-type="bibr" rid="ref10">10</xref>
                    </sup> avoiding repeated finite differencing during the Recursive Newton-Euler backward pass. The free-floating root joint uses seven generalised coordinates: three Cartesian translations [x, y, z] and a unit quaternion [qw, qx, qy, qz] representing orientation. This quaternion parameterisation avoids the ZYX Euler singularity at the root. Constrained joints are typed as spherical (3 DOF), revolute (1 DOF), or fixed (0 DOF).</p>
                <p>Recursive Newton-Euler algorithm for generalised forces</p>
                <p>The generalised force vector 
                    <italic toggle="yes">Q</italic> is computed using a Recursive Newton-Euler Algorithm (RNEA),
                    <sup>
                        <xref ref-type="bibr" rid="ref14">14</xref>
                    </sup> implemented in the rnea() method of PhysicsEngine. The algorithm proceeds in two passes over a breadth-first traversal of the kinematic tree.</p>
                <p>Forward pass: For each body, joint velocities and centripetal accelerations are propagated from root to leaves. At each joint, the appropriate kinematic mapping is applied: a scalar axis projection for revolute joints; the 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">E</mml:mi>
                                <mml:mtext>body</mml:mtext>
                            </mml:msub>
                        </mml:math>
</inline-formula> ZYX Jacobian for spherical joints; and the identity-plus 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">E</mml:mi>
                                <mml:mtext>world</mml:mtext>
                            </mml:msub>
                            <mml:mspace width="0.25em"/>
                        </mml:math>
</inline-formula>mapping for the free root joint.</p>
                <p>Backward pass: For each body in reverse order, the net force and moment required to produce the bias acceleration under gravity and external contacts is computed, propagated through the tree, and projected onto the joint axes to obtain Q. This formulation is O(N) in the number of bodies.</p>
                <p>Rigid body representation</p>
                <p>Each rigid body is represented by the RigidBody class (physics_rigid_body.py), which stores mass, a 3&#x00a0;&#x00d7;&#x00a0;3 body-frame inertia tensor, centre of mass (CoM) position in the local body frame, and an ordered list of ellipsoid geometry objects. The inertia tensor is specified as a six-component vector [Ixx, Iyy, Izz, Ixy, Iyz, Ixz] from which the symmetric 3&#x00a0;&#x00d7;&#x00a0;3 matrix is assembled. Positive semi-definiteness is enforced by eigen decomposition with clamping of negative eigenvalues to a minimum of 1&#x00a0;&#x00d7;&#x00a0;10
                    <sup>&#x2212;6</sup>&#x00a0;kg&#x00b7;m
                    <sup>2</sup>. Body orientation is maintained as both a rotation matrix R (for kinematic operations) and a unit quaternion (for output), with periodic Gram-Schmidt re-orthonormalisation to prevent drift over long simulations.</p>
                <p>Ellipsoid geometry representation</p>
                <p>Body geometry is represented exclusively by ellipsoids, defined by three semi-axis dimensions [a, b, c] and a 4&#x00a0;&#x00d7;&#x00a0;4 local transform matrix specifying the ellipsoid centre position and orientation relative to the body origin frame (geometry_ellipsoid.py). This representation provides smooth, differentiable geometry that avoids the sharp-edge artefacts common in polygonal mesh contact formulations, while remaining computationally efficient for contact detection.</p>
                <p>Contact detection and force model</p>
                <p>Contact detection is performed at each time step for all ellipsoid pairs satisfying the inter-model condition, and optionally for non-adjacent same-model pairs. For ground contact (z&#x00a0;=&#x00a0;0 plane), penetration depth is computed analytically using the quadratic z-extent of each ellipsoid. For body-body contacts, gradient-based outward surface normal are computed at each candidate contact point. A fast bounding-sphere cull eliminates non-overlapping pairs before the more expensive computation. Contact forces (
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">F</mml:mi>
                                <mml:mtext>total</mml:mtext>
                            </mml:msub>
                            <mml:mo stretchy="true">)</mml:mo>
                            <mml:mspace width="0.25em"/>
                        </mml:math>
</inline-formula>are computed using a penalty-based nonlinear viscoelastic model (
                    <xref ref-type="disp-formula" rid="e4">
Equation 4</xref>).
                    <disp-formula id="e4">

                        <mml:math display="block">
                            <mml:msub>
                                <mml:mi mathvariant="normal">F</mml:mi>
                                <mml:mtext>total</mml:mtext>
                            </mml:msub>
                            <mml:mo>=</mml:mo>
                            <mml:mi mathvariant="normal">&#x03b3;</mml:mi>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mo>|</mml:mo>
                                <mml:msub>
                                    <mml:mi mathvariant="normal">v</mml:mi>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                </mml:msub>
                                <mml:mo>|</mml:mo>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                            <mml:mo>&#x00b7;</mml:mo>
                            <mml:msub>
                                <mml:mi mathvariant="normal">F</mml:mi>
                                <mml:mtext>elastic</mml:mtext>
                            </mml:msub>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mi mathvariant="normal">&#x03b4;</mml:mi>
                                <mml:mo>,</mml:mo>
                                <mml:msub>
                                    <mml:mi mathvariant="normal">&#x03b4;</mml:mi>
                                    <mml:mi>max</mml:mi>
                                </mml:msub>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                            <mml:mo>&#x00b1;</mml:mo>
                            <mml:msub>
                                <mml:mi mathvariant="normal">F</mml:mi>
                                <mml:mtext>damping</mml:mtext>
                            </mml:msub>
                        </mml:math>

                        <label>[4]</label>
</disp-formula>where 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:mi mathvariant="normal">&#x03b3;</mml:mi>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mo>|</mml:mo>
                                <mml:msub>
                                    <mml:mi mathvariant="normal">v</mml:mi>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                </mml:msub>
                                <mml:mo>|</mml:mo>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                        </mml:math>
</inline-formula> is a dynamic amplification factor, 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">F</mml:mi>
                                <mml:mtext>elastic</mml:mtext>
                            </mml:msub>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mi mathvariant="normal">&#x03b4;</mml:mi>
                                <mml:mo>,</mml:mo>
                                <mml:msub>
                                    <mml:mi mathvariant="normal">&#x03b4;</mml:mi>
                                    <mml:mi>max</mml:mi>
                                </mml:msub>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                        </mml:math>
</inline-formula> is evaluated from a user-defined piecewise-linear force-penetration curve with hysteresis tracked via maximum penetration depth 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">&#x03b4;</mml:mi>
                                <mml:mi>max</mml:mi>
                            </mml:msub>
                        </mml:math>
</inline-formula> and 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">F</mml:mi>
                                <mml:mtext>damping</mml:mtext>
                            </mml:msub>
                        </mml:math>
</inline-formula> is a linear viscous term applied with opposite sign during loading and unloading. Coulomb friction is applied in the contact tangent plane with a smooth velocity ramp to prevent numerical chattering at near-zero sliding velocities. This formulation is implemented in the SimpleContact class (physics_constraints.py).</p>
                <p>Kinematic adjacency exclusion</p>
                <p>To prevent spurious contact forces between anatomically adjacent body segments that overlap by design in the resting pose, OpenMBD maintains a cached set of excluded body-index pairs. Pairs within two kinematic hops are permanently excluded from contact detection. Additionally, initial penetration offsets &#x03b4;
                    <sub>0</sub> are recorded for all same-model ellipsoid pairs at t&#x00a0;=&#x00a0;0, and contact forces are scaled by max(0, &#x03b4;&#x00a0;&#x2212;&#x00a0;&#x03b4;
                    <sub>0</sub>), ensuring that designed overlap generates no force at rest while genuine new contacts during motion are fully resolved.</p>
                <p>Physiological joint range-of-motion enforcement</p>
                <p>Physiological range-of-motion (ROM) limits are enforced by a penalty spring-damper that activates only when a joint angle violates its prescribed bounds for joint DOF with angle (
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:mi mathvariant="normal">&#x03b8;</mml:mi>
                        </mml:math>
</inline-formula>) limits (
                    <xref ref-type="disp-formula" rid="e5">
Equation 5</xref>)
                    <disp-formula id="e5">

                        <mml:math display="block">
                            <mml:msub>
                                <mml:mi mathvariant="normal">&#x03c4;</mml:mi>
                                <mml:mtext>penalty</mml:mtext>
                            </mml:msub>
                            <mml:mo>=</mml:mo>
                            <mml:mo>&#x2212;</mml:mo>
                            <mml:mi mathvariant="normal">k</mml:mi>
                            <mml:mo>&#x00b7;</mml:mo>
                            <mml:mtext>violation</mml:mtext>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mi mathvariant="normal">&#x03b8;</mml:mi>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                            <mml:mo>&#x2212;</mml:mo>
                            <mml:mi mathvariant="normal">c</mml:mi>
                            <mml:mo>&#x00b7;</mml:mo>
                            <mml:mover accent="true">
                                <mml:mi mathvariant="normal">&#x03b8;</mml:mi>
                                <mml:mo>&#x0307;</mml:mo>
                            </mml:mover>
                            <mml:mo>&#x00b7;</mml:mo>
                            <mml:mrow>
                                <mml:mo stretchy="true">[</mml:mo>
                                <mml:mn>1</mml:mn>
                                <mml:mspace width="0.25em"/>
                                <mml:mtext>if in violation</mml:mtext>
                                <mml:mo>,</mml:mo>
                                <mml:mspace width="0.25em"/>
                                <mml:mtext>else</mml:mtext>
                                <mml:mspace width="0.25em"/>
                                <mml:mn>0</mml:mn>
                                <mml:mo stretchy="true">]</mml:mo>
                            </mml:mrow>
                        </mml:math>

                        <label>[5]</label>
</disp-formula>where 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">&#x03c4;</mml:mi>
                                <mml:mtext>penalty</mml:mtext>
                            </mml:msub>
                        </mml:math>
</inline-formula> is the resulting penalty torque, k is the penalty spring stiffness, c is the penalty damper coefficient. ROM limits for all major joints of the lower and upper extremity and spine are defined in a lookup table based on American Academy of Orthopaedic Surgeons normative values.
                    <sup>
                        <xref ref-type="bibr" rid="ref15">15</xref>
                    </sup>
                </p>
                <p>Passive joint damping</p>
                <p>A passive viscous damping torque is applied across all non-root joint DOFs (
                    <xref ref-type="disp-formula" rid="e6">
Equation 6</xref>).
                    <disp-formula id="e6">

                        <mml:math display="block">
                            <mml:msub>
                                <mml:mi mathvariant="normal">Q</mml:mi>
                                <mml:mtext>passive</mml:mtext>
                            </mml:msub>
                            <mml:mrow>
                                <mml:mo stretchy="true">[</mml:mo>
                                <mml:mi mathvariant="normal">s</mml:mi>
                                <mml:mo>:</mml:mo>
                                <mml:mi mathvariant="normal">s</mml:mi>
                                <mml:mo>+</mml:mo>
                                <mml:mi>dof</mml:mi>
                                <mml:mo stretchy="true">]</mml:mo>
                            </mml:mrow>
                            <mml:mo>=</mml:mo>
                            <mml:mo>&#x2212;</mml:mo>
                            <mml:msub>
                                <mml:mi mathvariant="normal">D</mml:mi>
                                <mml:mtext>passive</mml:mtext>
                            </mml:msub>
                            <mml:mo>&#x00b7;</mml:mo>
                            <mml:mover accent="true">
                                <mml:mi mathvariant="normal">q</mml:mi>
                                <mml:mo>&#x0307;</mml:mo>
                            </mml:mover>
                            <mml:mrow>
                                <mml:mo stretchy="true">[</mml:mo>
                                <mml:mi mathvariant="normal">s</mml:mi>
                                <mml:mo>:</mml:mo>
                                <mml:mi mathvariant="normal">s</mml:mi>
                                <mml:mo>+</mml:mo>
                                <mml:mi>dof</mml:mi>
                                <mml:mo stretchy="true">]</mml:mo>
                            </mml:mrow>
                        </mml:math>

                        <label>[6]</label>
</disp-formula>where 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">Q</mml:mi>
                                <mml:mtext>passive</mml:mtext>
                            </mml:msub>
                            <mml:mspace width="0.25em"/>
                        </mml:math>
</inline-formula>is the viscous damping torque applied to non-root joints, 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi mathvariant="normal">D</mml:mi>
                                <mml:mtext>passive</mml:mtext>
                            </mml:msub>
                            <mml:mspace width="0.25em"/>
                        </mml:math>
</inline-formula>is the damping constant and 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:mover accent="true">
                                <mml:mi mathvariant="normal">q</mml:mi>
                                <mml:mo>&#x0307;</mml:mo>
                            </mml:mover>
                            <mml:mrow>
                                <mml:mo stretchy="true">[</mml:mo>
                                <mml:mi mathvariant="normal">s</mml:mi>
                                <mml:mo>:</mml:mo>
                                <mml:mi mathvariant="normal">s</mml:mi>
                                <mml:mo>+</mml:mo>
                                <mml:mi>dof</mml:mi>
                                <mml:mo stretchy="true">]</mml:mo>
                            </mml:mrow>
                        </mml:math>
</inline-formula> is the vector of generalised velocities for the specific joint. Root DOFs are excluded so that whole-body translational and rotational dynamics are governed solely by gravity and contact forces.</p>
                <p>Prescribed joint torque pulses</p>
                <p>OpenMBD supports the application of time-limited generalised torques to individual joints, enabling simulation of impulsive joint loading scenarios without requiring a full muscle model. Each prescribed torque is defined by a peak magnitude vector, a start time, and a pulse duration, and is applied as a smooth half-sine envelope over the specified interval.
                    <sup>
                        <xref ref-type="bibr" rid="ref16">16</xref>
                    </sup> This facility allows researchers to impose controlled joint-level perturbations (e.g., a hip abductor impulse, a lumbar flexion torque, or a shoulder extension pulse) as initial conditions for a subsequent passive dynamics simulation. For each registered torque entry, a scalar envelope function &#x03b3;(t) modulates the peak torque magnitude over the pulse window [t
                    <sub>0</sub>, t
                    <sub>0</sub>&#x00a0;+&#x00a0;T] (
                    <xref ref-type="disp-formula" rid="e7">
Equation 7</xref>).
                    <disp-formula id="e7">

                        <mml:math display="block">
                            <mml:mi mathvariant="normal">&#x03b3;</mml:mi>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mi mathvariant="normal">t</mml:mi>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                            <mml:mo>=</mml:mo>
                            <mml:mo>sin</mml:mo>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mi mathvariant="normal">&#x03c0;</mml:mi>
                                <mml:mo>&#x00b7;</mml:mo>
                                <mml:mrow>
                                    <mml:mo stretchy="true">(</mml:mo>
                                    <mml:mi mathvariant="normal">t</mml:mi>
                                    <mml:mo>&#x2212;</mml:mo>
                                    <mml:msub>
                                        <mml:mi mathvariant="normal">t</mml:mi>
                                        <mml:mn>0</mml:mn>
                                    </mml:msub>
                                    <mml:mo stretchy="true">)</mml:mo>
                                </mml:mrow>
                                <mml:mo>/</mml:mo>
                                <mml:mi mathvariant="normal">T</mml:mi>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                            <mml:mo>,</mml:mo>
                            <mml:mspace width="0.25em"/>
                            <mml:mspace width="0.25em"/>
                            <mml:msub>
                                <mml:mi mathvariant="normal">t</mml:mi>
                                <mml:mn>0</mml:mn>
                            </mml:msub>
                            <mml:mo>&#x2264;</mml:mo>
                            <mml:mi mathvariant="normal">t</mml:mi>
                            <mml:mo>&lt;</mml:mo>
                            <mml:msub>
                                <mml:mi mathvariant="normal">t</mml:mi>
                                <mml:mn>0</mml:mn>
                            </mml:msub>
                            <mml:mo>+</mml:mo>
                            <mml:mi mathvariant="normal">T</mml:mi>
                        </mml:math>

                        <label>[7]</label>
</disp-formula>where t
                    <sub>0</sub> is the pulse start time (s) and T is the pulse duration (s). The envelope rises smoothly from zero at t
                    <sub>0</sub>, reaches a peak of unity at the pulse midpoint t
                    <sub>0</sub>&#x00a0;+&#x00a0;T/2, and returns to zero at t
                    <sub>0</sub>&#x00a0;+&#x00a0;T. Outside this window &#x03b3;(t)&#x00a0;=&#x00a0;0. The half-sine profile was selected in preference to a rectangular step pulse for two reasons. First, it eliminates the step discontinuities in the generalised force vector B that occur at t
                    <sub>0</sub> and t
                    <sub>0</sub>&#x00a0;+&#x00a0;T under a rectangular envelope, which would otherwise induce a brief numerical transient in the acceleration solution at those instants. Second, it is broadly representative of the temporal shape of voluntary muscle activation bursts, which typically exhibit graded onset and offset rather than instantaneous switching.
                    <sup>
                        <xref ref-type="bibr" rid="ref16">16</xref>
                    </sup> The instantaneous prescribed generalised torque contribution (
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi>&#x03c4;</mml:mi>
                                <mml:mtext>presc</mml:mtext>
                            </mml:msub>
                            <mml:mo stretchy="true">)</mml:mo>
                            <mml:mspace width="0.25em"/>
                        </mml:math>
</inline-formula>at time t is given by 
                    <xref ref-type="disp-formula" rid="e8">
Equation 8</xref>.
                    <disp-formula id="e8">

                        <mml:math display="block">
                            <mml:msub>
                                <mml:mi>&#x03c4;</mml:mi>
                                <mml:mtext>presc</mml:mtext>
                            </mml:msub>
                            <mml:mrow>
                                <mml:mo stretchy="true">[</mml:mo>
                                <mml:mi>s</mml:mi>
                                <mml:mo>:</mml:mo>
                                <mml:mi>s</mml:mi>
                                <mml:mo>+</mml:mo>
                                <mml:mi>n</mml:mi>
                                <mml:mo stretchy="true">]</mml:mo>
                            </mml:mrow>
                            <mml:mo>=</mml:mo>
                            <mml:msub>
                                <mml:mi>&#x03c4;</mml:mi>
                                <mml:mtext>peak</mml:mtext>
                            </mml:msub>
                            <mml:mrow>
                                <mml:mo stretchy="true">[</mml:mo>
                                <mml:mo>:</mml:mo>
                                <mml:mi>n</mml:mi>
                                <mml:mo stretchy="true">]</mml:mo>
                            </mml:mrow>
                            <mml:mo>&#x00b7;</mml:mo>
                            <mml:mi>&#x03b3;</mml:mi>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:mi>t</mml:mi>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                        </mml:math>

                        <label>[8]</label>
</disp-formula>where 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi>&#x03c4;</mml:mi>
                                <mml:mtext>peak</mml:mtext>
                            </mml:msub>
                            <mml:mspace width="0.25em"/>
                        </mml:math>
</inline-formula>is the user-specified peak torque vector (N&#x00b7;m) for the joint, s is the start index of that joint&#x2019;s degrees of freedom in the generalised coordinate vector, and 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:mi>n</mml:mi>
                        </mml:math>
</inline-formula> = min (dof,|
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mi>&#x03c4;</mml:mi>
                                <mml:mtext>peak</mml:mtext>
                            </mml:msub>
                        </mml:math>
</inline-formula>|) ensures safe handling of joints with fewer DOF than the three-component input vector. This term is added to the generalised force vector B in assemble_A_and_B() alongside the Recursive Newton&#x2013;Euler gravity and contact forces, the joint-limit penalty torques, and the passive viscous damping torques: B&#x00a0;=&#x00a0;rnea(q, qdot); B&#x00a0;+&#x00a0;= compute_joint_limit_torques(q, qdot); B&#x00a0;+&#x00a0;= _compute_passive_damping_ torques(qdot); B&#x00a0;+&#x00a0;= _compute_prescribed_torques(t).</p>
                <p>Since the prescribed torque is added directly to B in generalised coordinates, it is automatically projected through the mass matrix inversion A
                    <sup>&#x2212;1</sup> B at each timestep, producing physically consistent accelerations that respect the inertial properties and kinematic constraints of the full multibody system. No special handling is required for joint type. The same mechanism applies to spherical (3 DOF), revolute (1 DOF), and free (7 DOF) root joints, with the torque vector sliced to the appropriate DOF count. Multiple torque pulses may be active simultaneously on different joints of the same model or across different loaded models. Each pulse is stored as an independent entry in the prescribed_torques list in PhysicsEngine, keyed by model index and joint name. Entries are populated from ModelConfig.joint_torques at finalise time via _load_prescribed_torques_from_config(), which purges stale entries for the relevant model index before registering new ones, ensuring that repeated calls to rebuild_physics() always produce a clean state.</p>
                <p>Mass matrix assembly and numerical integration</p>
                <p>At each time step, the symmetric positive-definite generalised mass matrix (M) is assembled from contributions of all rigid bodies using the analytic Jacobians. A regularisation term &#x03b5;&#x00a0;=&#x00a0;1&#x00a0;&#x00d7;&#x00a0;10
                    <sup>&#x2212;4</sup> is added to the diagonal to ensure numerical non-singularity. The equation of motion is solved using numpy.linalg.solve, with fallback to the pseudoinverse if a singular matrix is encountered. Accelerations are clamped to &#x00b1;10
                    <sup>5</sup>&#x00a0;rad/s
                    <sup>2</sup> to prevent blow-up from pathological initial conditions. Numerical integration uses the Symplectic (semi-implicit) Euler scheme (
                    <xref ref-type="disp-formula" rid="e9">
Equation 9</xref> and 
                    <xref ref-type="disp-formula" rid="e10">
10</xref>).
                    <disp-formula id="e9">

                        <mml:math display="block">
                            <mml:msub>
                                <mml:mover accent="true">
                                    <mml:mi mathvariant="normal">q</mml:mi>
                                    <mml:mo>&#x0307;</mml:mo>
                                </mml:mover>
                                <mml:mrow>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                    <mml:mo>+</mml:mo>
                                    <mml:mn>1</mml:mn>
                                </mml:mrow>
                            </mml:msub>
                            <mml:mo>=</mml:mo>
                            <mml:msub>
                                <mml:mover accent="true">
                                    <mml:mi mathvariant="normal">q</mml:mi>
                                    <mml:mo>&#x0307;</mml:mo>
                                </mml:mover>
                                <mml:mi mathvariant="normal">n</mml:mi>
                            </mml:msub>
                            <mml:mo>+</mml:mo>
                            <mml:mi>&#x0394;t</mml:mi>
                            <mml:mo>&#x00b7;</mml:mo>
                            <mml:msup>
                                <mml:mi mathvariant="normal">M</mml:mi>
                                <mml:mrow>
                                    <mml:mo>&#x2212;</mml:mo>
                                    <mml:mn>1</mml:mn>
                                </mml:mrow>
                            </mml:msup>
                            <mml:mi mathvariant="normal">Q</mml:mi>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:msub>
                                    <mml:mi mathvariant="normal">q</mml:mi>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                </mml:msub>
                                <mml:mo>,</mml:mo>
                                <mml:msub>
                                    <mml:mover accent="true">
                                        <mml:mi mathvariant="normal">q</mml:mi>
                                        <mml:mo>&#x0307;</mml:mo>
                                    </mml:mover>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                </mml:msub>
                                <mml:mo>,</mml:mo>
                                <mml:msub>
                                    <mml:mi mathvariant="normal">t</mml:mi>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                </mml:msub>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                        </mml:math>

                        <label>[9]</label>
</disp-formula>

                    <disp-formula id="e10">

                        <mml:math display="block">
                            <mml:msub>
                                <mml:mi mathvariant="normal">q</mml:mi>
                                <mml:mrow>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                    <mml:mo>+</mml:mo>
                                    <mml:mn>1</mml:mn>
                                </mml:mrow>
                            </mml:msub>
                            <mml:mo>=</mml:mo>
                            <mml:msub>
                                <mml:mi mathvariant="normal">q</mml:mi>
                                <mml:mi mathvariant="normal">n</mml:mi>
                            </mml:msub>
                            <mml:mo>+</mml:mo>
                            <mml:mi>&#x0394;t</mml:mi>
                            <mml:mo>&#x00b7;</mml:mo>
                            <mml:msub>
                                <mml:mover accent="true">
                                    <mml:mi mathvariant="normal">q</mml:mi>
                                    <mml:mo>&#x0307;</mml:mo>
                                </mml:mover>
                                <mml:mrow>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                    <mml:mo>+</mml:mo>
                                    <mml:mn>1</mml:mn>
                                </mml:mrow>
                            </mml:msub>
                        </mml:math>

                        <label>[10]</label>
</disp-formula>
                </p>
                <p>

                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msub>
                                <mml:mover accent="true">
                                    <mml:mi mathvariant="normal">q</mml:mi>
                                    <mml:mo>&#x0307;</mml:mo>
                                </mml:mover>
                                <mml:mrow>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                    <mml:mo>+</mml:mo>
                                    <mml:mn>1</mml:mn>
                                </mml:mrow>
                            </mml:msub>
                            <mml:mspace width="0.25em"/>
                            <mml:mtext>and</mml:mtext>
                            <mml:mspace width="0.25em"/>
                            <mml:msub>
                                <mml:mi mathvariant="normal">q</mml:mi>
                                <mml:mrow>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                    <mml:mo>+</mml:mo>
                                    <mml:mn>1</mml:mn>
                                </mml:mrow>
                            </mml:msub>
                        </mml:math>
</inline-formula> are the generalised velocity and position for the next time step, respectively. 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:mi>&#x0394;t</mml:mi>
                        </mml:math>
</inline-formula> is the integration time step. The default time step is 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:mi>&#x0394;t</mml:mi>
                        </mml:math>
</inline-formula> = 0.0001&#x00a0;s (10,000&#x00a0;Hz). 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:msup>
                                <mml:mi mathvariant="normal">M</mml:mi>
                                <mml:mrow>
                                    <mml:mo>&#x2212;</mml:mo>
                                    <mml:mn>1</mml:mn>
                                </mml:mrow>
                            </mml:msup>
                            <mml:mspace width="0.25em"/>
                        </mml:math>
</inline-formula>is the inverse of the generalised mass matrix. 
                    <inline-formula>

                        <mml:math display="inline">
                            <mml:mi mathvariant="normal">Q</mml:mi>
                            <mml:mrow>
                                <mml:mo stretchy="true">(</mml:mo>
                                <mml:msub>
                                    <mml:mi mathvariant="normal">q</mml:mi>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                </mml:msub>
                                <mml:mo>,</mml:mo>
                                <mml:msub>
                                    <mml:mover accent="true">
                                        <mml:mi mathvariant="normal">q</mml:mi>
                                        <mml:mo>&#x0307;</mml:mo>
                                    </mml:mover>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                </mml:msub>
                                <mml:mo>,</mml:mo>
                                <mml:msub>
                                    <mml:mi mathvariant="normal">t</mml:mi>
                                    <mml:mi mathvariant="normal">n</mml:mi>
                                </mml:msub>
                                <mml:mo stretchy="true">)</mml:mo>
                            </mml:mrow>
                        </mml:math>
</inline-formula> is the generalised force vector at the current state.</p>
                <p>Model file format</p>
                <p>Rigid body systems are defined in a human-readable JSON format (models_parser.py). Each file contains two top-level objects: bodies and joints. Each body entry specifies mass (kg), a six-component inertia vector (kg&#x00b7;m
                    <sup>2</sup>), CoM position (m), and a list of ellipsoids, each with semi-axis dimensions, a local 4&#x00a0;&#x00d7;&#x00a0;4 transform, and a piecewise-linear force-penetration curve. Each joint entry specifies its type (fixed, revolute, spherical or free), parent and child body names, and two 4&#x00a0;&#x00d7;&#x00a0;4 homogeneous transform matrices T1 and T2 defining the joint anchor location and orientation relative to each body. OpenMBD ships with the model files described below.</p>
                <p>Adult male model (openmbd_male.json): The male model (rigid bodies: 21; joints: 21; ellipsoids: 35; height: 175.4&#x00a0;cm; body mass: 90.3&#x00a0;kg
                    <sup>
                        <xref ref-type="bibr" rid="ref17">17</xref>
                    </sup>) is parameterised as follows. Segment masses and principal inertia tensors are derived from the de Leva
                    <sup>
                        <xref ref-type="bibr" rid="ref18">18</xref>
                    </sup> regression equations. Segment lengths and joint centre locations follow Winter
                    <sup>
                        <xref ref-type="bibr" rid="ref19">19</xref>
                    </sup> and Clauser et al.
                    <sup>
                        <xref ref-type="bibr" rid="ref20">20</xref>
                    </sup> Hip joint centre positions are computed from the regression equations of Bell et al.,
                    <sup>
                        <xref ref-type="bibr" rid="ref21">21</xref>
                    </sup> which predict centre location from inter-ASIS distance and pelvic dimensions. External body proportions draw on the ANSUR II
                    <sup>
                        <xref ref-type="bibr" rid="ref22">22</xref>
                    </sup> anthropometric survey and Pheasant.
                    <sup>
                        <xref ref-type="bibr" rid="ref23">23</xref>
                    </sup> Piecewise-linear contact force-penetration curves are assigned per segment using published experimental data: thorax stiffness follows Kroell et al.
                    <sup>
                        <xref ref-type="bibr" rid="ref24">24</xref>
                    </sup>; head impact properties follow Nahum et al.
                    <sup>
                        <xref ref-type="bibr" rid="ref25">25</xref>
                    </sup>; lower-limb soft tissue dynamic properties are from Saraf et al.
                    <sup>
                        <xref ref-type="bibr" rid="ref26">26</xref>
                    </sup>; gluteal adipose tissue viscoelasticity draws on Gefen and Haberman
                    <sup>
                        <xref ref-type="bibr" rid="ref27">27</xref>
                    </sup>; foot plantar fascia stiffness references Ker et al.
                    <sup>
                        <xref ref-type="bibr" rid="ref28">28</xref>
                    </sup> and Cavanagh and Lafortune
                    <sup>
                        <xref ref-type="bibr" rid="ref29">29</xref>
                    </sup>; cortical and trabecular bone stiffness draws on Yamada.
                    <sup>
                        <xref ref-type="bibr" rid="ref30">30</xref>
                    </sup>
                </p>
                <p>Adult female model (openmbd_female.json): The female model derives from the male model and uses sex-specific anthropometric data from CDC NHANES 2021&#x2013;2023
                    <sup>
                        <xref ref-type="bibr" rid="ref17">17</xref>
                    </sup> for standing height (161.2&#x00a0;cm) and body mass (77.9&#x00a0;kg), with segment mass fractions and radii of gyration from the de Leva
                    <sup>
                        <xref ref-type="bibr" rid="ref18">18</xref>
                    </sup> female regression tables. Biacromial and biiliac width scaling uses the ANSUR data summarised in Gordon et al.
                    <sup>
                        <xref ref-type="bibr" rid="ref22">22</xref>
                    </sup> All contact force-penetration curves use the same experimental sources as the male model, scaled to female segment geometry and mass.</p>
                <p>Car model (openmbd_car.json): The multi-rigid-body car model (total mass: 1,450&#x00a0;kg; height: 158&#x00a0;cm; 12 bodies; 75 ellipsoids) represents a generic mid-size passenger sedan decomposed into physically distinct contact components. Each component is a separate rigid body connected to the central chassis via a fixed joint, preserving single 6-DOF vehicle kinematics. The 13 bodies are: chassis/floor assembly (10 ellipsoids), pillars (6), front bumper (11), bonnet (4), front fenders (6), windscreen (3), roof (3), doors (12), rear screen (2), boot lid (5), rear bumper (5), front wheels (6) and rear wheels (6). Principal inertia tensors were computed analytically using thin-plate approximations for panel components and rectangular-box approximations for the chassis, bumpers and door assembly. Front-end stiffness follows Maki and Kajzer
                    <sup>
                        <xref ref-type="bibr" rid="ref31">31</xref>
                    </sup>: bonnet surface ellipsoids with post-peak reduction reflecting panel fold with front bumper ellipsoids capture the foam crush plateau followed by beam engagement.
                    <sup>
                        <xref ref-type="bibr" rid="ref32">32</xref>
                    </sup> Windscreen and rear screen ellipsoids reflect laminated glass behaviour.
                    <sup>
                        <xref ref-type="bibr" rid="ref33">33</xref>
                    </sup> Door and roof panels follow Maltese et al.
                    <sup>
                        <xref ref-type="bibr" rid="ref34">34</xref>
                    </sup> rear bumper follows Untaroiu et al.
                    <sup>
                        <xref ref-type="bibr" rid="ref35">35</xref>
                    </sup> Pillar and structural ellipsoids (chassis rails, sills, cross-members) follows Untaroiu et al.
                    <sup>
                        <xref ref-type="bibr" rid="ref35">35</xref>
                    </sup> Unloading curves are set at 20&#x2013;25% of loading stiffness, consistent with measured panel coefficients of restitution of 0.10&#x2013;0.15.
                    <sup>
                        <xref ref-type="bibr" rid="ref31">31</xref>
                    </sup>
                </p>
                <p>Bicycle model (openmbd_bicycle.json): The bicycle is represented as a simple three-body system (frame, front wheel, rear wheel) with a total mass of 18.3&#x00a0;kg and height of 133.2&#x00a0;cm. Joint definitions and contact geometry are consistent with Maki and Kajzer.
                    <sup>
                        <xref ref-type="bibr" rid="ref31">31</xref>,
                        <xref ref-type="bibr" rid="ref36">36</xref>
                    </sup>
                </p>
            </sec>
            <sec id="sec8">
                <title>Operation</title>
                <p>System requirements</p>
                <p>OpenMBD runs on any platform supporting Python 3.8 or later. The following software environment is required:
                    <list list-type="bullet">
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Python 3.8 or later</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>NumPy &#x2265;1.21</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Matplotlib&#x00a0;&#x2265;&#x00a0;3.5 (includes the TkAgg backend used for the interactive 3D viewport)</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Pillow&#x00a0;&#x2265;&#x00a0;9.0 (required only for GIF animation export)</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Tkinter (included with all standard CPython distributions; no separate installation required)</p>
                        </list-item>
                    </list>
                </p>
                <p>Installation</p>
                <p>The source code is available from the GitHub repository (see Software Availability). Dependencies are installed with a single command:
                    <list list-type="bullet">
                        <list-item>
                            <label>&#x2022;</label>
                            <p>pip install numpy matplotlib pillow</p>
                        </list-item>
                    </list>
                </p>
                <p>No package installation of OpenMBD itself is required. The simulator is launched by executing the entry-point script directly:
                    <list list-type="bullet">
                        <list-item>
                            <label>&#x2022;</label>
                            <p>python openmbd_simulator.py</p>
                        </list-item>
                    </list>
                </p>
                <p>Workflow</p>
                <p>The standard simulation workflow proceeds through three stages, each corresponding to a tab in the graphical user interface:</p>
                <p>

                    <bold>Stage 1 &#x2014; Setup:</bold>

                    <list list-type="bullet">
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Load one or more model JSON files (up to three simultaneous models are supported).</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Set initial conditions: root position [x, y, z] (m), linear velocity (m/s), root angular velocity (rad/s, ZYX), and per-joint angles (degrees) and angular velocities (rad/s).</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Configure physics parameters: simulation time step &#x0394;t (s), output time step &#x0394;t
                                <sub>out</sub> (s), simulation duration (s), friction coefficient &#x03bc;, and contact damping c (N&#x00b7;s/m).</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Configure torque pulses: specify the peak torque components about the ZYX body axes over a range of &#x2212;500 to +500&#x00a0;N&#x00b7;m and specify the pulse start time (s) and duration (s).</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Click Finalise to build the physics engine, construct the kinematic tree, record initial overlaps, and initialise the state vector.</p>
                        </list-item>
                    </list>
                </p>
                <p>

                    <bold>Stage 2 &#x2014; Run:</bold>

                    <list list-type="bullet">
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Click Run to begin integration in a background thread. The 3D viewport updates in real time, showing all body ellipsoids colour-coded by model instance.</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Simulation continues until the configured duration is reached.</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>On completion, three output files are automatically exported to the working directory.</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Click Reset to restore the initial state and prepare for a new run with modified parameters.</p>
                        </list-item>
                    </list>
                </p>
                <p>

                    <bold>Stage 3 &#x2014; Analysis:</bold>

                    <list list-type="bullet">
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Time-series plots of position, velocity, angular velocity, and contact force magnitude are generated for any selected rigid body.</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Plots are rendered interactively using Matplotlib and can be exported as image files.</p>
                        </list-item>
                    </list>
                </p>
                <p>Output files</p>
                <p>Three output files are automatically generated with a timestamp-based filename on completion of each simulation run:
                    <list list-type="bullet">
                        <list-item>
                            <label>&#x2022;</label>
                            <p>

                                <bold>_output.csv:</bold> Time-series of position (x, y, z), quaternion (w, x, y, z), linear velocity, angular velocity, linear acceleration, angular acceleration, resultant contact force, and resultant contact torque for every rigid body at each recorded timestep.</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>

                                <bold>_summary.txt:</bold> Human-readable record of all simulation parameters, model file paths, initial conditions, and aggregate statistics.</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>

                                <bold>.gif:</bold> Frame-by-frame animation captured from the RGBA render buffer and assembled into a looping GIF using Pillow.</p>
                        </list-item>
                    </list>
                </p>
                <p>Model editor</p>
                <p>A standalone browser-based model editor (openmbd_model_editor.html) is provided for inspection and modification of JSON model files without running Python. The editor uses Three.js (r128) for interactive 3D visualisation of the ellipsoid geometry and joint hierarchy. Features include a body hierarchy tree view, per-body property editing (mass, inertia, CoM), ellipsoid dimension and transform editing, joint type and anchor editing, interactive force-curve editing, model scaling by height and mass, undo history, and JSON import/export. The editor requires no installation and runs in any modern web browser (
                    <xref ref-type="fig" rid="f1">
Figure 1</xref>).</p>
            </sec>
        </sec>
        <sec id="sec9">
            <title>Use Cases</title>
            <p>The following use cases illustrate the principal applications of OpenMBD using the model files distributed with the software.</p>
            <sec id="sec10">
                <title>Use Case 1: Fall simulation</title>
                <p>This use case demonstrates the reconstruction of a typical fall experienced by an older adult, a common mechanism of injury in community and residential care settings. Falls among older adults frequently occur during everyday activities such as walking, turning, or losing balance while standing, often resulting in ground impacts involving the hands, knees, hips, or head. The simulation therefore represents a scenario where a human model loses balance and falls under gravity (
                    <xref ref-type="fig" rid="f2">
Figure 2</xref>).</p>
                <fig fig-type="figure" id="f2" orientation="portrait" position="float">
                    <label>
Figure 2. </label>
                    <caption>
                        <title>Example OpenMBD reconstruction of a fall.</title>
                    </caption>
                    <graphic id="gr2" orientation="portrait" position="float" xlink:href="https://f1000research-files.f1000.com/manuscripts/197643/6fd687b0-1bcd-46bf-be39-d323591b7dc7_figure2.gif"/>
                </fig>
                <p>The articulated multibody representation allows the simulation to resolve segment-level kinematics and contact forces during the impact phase. Sequential contact events are detected between body segments and the ground plane, and the contact model computes forces based on penetration depth, surface stiffness, damping, and friction parameters. These forces propagate through the skeletal chain, influencing joint motion and subsequent impacts. Simulation outputs include the full-body kinematic trajectories, location, and magnitude of ground contact forces. These results enable reconstruction and analysis of impact severity, body segment loading, and potential injury mechanisms, which are particularly relevant for studying fall-related injuries in older adults such as wrist fractures, hip fractures, and head impacts. Such simulations can support research into fall biomechanics, injury risk assessment, and the evaluation of fall prevention strategies, including assistive devices, environmental modifications, or protective equipment.</p>
            </sec>
            <sec id="sec11">
                <title>Use Case 2: Rugby tackle simulation</title>
                <p>This use case represents a player-player collision scenario typical of a rugby tackle. Two human models are initialised with velocities, representing the tackler and the ball carrier, and positioned to collide during motion. During simulation, the collision generates multiple contact events between body segments, depending on the initial configuration. Outputs include full-body kinematics, contact force magnitudes, and the location of impact. These simulations can be used to investigate head acceleration events, tackle mechanics, and player safety interventions, making them relevant for sports biomechanics research and injury prevention.</p>
            </sec>
            <sec id="sec12">
                <title>Use Case 3: Vehicle-Pedestrian impact simulation</title>
                <p>This use case demonstrates a vehicle-pedestrian collision scenario using a simplified vehicle model interacting with the articulated male model. The vehicle is represented as a rigid body with an initial forward velocity, while the pedestrian model is positioned upright in the vehicle path (
                    <xref ref-type="fig" rid="f3">
Figure 3</xref>). Upon impact, the simulation captures the sequence of contacts between the vehicle and body segments, followed by potential secondary impacts with the ground. The multibody dynamics framework enables analysis of body segment trajectories and ground impact events. Simulation outputs provide detailed kinematic data and contact force histories, supporting analysis relevant to pedestrian injury biomechanics, crash reconstruction, and road safety research.</p>
                <fig fig-type="figure" id="f3" orientation="portrait" position="float">
                    <label>
Figure 3. </label>
                    <caption>
                        <title>Example OpenMBD reconstruction of a vehicle-pedestrian impact.</title>
                    </caption>
                    <graphic id="gr3" orientation="portrait" position="float" xlink:href="https://f1000research-files.f1000.com/manuscripts/197643/6fd687b0-1bcd-46bf-be39-d323591b7dc7_figure3.gif"/>
                </fig>
            </sec>
            <sec id="sec13">
                <title>Use Case 4: Custom model definition using the JSON format and model editor</title>
                <p>This use case demonstrates the extensibility of OpenMBD by describing the workflow for defining a novel rigid body system using the open JSON model format and the browser-based model editor. Users who wish to simulate systems not included in the distributed model library, for example, a simplified prosthetic limb, an animal model, or an industrial mechanism can define a new model without writing any Python code.</p>
            </sec>
            <sec id="sec14">
                <title>JSON model structure</title>
                <p>A minimal OpenMBD model JSON file requires two top-level fields: bodies and joints. The inertia field accepts a six-component vector [Ixx, Iyy, Izz, Ixy, Iyz, Ixz] in kg&#x00b7;m
                    <sup>2</sup>. The force_curve field is a piecewise-linear lookup table mapping penetration depth (m) to elastic contact force (N); the shape of this curve determines the stiffness of the body surface and should be calibrated to the properties of the segment being modelled.</p>
            </sec>
            <sec id="sec15">
                <title>Model editor workflow</title>
                <p>The browser-based model editor (openmbd_model_editor.html) provides a graphical interface for all model definition operations. A new model can be assembled through the following steps, entirely without a text editor:
                    <list list-type="order">
                        <list-item>
                            <label>1.</label>
                            <p>Open the editor in any modern web browser (no installation required).</p>
                        </list-item>
                        <list-item>
                            <label>2.</label>
                            <p>Click Add Body to create a new body segment; enter mass, inertia components, and CoM position in the property panel.</p>
                        </list-item>
                        <list-item>
                            <label>3.</label>
                            <p>Click Add Ellipsoid within the body panel; set semi-axis dimensions and adjust the local transform using the interactive 3D viewport.</p>
                        </list-item>
                        <list-item>
                            <label>4.</label>
                            <p>Use the graphical force curve editor to define the contact stiffness curve by clicking to add control points.</p>
                        </list-item>
                        <list-item>
                            <label>5.</label>
                            <p>Click Add Joint to connect bodies; select parent and child bodies, set joint type (spherical, revolute, or fixed), and position the joint anchors T1 and T2 visually in the 3D view.</p>
                        </list-item>
                        <list-item>
                            <label>6.</label>
                            <p>Use the Scale Model panel to rescale the entire model to a target height and mass, with inertia tensors updated automatically.</p>
                        </list-item>
                        <list-item>
                            <label>7.</label>
                            <p>Click Export JSON to save the completed model file, which can then be loaded directly into the OpenMBD simulator.</p>
                        </list-item>
                    </list>
                </p>
            </sec>
        </sec>
        <sec id="sec16" sec-type="discussion">
            <title>Discussion</title>
            <sec id="sec17">
                <title>Comparison with existing multibody dynamics tools</title>
                <p>The principal differentiating characteristics of OpenMBD relative to the existing tools described in the Introduction are its combination of Python nativity, zero-compilation installation, GUI accessibility, and biomechanics-specific features in a single package. OpenSim remains the most mature and widely validated open-source platform for musculoskeletal systems with a large model repository, extensive documentation, and an active user community.
                    <sup>
                        <xref ref-type="bibr" rid="ref1">1</xref>
                    </sup> OpenSim is the appropriate tool of choice for studies requiring detailed muscle force estimation, motion-capture-driven inverse kinematics, or integration with the broader OpenSim ecosystem. OpenMBD does not replicate this functionality and is not intended to replace OpenSim in those applications. The relative advantage of OpenMBD lies in scenarios where the analyst requires a self-contained forward dynamics simulation with explicit contact mechanics and requires rapid simulating of novel body geometries. MuJoCo offers superior simulation speed, particularly for reinforcement learning workloads requiring thousands of parallel rollouts and a more sophisticated contact solver based on convex optimisation.
                    <sup>
                        <xref ref-type="bibr" rid="ref3">3</xref>
                    </sup> However, MuJoCo is robotics and control focused and does not provide physiological ROM constraints or a dedicated impact biomechanics GUI. OpenMBD&#x2019;s penalty-contact approach, while less computationally sophisticated than MuJoCo&#x2019;s convex solver, is transparently parameterisable through user-defined force-penetration curves, which aligns well with the empirical characterisation of soft tissue material properties from cadaveric impact data. PyBullet and RBDL are appropriate for robotics applications requiring high-speed simulation but lack physiological joint limits, anatomically parameterised body segment inertia, and a biomechanics-oriented user interface.
                    <sup>
                        <xref ref-type="bibr" rid="ref8">8</xref>,
                        <xref ref-type="bibr" rid="ref9">9</xref>
                    </sup> PyDy provides a powerful symbolic modelling framework but is intended for users comfortable deriving and manipulating equations of motion manually.
                    <sup>
                        <xref ref-type="bibr" rid="ref7">7</xref>
                    </sup> OpenMBD occupies a complementary niche: it abstracts the dynamics formulation entirely and exposes only the model geometry, initial conditions, and physics parameters to the user.</p>
            </sec>
            <sec id="sec18">
                <title>Principal strengths</title>
                <p>Minimal installation barrier: The three-package dependency (NumPy, Matplotlib, Pillow) and absence of any compilation step represent a substantially lower barrier to adoption than C++&#x00a0;&#x2212;&#x00a0;based alternatives. A researcher with a standard Python installation can be running simulations within minutes of downloading the repository.</p>
                <p>Transparent, auditable physics: Every component of the dynamics formulation is implemented in readable Python with inline documentation. This transparency supports pedagogical use and facilitates modification and extension.</p>
                <p>Open, human-readable model format: The JSON model format is self-documenting and editable in any text editor or the browser-based model editor.</p>
                <p>Human body models: The adult male and female models are parameterised from CDC NHANES 2021&#x2013;2023 population data,
                    <sup>
                        <xref ref-type="bibr" rid="ref17">17</xref>
                    </sup> with segment masses and inertia tensors derived from the de Leva
                    <sup>
                        <xref ref-type="bibr" rid="ref18">18</xref>
                    </sup> regression equations and sex-specific geometric scaling from ANSUR anthropometric surveys.
                    <sup>
                        <xref ref-type="bibr" rid="ref22">22</xref>
                    </sup> This grounding in population-representative anthropometry makes the models appropriate for population-level biomechanics research.</p>
                <p>Structured, timestamped output: The automatic export of three output files on completion of every run ensures that all simulation results are immediately available for analysis and that runs are uniquely identified by timestamp, preventing accidental overwriting. The columnar CSV format is compatible with Python, R, MATLAB, and Excel without format conversion.</p>
            </sec>
            <sec id="sec19">
                <title>Limitations</title>
                <p>Rigid Body Assumption: All body segments in OpenMBD are treated as perfectly rigid. Biological tissues exhibit viscoelastic deformation under load (e.g., bone flexes, soft tissue deforms, and joint cartilage compresses), all of which are absent from the rigid body model. This approximation is standard in gross-motion multibody dynamics simulations
                    <sup>
                        <xref ref-type="bibr" rid="ref14">14</xref>
                    </sup> and is generally acceptable for studying segment kinematics and gross contact forces, but it means that OpenMBD is not appropriate for applications requiring internal stress distribution, tissue deformation fields, or bone fracture prediction.</p>
                <p>Ellipsoid Contact Geometry: The exclusive use of ellipsoid geometry simplifies contact detection and provides smooth surface normals, but it cannot capture the concave anatomical features of real body segments that influence contact area, pressure distribution, and joint congruency. The current ellipsoid approximation is most appropriate for gross-motion and impact studies where the precise contact geometry is a secondary concern relative to the overall trajectory and force magnitude.</p>
                <p>Explicit Euler Integration and Time Step Sensitivity: The Symplectic Euler integration scheme, while exhibiting superior energy conservation properties compared with explicit Euler for oscillatory systems, remains a first-order method and is sensitive to the choice of time step. The default &#x0394;t&#x00a0;=&#x00a0;0.0001&#x00a0;s was selected to satisfy the explicit-Euler stability criterion for the stiffest joint in the human model and to resolve the fast dynamics of ground impact events.</p>
                <p>Single-Threaded Integration: The integration loop runs on a single CPU thread. This architecture is appropriate for the interactive, exploratory use case for which OpenMBD is designed, but it does not exploit multi-core parallelism. For applications requiring large numbers of simulation runs (e.g., Monte Carlo sensitivity analyses, parameter optimisation, or training data generation for machine learning), a batch simulation mode without the GUI overhead would be desirable.</p>
                <p>Contact Model Parameterisation: The piecewise-linear force-penetration curves that define contact stiffness for each ellipsoid must be specified by the user and are not automatically calibrated to measured tissue properties. The curves distributed with the models are based on published impact data and provide physically plausible results for impact scenarios, but they have not been formally validated against instrumented impact experiments for the full range of loading conditions. Researchers requiring quantitatively accurate contact force predictions should treat simulation outputs as order-of-magnitude estimates and calibrate force-penetration curves against segment-specific experimental data where possible.</p>
            </sec>
            <sec id="sec20">
                <title>Controls for bias and sources of variability</title>
                <p>Several design decisions in OpenMBD were made specifically to control for known sources of bias and variability in multibody dynamics simulation:</p>
                <p>Initial overlap suppression: The recording of initial ellipsoid penetration offsets at t&#x00a0;=&#x00a0;0 and subtraction of these offsets from contact force calculations prevents the resting geometry of the model from generating spurious forces from the very first timestep.</p>
                <p>Adjacency exclusion: The exclusion of contact pairs within two kinematic hops prevents neighbouring body segments from generating contact forces through their designed geometric overlap, analogous to the self-collision exclusion masks used in character animation and robotics simulation.
                    <sup>
                        <xref ref-type="bibr" rid="ref8">8</xref>
                    </sup>
                </p>
                <p>Inertia tensor regularisation: Eigen decomposition with negative eigenvalue clamping and diagonal mass matrix regularisation prevent singular or indefinite mass matrices that would produce non-physical accelerations.</p>
            </sec>
            <sec id="sec21">
                <title>Future development</title>
                <p>Several extensions to OpenMBD are planned or identified as high-priority for future development:
                    <list list-type="bullet">
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Batch simulation mode: A headless, command-line simulation mode without the Tkinter GUI would enable scripted parameter sweeps, Monte Carlo analyses, and integration with Python-based optimisation frameworks.</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Expanded model library: Additional models including paediatric body models, sport-specific equipment, and animal models would broaden the range of research applications directly supported by the distributed model library.</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Formal experimental validation: Comparison of simulation outputs against gold standard approaches would provide a quantitative accuracy benchmark for the contact model.</p>
                        </list-item>
                    </list>
                </p>
            </sec>
        </sec>
        <sec id="sec22" sec-type="conclusions">
            <title>Conclusions</title>
            <p>OpenMBD addresses a genuine gap in the open-source biomechanics software landscape by providing a Python-native forward dynamics simulator that is simultaneously physically rigorous, installation-trivial, GUI-accessible, and biomechanically parameterised. The simulator&#x2019;s combination of the Principle of Virtual Power formulation, analytic Jacobians, Recursive Newton-Euler generalised forces, ellipsoid contact geometry with hysteresis, and physiological joint limits constitutes a coherent and internally consistent dynamics engine that is transparent and modifiable at the source code level. The distributed model files, open JSON format, and browser-based model editor collectively lower the barrier to entry for researchers wishing to simulate human or mechanical rigid body systems. By releasing OpenMBD under the MIT licence with full source code, model files, and documentation, this work contributes a reproducible, extensible platform to the open biomechanics research community and provides a foundation on which future capability enhancements can be built.</p>
        </sec>
        <sec id="sec23">
            <title>Software availability</title>
            <p>Software available from: 
                <ext-link ext-link-type="uri" xlink:href="https://gtbiomech.github.io/OpenMBD/">https://gtbiomech.github.io/OpenMBD/</ext-link>
            </p>
            <p>Source code available from: 
                <ext-link ext-link-type="uri" xlink:href="https://github.com/GTBiomech/OpenMBD">https://github.com/GTBiomech/OpenMBD</ext-link>
            </p>
            <p>Archived source code at time of publication: 
                <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.5281/zenodo.19125875">https://doi.org/10.5281/zenodo.19125875</ext-link>
            </p>
            <p>License: MIT License.</p>
            <p>Programming language: Python 3.</p>
            <p>Dependencies: NumPy &#x2265;1.21, Matplotlib &#x2265;3.5, Pillow &#x2265;9.0.</p>
            <p>Tested on: Python 3.10, 3.11; Windows 11.</p>
        </sec>
    </body>
    <back>
        <sec id="sec26" sec-type="data-availability">
            <title>Data availability</title>
            <p>No data associated with this article.</p>
        </sec>
        <ack>
            <title>Acknowledgements</title>
            <p>The author would like to acknowledge Prof. Ciaran Simms&#x2019;s Multibody Dynamics lecture notes that contributed towards the theoretical basis for OpenMBD.</p>
        </ack>
        <ref-list>
            <title>References</title>
            <ref id="ref1">
                <label>1</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Delp</surname>
                            <given-names>SL</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Anderson</surname>
                            <given-names>FC</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Arnold</surname>
                            <given-names>AS</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>OpenSim: open-source software to create and analyze dynamic simulations of movement.</article-title>
                    <source>

                        <italic toggle="yes">IEEE Trans. Biomed. Eng.</italic>
</source>
                    <year>2007</year>;<volume>54</volume>:<fpage>1940</fpage>&#x2013;<lpage>1950</lpage>.
                    <pub-id pub-id-type="pmid">18018689</pub-id>
                    <pub-id pub-id-type="doi">10.1109/TBME.2007.901024</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref2">
                <label>2</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Lund</surname>
                            <given-names>ME</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Zee</surname>
                            <given-names>M</given-names>
                            <prefix>de</prefix>
                        </name>

                        <name name-style="western">
                            <surname>Andersen</surname>
                            <given-names>MS</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>On validation of multibody musculoskeletal models.</article-title>
                    <source>

                        <italic toggle="yes">Proc. Inst. Mech. Eng. H J. Eng. Med.</italic>
</source>
                    <year>2012</year>;<volume>226</volume>:<fpage>82</fpage>&#x2013;<lpage>94</lpage>.
                    <pub-id pub-id-type="pmid">22468460</pub-id>
                    <pub-id pub-id-type="doi">10.1177/0954411911431516</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref3">
                <label>3</label>
                <mixed-citation publication-type="other">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Todorov</surname>
                            <given-names>E</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Erez</surname>
                            <given-names>T</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Tassa</surname>
                            <given-names>Y</given-names>
                        </name>
</person-group>:
                    <chapter-title>Mujoco: A physics engine for model-based control.</chapter-title>
                    <source>

                        <italic toggle="yes">2012 IEEE/RSJ international conference on intelligent robots and systems.</italic>
</source>
                    <year>2012</year>;<fpage>5026</fpage>&#x2013;<lpage>5033</lpage>.</mixed-citation>
            </ref>
            <ref id="ref4">
                <label>4</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Tierney</surname>
                            <given-names>G</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Simms</surname>
                            <given-names>C</given-names>
                        </name>
</person-group>:
                    <article-title>Predictive Capacity of the MADYMO Multibody Human Body Model Applied to Head Kinematics during Rugby Union Tackles.</article-title>
                    <source>

                        <italic toggle="yes">Appl. Sci.</italic>
</source>
                    <year>2019</year>;<volume>9</volume>:<fpage>726</fpage>.
                    <pub-id pub-id-type="doi">10.3390/app9040726</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref5">
                <label>5</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Rasmussen</surname>
                            <given-names>J</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Damsgaard</surname>
                            <given-names>M</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Voigt</surname>
                            <given-names>M</given-names>
                        </name>
</person-group>:
                    <article-title>Muscle recruitment by the min/max criterion&#x2014;a comparative numerical study.</article-title>
                    <source>

                        <italic toggle="yes">J. Biomech.</italic>
</source>
                    <year>2001</year>;<volume>34</volume>:<fpage>409</fpage>&#x2013;<lpage>415</lpage>.
                    <pub-id pub-id-type="pmid">11182135</pub-id>
                    <pub-id pub-id-type="doi">10.1016/S0021-9290(00)00191-3</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref6">
                <label>6</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Sherman</surname>
                            <given-names>MA</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Seth</surname>
                            <given-names>A</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Delp</surname>
                            <given-names>SL</given-names>
                        </name>
</person-group>:
                    <article-title>Simbody: multibody dynamics for biomedical research.</article-title>
                    <source>

                        <italic toggle="yes">Procedia Iutam.</italic>
</source>
                    <year>2011</year>;<volume>2</volume>:<fpage>241</fpage>&#x2013;<lpage>261</lpage>.
                    <pub-id pub-id-type="pmid">25866705</pub-id>
                    <pub-id pub-id-type="doi">10.1016/j.piutam.2011.04.023</pub-id>
                    <pub-id pub-id-type="pmcid">PMC4390141</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref7">
                <label>7</label>
                <mixed-citation publication-type="other">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Gede</surname>
                            <given-names>G</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Peterson</surname>
                            <given-names>DL</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Nanjangud</surname>
                            <given-names>AS</given-names>
                        </name>

                        <etal/>
</person-group>;
                    <chapter-title>Constrained multibody dynamics with Python: From symbolic equation generation to publication.</chapter-title>
                    <source>

                        <italic toggle="yes">International Design Engineering Technical Conferences and Computers and Information in Engineering Conference.</italic>
</source>
                    <year>2013</year>;<fpage>V07BT10A051</fpage>.</mixed-citation>
            </ref>
            <ref id="ref8">
                <label>8</label>
                <mixed-citation publication-type="other">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Coumans</surname>
                            <given-names>E</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Bai</surname>
                            <given-names>Y</given-names>
                        </name>
</person-group>:
                    <article-title>Pybullet, a python module for physics simulation for games, robotics and machine learning (2016&#x2013;2021).</article-title>
                    <ext-link ext-link-type="uri" xlink:href="http://pybullet.org">Reference Source</ext-link>
                </mixed-citation>
            </ref>
            <ref id="ref9">
                <label>9</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Felis</surname>
                            <given-names>ML</given-names>
                        </name>
</person-group>:
                    <article-title>RBDL: an efficient rigid-body dynamics library using recursive algorithms.</article-title>
                    <source>

                        <italic toggle="yes">Auton. Robot.</italic>
</source>
                    <year>2017</year>;<volume>41</volume>:<fpage>495</fpage>&#x2013;<lpage>511</lpage>.
                    <pub-id pub-id-type="doi">10.1007/s10514-016-9574-0</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref10">
                <label>10</label>
                <mixed-citation publication-type="book">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Wittenburg</surname>
                            <given-names>J</given-names>
                        </name>
</person-group>:
                    <source>

                        <italic toggle="yes">Dynamics of Multibody Systems.</italic>
</source>
                    <publisher-loc>Berlin</publisher-loc>:
                    <publisher-name>Springer</publisher-name>;<year>2008</year>.</mixed-citation>
            </ref>
            <ref id="ref11">
                <label>11</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Van Der Walt</surname>
                            <given-names>S</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Colbert</surname>
                            <given-names>SC</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Varoquaux</surname>
                            <given-names>G</given-names>
                        </name>
</person-group>:
                    <article-title>The NumPy array: a structure for efficient numerical computation.</article-title>
                    <source>

                        <italic toggle="yes">Computing in science &amp; engineering.</italic>
</source>
                    <year>2011</year>;<volume>13</volume>:<fpage>22</fpage>&#x2013;<lpage>30</lpage>.
                    <pub-id pub-id-type="doi">10.1109/MCSE.2011.37</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref12">
                <label>12</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Hunter</surname>
                            <given-names>JD</given-names>
                        </name>
</person-group>:
                    <article-title>Matplotlib: A 2D graphics environment.</article-title>
                    <source>

                        <italic toggle="yes">Computing in Science &amp; Engineering.</italic>
</source>
                    <year>2007</year>;<volume>9</volume>(<issue>3</issue>):<fpage>90</fpage>&#x2013;<lpage>95</lpage>.
                    <pub-id pub-id-type="doi">10.1109/MCSE.2007.55</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref13">
                <label>13</label>
                <mixed-citation publication-type="other">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Clark</surname>
                            <given-names>A</given-names>
                        </name>
</person-group>:
                    <article-title>Pillow (pil fork) documentation. readthedocs.</article-title>
                    <year>2015</year>.</mixed-citation>
            </ref>
            <ref id="ref14">
                <label>14</label>
                <mixed-citation publication-type="book">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Featherstone</surname>
                            <given-names>R</given-names>
                        </name>
</person-group>:
                    <source>

                        <italic toggle="yes">Rigid body dynamics algorithms.</italic>
</source>
                    <publisher-loc>Boston, MA</publisher-loc>:
                    <publisher-name>Springer</publisher-name>;<year>2008</year>.
                    <pub-id pub-id-type="doi">10.1007/978-1-4899-7560-7</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref15">
                <label>15</label>
                <mixed-citation publication-type="book">
                    <collab>American Academy of Orthopaedic Surgeons</collab>:
                    <source>

                        <italic toggle="yes">Joint motion: method of measuring and recording.</italic>
</source>
                    <publisher-loc>Edinburgh, UK</publisher-loc>:
                    <publisher-name>British Orthopaedic Association</publisher-name>;<year>1965</year>.</mixed-citation>
            </ref>
            <ref id="ref16">
                <label>16</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Van Zandwijk</surname>
                            <given-names>JP</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Bobbert</surname>
                            <given-names>MF</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Baan</surname>
                            <given-names>GC</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>From twitch to tetanus: performance of excitation dynamics optimized for a twitch in predicting tetanic muscle forces.</article-title>
                    <source>

                        <italic toggle="yes">Biol. Cybern.</italic>
</source>
                    <year>1996</year>;<volume>75</volume>:<fpage>409</fpage>&#x2013;<lpage>417</lpage>.
                    <pub-id pub-id-type="doi">10.1007/s004220050306</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref17">
                <label>17</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Fryar</surname>
                            <given-names>CD</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Gu</surname>
                            <given-names>Q</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Afful</surname>
                            <given-names>J</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>Anthropometric Reference Data for Children and Adults: United States, August 2021&#x2013;August 2023.</article-title>
                    <source>

                        <italic toggle="yes">Vital Health Stat.</italic>
</source>
                    <year>2025</year>;<volume>3</volume>:<fpage>50</fpage>.</mixed-citation>
            </ref>
            <ref id="ref18">
                <label>18</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>De Leva</surname>
                            <given-names>P</given-names>
                        </name>
</person-group>:
                    <article-title>Adjustments to Zatsiorsky-Seluyanov's segment inertia parameters.</article-title>
                    <source>

                        <italic toggle="yes">J. Biomech.</italic>
</source>
                    <year>1996</year>;<volume>29</volume>:<fpage>1223</fpage>&#x2013;<lpage>1230</lpage>.
                    <pub-id pub-id-type="pmid">8872282</pub-id>
                    <pub-id pub-id-type="doi">10.1016/0021-9290(95)00178-6</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref19">
                <label>19</label>
                <mixed-citation publication-type="book">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Winter</surname>
                            <given-names>DA</given-names>
                        </name>
</person-group>:
                    <source>

                        <italic toggle="yes">Biomechanics and motor control of human movement.</italic>
</source>
                    <publisher-loc>Hoboken, NJ</publisher-loc>:
                    <publisher-name>John Wiley &amp; Sons</publisher-name>;<year>2009</year>.</mixed-citation>
            </ref>
            <ref id="ref20">
                <label>20</label>
                <mixed-citation publication-type="book">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Clauser</surname>
                            <given-names>CE</given-names>
                        </name>

                        <name name-style="western">
                            <surname>McConville</surname>
                            <given-names>JT</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Young</surname>
                            <given-names>JW</given-names>
                        </name>
</person-group>:
                    <source>

                        <italic toggle="yes">Weight, volume, and center of mass of segments of the human body.</italic>
</source>
                    <publisher-name>NASA</publisher-name>;<year>1969</year>.</mixed-citation>
            </ref>
            <ref id="ref21">
                <label>21</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Bell</surname>
                            <given-names>AL</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Brand</surname>
                            <given-names>RA</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Pedersen</surname>
                            <given-names>DR</given-names>
                        </name>
</person-group>:
                    <article-title>Prediction of hip joint centre location from external landmarks.</article-title>
                    <source>

                        <italic toggle="yes">Hum. Mov. Sci.</italic>
</source>
                    <year>1989</year>;<volume>8</volume>:<fpage>3</fpage>&#x2013;<lpage>16</lpage>.
                    <pub-id pub-id-type="doi">10.1016/0167-9457(89)90020-1</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref22">
                <label>22</label>
                <mixed-citation publication-type="book">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Gordon</surname>
                            <given-names>CC</given-names>
                        </name>
</person-group>:
                    <source>

                        <italic toggle="yes">Anthropometric Survey of US Army Personnel (ANSUR II).</italic>
</source>
                    <publisher-name>US Army Natick Soldier Research, Development, and Engineering Center</publisher-name>;<year>2012</year>.</mixed-citation>
            </ref>
            <ref id="ref23">
                <label>23</label>
                <mixed-citation publication-type="book">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Pheasant</surname>
                            <given-names>S</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Haslegrave</surname>
                            <given-names>CM</given-names>
                        </name>
</person-group>:
                    <source>

                        <italic toggle="yes">Bodyspace: Anthropometry, ergonomics and the design of work.</italic>
</source>
                    <publisher-loc>Boca Raton, FL</publisher-loc>:
                    <publisher-name>CRC press</publisher-name>;<year>2018</year>.</mixed-citation>
            </ref>
            <ref id="ref24">
                <label>24</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Kroell</surname>
                            <given-names>CK</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Schneider</surname>
                            <given-names>DC</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Nahum</surname>
                            <given-names>AM</given-names>
                        </name>
</person-group>:
                    <article-title>Impact tolerance and response of the human thorax II.</article-title>
                    <source>

                        <italic toggle="yes">SAE Trans.</italic>
</source>
                    <year>1974</year>;<volume>83</volume>:<fpage>3724</fpage>&#x2013;<lpage>3762</lpage>.</mixed-citation>
            </ref>
            <ref id="ref25">
                <label>25</label>
                <mixed-citation publication-type="other">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Nahum</surname>
                            <given-names>AM</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Smith</surname>
                            <given-names>R</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Ward</surname>
                            <given-names>CC</given-names>
                        </name>
</person-group>:
                    <chapter-title>Intracranial pressure dynamics during head impact.</chapter-title>
                    <source>

                        <italic toggle="yes">SAE Technical Paper.</italic>
</source>
                    <year>1977</year>;<fpage>770922</fpage>.</mixed-citation>
            </ref>
            <ref id="ref26">
                <label>26</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Saraf</surname>
                            <given-names>H</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Ramesh</surname>
                            <given-names>KT</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Lennon</surname>
                            <given-names>AM</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>Mechanical properties of soft human tissues under dynamic loading.</article-title>
                    <source>

                        <italic toggle="yes">J. Biomech.</italic>
</source>
                    <year>2007</year>;<volume>40</volume>:<fpage>1960</fpage>&#x2013;<lpage>1967</lpage>.
                    <pub-id pub-id-type="doi">10.1016/j.jbiomech.2006.09.021</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref27">
                <label>27</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Gefen</surname>
                            <given-names>A</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Haberman</surname>
                            <given-names>E</given-names>
                        </name>
</person-group>:
                    <article-title>Viscoelastic properties of ovine adipose tissue covering the gluteus muscles.</article-title>
                    <source>

                        <italic toggle="yes">J. Biomech. Eng.</italic>
</source>
                    <year>2007</year>;<volume>129</volume>:<fpage>924</fpage>&#x2013;<lpage>930</lpage>.
                    <pub-id pub-id-type="doi">10.1115/1.2800830</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref28">
                <label>28</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Ker</surname>
                            <given-names>RF</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Bennett</surname>
                            <given-names>MB</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Bibby</surname>
                            <given-names>SR</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>The spring in the arch of the human foot.</article-title>
                    <source>

                        <italic toggle="yes">Nature.</italic>
</source>
                    <year>1987</year>;<volume>325</volume>:<fpage>147</fpage>&#x2013;<lpage>149</lpage>.
                    <pub-id pub-id-type="doi">10.1038/325147a0</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref29">
                <label>29</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Cavanagh</surname>
                            <given-names>PR</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Lafortune</surname>
                            <given-names>MA</given-names>
                        </name>
</person-group>:
                    <article-title>Ground reaction forces in distance running.</article-title>
                    <source>

                        <italic toggle="yes">J. Biomech.</italic>
</source>
                    <year>1980</year>;<volume>13</volume>:<fpage>397</fpage>&#x2013;<lpage>406</lpage>.
                    <pub-id pub-id-type="doi">10.1016/0021-9290(80)90033-0</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref30">
                <label>30</label>
                <mixed-citation publication-type="book">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Yamada</surname>
                            <given-names>H</given-names>
                        </name>
</person-group>:
                    <source>

                        <italic toggle="yes">Strength of Biological Materials.</italic>
</source>
                    <publisher-loc>Malabar, FL</publisher-loc>:
                    <publisher-name>Krieger Publishing Company</publisher-name>;<year>1970</year>.</mixed-citation>
            </ref>
            <ref id="ref31">
                <label>31</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Maki</surname>
                            <given-names>T</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Kajzer</surname>
                            <given-names>J</given-names>
                        </name>
</person-group>:
                    <article-title>Parametric study of vehicle front-end contact conditions for pedestrian safety simulation.</article-title>
                    <source>

                        <italic toggle="yes">J. Biomech.</italic>
</source>
                    <year>2000</year>;<volume>33</volume>:<fpage>813</fpage>&#x2013;<lpage>825</lpage>.</mixed-citation>
            </ref>
            <ref id="ref32">
                <label>32</label>
                <mixed-citation publication-type="other">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Kerrigan</surname>
                            <given-names>JR</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Bhalla</surname>
                            <given-names>KS</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Madeley</surname>
                            <given-names>NJ</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <chapter-title>Experiments for establishing pedestrian-impact lower limb injury criteria.</chapter-title>
                    <source>

                        <italic toggle="yes">SAE Technical Paper.</italic>
</source>
                    <year>2003</year>;<fpage>2003&#x2013;0895</fpage>.</mixed-citation>
            </ref>
            <ref id="ref33">
                <label>33</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Yasuki</surname>
                            <given-names>T</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Yamamae</surname>
                            <given-names>Y</given-names>
                        </name>
</person-group>:
                    <article-title>Validation of kinematics and lower extremity injuries estimated by total human model for safety in SUV to pedestrian impact simulation.</article-title>
                    <source>

                        <italic toggle="yes">Int J Crashworthiness.</italic>
</source>
                    <year>2010</year>;<volume>15</volume>:<fpage>425</fpage>&#x2013;<lpage>444</lpage>.</mixed-citation>
            </ref>
            <ref id="ref34">
                <label>34</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Maltese</surname>
                            <given-names>MR</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Eppinger</surname>
                            <given-names>RH</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Antona-Makoshi</surname>
                            <given-names>J</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>Agerelated regional material properties of the human head.</article-title>
                    <source>

                        <italic toggle="yes">Accid. Anal. Prev.</italic>
</source>
                    <year>2008</year>;<volume>40</volume>:<fpage>1731</fpage>&#x2013;<lpage>1736</lpage>.</mixed-citation>
            </ref>
            <ref id="ref35">
                <label>35</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Untaroiu</surname>
                            <given-names>CD</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Meissner</surname>
                            <given-names>MU</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Crandall</surname>
                            <given-names>JR</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>Crash reconstruction of pedestrian accidents using optimization techniques.</article-title>
                    <source>

                        <italic toggle="yes">J. Biomech. Eng.</italic>
</source>
                    <year>2010</year>;<volume>132</volume>.</mixed-citation>
            </ref>
            <ref id="ref36">
                <label>36</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Maki</surname>
                            <given-names>T</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Asai</surname>
                            <given-names>T</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Kajzer</surname>
                            <given-names>J</given-names>
                        </name>
</person-group>:
                    <article-title>The behavior of bicyclists in accidents with cars.</article-title>
                    <source>

                        <italic toggle="yes">JSAE Rev.</italic>
</source>
                    <year>2000</year>;<volume>21</volume>:<fpage>357</fpage>&#x2013;<lpage>363</lpage>.</mixed-citation>
            </ref>
        </ref-list>
    </back>
</article>
