├── .github └── workflows │ └── test.yml ├── .gitignore ├── .readthedocs.yml ├── AUTHORS ├── CHANGELOG.rst ├── LICENSE.txt ├── MANIFEST.in ├── Procfile ├── README.rst ├── RELEASE.rst ├── bicycleparameters ├── __init__.py ├── _mooreriderlean2012.py ├── app-data │ └── bicycles │ │ ├── Benchmark │ │ └── Parameters │ │ │ └── BenchmarkBenchmark.txt │ │ ├── Browser │ │ └── Parameters │ │ │ └── BrowserBenchmark.txt │ │ ├── Browserins │ │ └── Parameters │ │ │ └── BrowserinsBenchmark.txt │ │ ├── Crescendo │ │ └── Parameters │ │ │ └── CrescendoBenchmark.txt │ │ ├── Fisher │ │ └── Parameters │ │ │ └── FisherBenchmark.txt │ │ ├── Pista │ │ └── Parameters │ │ │ └── PistaBenchmark.txt │ │ ├── Rigid │ │ └── Parameters │ │ │ └── RigidBenchmark.txt │ │ ├── Silver │ │ └── Parameters │ │ │ └── SilverBenchmark.txt │ │ ├── Yellow │ │ └── Parameters │ │ │ └── YellowBenchmark.txt │ │ └── Yellowrev │ │ └── Parameters │ │ └── YellowrevBenchmark.txt ├── app.py ├── assets │ ├── app-explanation.md │ └── styles.css ├── bicycle.py ├── com.py ├── conversions.py ├── geometry.py ├── inertia.py ├── io.py ├── main.py ├── models.py ├── parameter_dicts.py ├── parameter_sets.py ├── period.py ├── plot.py ├── rider.py ├── tables.py ├── tests │ ├── __init__.py │ ├── parameter_sets │ │ ├── benchmark-benchmark.yml │ │ ├── benchmark-browser.yml │ │ ├── benchmark-extendedoptc.yml │ │ ├── benchmark-pista.yml │ │ ├── benchmark-pistarider.yml │ │ ├── benchmark-pistarideroptimized3ms.yml │ │ ├── benchmark-realizedopttwo.yml │ │ ├── principal-browserjason.yml │ │ └── principal-extendedoptf.yml │ ├── sample_data │ │ └── BrowserForkCompoundFirst1.mat │ ├── test_bicycle.py │ ├── test_bicycleparameters.py │ ├── test_io.py │ ├── test_models.py │ └── test_parameter_sets.py └── version.py ├── conda ├── bicycleparameters-1.0.0 │ └── meta.yaml ├── bicycleparameters-dev-old.yml ├── bicycleparameters-dev.yml └── cycle-app-environment.yml ├── data ├── bicycles │ ├── Balanceassistv1 │ │ ├── Parameters │ │ │ └── Balanceassistv1Benchmark.txt │ │ └── RawData │ │ │ └── Balanceassistv1Measured.txt │ ├── Benchmark │ │ └── Parameters │ │ │ └── BenchmarkBenchmark.txt │ ├── Browser │ │ ├── Parameters │ │ │ └── BrowserBenchmark.txt │ │ └── RawData │ │ │ └── BrowserMeasured.txt │ ├── Browserins │ │ ├── Parameters │ │ │ └── BrowserinsBenchmark.txt │ │ └── RawData │ │ │ └── BrowserinsMeasured.txt │ ├── Crescendo │ │ ├── Parameters │ │ │ └── CrescendoBenchmark.txt │ │ └── RawData │ │ │ └── CrescendoMeasured.txt │ ├── Fisher │ │ ├── Parameters │ │ │ └── FisherBenchmark.txt │ │ └── RawData │ │ │ └── FisherMeasured.txt │ ├── Gyro │ │ └── RawData │ │ │ └── GyroMeasured.txt │ ├── MeasuredTemplate.txt │ ├── Pista │ │ ├── Parameters │ │ │ └── PistaBenchmark.txt │ │ └── RawData │ │ │ └── PistaMeasured.txt │ ├── Rigid │ │ ├── Parameters │ │ │ └── RigidBenchmark.txt │ │ └── RawData │ │ │ └── RigidMeasured.txt │ ├── Rigidcl │ │ └── RawData │ │ │ └── RigidclMeasured.txt │ ├── Silver │ │ ├── Parameters │ │ │ └── SilverBenchmark.txt │ │ └── RawData │ │ │ └── SilverMeasured.txt │ ├── Stratos │ │ └── RawData │ │ │ └── StratosMeasured.txt │ ├── Tms │ │ └── Parameters │ │ │ └── TmsBenchmark.txt │ ├── Yellow │ │ ├── Parameters │ │ │ └── YellowBenchmark.txt │ │ └── RawData │ │ │ └── YellowMeasured.txt │ └── Yellowrev │ │ ├── Parameters │ │ └── YellowrevBenchmark.txt │ │ └── RawData │ │ └── YellowrevMeasured.txt └── riders │ ├── Aurelia │ └── RawData │ │ └── AureliaYeadonMeas.txt │ ├── Charlie │ └── RawData │ │ ├── CharlieRigidclYeadonCFG.txt │ │ └── CharlieYeadonMeas.txt │ ├── Child │ └── RawData │ │ ├── ChildGyroYeadonCFG.txt │ │ ├── ChildYeadonMeas.txt │ │ └── convert.py │ ├── Chris │ └── RawData │ │ └── ChrisYeadonMeas.txt │ ├── Jason │ ├── Parameters │ │ ├── JasonBalanceassistv1Benchmark.txt │ │ ├── JasonBrowserBenchmark.txt │ │ └── JasonRigidBenchmark.txt │ └── RawData │ │ ├── JasonBalanceassistv1YeadonCFG.txt │ │ ├── JasonBrowserYeadonCFG.txt │ │ ├── JasonBrowserinsYeadonCFG.txt │ │ ├── JasonRigidYeadonCFG.txt │ │ ├── JasonStratosYeadonCFG.txt │ │ └── JasonYeadonMeas.txt │ ├── Luke │ └── RawData │ │ ├── LukeRigidclYeadonCFG.txt │ │ └── LukeYeadonMeas.txt │ └── Mont │ └── RawData │ └── MontYeadonMeas.txt ├── docs ├── Makefile ├── api │ ├── bicycle.rst │ ├── com.rst │ ├── geometry.rst │ ├── inertia.rst │ ├── io.rst │ ├── main.rst │ ├── models.rst │ ├── parameter_sets.rst │ ├── period.rst │ ├── plot.rst │ ├── rider.rst │ └── tables.rst ├── app.rst ├── bicycleparameters.rst ├── conf.py ├── data.rst ├── description.rst ├── index.rst ├── installation.rst └── make.bat ├── gallery ├── README.rst ├── examples │ ├── README.rst │ ├── plot_balanceassistv1.py │ ├── plot_benchmark.py │ ├── plot_lqr.py │ └── plot_mooreriderlean2012.py ├── plot_bicycle.py ├── plot_models.py └── plot_parameter_set.py ├── requirements.txt ├── setup.py └── utils ├── create_bicycle_files.py ├── largest_eigenvalue_plot.py ├── package_data.py └── time_eig.py /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | # based on https://github.com/mamba-org/provision-with-micromamba 2 | name: test 3 | on: 4 | push: 5 | branches: master 6 | pull_request: 7 | branches: master 8 | # cancels prior builds for this workflow when new commit is pushed 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.ref }} 11 | cancel-in-progress: true 12 | jobs: 13 | test: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | dependency-set: ["-old", ""] 18 | python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] 19 | exclude: 20 | - dependency-set: "-old" 21 | python-version: "3.10" 22 | - dependency-set: "-old" 23 | python-version: "3.11" 24 | - dependency-set: "-old" 25 | python-version: "3.12" 26 | - dependency-set: "-old" 27 | python-version: "3.13" 28 | name: test 29 | steps: 30 | - uses: actions/checkout@v4 31 | - name: Setup Conda environment 32 | uses: conda-incubator/setup-miniconda@v3 33 | with: 34 | auto-update-conda: true 35 | python-version: ${{ matrix.python-version }} 36 | channels: conda-forge 37 | environment-file: conda/bicycleparameters-dev${{ matrix.dependency-set }}.yml 38 | - name: run tests 39 | shell: bash -l {0} 40 | run: | 41 | conda info 42 | conda list 43 | python -c "import bicycleparameters" 44 | py.test --doctest-modules bicycleparameters/ 45 | - name: build documentation 46 | shell: bash -l {0} 47 | run: | 48 | conda info 49 | conda list 50 | cd docs 51 | make html 52 | - name: test installation 53 | shell: bash -l {0} 54 | run: | 55 | conda info 56 | python setup.py install 57 | conda list 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # sphinx and sphinx gallery output 2 | docs/_build/ 3 | docs/gallery/ 4 | docs/sg_execution_times.rst 5 | 6 | # vim 7 | .*.sw[a-z] 8 | *.un~ 9 | Session.vim 10 | 11 | # python 12 | *.py[co] 13 | 14 | # Packages 15 | *.egg 16 | *.egg-info 17 | dist 18 | build 19 | eggs 20 | parts 21 | bin 22 | var 23 | sdist 24 | develop-eggs 25 | .installed.cfg 26 | 27 | # Installer logs 28 | pip-log.txt 29 | 30 | # Unit test / coverage reports 31 | .coverage 32 | .tox 33 | 34 | #Translations 35 | *.mo 36 | 37 | #Mr Developer 38 | .mr.developer.cfg 39 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | build: 3 | os: "ubuntu-22.04" 4 | tools: 5 | python: "mambaforge-22.9" 6 | sphinx: 7 | configuration: docs/conf.py 8 | formats: all 9 | conda: 10 | environment: conda/bicycleparameters-dev.yml 11 | python: 12 | install: 13 | - method: setuptools 14 | path: . 15 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Jason K. Moore 2 | Chris Dembia 3 | Oliver Lee 4 | Lyla Sanders 5 | Julie van Vlerken 6 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | Release Notes 2 | ============= 3 | 4 | 1.3.0 5 | ----- 6 | 7 | - Drop support for Python 3.8. 8 | - Moved example usage into a Sphinx Gallery and created a number of examples. 9 | - Added a new rider lean linear model and example demonstrating its use. 10 | - Added a new model that implements full state feedback on the linear 11 | Carvallo-Whipple model and example demonstrating its use. 12 | - Fixed numerous bugs in models.py to support models with more state variables. 13 | 14 | 1.2.0 15 | ----- 16 | 17 | - Support Python 3.13. 18 | - Revert to ``unumpy.matrix`` in mass center and inertia calculations. 19 | - Updated the raw data mat file loading to work with current Python versions. 20 | - Support raw data pendulum measurement files with time as an array as well as 21 | a fixed sample rate (as before). 22 | - Remove the unnecessary ``__new__`` method from ``Bicycle``. 23 | - Added options to show stable ranges and to hide zero eigenvalues in the 24 | ``Model`` eigenvalues parts plot. 25 | - Skip data truncation on raw pendulum time series that have the explicit time 26 | array (this is a hack for the Balanceassistv1 data to have valid handlebar 27 | inertia). 28 | - Modernized some internal plotting code. 29 | - Added measured and calculated parameter data for the Balanceassistv1 bike we 30 | measured in the summer of 2024. This is a Gazelle Grenoble C8 HMB electric 31 | bicycle with a custom headtube with a steering motor. 32 | 33 | 1.1.1 34 | ----- 35 | 36 | - Ensure that the app's data files are installed. 37 | 38 | 1.1.0 39 | ----- 40 | 41 | - Introduced a Dash based web application for interactive use. 42 | 43 | - https://github.com/moorepants/BicycleParameters/pull/34 44 | - https://github.com/moorepants/BicycleParameters/pull/88 45 | 46 | - Dropped support for Python 2.7, 3.4, 3.5, 3.6, and 3.7. Added support for 47 | Python 3.8, 3.9, 3.10, 3.11, 3.12. 48 | - Bumped dependency minimum verions to match Ubuntu 22.04. 49 | - Moved to mamba and Github action based continuous integration testing. 50 | - Introduced new parameter_sets and models modules for future class hierarchies 51 | and better design. 52 | - ``bicycleparameters/test/`` moved to ``bicycleparameters/tests/``. 53 | - Removed remaining NumPy ``matrix()`` calls. 54 | - Improved some of the matplotlib plots. 55 | 56 | 1.0.0 57 | ----- 58 | 59 | - Support Python 3 60 | 61 | 0.2.0 62 | ----- 63 | 64 | - Commands using the state space form of the Whipple model have been reordered 65 | to [roll angle, steer angle, roll rate, steer rate] 66 | - Added another rider's measurments. 67 | - Added a module for printing tables of data. 68 | - Added the Gyrobike and the ability to manage it's flywheel rigidbody. 69 | - Fixed a bug in `calculate_abc_geometry()` that gave incorrect geometry 70 | values. 71 | - Handles two additional points for the Davis Instrumented Bicycle. 72 | - Added a child sized person based on scaling Charlie's measurements. 73 | - Added Bode plot commands. 74 | - Added nominal output options for several methods. 75 | - Added a dependency to DynamicistToolKit 76 | - Updated core dependencies to a minimum from the Ubuntu 12.04 release. 77 | - Tested with DTK 0.1.0 to 0.3.5. 78 | - Added Travis support. 79 | - The minimum yeadon version is bumped to 1.1.1 and code updated to reflect the 80 | new yeadon api. 81 | - The minimum version of uncertainties is bumped to 2.0. 82 | 83 | 0.1.3 84 | ----- 85 | 86 | - Speed increase for the eigenvalue calculations. 87 | - Added measurements for the human configuration on some bikes. 88 | 89 | 0.1.2 90 | ----- 91 | 92 | - Fixed the tex related bug for the pendulum fit plots 93 | - Fixed some import bugs affecting the split fork/handlebar calcs 94 | 95 | 0.1.1 96 | ----- 97 | 98 | - changed the default directory to . 99 | - added pip install notes 100 | - fixed urls in setup.py and the readme 101 | - added version number to the package 102 | - removed the human machine classifier 103 | - reduced the size of the images in the docs 104 | - broke bicycleparameters.py into several modules 105 | - updated the documentation 106 | 107 | 0.1.0 108 | ----- 109 | 110 | - Initial release. 111 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2025, BicycleParameters Authors 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | The views and conclusions contained in the software and documentation are those 26 | of the authors and should not be interpreted as representing official policies, 27 | either expressed or implied, of Jason Keith Moore. 28 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include AUTHORS 2 | include CHANGELOG.rst 3 | include LICENSE.txt 4 | include README.rst 5 | include bicycleparameters/assets/* 6 | include bicycleparameters/tests/sample_data/*.mat 7 | include docs/Makefile 8 | include docs/conf.py 9 | include docs/make.bat 10 | recursive-include bicycleparameters/ *.yml 11 | recursive-include bicycleparameters/app-data/ *.txt 12 | recursive-include data/ *.txt 13 | recursive-include docs *.rst 14 | recursive-include gallery/ *.py 15 | recursive-include gallery/ *.rst 16 | prune docs/gallery/ 17 | prune docs/sg_execution_times.rst 18 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn bicycleparameters.app:server 2 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | BicycleParameters 3 | ================= 4 | 5 | A Python program designed to generate, manipulate, and visualize the parameters 6 | of the bicycle dynamics models. 7 | 8 | .. list-table:: 9 | 10 | * - Download from PyPi 11 | - |PyPi| 12 | * - Download from Anaconda 13 | - |Anaconda| 14 | * - Documentation 15 | - |RTD| 16 | * - CI Status 17 | - |GHCI| 18 | * - Render App 19 | - |Render| 20 | 21 | .. |PyPi| image:: https://img.shields.io/pypi/v/BicycleParameters.svg 22 | :target: https://pypi.org/project/BicycleParameters/ 23 | 24 | .. |Anaconda| image:: https://anaconda.org/conda-forge/bicycleparameters/badges/version.svg 25 | :target: https://anaconda.org/conda-forge/bicycleparameters 26 | 27 | .. |GHCI| image:: https://github.com/moorepants/BicycleParameters/actions/workflows/test.yml/badge.svg 28 | 29 | .. |RTD| image:: https://readthedocs.org/projects/bicycleparameters/badge/?version=latest 30 | :target: https://bicycleparameters.readthedocs.io/ 31 | :alt: Documentation Status 32 | 33 | .. |Render| image:: https://img.shields.io/badge/Bicycle_Dynamics_App-Render.io-blue 34 | :target: https://bicycle-dynamics.onrender.com 35 | 36 | Dependencies 37 | ============ 38 | 39 | Required 40 | -------- 41 | 42 | - `DynamicistToolKit >= 0.5.3 `_ 43 | - `Matplotlib >= 3.5.1 `_ 44 | - `NumPy >= 1.21.5 `_ 45 | - `Python >= 3.8 `_ 46 | - `SciPy >= 1.8.0 `_ 47 | - `Uncertainties >= 3.1.5 `_ 48 | - `yeadon >= 1.3.0 `_ 49 | 50 | Optional 51 | -------- 52 | 53 | These are required to run the Dash web application: 54 | 55 | - `Dash >= 2.0 `_ 56 | - `dash-bootstrap-components `_ 57 | - `Pandas >= 1.3.5 `_ 58 | 59 | These are required to build the documentation: 60 | 61 | - `Sphinx >= 4.3.2 `_ 62 | - `Numpydoc >= 1.2 `_ 63 | - `sphinx-reredirects `_ 64 | - `Sphinx-Gallery `_ 65 | 66 | Installation 67 | ============ 68 | 69 | We recommend installing BicycleParameters with conda_ or pip_. 70 | 71 | .. _conda: https://docs.conda.io 72 | .. _pip: https://pip.pypa.io 73 | 74 | For conda:: 75 | 76 | $ conda install -c conda-forge bicycleparameters 77 | 78 | For pip:: 79 | 80 | $ pip install BicycleParameters 81 | 82 | The package can also be installed from the source code. The options for getting 83 | the source code are: 84 | 85 | 1. Clone the source code with Git: ``git clone 86 | git://github.com/moorepants/BicycleParameters.git`` 87 | 2. `Download the source from Github`__. 88 | 3. Download the source from pypi__. 89 | 90 | .. __: https://github.com/moorepants/BicycleParameters 91 | .. __: http://pypi.python.org/pypi/BicycleParameters 92 | 93 | Once you have the source code navigate to the directory and run:: 94 | 95 | >>> python setup.py install 96 | 97 | This will install the software into your system. You can check if it installs 98 | with:: 99 | 100 | $ python -c "import bicycleparameters" 101 | 102 | Example Code 103 | ============ 104 | 105 | .. code-block:: python 106 | 107 | >>> import bicycleparameters as bp 108 | >>> import numpy as np 109 | >>> rigid = bp.Bicycle('Rigid') 110 | >>> par = rigid.parameters['Benchmark'] 111 | >>> rigid.plot_bicycle_geometry() 112 | >>> speeds = np.linspace(0., 10., num=100) 113 | >>> rigid.plot_eigenvalues_vs_speed(speeds) 114 | 115 | See `example usage `_ in the 116 | documentation. 117 | 118 | Sample Data 119 | =========== 120 | 121 | Some sample data is included in the repository but a full source with all the 122 | raw data files can be downloaded from here: 123 | 124 | http://dx.doi.org/10.6084/m9.figshare.1198429 125 | 126 | Documentation 127 | ============= 128 | 129 | Please refer to the `online documentation 130 | `_ for more information. 131 | 132 | Grant Information 133 | ================= 134 | 135 | This material is partially based upon work supported by the National Science 136 | Foundation under `Grant No. 0928339`_. Any opinions, findings, and conclusions 137 | or recommendations expressed in this material are those of the authors and do 138 | not necessarily reflect the views of the National Science Foundation. 139 | 140 | .. _Grant No. 0928339: https://www.nsf.gov/awardsearch/showAward?AWD_ID=0928339 141 | 142 | This material is partially based upon work supported by the TKI CLICKNL grant 143 | "Fiets van de Toekomst"(Grant No. TKI1706). 144 | -------------------------------------------------------------------------------- /RELEASE.rst: -------------------------------------------------------------------------------- 1 | These are the instructions for updating the package. 2 | 3 | 1. Merge all commits from changes. 4 | 2. Update the CHANGELOG. 5 | 3. Update the dependency version info in setup.py, the README, and the docs 6 | description.rst. 7 | 4. Update the version number in bicycleparameters/version.py 8 | 5. Make sure the docs build. 9 | 6. Build the sdist and check contents ``python setup.py sdist``. 10 | 7. Git tag for the new version with ``git tag -a "Version X.X.X``. 11 | 8. Build the sdist ``python setup.py sdist``. 12 | 9. ``twine updload dists/.tar.gz`` 13 | -------------------------------------------------------------------------------- /bicycleparameters/__init__.py: -------------------------------------------------------------------------------- 1 | # import all the important classes and functions from the bicycleparametes 2 | # module 3 | from .main import Bicycle 4 | from .plot import plot_eigenvalues, compare_bode_bicycles 5 | from .tables import Table 6 | from .version import __version_info__, __version__ 7 | 8 | # the modules that are imported when 'from bicycleparameters import *' 9 | __all__ = [ 10 | 'bicycle', 11 | 'com', 12 | 'geometry', 13 | 'inertia', 14 | 'io', 15 | 'main', 16 | 'period', 17 | 'plot', 18 | 'rider', 19 | 'tables', 20 | ] 21 | -------------------------------------------------------------------------------- /bicycleparameters/app-data/bicycles/Benchmark/Parameters/BenchmarkBenchmark.txt: -------------------------------------------------------------------------------- 1 | w = 1.02+/-0.0 2 | c = 0.08+/-0.0 3 | lam = 0.314159265358979323846+/-0.0 4 | g = 9.81+/-0.0 5 | rR = 0.3+/-0.0 6 | mR = 2.0+/-0.0 7 | IRxx = 0.0603+/-0.0 8 | IRyy = 0.12+/-0.0 9 | xB = 0.3+/-0.0 10 | zB = -0.9+/-0.0 11 | mB = 85.0+/-0.0 12 | IBxx = 9.2+/-0.0 13 | IByy = 11.0+/-0.0 14 | IBzz = 2.8+/-0.0 15 | IBxz = 2.4+/-0.0 16 | xH = 0.9+/-0.0 17 | zH = -0.7+/-0.0 18 | mH = 4.0+/-0.0 19 | IHxx = 0.0589+/-0.0 20 | IHyy = 0.06+/-0.0 21 | IHzz = 0.0071+/-0.0 22 | IHxz = -0.0076+/-0.0 23 | rF = 0.35+/-0.0 24 | mF = 3.0+/-0.0 25 | IFxx = 0.1405+/-0.0 26 | IFyy = 0.28+/-0.0 27 | -------------------------------------------------------------------------------- /bicycleparameters/app-data/bicycles/Browser/Parameters/BrowserBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 0.5296+/-0.00247550148476 2 | IBxz = -0.1163+/-0.00114783359707 3 | IByy = 1.3164+/-0.00400774617153 4 | IBzz = 0.7568+/-0.00330394515109 5 | IFxx = 0.0884+/-0.00035969731805 6 | IFyy = 0.1492+/-0.00151585483097 7 | IHxx = 0.2534+/-0.00126852786611 8 | IHxz = -0.0720+/-0.000790281755242 9 | IHyy = 0.2458+/-0.00299166644562 10 | IHzz = 0.0956+/-0.000737521114809 11 | IRxx = 0.0904+/-0.000367953786506 12 | IRyy = 0.1524+/-0.00113908424669 13 | c = 0.0686+/-0.00169464113488 14 | g = 9.81+/-0.01 15 | lam = 0.399680398707+/-0.00349065850399 16 | mB = 9.9+/-0.02 17 | mF = 2.0+/-0.02 18 | mH = 3.2+/-0.02 19 | mR = 3.1+/-0.02 20 | rF = 0.344+/-0.000122426879301 21 | rR = 0.341+/-0.000122426879301 22 | w = 1.121+/-0.002 23 | xB = 0.274+/-0.00309782583552 24 | xH = 0.867+/-0.003842300035 25 | zB = -0.538+/-0.00265022978777 26 | zH = -0.748+/-0.00263543623177 27 | -------------------------------------------------------------------------------- /bicycleparameters/app-data/bicycles/Browserins/Parameters/BrowserinsBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 1.0451+/-0.00504180663254 2 | IBxz = -0.1123+/-0.00342792103562 3 | IByy = 2.4030+/-0.00678076158267 4 | IBzz = 1.8501+/-0.0076900136829 5 | IFxx = 0.0884+/-0.00035969731805 6 | IFyy = 0.1492+/-0.00151585483097 7 | IHxx = 0.2534+/-0.00126852786611 8 | IHxz = -0.0720+/-0.000790281755242 9 | IHyy = 0.2458+/-0.00299166644562 10 | IHzz = 0.0956+/-0.000737521114809 11 | IRxx = 0.0904+/-0.000367953786506 12 | IRyy = 0.1524+/-0.00113908424669 13 | c = 0.068+/-0.00169155184938 14 | g = 9.81+/-0.01 15 | lam = 0.399680398707+/-0.00349065850399 16 | mB = 14.7+/-0.02 17 | mF = 2.0+/-0.02 18 | mH = 3.2+/-0.02 19 | mR = 3.1+/-0.02 20 | rF = 0.343+/-0.000122426879301 21 | rR = 0.341+/-0.000122426879301 22 | w = 1.121+/-0.002 23 | xB = 0.217+/-0.00260084278255 24 | xH = 0.867+/-0.003842300035 25 | zB = -0.622+/-0.00294167899872 26 | zH = -0.747+/-0.00263543623177 27 | -------------------------------------------------------------------------------- /bicycleparameters/app-data/bicycles/Crescendo/Parameters/CrescendoBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 0.4997+/-0.00218886827509 2 | IBxz = -0.0148+/-0.0011316149926 3 | IByy = 1.1174+/-0.00350925696921 4 | IBzz = 0.7393+/-0.00309105815486 5 | IFxx = 0.0954+/-0.000388267862788 6 | IFyy = 0.1656+/-0.00117747774467 7 | IHxx = 0.3840+/-0.0017423135025 8 | IHxz = -0.0778+/-0.00114110113858 9 | IHyy = 0.3631+/-0.00410499482239 10 | IHzz = 0.1664+/-0.00132747251116 11 | IRxx = 0.0966+/-0.000393325323081 12 | IRyy = 0.1438+/-0.00112425225803 13 | c = 0.083+/-0.0016907620071 14 | g = 9.81+/-0.01 15 | lam = 0.366519142919+/-0.00349065850399 16 | mB = 9.1+/-0.02 17 | mF = 3.5+/-0.02 18 | mH = 4.6+/-0.02 19 | mR = 4.0+/-0.02 20 | rF = 0.343+/-0.000122426879301 21 | rR = 0.340+/-0.000122426879301 22 | w = 1.101+/-0.002 23 | xB = 0.312+/-0.00284415365691 24 | xH = 0.907+/-0.00503272487149 25 | zB = -0.526+/-0.00341340590315 26 | zH = -0.803+/-0.00253087563355 27 | -------------------------------------------------------------------------------- /bicycleparameters/app-data/bicycles/Fisher/Parameters/FisherBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 0.2825+/-0.00127383578938 2 | IBxz = 0.0559+/-0.00032406554195 3 | IByy = 0.4697+/-0.00284777713914 4 | IBzz = 0.2677+/-0.00118544629608 5 | IFxx = 0.0631+/-0.000256982558173 6 | IFyy = 0.1062+/-0.00143256408253 7 | IHxx = 0.1147+/-0.00096842589825 8 | IHxz = -0.0182+/-0.00120624722635 9 | IHyy = 0.1000+/-0.00368850446069 10 | IHzz = 0.0226+/-0.00059383598588 11 | IRxx = 0.0630+/-0.000256485390265 12 | IRyy = 0.1008+/-0.00107522785415 13 | c = 0.072+/-0.00162907266827 14 | g = 9.81+/-0.01 15 | lam = 0.329867228627+/-0.00349065850399 16 | mB = 4.5+/-0.02 17 | mF = 1.5+/-0.02 18 | mH = 2.5+/-0.02 19 | mR = 1.9+/-0.02 20 | rF = 0.330+/-0.000113682102208 21 | rR = 0.339+/-0.000113682102208 22 | w = 1.07+/-0.002 23 | xB = 0.367+/-0.00248108393213 24 | xH = 0.960+/-0.00631607383256 25 | zB = -0.499+/-0.0030479185727 26 | zH = -0.719+/-0.00351009078132 27 | -------------------------------------------------------------------------------- /bicycleparameters/app-data/bicycles/Pista/Parameters/PistaBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 0.2900+/-0.00157896728396 2 | IBxz = 0.0502+/-0.00104541145109 3 | IByy = 0.4758+/-0.00928289658533 4 | IBzz = 0.2494+/-0.0012401842031 5 | IFxx = 0.0553+/-0.000225252175919 6 | IFyy = 0.1062+/-0.00137178526192 7 | IHxx = 0.0980+/-0.000400797112661 8 | IHxz = -0.0044+/-0.000293006332405 9 | IHyy = 0.0692+/-0.00207906543331 10 | IHzz = 0.0396+/-0.000166321860227 11 | IRxx = 0.0552+/-0.000224760513182 12 | IRyy = 0.0764+/-0.00113609058577 13 | c = 0.062+/-0.00160776211474 14 | g = 9.81+/-0.01 15 | lam = 0.275762021815+/-0.00349065850399 16 | mB = 4.5+/-0.02 17 | mF = 1.6+/-0.02 18 | mH = 2.3+/-0.02 19 | mR = 1.4+/-0.02 20 | rF = 0.334+/-0.000113682102208 21 | rR = 0.332+/-0.000113682102208 22 | w = 0.989+/-0.002 23 | xB = 0.383+/-0.0167166513945 24 | xH = 0.906+/-0.00453451662332 25 | zB = -0.477+/-0.00737825561617 26 | zH = -0.733+/-0.00234292942429 27 | -------------------------------------------------------------------------------- /bicycleparameters/app-data/bicycles/Rigid/Parameters/RigidBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 2.6375+/-0.011141147301 2 | IBxz = 0.6536+/-0.00257157016663 3 | IByy = 4.2768+/-0.0117267758886 4 | IBzz = 1.9428+/-0.0194143157306 5 | IFxx = 0.0524+/-0.000168690908608 6 | IFyy = 0.0984+/-0.000678080004122 7 | IGxx = 0.0497+/-0.000174455202321 8 | IGxz = 0.0049+/-2.83090548638e-05 9 | IGyy = 0.0174+/-0.000197222100405 10 | IGzz = 0.0622+/-0.000224153263826 11 | IHxx = 0.3439+/-0.00300081291905 12 | IHxz = -0.0919+/-0.00137845404385 13 | IHyy = 0.3399+/-0.00401223893069 14 | IHzz = 0.1031+/-0.000713162568858 15 | IRxx = 0.0701+/-0.000225450850594 16 | IRyy = 0.1293+/-0.000591786942138 17 | ISxx = 0.0827+/-0.00029149825545 18 | ISxz = -0.0351+/-0.000126243191633 19 | ISyy = 0.0930+/-0.00108855640875 20 | ISzz = 0.0229+/-0.000125326498665 21 | c = 0.060+/-0.000144359307346 22 | g = 9.81+/-0.01 23 | lam = 0.317489078499+/-0.000324568695876 24 | mB = 22.9+/-0.01 25 | mF = 1.6+/-0.01 26 | mG = 3.6+/-0.01 27 | mH = 5.4+/-0.0141421356237 28 | mR = 4.9+/-0.01 29 | mS = 2.1+/-0.01 30 | rF = 0.336+/-9.1888149237e-06 31 | rR = 0.333+/-9.1888149237e-06 32 | w = 1.064+/-0.000166142163674 33 | xB = 0.335+/-0.00690189995787 34 | xG = 0.773+/-0.00204578962755 35 | xH = 0.818+/-0.00132894376927 36 | xS = 0.892+/-0.000835322896001 37 | zB = -0.736+/-0.00476533104829 38 | zG = -1.141+/-0.00231836644684 39 | zH = -0.986+/-0.00164933184028 40 | zS = -0.733+/-0.00155310201047 41 | -------------------------------------------------------------------------------- /bicycleparameters/app-data/bicycles/Silver/Parameters/SilverBenchmark.txt: -------------------------------------------------------------------------------- 1 | w = 1.010+/-0.0 2 | c = 0.190+/-0.0 3 | lam = 0.366519143+/-0.0 4 | g = 9.81+/-0.0 5 | rR = 0.35+/-0.0 6 | mR = 2.6+/-0.0 7 | IRxx = 0.078+/-0.0 8 | IRyy = 0.156+/-0.0 9 | IRzz = 0.078+/-0.0 10 | xB = 0.32+/-0.0 11 | yB = 0.0+/-0.0 12 | zB = -0.627+/-0.0 13 | mB = 12.1+/-0.0 14 | IBxx = 0.8155+/-0.0 15 | IBxz = 0.0327+/-0.0 16 | IByy = 1.2+/-0.0 17 | IBzz = 1.0825+/-0.0 18 | xH = 0.907+/-0.0 19 | yH = 0.0+/-0.0 20 | zH = -0.8+/-0.0 21 | mH = 2.5+/-0.0 22 | IHxx = 0.0860+/-0.0 23 | IHxz = -0.0311+/-0.0 24 | IHyy = 0.1+/-0.0 25 | IHzz = 0.0169+/-0.0 26 | rF = 0.349+/-0.0 27 | mF = 2.05+/-0.0 28 | IFxx = 0.081+/-0.0 29 | IFyy = 0.162+/-0.0 30 | IFzz = 0.081+/-0.0 31 | -------------------------------------------------------------------------------- /bicycleparameters/app-data/bicycles/Yellow/Parameters/YellowBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 0.2240+/-0.000924337136702 2 | IBxz = 0.0182+/-0.000123765736234 3 | IByy = 0.3879+/-0.00457262650146 4 | IBzz = 0.2160+/-0.000899957967889 5 | IFxx = 0.0852+/-0.000346541216905 6 | IFyy = 0.1466+/-0.00158129157014 7 | IHxx = 0.1452+/-0.000640851479448 8 | IHxz = -0.0194+/-0.000517327473538 9 | IHyy = 0.1200+/-0.00250714868146 10 | IHzz = 0.0292+/-0.00034384832588 11 | IRxx = 0.0877+/-0.000356796414278 12 | IRyy = 0.1487+/-0.0012536133519 13 | c = 0.0473+/-0.00162727102983 14 | g = 9.81+/-0.01 15 | lam = 0.301941960595+/-0.00349065850399 16 | mB = 3.3+/-0.02 17 | mF = 1.9+/-0.02 18 | mH = 2.5+/-0.02 19 | mR = 2.6+/-0.02 20 | rF = 0.342+/-0.000122426879301 21 | rR = 0.341+/-0.000122426879301 22 | w = 1.089+/-0.002 23 | xB = 0.422+/-0.00384241188261 24 | xH = 0.948+/-0.00438045273196 25 | zB = -0.603+/-0.00365196117253 26 | zH = -0.788+/-0.00232630323345 27 | -------------------------------------------------------------------------------- /bicycleparameters/app-data/bicycles/Yellowrev/Parameters/YellowrevBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 0.2254+/-0.00092916150614 2 | IBxz = 0.0179+/-0.000129627296249 3 | IByy = 0.3879+/-0.00457262650146 4 | IBzz = 0.2147+/-0.000893315075898 5 | IFxx = 0.0852+/-0.000346541216905 6 | IFyy = 0.1466+/-0.00158129157014 7 | IHxx = 0.1475+/-0.000640700256464 8 | IHxz = -0.0172+/-0.000527993839439 9 | IHyy = 0.1195+/-0.00245444440384 10 | IHzz = 0.0294+/-0.000366277717216 11 | IRxx = 0.0877+/-0.000356796414278 12 | IRyy = 0.1487+/-0.0012536133519 13 | c = 0.180+/-0.00176864639495 14 | g = 9.81+/-0.01 15 | lam = 0.338593874887+/-0.00349065850399 16 | mB = 3.3+/-0.02 17 | mF = 1.9+/-0.02 18 | mH = 2.5+/-0.02 19 | mR = 2.6+/-0.02 20 | rF = 0.342+/-0.000122426879301 21 | rR = 0.341+/-0.000122426879301 22 | w = 0.985+/-0.002 23 | xB = 0.412+/-0.00379563686367 24 | xH = 0.919+/-0.00455107965017 25 | zB = -0.618+/-0.00370055269932 26 | zH = -0.816+/-0.00225140598256 27 | -------------------------------------------------------------------------------- /bicycleparameters/assets/app-explanation.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This web application computes the eigenvalues of the Whipple-Carvallo [1,2] 4 | linearized bicycle model about the upright constant speed equilibrium state. 5 | The eigenvalues are a function of 27 parameters as defined in [3]. The 6 | eigenvalues can be used to assess the uncontrolled stability ("self-stability") 7 | of a given bicycle design as well as characterize the growth and decay rates 8 | and oscillatory nature of the time evolutions of the two degrees of freedom: 9 | roll and steer. 10 | 11 | # Inputs 12 | 13 | ## Parameter Set Selection 14 | 15 | Several pre-defined bicycles are provided and can be selected for analysis. 16 | These bicycles and the methods of obtaining the parameter values are described 17 | in detail in [4,5]. 18 | 19 | - Benchmark: Benchmark parameter set in [3]. Note this includes the rider. 20 | - Batavus Browser: Urban bicycle with swept back handlebars 21 | - Rigid: Instrumented bicycle used in [4] 22 | - Batavus Crescendo Deluxe: Urban bicycle with swept back handlebars 23 | - Batavus Stratos Deluxe: Urban bicycle with straight handlebars 24 | - Gary Fisher: Mountain bike 25 | - Bianchi Pista: Track bicycle 26 | - Silver: Bicycle used in [6] 27 | - Yellow Bicycle: Simple road bicycle with minimal accessories 28 | - Yellow Bicycle Reversed Fork: Simple road bicycle with minimal accessories 29 | with the fork rotated 180 degrees from the normal orientation. 30 | 31 | ## Speed Range Selector 32 | 33 | Use the slider to select the range of speeds the eigenvalues are calculated 34 | for. This corresponds to the abscissa of the "Eigenvalues vs. Speed" plot. 35 | 36 | ## Model Parameters 37 | 38 | The numerical values of 27 parameters can be edited in the table. These 39 | parameters are defined in [3]. Select the numerical value, change the number to 40 | the desired number, and press enter to see the figures update. Note the units 41 | of the parameters. The "Reset Table" button will change all of the values in 42 | the table back to the currently selected bicycle parameter set. 43 | 44 | # Outputs 45 | 46 | ## Geometry Plot 47 | 48 | This plot depicts a side view schematic of the basic bicycle geometry: circles 49 | representing the front and rear wheels and lines representing the steer axis 50 | (dotted) and front and rear wheel offsets from the steer axis. The mass centers 51 | of the front wheel [F], rear wheel [R], rear frame (and rider) [B], and fork 52 | and handlebar [H] are indicated for each rigid body. Inertial ellipsoids are 53 | shown for each body with a matching color to the mass center symbol. 54 | 55 | ## Eigenvalue Plot 56 | 57 | The real parts (solid lines) and imaginary parts (dotted lines) of the 58 | eigenvalues are plotted on the ordinate versus speed on the abscissa. Any 59 | speeds in which the real parts are all negative indicate self-stability at 60 | those speeds. The "Show Self-stability" checkbox will plot a shaded region for 61 | these speeds. 62 | 63 | # Colophon 64 | 65 | This website was designed by Lyla Sanders and Julie van Vlerken with mentorship 66 | from Jason K. Moore and Andrew Dressel. 67 | 68 | The software that powers the website is open source and information on it can 69 | be found here: 70 | 71 | - Github Repository: https://github.com/moorepants/BicycleParameters 72 | - Documentation: https://bicycleparameters.readthedocs.io 73 | 74 | Contributions and issue reports are welcome! 75 | 76 | This software is partially based upon work supported by the National Science 77 | Foundation under [Grant No. 78 | 0928339](https://www.nsf.gov/awardsearch/showAward?AWD_ID=0928339). Any 79 | opinions, findings, and conclusions or recommendations expressed in this 80 | material are those of the authors and do not necessarily reflect the views of 81 | the National Science Foundation. 82 | 83 | This software is partially based upon work supported by the TKI CLICKNL grant 84 | "Fiets van de Toekomst"(Grant No. TKI1706). 85 | 86 | # References 87 | 88 | 1. F. J. W. Whipple, "The stability of the motion of a bicycle," Quarterly 89 | Journal of Pure and Applied Mathematics, vol. 30, pp. 312–348, 1899. 90 | 2. E. Carvallo, Théorie du mouvement du monocycle et de la bicyclette. Paris, 91 | France: Gauthier- Villars, 1899. 92 | 3. J.P Meijaard, Jim M Papadopoulos, Andy Ruina and A.L Schwab. 2007. 93 | Linearized dynamics equations for the balance and steer of a bicycle: a 94 | benchmark and review. Proc. R. Soc. A.4631955–1982 95 | http://doi.org/10.1098/rspa.2007.1857 96 | 4. J. K. Moore, "Human Control of a Bicycle," Doctor of Philosophy, University 97 | of California, Davis, CA, 2012. http://moorepants.github.io/dissertation 98 | 5. J. K. Moore, M. Hubbard, D. L. Peterson, A. L. Schwab, and J. D. G. 99 | Kooijman, "An Accurate Method of Measuring and Comparing a Bicycle’s 100 | Physical Parameters," in Proceedings of Bicycle and Motorcycle Dynamics: 101 | Symposium on the Dynamics and Control of Single Track Vehicles, Delft, 102 | Netherlands, Oct. 2010. 103 | 6. Kooijman, J. D. G., Schwab, A. L. & Meijaard, J. P. 2007 Experimental 104 | validation of a model of an uncontrolled bicycle. 105 | -------------------------------------------------------------------------------- /bicycleparameters/assets/styles.css: -------------------------------------------------------------------------------- 1 | .dash-table-container .row { 2 | display: block; 3 | margin: 0px; 4 | } 5 | 6 | .h1, h1 { 7 | font-size: 2.5rem; 8 | text-align: center; 9 | } 10 | 11 | .h2, h2 { 12 | font-size: 2rem; 13 | } 14 | 15 | .h3, h3 { 16 | font-size: 1.75rem; 17 | } 18 | 19 | .h4, h4 { 20 | font-size: 1.5rem; 21 | } 22 | 23 | .h5, h5 { 24 | font-size: 1.25rem; 25 | } 26 | 27 | .h6, h6 { 28 | font-size: 1rem; 29 | } 30 | 31 | .centered { 32 | text-align: center; 33 | } 34 | -------------------------------------------------------------------------------- /bicycleparameters/conversions.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from .com import total_com 4 | from .inertia import parallel_axis 5 | 6 | 7 | def _rotate_inertia_about_y(inertia, angle): 8 | """Returns inertia tensor rotated through an angle about the Y axis. 9 | 10 | Parameters 11 | ========== 12 | inertia : array_like, shape(3,3) 13 | An inertia tensor of a single rigid body defined relative to an XYZ 14 | Cartesian coordinate system. 15 | angle : float 16 | Angle in radians about the positive Y axis of which to rotate the 17 | coordinate system. 18 | 19 | Returns 20 | ======= 21 | ndarray, shape(3,3) 22 | An inertia tensor of a single rigid body expressed relative to a 23 | rotated Cartesian coordinate system. 24 | 25 | """ 26 | ca = np.cos(angle) 27 | sa = np.sin(angle) 28 | C = np.array([[ca, 0.0, -sa], 29 | [0.0, 1., 0.0], 30 | [sa, 0.0, ca]]) 31 | return C @ inertia @ C.T 32 | 33 | 34 | def _sum_central_inertias(m1, com1, I1, m2, com2, I2): 35 | # SUM_CENTRAL_INERTIAS - Returns the combined inertia of two bodies. 36 | # 37 | # Syntax : I = sum_central_inertias(m1, com1, I1, m2, com2, I2) 38 | # 39 | # Inputs: 40 | # m1 - 1x1 double, mass of the first body 41 | # com1 - 3x1 double, center of mass of the first body 42 | # I1 - 3x3 double, central inertia tensor of the first body 43 | # m2 - 1x1 double, mass of the second body 44 | # com2 - 3x1 double, center of mass of the second body 45 | # I2 - 3x3 double, central inertia tensor of the second body 46 | # Outputs: 47 | # I - combined central inertia tensor of both bodies 48 | m, com = total_com(np.vstack([com1, com2]).T, [m1, m2]) 49 | return parallel_axis(I1, m1, com-com1) + parallel_axis(I2, m2, com-com2) 50 | 51 | 52 | def _convert_principal_to_benchmark(principal_par): 53 | # CONVERT_PRINCIPAL_TO_BENCHMARK - Returns a structure containing the 54 | # benchmark bicycle parameters as defined in Meijaard2007 which are 55 | # converted from the principal parameters as defined in MooreHubbard2019. 56 | # 57 | # Syntax: benchmark_par = convert_principal_to_benchmark(principal_par) 58 | # 59 | # Inputs: 60 | # principal_par - Structure containing parameter names mapped to doubles. 61 | # Outputs: 62 | # benchmark_par - Structure containing parameter names mapped to doubles. 63 | 64 | p = principal_par 65 | 66 | b = {} 67 | 68 | ########################################################################### 69 | # primary geometry, gravity, and speed 70 | ########################################################################### 71 | b["w"] = p["w"] 72 | b["c"] = p["c"] 73 | b["lam"] = p["lam"] 74 | b["g"] = p["g"] 75 | b["v"] = p["v"] 76 | 77 | ########################################################################### 78 | # rear frame [B] 79 | ########################################################################### 80 | coordinates = np.array([[p["xD"], p["xP"]], 81 | [p["yD"], p["yP"]], 82 | [p["zD"], p["zP"]]]) 83 | masses = np.array([p["mD"], p["mP"]]) 84 | b["mB"], (b["xB"], b["yB"], b["zB"]) = total_com(coordinates, masses) 85 | 86 | # symmetry is assumed about the XZ plane 87 | ID_principal = p["mD"]*np.diag([p["kDaa"]**2, p["kDyy"]**2, p["kDbb"]**2]) 88 | IDxyz = _rotate_inertia_about_y(ID_principal, -p["alphaD"]) 89 | 90 | # person 91 | IP_principal = p["mP"]*np.diag([p["kPaa"]**2, p["kPyy"]**2, p["kPbb"]**2]) 92 | IPxyz = _rotate_inertia_about_y(IP_principal, -p["alphaP"]) 93 | 94 | # combined rear frame and person 95 | comD = np.array([p["xD"], p["yD"], p["zD"]]) 96 | comP = np.array([p["xP"], p["yP"], p["zP"]]) 97 | IBxyz = _sum_central_inertias(p["mD"], comD, IDxyz, p["mP"], comP, IPxyz) 98 | b["IBxx"] = IBxyz[0, 0] 99 | b["IByy"] = IBxyz[1, 1] 100 | b["IBzz"] = IBxyz[2, 2] 101 | b["IBxz"] = IBxyz[0, 2] 102 | 103 | ########################################################################### 104 | # front frame [H] 105 | ########################################################################### 106 | b["mH"] = p["mH"] 107 | b["xH"] = p["xH"] 108 | b["yH"] = p["yH"] 109 | b["zH"] = p["zH"] 110 | 111 | # symmetry is assumed about the XZ plane 112 | IH123 = p["mH"]*np.diag([p["kHaa"]**2, p["kHyy"]**2, p["kHbb"]**2]) 113 | IH = _rotate_inertia_about_y(IH123, -p["alphaH"]) 114 | b["IHxx"] = IH[0, 0] 115 | b["IHyy"] = IH[1, 1] 116 | b["IHzz"] = IH[2, 2] 117 | b["IHxz"] = IH[0, 2] 118 | 119 | ########################################################################### 120 | # rear wheel [R] 121 | ########################################################################### 122 | b["rR"] = p["rR"] 123 | b["mR"] = p["mR"] 124 | # wheel is symmetric about XY, YZ, and XZ planes, thus no products of 125 | # inertia, wheel is ring or disc like, thus Ixx=Izz and Iyy > Ixx 126 | b["IRxx"] = p["mR"] * p["kRaa"]**2 127 | b["IRyy"] = p["mR"] * p["kRyy"]**2 128 | b["IRzz"] = p["mR"] * p["kRaa"]**2 129 | 130 | ########################################################################### 131 | # front wheel [F] 132 | ########################################################################### 133 | b["rF"] = p["rF"] 134 | b["mF"] = p["mF"] 135 | # wheel is symmetric about XY, YZ, and XZ planes, thus no prodcuts of 136 | # inertia, wheel is always ring or disc like, thus Ixx=Izz and Iyy > Ixx 137 | b["IFxx"] = p["mF"] * p["kFaa"]**2 138 | b["IFyy"] = p["mF"] * p["kFyy"]**2 139 | b["IFzz"] = p["mF"] * p["kFaa"]**2 140 | 141 | # return the benchmark parameters 142 | return b 143 | -------------------------------------------------------------------------------- /bicycleparameters/parameter_dicts.py: -------------------------------------------------------------------------------- 1 | meijaard2007_browser_jason = { 2 | 'IBxx': 11.3557360401, 3 | 'IBxz': -1.96756380745, 4 | 'IByy': 12.2177848012, 5 | 'IBzz': 3.12354397008, 6 | 'IFxx': 0.0904106601579, 7 | 'IFyy': 0.149389340425, 8 | 'IHxx': 0.253379594731, 9 | 'IHxz': -0.0720452391817, 10 | 'IHyy': 0.246138810935, 11 | 'IHzz': 0.0955770796289, 12 | 'IRxx': 0.0883819364527, 13 | 'IRyy': 0.152467620286, 14 | 'c': 0.0685808540382, 15 | 'g': 9.81, 16 | 'lam': 0.399680398707, 17 | 'mB': 81.86, 18 | 'mF': 2.02, 19 | 'mH': 3.22, 20 | 'mR': 3.11, 21 | 'rF': 0.34352982332, 22 | 'rR': 0.340958858855, 23 | 'v': 1.0, 24 | 'w': 1.121, 25 | 'xB': 0.289099434117, 26 | 'xH': 0.866949640247, 27 | 'zB': -1.04029228321, 28 | 'zH': -0.748236400835, 29 | } 30 | 31 | moore2019_browser_jason = { 32 | 'alphaD': 1.1722101094171953, 33 | 'alphaH': 0.3699481738478786, 34 | 'alphaP': 0.18617531745505142, 35 | 'c': 0.0685808540382, 36 | 'g': 9.81, 37 | 'kDaa': 0.28586689, 38 | 'kDbb': 0.22079007, 39 | 'kDyy': 0.36538846, 40 | 'kFaa': 0.20917410328468122, 41 | 'kFyy': 0.27179382778091554, 42 | 'kHaa': 0.29556015, 43 | 'kHbb': 0.14493343, 44 | 'kHyy': 0.27630431, 45 | 'kPaa': 0.36717241, 46 | 'kPbb': 0.15276369, 47 | 'kPyy': 0.36796654, 48 | 'kRaa': 0.17050278555427911, 49 | 'kRyy': 0.22136034463264698, 50 | 'lP': 1.728, 51 | 'lam': 0.399680398707, 52 | 'mD': 9.86, 53 | 'mF': 2.02, 54 | 'mH': 3.22, 55 | 'mP': 83.50000000000001, 56 | 'mR': 3.11, 57 | 'rF': 0.34352982332, 58 | 'rR': 0.340958858855, 59 | 'v': 3.0, 60 | 'w': 1.121, 61 | 'wP': 0.483, 62 | 'xD': 0.275951285677, 63 | 'xH': 0.866949640247, 64 | 'xP': 0.3157679154070924, 65 | 'xR': 0.0, 66 | 'yD': 0.0, 67 | 'yF': 0.0, 68 | 'yH': 0.0, 69 | 'yP': 0.0, 70 | 'yR': 0.0, 71 | 'zD': -0.537842424305, 72 | 'zH': -0.748236400835, 73 | 'zP': -1.0989885659819278, 74 | } 75 | 76 | # NOTE : These are the values used for the rider lean model in Jason Moore's 77 | # 2012 dissertation. The BrowserLegs = Browser Bike + Jason's legs (from Yeadon 78 | # calcs) for the rigid body C. The upper body G is from Jason's torso, arms, 79 | # head (from Yeadon calcs). 80 | # BrowserLegs data is taken from https://doi.org/10.6084/m9.figshare.1198429.v2 81 | # and originally used in 82 | # https://github.com/moorepants/dissertation/tree/master/src/extensions/lean. 83 | mooreriderlean2012_browser_jason = { 84 | 'c9': 0.0, 85 | 'd1': 0.9631492634872098, 86 | 'd2': 0.4338396131640938, 87 | 'd3': 0.0705000000001252, 88 | 'd4': -1.011421527346159 + 0.340958858855, # + rr 89 | 'g': 9.81, 90 | 'ic11': 2.296859222953584, 91 | 'ic22': 2.9922715238, 92 | 'ic31': 0.01594448114273473, 93 | 'ic33': 1.5101858377464155, 94 | 'id11': 0.0904106601579, 95 | 'id22': 0.152467620286, 96 | 'ie11': 0.2811355367159554, 97 | 'ie22': 0.246138810935, 98 | 'ie31': 0.0063377219110826045, 99 | 'ie33': 0.06782113764394461, 100 | 'if11': 0.0883819364527, 101 | 'if22': 0.149389340425, 102 | 'ig11': 2.038073562525466, 103 | 'ig22': 1.692108544034995, 104 | 'ig31': 0.002113501449812, 105 | 'ig33': 1.100753962972129, 106 | 'k9': 0.0, 107 | 'l1': 0.47759794513190806, 108 | 'l2': -0.1680324796714025, 109 | 'l3': -0.07654646159268344, 110 | 'l4': -0.47166687226492093, 111 | 'l5': 0.231223496809401, 112 | 'l6': -1.283035074598082 + 0.340958858855 - (-1.011421527346159 + 0.340958858855), # rr - d4 113 | 'mc': 33.044, 114 | 'md': 3.11, 115 | 'me': 3.22, 116 | 'mf': 2.02, 117 | 'mg': 48.816, 118 | 'rf': 0.34352982332, 119 | 'rr': 0.340958858855, 120 | 'v': 1.0, 121 | } 122 | 123 | # NOTE : This is Jason sitting on the Browser but only with the inertia of 124 | # Jason's legs included in the mass distribution properties of the rear frame. 125 | # Taken from https://doi.org/10.6084/m9.figshare.1198429.v2 and originally used 126 | # in 127 | # https://github.com/moorepants/dissertation/tree/master/src/extensions/lean. 128 | meijaard2007_browser_jasonlegs = { 129 | 'IBxx': 2.18917391377, 130 | 'IBxz': -0.27087131147, 131 | 'IByy': 2.9922715238, 132 | 'IBzz': 1.61787114693, 133 | 'IFxx': 0.0883819364527, 134 | 'IFyy': 0.149389340425, 135 | 'IHxx': 0.253379594731, 136 | 'IHxz': -0.0720452391817, 137 | 'IHyy': 0.246138810935, 138 | 'IHzz': 0.0955770796289, 139 | 'IRxx': 0.0904106601579, 140 | 'IRyy': 0.152467620286, 141 | 'c': 0.0685808540382, 142 | 'g': 9.81, 143 | 'lam': 0.399680398707, 144 | 'mB': 33.044, 145 | 'mF': 2.02, 146 | 'mH': 3.22, 147 | 'mR': 3.11, 148 | 'rF': 0.34352982332, 149 | 'rR': 0.340958858855, 150 | 'v': 1.0, 151 | 'w': 1.121, 152 | 'xB': 0.374570794542, 153 | 'xH': 0.866949640247, 154 | 'zB': -0.681592725778, 155 | 'zH': -0.748236400835, 156 | } 157 | -------------------------------------------------------------------------------- /bicycleparameters/plot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | 6 | 7 | def compare_bode_bicycles(bikes, speed, u, y, fig=None): 8 | """Returns a figure with the Bode plots of multiple bicycles. 9 | 10 | Parameters 11 | ---------- 12 | bikes : list 13 | A list of bicycleparameters.Bicycle instances. 14 | speed : float 15 | The speed at which to evaluate the system. 16 | u : integer 17 | An integer between 0 and 1 corresponding to the inputs roll torque 18 | and steer torque. 19 | y : integer 20 | An integer between 0 and 3 corresponding to the inputs roll rate, 21 | steer rate, roll angle and steer angle. 22 | 23 | Returns 24 | ------- 25 | fig : matplotlib.Figure instance 26 | The Bode plot. 27 | 28 | Notes 29 | ----- 30 | The phases are matched around zero degrees at with respect to the first 31 | frequency. 32 | 33 | """ 34 | 35 | if fig is None: 36 | fig = plt.figure() 37 | 38 | for bike in bikes: 39 | bike.plot_bode(speed, u, y, label=bike.bicycleName, fig=fig) 40 | 41 | # take care of phase misalignment 42 | phaseLines = fig.ax2.lines 43 | for line in phaseLines: 44 | firstValue = line.get_ydata()[0] 45 | n = np.ceil(np.floor(abs(firstValue / 180.)) / 2.) 46 | line.set_ydata(line.get_ydata() - np.sign(firstValue) * n * 360.) 47 | 48 | return fig 49 | 50 | 51 | def plot_eigenvalues(bikes, speeds, colors=None, linestyles=None, 52 | largest=False, show=False): 53 | '''Returns a figure with the eigenvalues vs speed for multiple bicycles. 54 | 55 | Parameters 56 | ---------- 57 | bikes : list 58 | A list of Bicycle objects. 59 | speeds : ndarray, shape(n,) 60 | An array of speeds. 61 | colors : list 62 | A list of matplotlib colors for each bicycle. 63 | linestyles : list 64 | A list of matplotlib linestyles for each bicycle. 65 | largest : boolean 66 | If true, only plots the largest eigenvalue. 67 | 68 | Returns 69 | ------- 70 | fig : matplotlib figure 71 | 72 | ''' 73 | 74 | numBikes = len(bikes) 75 | 76 | if not colors: 77 | # define some colors for the parts 78 | cmap = plt.get_cmap('gist_rainbow') 79 | colors = [] 80 | for i in range(numBikes): 81 | colors.append(cmap(1. * i / numBikes)) 82 | 83 | if not linestyles: 84 | linestyles = ['-'] * numBikes 85 | 86 | for i, bike in enumerate(bikes): 87 | if i == 0: 88 | fig = None 89 | fig = bike.plot_eigenvalues_vs_speed(speeds, fig=fig, color=colors[i], 90 | largest=largest, generic=True, 91 | linestyle=linestyles[i], 92 | show=False) 93 | plt.legend() 94 | plt.axis('tight') 95 | 96 | if show is True: 97 | plt.show() 98 | 99 | return fig 100 | 101 | 102 | def _generate_ellipse_plot_data(x_center, y_center, ax1, ax2, a, b, N): 103 | # x_center, y_center the coordinates of ellipse center 104 | # ax1 ax2 two orthonormal vectors representing the ellipse axis directions 105 | # a, b the ellipse parameters 106 | t = np.linspace(0, 2 * np.pi, N) 107 | # ellipse parameterization with respect to a system of axes of directions 108 | # a1, a2 109 | xs = a * np.cos(t) 110 | ys = b * np.sin(t) 111 | # rotation matrix 112 | R = np.array([ax1, ax2]).T 113 | # coordinate of the ellipse points with respect to the system of axes[1, 114 | # 0], [0, 1] with origin(0, 0) 115 | xp, yp = np.dot(R, [xs, ys]) 116 | x = xp + x_center 117 | y = yp + y_center 118 | return x, y 119 | -------------------------------------------------------------------------------- /bicycleparameters/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moorepants/BicycleParameters/0f2ae79e246aff822fe480aa1080fe6ee594748c/bicycleparameters/tests/__init__.py -------------------------------------------------------------------------------- /bicycleparameters/tests/parameter_sets/benchmark-benchmark.yml: -------------------------------------------------------------------------------- 1 | parameterization: benchmark # the set of symbols 2 | parameters: benchmark # the specific parameter values tied to a bicycle(+rider) 3 | rider: True # if the parameter values include a rider lumped into the rear frame 4 | description: | 5 | These are the benchmark numerical parameters for the benchmark 6 | parameterization from Meijaard2007. In particular, the minimal set of 7 | non-zero parameters. 8 | values: 9 | IBxx: 9.2 10 | IBxz: 2.4 11 | IByy: 11.0 12 | IBzz: 2.8 13 | IFxx: 0.1405 14 | IFyy: 0.28 15 | IHxx: 0.05892 16 | IHxz: -0.00756 17 | IHyy: 0.06 18 | IHzz: 0.00708 19 | IRxx: 0.0603 20 | IRyy: 0.12 21 | c: 0.08 22 | g: 9.81 23 | lam: 0.31415926535897932385 24 | mB: 85.0 25 | mF: 3.0 26 | mH: 4.0 27 | mR: 2.0 28 | rF: 0.35 29 | rR: 0.3 30 | v: 5.0 31 | w: 1.02 32 | xB: 0.3 33 | xH: 0.9 34 | zB: -0.9 35 | zH: -0.7 36 | -------------------------------------------------------------------------------- /bicycleparameters/tests/parameter_sets/benchmark-browser.yml: -------------------------------------------------------------------------------- 1 | # Parameters generated from the measurements of the Browser bicycle. 2 | IBxx: 0.52962890621 3 | IBxz: -0.116285607878 4 | IByy: 1.3163960125 5 | IBzz: 0.756786895402 6 | IFxx: 0.0883826870796 7 | IFyy: 0.149221207336 8 | IHxx: 0.25335539588 9 | IHxz: -0.0720217263293 10 | IHyy: 0.245827908036 11 | IHzz: 0.0955686343473 12 | IRxx: 0.0904114316323 13 | IRyy: 0.152391250767 14 | c: 0.0685808540382 15 | g: 9.81 16 | lam: 0.399680398707 17 | mB: 9.86 18 | mF: 2.02 19 | mH: 3.22 20 | mR: 3.11 21 | rF: 0.34352982332 22 | rR: 0.340958858855 23 | v: 5.0 24 | w: 1.121 25 | xB: 0.275951285677 26 | xH: 0.866949640247 27 | zB: -0.537842424305 28 | zH: -0.748236400835 29 | -------------------------------------------------------------------------------- /bicycleparameters/tests/parameter_sets/benchmark-extendedoptc.yml: -------------------------------------------------------------------------------- 1 | # A set of parameters derived from the Jason+Browser initial guess for the BMD 2 | # 2019 conference paper. 3 | IBxx: 54.349 4 | IBxz: -3.3611 5 | IByy: 64.693 6 | IBzz: 13.535 7 | IFxx: 0.0040323 8 | IFyy: 0.016129 9 | IFzz: 0.0040323 10 | IHxx: 1.9875e-05 11 | IHxz: -2.5611e-05 12 | IHyy: 0.0 13 | IHzz: 6.3938e-05 14 | IRxx: 3.2812 15 | IRyy: 13.125 16 | IRzz: 3.2812 17 | c: 0.042100 18 | g: 9.8100 19 | lam: -0.89910 20 | mB: 90.746 21 | mF: 1.0 22 | mH: 0.25000 23 | mR: 12.568 24 | rF: 0.12700 25 | rR: 1.0219 26 | v: 3.0 27 | w: 1.2419 28 | xB: 0.50769 29 | xH: 3.4103 30 | yB: 0.0 31 | yH: 0.0 32 | zB: -0.55646 33 | zH: -1.8086 34 | -------------------------------------------------------------------------------- /bicycleparameters/tests/parameter_sets/benchmark-pista.yml: -------------------------------------------------------------------------------- 1 | # Parameters of the Bianchi Pista (without rider) derived from measurements. 2 | IBxx: 0.289968529291 3 | IBxz: 0.0502317583637 4 | IByy: 0.475817094274 5 | IBzz: 0.249418014295 6 | IFxx: 0.0553476418952 7 | IFyy: 0.106185287785 8 | IHxx: 0.0979884309288 9 | IHxz: -0.00440828467861 10 | IHyy: 0.0691907586693 11 | IHzz: 0.0396107377431 12 | IRxx: 0.0552268228143 13 | IRyy: 0.0764034890242 14 | c: 0.0617300113263 15 | g: 9.81 16 | lam: 0.275762021815 17 | mB: 4.49 18 | mF: 1.58 19 | mH: 2.27 20 | mR: 1.38 21 | rF: 0.333838861345 22 | rR: 0.332088156971 23 | v: 3.0 24 | w: 0.989 25 | xB: 0.382963782674 26 | xH: 0.906321313298 27 | zB: -0.476798507146 28 | zH: -0.732376356772 29 | -------------------------------------------------------------------------------- /bicycleparameters/tests/parameter_sets/benchmark-pistarider.yml: -------------------------------------------------------------------------------- 1 | # Parameters taken from HumanControl of the Pista + a rider. I am not quite 2 | # sure how I calculated the addition of the rider because I can't find any of 3 | # the related rider files in the BicycleParameters directory. I had to somehow 4 | # add a rider to all the bike in Hess2012. I may have simply added the same 5 | # rider in the same configuration to all the bikes in that repository. 6 | IBxx: 9.97823319202 7 | IBxz: -2.12302552044 8 | IByy: 10.2705785413 9 | IBzz: 2.64767743966 10 | IFxx: 0.0552267034481 11 | IFyy: 0.10618332427 12 | IHxx: 0.0979880530249 13 | IHxz: -0.0044084941665 14 | IHyy: 0.069253053453 15 | IHzz: 0.0396106018108 16 | IRxx: 0.0553472759338 17 | IRyy: 0.0764143975968 18 | c: 0.0617300113263 19 | g: 9.81 20 | lam: 0.275762021815 21 | mB: 76.49 22 | mF: 1.58 23 | mH: 2.27 24 | mR: 1.38 25 | rF: 0.333838861345 26 | rR: 0.332088156971 27 | v: 3.0 28 | w: 0.989 29 | xB: 0.296304188576 30 | xH: 0.906321313298 31 | zB: -1.07198359651 32 | zH: -0.732376356772 33 | -------------------------------------------------------------------------------- /bicycleparameters/tests/parameter_sets/benchmark-pistarideroptimized3ms.yml: -------------------------------------------------------------------------------- 1 | # Parameters taken from HumanControl of the Pista + a rider and then run 2 | # through the four parameer optimization procedure for v = 3 m/s. This is the 3 | # target parameter set for the second realized bicycle we constructed. 4 | IBxx: 9.97823319202 5 | IBxz: -2.12302552044 6 | IByy: 10.2705785413 7 | IBzz: 2.64767743966 8 | IFxx: 0.0552267034481 9 | IFyy: 0.0617 10 | IHxx: 0.0979880530249 11 | IHxz: -0.0044084941665 12 | IHyy: 0.069253053453 13 | IHzz: 0.0396106018108 14 | IRxx: 0.0553472759338 15 | IRyy: 0.0764143975968 16 | c: 0.75461 17 | g: 9.81 18 | lam: -0.05486 19 | mB: 76.49 20 | mF: 1.58 21 | mH: 2.27 22 | mR: 1.38 23 | rF: 0.226 24 | rR: 0.332088156971 25 | v: 3.0 26 | w: 0.41 27 | xB: 0.296304188576 28 | xH: 0.906321313298 29 | zB: -1.07198359651 30 | zH: -0.732376356772 31 | -------------------------------------------------------------------------------- /bicycleparameters/tests/parameter_sets/benchmark-realizedopttwo.yml: -------------------------------------------------------------------------------- 1 | # These are the parameters derived from the CAD drawing of the second realized 2 | # optimal handling bicycle. The parameters are based on the Pista with Jason as 3 | # a rider with four parameters optimized for handling. 4 | IBxx: 5.9257 5 | IBxz: -1.0621 6 | IByy: 8.0774 7 | IBzz: 3.5778 8 | IFxx: 0.0314 9 | IFyy: 0.0623 10 | IHxx: 0.5110 11 | IHxz: 0.0799 12 | IHyy: 0.7750 13 | IHzz: 0.3559 14 | IRxx: 0.0157 15 | IRyy: 0.078 16 | c: 0.75461 17 | g: 9.81 18 | lam: -0.05486 19 | mB: 65.4813 20 | mF: 1.5477 21 | mH: 6.7292 22 | mR: 5.3486 23 | rF: 0.226 24 | rR: 0.332 25 | v: 3.0 26 | w: 0.41 27 | xB: 0.2275 28 | xH: 0.9309 29 | zB: -0.9044 30 | zH: -0.4385 31 | -------------------------------------------------------------------------------- /bicycleparameters/tests/parameter_sets/principal-browserjason.yml: -------------------------------------------------------------------------------- 1 | parameterization: principal 2 | parameters: browserjason 3 | rider: True 4 | description: | 5 | Jason riding the Batavus browser. 6 | values: 7 | alphaD: 1.1722 8 | alphaH: 0.36995 9 | alphaP: 0.18618 10 | c: 0.068581 11 | g: 9.8100 12 | kDaa: 0.28587 13 | kDbb: 0.22079 14 | kDyy: 0.36539 15 | kFyy: 0.27179 16 | kFaa: 0.20917 17 | kFbb: 0.20917 18 | kHaa: 0.29556 19 | kHbb: 0.14493 20 | kHyy: 0.27630 21 | kPaa: 0.36797 22 | kPbb: 0.15276 23 | kPyy: 0.36717 24 | kRyy: 0.22136 25 | kRaa: 0.17050 26 | kRbb: 0.17050 27 | lP: 1.7280 28 | lam: 0.39968 29 | mD: 9.8600 30 | mF: 2.0200 31 | mH: 3.2200 32 | mP: 83.500 33 | mR: 3.1100 34 | rF: 0.34353 35 | rR: 0.34096 36 | v: 3.0 37 | w: 1.1210 38 | wP: 0.48300 39 | xD: 0.27595 40 | xF: 1.1210 41 | xH: 0.86695 42 | xP: 0.31577 43 | xR: 0.0 44 | yD: 0.0 45 | yF: 0.0 46 | yH: 0.0 47 | yP: 0.0 48 | yR: 0.0 49 | zD: -0.53784 50 | zF: -0.34353 51 | zH: -0.74824 52 | zP: -1.0990 53 | zR: -0.34096 54 | -------------------------------------------------------------------------------- /bicycleparameters/tests/parameter_sets/principal-extendedoptf.yml: -------------------------------------------------------------------------------- 1 | # Best ever solution for 9 m/s Jason+Browswer Initial Guess 2 | alphaD: 1.0767 3 | alphaH: 0.23760 4 | alphaP: 1.5584 5 | c: -0.48397 6 | g: 9.8100 7 | kDaa: 0.86084 8 | kDbb: 2.0139 9 | kDyy: 2.0305 10 | kFaa: 1.0314 11 | kFbb: 1.0314 12 | kFyy: 2.0628 13 | kHaa: 2.8463 14 | kHbb: 0.16848 15 | kHyy: 0.66922 16 | kPaa: 0.36797 17 | kPbb: 0.15276 18 | kPyy: 0.36717 19 | kRaa: 1.5135 20 | kRbb: 1.5135 21 | kRyy: 3.0270 22 | lP: 1.7280 23 | lam: 0.23941 24 | mD: 7.0223 25 | mF: 5.5058 26 | mH: 3.5435 27 | mP: 83.500 28 | mR: 2.2534 29 | rF: 2.0628 30 | rR: 3.0270 31 | v: 9.0 32 | w: 5.5573 33 | wP: 0.48300 34 | xD: 1.0204 35 | xF: 5.5573 36 | xH: 5.6145 37 | xP: 1.0791 38 | xR: 0.0 39 | yD: 0.0 40 | yF: 0.0 41 | yH: 0.0 42 | yP: 0.0 43 | yR: 0.0 44 | zD: -4.0653 45 | zF: -2.0628 46 | zH: -1.7755 47 | zP: -2.6623 48 | zR: -3.0270 49 | -------------------------------------------------------------------------------- /bicycleparameters/tests/sample_data/BrowserForkCompoundFirst1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moorepants/BicycleParameters/0f2ae79e246aff822fe480aa1080fe6ee594748c/bicycleparameters/tests/sample_data/BrowserForkCompoundFirst1.mat -------------------------------------------------------------------------------- /bicycleparameters/tests/test_bicycle.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import numpy as np 4 | 5 | from ..bicycle import sort_eigenmodes 6 | 7 | from dtk import bicycle as dtkbicycle 8 | 9 | # local dependencies 10 | import bicycleparameters 11 | from bicycleparameters import bicycle 12 | 13 | 14 | def test_benchmark_to_canonical(): 15 | M, C1, K0, K2 = dtkbicycle.benchmark_matrices() 16 | par = dtkbicycle.benchmark_parameters() 17 | 18 | bpM, bpC1, bpK0, bpK2 = bicycle.benchmark_par_to_canonical(par) 19 | 20 | np.testing.assert_allclose(M, bpM) 21 | np.testing.assert_allclose(C1, bpC1) 22 | np.testing.assert_allclose(K0, bpK0) 23 | np.testing.assert_allclose(K2, bpK2) 24 | 25 | 26 | def test_benchmark_eigenvalues(): 27 | 28 | expected = dtkbicycle.benchmark_matrices() 29 | path_to_package = os.path.split(bicycleparameters.__file__)[0] 30 | path_to_data = os.path.join(path_to_package, '..', 'data') 31 | 32 | benchmark = bicycleparameters.Bicycle('Benchmark', path_to_data, True, 33 | True) 34 | M, C1, K0, K2 = benchmark.canonical(nominal=True) 35 | 36 | np.testing.assert_allclose(M, expected[0]) 37 | np.testing.assert_allclose(C1, expected[1]) 38 | np.testing.assert_allclose(K0, expected[2]) 39 | np.testing.assert_allclose(K2, expected[3]) 40 | 41 | 42 | def test_sort_eigenmodes(): 43 | 44 | 45 | w = np.array([ 46 | [-6.88390903+0.j, -2.92048758+0.j, 3.32151181+0.73198362j, 3.32151181-0.73198362j], 47 | [ 3.25058404+0.83425573j, 3.25058404-0.83425573j, -7.02339158+0.j, -2.92654704+0.j, ], 48 | [-7.16278369+0.j, 3.17964562+0.92400675j, 3.17964562-0.92400675j, -2.93267564+0.j] 49 | ]) 50 | 51 | v = np.array([ 52 | [[ 0.00196065+0.j, -0.29800463+0.j, 0.02930766-0.08781924j, 0.02930766+0.08781924j], 53 | [ 0.14374404+0.j, 0.127017 +0.j, -0.26020427+0.05734294j, -0.26020427-0.05734294j], 54 | [-0.01349694+0.j, 0.87031883+0.j, 0.16162797-0.27023993j, 0.16162797+0.27023993j], 55 | [-0.98952091+0.j, -0.37095156+0.j, -0.90624564+0.j, -0.90624564-0.j]], 56 | [[ -0.01543099+0.09712139j, -0.01543099-0.09712139j, 0.00191713+0.j, -0.30037796+0.j,], 57 | [ 0.25968865-0.06664856j, 0.25968865+0.06664856j, 0.14094669+0.j, 0.11968475+0.j,], 58 | [ -0.13118381+0.30282786j, -0.13118381-0.30282786j, -0.01346473+0.j, 0.87907022+0.j,], 59 | [ 0.89974174+0.j, 0.89974174-0.j , -0.98992376+0.j, -0.35026304+0.j,]], 60 | [[ 0.00184873+0.j, 0.00157195-0.10415391j, 0.00157195+0.10415391j, -0.30250698+0.j], 61 | [ 0.13825716+0.j, -0.25897887+0.0752594j , -0.25897887-0.0752594j , 0.11247147+0.j], 62 | [-0.01324205+0.j, 0.10123715-0.32972004j, 0.10123715+0.32972004j, 0.88715484+0.j], 63 | [-0.99030611+0.j, -0.89300123+0.j, -0.89300123-0.j , -0.32984235+0.j]] 64 | ]) 65 | 66 | w_expected = np.array([ 67 | [-6.88390903+0.j, -2.92048758+0.j, 3.32151181+0.73198362j, 3.32151181-0.73198362j], 68 | [-7.02339158+0.j, -2.92654704+0.j, 3.25058404+0.83425573j, 3.25058404-0.83425573j], 69 | [-7.16278369+0.j, -2.93267564+0.j, 3.17964562+0.92400675j, 3.17964562-0.92400675j] 70 | ]) 71 | 72 | v_expected = np.array([ 73 | [[ 0.00196065+0.j, -0.29800463+0.j, 0.02930766-0.08781924j, 0.02930766+0.08781924j], 74 | [ 0.14374404+0.j, 0.127017 +0.j, -0.26020427+0.05734294j, -0.26020427-0.05734294j], 75 | [-0.01349694+0.j, 0.87031883+0.j, 0.16162797-0.27023993j, 0.16162797+0.27023993j], 76 | [-0.98952091+0.j, -0.37095156+0.j, -0.90624564+0.j, -0.90624564-0.j]], 77 | [[ 0.00191713+0.j, -0.30037796+0.j, -0.01543099+0.09712139j, -0.01543099-0.09712139j], 78 | [ 0.14094669+0.j, 0.11968475+0.j, 0.25968865-0.06664856j, 0.25968865+0.06664856j], 79 | [-0.01346473+0.j, 0.87907022+0.j, -0.13118381+0.30282786j, -0.13118381-0.30282786j], 80 | [-0.98992376+0.j, -0.35026304+0.j, 0.89974174+0.j, 0.89974174-0.j]], 81 | [[ 0.00184873+0.j, -0.30250698+0.j, 0.00157195-0.10415391j, 0.00157195+0.10415391j], 82 | [ 0.13825716+0.j, 0.11247147+0.j, -0.25897887+0.0752594j , -0.25897887-0.0752594j ], 83 | [-0.01324205+0.j, 0.88715484+0.j, 0.10123715-0.32972004j, 0.10123715+0.32972004j], 84 | [-0.99030611+0.j, -0.32984235+0.j, -0.89300123+0.j, -0.89300123-0.j]] 85 | ]) 86 | 87 | w_sorted, v_sorted = sort_eigenmodes(w, v) 88 | 89 | np.testing.assert_allclose(w_sorted, w_expected) 90 | np.testing.assert_allclose(v_sorted, v_expected) 91 | -------------------------------------------------------------------------------- /bicycleparameters/tests/test_bicycleparameters.py: -------------------------------------------------------------------------------- 1 | from bicycleparameters import io 2 | 3 | def test_filename_to_dict(): 4 | out = io.filename_to_dict('BrowserFrameCompoundFirst1.mat') 5 | ans = {'angleOrder': 'First', 6 | 'bicycle': 'Browser', 7 | 'part': 'Frame', 8 | 'pendulum': 'Compound', 9 | 'trial': '1'} 10 | assert out == ans 11 | -------------------------------------------------------------------------------- /bicycleparameters/tests/test_io.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | from bicycleparameters.io import load_pendulum_mat_file 4 | 5 | TESTS_DIR = os.path.dirname(__file__) 6 | 7 | 8 | def test_load_pendulum_mat_file(): 9 | path = os.path.join(TESTS_DIR, 'sample_data', 10 | 'BrowserForkCompoundFirst1.mat') 11 | 12 | d = load_pendulum_mat_file(path) 13 | 14 | assert d['angle'] == 'First' 15 | assert d['ActualRate'] == 1000 16 | assert d['bicycle'] == 'BrowserIns' 17 | assert d['data'].shape == (30000,) 18 | np.testing.assert_allclose( 19 | d['data'][0:5], 20 | np.array([0.33034183, 0.32525861, 0.31509219, 0.31509219, 0.33034183])) 21 | assert d['duration'] == 30 22 | assert d['filename'] == 'BrowserInsForkCompoundFirst1' 23 | assert d['notes'] == '' 24 | assert d['part'] == 'Fork' 25 | assert d['pendulum'] == 'Compound' 26 | assert d['trial'] == '1' 27 | -------------------------------------------------------------------------------- /bicycleparameters/tests/test_models.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from pytest import raises 3 | 4 | from ..parameter_sets import (Meijaard2007ParameterSet, 5 | Meijaard2007WithFeedbackParameterSet) 6 | from ..models import Meijaard2007Model, Meijaard2007WithFeedbackModel 7 | 8 | meijaard2007_parameters = { # dictionary of the parameters in Meijaard 2007 9 | 'IBxx': 9.2, 10 | 'IBxz': 2.4, 11 | 'IByy': 11.0, 12 | 'IBzz': 2.8, 13 | 'IFxx': 0.1405, 14 | 'IFyy': 0.28, 15 | 'IHxx': 0.05892, 16 | 'IHxz': -0.00756, 17 | 'IHyy': 0.06, 18 | 'IHzz': 0.00708, 19 | 'IRxx': 0.0603, 20 | 'IRyy': 0.12, 21 | 'c': 0.08, 22 | 'g': 9.81, 23 | 'lam': np.pi/10.0, 24 | 'mB': 85.0, 25 | 'mF': 3.0, 26 | 'mH': 4.0, 27 | 'mR': 2.0, 28 | 'rF': 0.35, 29 | 'rR': 0.3, 30 | 'v': 5.0, 31 | 'w': 1.02, 32 | 'xB': 0.3, 33 | 'xH': 0.9, 34 | 'zB': -0.9, 35 | 'zH': -0.7, 36 | } 37 | 38 | 39 | def test_parse_parameter_overrides(): 40 | 41 | parameter_set = Meijaard2007ParameterSet(meijaard2007_parameters, True) 42 | 43 | model = Meijaard2007Model(parameter_set) 44 | 45 | par, array_keys, array_len = model._parse_parameter_overrides(zH=4.0) 46 | assert par['zH'] == 4.0 47 | assert array_keys == [] 48 | assert array_len is None 49 | 50 | par, array_keys, array_len = model._parse_parameter_overrides( 51 | zH=4.0, IBxx=6.0) 52 | assert par['zH'] == 4.0 53 | assert par['IBxx'] == 6.0 54 | assert array_keys == [] 55 | assert array_len is None 56 | 57 | par, array_keys, array_len = model._parse_parameter_overrides( 58 | zH=4.0, IBxx=[1.0, 2.0, 3.0]) 59 | assert par['zH'] == 4.0 60 | assert array_keys == ['IBxx'] 61 | np.testing.assert_allclose(par['IBxx'], [1.0, 2.0, 3.0]) 62 | assert array_len == 3 63 | 64 | par, array_keys, array_len = model._parse_parameter_overrides( 65 | v=[1.0, 2.0, 3.0]) 66 | np.testing.assert_allclose(par['v'], [1.0, 2.0, 3.0]) 67 | assert array_keys == ['v'] 68 | assert array_len == 3 69 | 70 | par, array_keys, array_len = model._parse_parameter_overrides( 71 | g=[1.0, 2.0, 3.0]) 72 | np.testing.assert_allclose(par['g'], [1.0, 2.0, 3.0]) 73 | assert array_keys == ['g'] 74 | assert array_len == 3 75 | 76 | par, array_keys, array_len = model._parse_parameter_overrides( 77 | zH=4.0, v=[1.0, 2.0, 3.0]) 78 | assert par['zH'] == 4.0 79 | assert array_keys == ['v'] 80 | np.testing.assert_allclose(par['v'], [1.0, 2.0, 3.0]) 81 | assert array_len == 3 82 | 83 | par, array_keys, array_len = model._parse_parameter_overrides( 84 | zH=[5.0, 6.0, 7.0], v=[1.0, 2.0, 3.0]) 85 | assert array_keys == ['zH', 'v'] 86 | np.testing.assert_allclose(par['v'], [1.0, 2.0, 3.0]) 87 | np.testing.assert_allclose(par['zH'], [5.0, 6.0, 7.0]) 88 | assert array_len == 3 89 | 90 | with raises(ValueError): 91 | par, array_keys, array_len = model._parse_parameter_overrides( 92 | zH=[5.0, 6.0], v=[1.0, 2.0, 3.0]) 93 | 94 | 95 | def test_Meijaard2007Model(show=False): 96 | 97 | parameter_set = Meijaard2007ParameterSet(meijaard2007_parameters, True) 98 | 99 | model = Meijaard2007Model(parameter_set) 100 | 101 | M, C1, K0, K2 = model.form_reduced_canonical_matrices() 102 | assert M.shape == (2, 2) 103 | assert C1.shape == (2, 2) 104 | assert K0.shape == (2, 2) 105 | assert K2.shape == (2, 2) 106 | M, C1, K0, K2 = model.form_reduced_canonical_matrices( 107 | w=np.linspace(0.5, 1.5, num=5)) 108 | assert M.shape == (5, 2, 2) 109 | assert C1.shape == (5, 2, 2) 110 | assert K0.shape == (5, 2, 2) 111 | assert K2.shape == (5, 2, 2) 112 | M, C1, K0, K2 = model.form_reduced_canonical_matrices( 113 | w=np.linspace(0.5, 1.5, num=10), v=np.linspace(1, 3, num=10)) 114 | assert M.shape == (10, 2, 2) 115 | assert C1.shape == (10, 2, 2) 116 | assert K0.shape == (10, 2, 2) 117 | assert K2.shape == (10, 2, 2) 118 | 119 | A, B = model.form_state_space_matrices() 120 | assert A.shape == (4, 4) 121 | assert B.shape == (4, 2) 122 | A, B = model.form_state_space_matrices(w=np.linspace(0.5, 1.5, num=5)) 123 | assert A.shape == (5, 4, 4) 124 | assert B.shape == (5, 4, 2) 125 | A, B = model.form_state_space_matrices(v=np.linspace(0, 10, num=10)) 126 | assert A.shape == (10, 4, 4) 127 | assert B.shape == (10, 4, 2) 128 | 129 | A, B = model.form_state_space_matrices(v=np.linspace(0, 10, num=10), 130 | g=np.linspace(0, 10, num=10)) 131 | assert A.shape == (10, 4, 4) 132 | assert B.shape == (10, 4, 2) 133 | 134 | evals, evecs = model.calc_eigen() 135 | assert evals.shape == (4,) 136 | assert evecs.shape == (4, 4) 137 | evals, evecs = model.calc_eigen(g=6.0) 138 | assert evals.shape == (4,) 139 | assert evecs.shape == (4, 4) 140 | evals, evecs = model.calc_eigen(v=np.linspace(0, 10, num=10)) 141 | assert evals.shape == (10, 4) 142 | assert evecs.shape == (10, 4, 4) 143 | model.plot_eigenvalue_parts(v=np.linspace(0, 10, num=10)) 144 | model.plot_eigenvectors(v=np.linspace(0, 10, num=4)) 145 | if show: 146 | import matplotlib.pyplot as plt 147 | plt.show() 148 | 149 | 150 | def test_Meijaard2007WithFeedbackModel(show=False): 151 | 152 | parameter_set = Meijaard2007ParameterSet(meijaard2007_parameters, True) 153 | 154 | model = Meijaard2007WithFeedbackModel(parameter_set) 155 | assert type(model.parameter_set) == Meijaard2007WithFeedbackParameterSet 156 | 157 | M, C1, K0, K2 = model.form_reduced_canonical_matrices() 158 | assert M.shape == (2, 2) 159 | assert C1.shape == (2, 2) 160 | assert K0.shape == (2, 2) 161 | assert K2.shape == (2, 2) 162 | 163 | A, B = model.form_state_space_matrices() 164 | assert A.shape == (4, 4) 165 | assert B.shape == (4, 2) 166 | A, B = model.form_state_space_matrices(w=np.linspace(0.5, 1.5, num=5)) 167 | assert A.shape == (5, 4, 4) 168 | assert B.shape == (5, 4, 2) 169 | A, B = model.form_state_space_matrices(v=np.linspace(0, 10, num=10)) 170 | assert A.shape == (10, 4, 4) 171 | assert B.shape == (10, 4, 2) 172 | 173 | A, B = model.form_state_space_matrices(v=np.linspace(0, 10, num=10), 174 | g=np.linspace(0, 10, num=10)) 175 | assert A.shape == (10, 4, 4) 176 | assert B.shape == (10, 4, 2) 177 | 178 | with raises(ValueError): 179 | # one parameter must be an array 180 | model.plot_gains() 181 | 182 | model.plot_gains(g=np.linspace(0, 10, num=10)) 183 | 184 | model.plot_gains(g=np.linspace(0, 10, num=10), 185 | kTdel_phi=np.linspace(0, 10, num=10)) 186 | 187 | model.plot_gains(g=np.linspace(0, 10, num=10), 188 | v=np.linspace(0, 10, num=10), 189 | kTdel_phi=np.linspace(0, 10, num=10)) 190 | 191 | if show: 192 | import matplotlib.pyplot as plt 193 | plt.show() 194 | -------------------------------------------------------------------------------- /bicycleparameters/tests/test_parameter_sets.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import yaml 4 | import numpy as np 5 | import matplotlib.pyplot as plt 6 | 7 | from ..parameter_sets import (Meijaard2007ParameterSet, Moore2019ParameterSet, 8 | Meijaard2007WithFeedbackParameterSet) 9 | 10 | PARDIR_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 11 | 'parameter_sets') 12 | 13 | 14 | def test_Meijaard2007ParameterSet(plot=False): 15 | 16 | filepath = os.path.join(PARDIR_PATH, 'benchmark-benchmark.yml') 17 | with open(filepath, 'r') as f: 18 | benchmark_par = yaml.load(f, Loader=yaml.FullLoader)['values'] 19 | 20 | pset = Meijaard2007ParameterSet(benchmark_par, True) 21 | 22 | pset2 = Meijaard2007ParameterSet._from_yaml(filepath) 23 | 24 | assert pset.parameters == pset2.parameters 25 | assert pset2.includes_rider 26 | 27 | assert pset.includes_rider is True 28 | assert pset.parameters['v'] == 5.0 29 | 30 | expected_IH = np.array([[0.05892, 0.0, -0.00756], 31 | [0.0, 0.06, 0.0], 32 | [-0.00756, 0.0, 0.00708]]) 33 | np.testing.assert_allclose(pset.form_inertia_tensor('H'), 34 | expected_IH) 35 | 36 | expected_comB = np.array([0.3, 0.0, -0.9]) 37 | expected_comF = np.array([1.02, 0.0, -0.35]) 38 | expected_comH = np.array([0.9, 0.0, -0.7]) 39 | expected_comR = np.array([0.0, 0.0, -0.3]) 40 | 41 | np.testing.assert_allclose(expected_comB, 42 | pset.form_mass_center_vector('B')) 43 | np.testing.assert_allclose(expected_comF, 44 | pset.form_mass_center_vector('F')) 45 | np.testing.assert_allclose(expected_comH, 46 | pset.form_mass_center_vector('H')) 47 | np.testing.assert_allclose(expected_comR, 48 | pset.form_mass_center_vector('R')) 49 | 50 | np.testing.assert_allclose(pset.form_mass_center_vector('H'), 51 | pset.mass_center_of('H')) 52 | 53 | com_total = pset.mass_center_of('F', 'R') 54 | 55 | x = (1.02*3.0 + 0.0*2.0)/(3.0 + 2.0) 56 | y = 0.0 57 | z = (-0.35*3.0 + -0.3*2.0)/(3.0 + 2.0) 58 | 59 | np.testing.assert_allclose(com_total, np.array([x, y, z])) 60 | 61 | if plot: 62 | ax = pset.plot_geometry() 63 | ax = pset.plot_principal_radii_of_gyration(ax=ax) 64 | ax = pset.plot_principal_inertia_ellipsoids(ax=ax) 65 | ax = pset.plot_mass_centers(ax=ax) 66 | plt.show() 67 | 68 | 69 | def test_Moore2019ParameterSet(plot=False): 70 | 71 | with open(os.path.join(PARDIR_PATH, 72 | 'principal-browserjason.yml'), 'r') as f: 73 | principal_par = yaml.load(f, Loader=yaml.FullLoader)['values'] 74 | 75 | pset = Moore2019ParameterSet(principal_par) 76 | 77 | ax = pset.plot_geometry() 78 | ax = pset.plot_person_diamond(ax=ax) 79 | ax = pset.plot_principal_radii_of_gyration(ax=ax) 80 | ax = pset.plot_body_mass_center('D', ax=ax) 81 | ax = pset.plot_body_mass_center('F', ax=ax) 82 | ax = pset.plot_body_mass_center('H', ax=ax) 83 | ax = pset.plot_body_mass_center('P', ax=ax) 84 | ax = pset.plot_body_mass_center('R', ax=ax) 85 | ax = pset.plot_body_principal_inertia_ellipsoid('D', ax=ax) 86 | ax = pset.plot_body_principal_inertia_ellipsoid('P', ax=ax) 87 | ax = pset.plot_body_principal_inertia_ellipsoid('H', ax=ax) 88 | 89 | if plot: 90 | plt.show() 91 | 92 | 93 | def test_conversion(plot=False): 94 | with open(os.path.join(PARDIR_PATH, 95 | 'principal-browserjason.yml'), 'r') as f: 96 | par_dict = yaml.load(f, Loader=yaml.FullLoader)['values'] 97 | pset = Moore2019ParameterSet(par_dict) 98 | pset.plot_all() 99 | bench_pset = pset.to_parameterization('Meijaard2007') 100 | bench_pset.plot_all() 101 | if plot: 102 | plt.show() 103 | 104 | 105 | def test_Meijaard2007WithFeedbackParameterSet(): 106 | 107 | filepath = os.path.join(PARDIR_PATH, 'benchmark-benchmark.yml') 108 | with open(filepath, 'r') as f: 109 | benchmark_par = yaml.load(f, Loader=yaml.FullLoader)['values'] 110 | 111 | pset = Meijaard2007ParameterSet( 112 | benchmark_par, True).to_parameterization('Meijaard2007WithFeedback') 113 | 114 | pset2 = Meijaard2007WithFeedbackParameterSet(pset.parameters, True) 115 | 116 | assert type(pset) == Meijaard2007WithFeedbackParameterSet 117 | assert type(pset2) == Meijaard2007WithFeedbackParameterSet 118 | 119 | gain_names = ['kTphi_phi', 'kTphi_del', 'kTphi_phid', 'kTphi_deld', 120 | 'kTdel_phi', 'kTdel_del', 'kTdel_phid', 'kTdel_deld'] 121 | 122 | for name in gain_names: 123 | assert pset.parameters[name] == 0.0 124 | assert pset2.parameters[name] == 0.0 125 | 126 | assert pset.par_strings['kTphi_phi'] == r'k_{T_{\phi}\phi}' 127 | assert pset2.par_strings['kTphi_phi'] == r'k_{T_{\phi}\phi}' 128 | 129 | expected_IH = np.array([[0.05892, 0.0, -0.00756], 130 | [0.0, 0.06, 0.0], 131 | [-0.00756, 0.0, 0.00708]]) 132 | np.testing.assert_allclose(pset.form_inertia_tensor('H'), 133 | expected_IH) 134 | np.testing.assert_allclose(pset2.form_inertia_tensor('H'), 135 | expected_IH) 136 | -------------------------------------------------------------------------------- /bicycleparameters/version.py: -------------------------------------------------------------------------------- 1 | __version_info__ = (1, 4, 0, 'dev0') 2 | __version__ = '.'.join(map(str, __version_info__)) 3 | -------------------------------------------------------------------------------- /conda/bicycleparameters-1.0.0/meta.yaml: -------------------------------------------------------------------------------- 1 | {% set name = "BicycleParameters" %} 2 | {% set version = "1.0.0" %} 3 | {% set sha256 = "e3aea4dc5a0cf8b21707b77db4c8e887e0366d8f9dbcaf0761a61080e1f2eb3d" %} 4 | 5 | package: 6 | name: {{ name|lower }} 7 | version: {{ version }} 8 | 9 | source: 10 | fn: {{ name }}-{{ version }}.tar.gz 11 | url: https://pypi.io/packages/source/{{ name[0] }}/{{ name }}/{{ name }}-{{ version }}.tar.gz 12 | sha256: {{ sha256 }} 13 | 14 | build: 15 | number: 0 16 | script: python setup.py install --single-version-externally-managed --record record.txt 17 | 18 | 19 | requirements: 20 | build: 21 | - python 22 | - setuptools 23 | 24 | run: 25 | - python 26 | - numpy >=1.6.1 27 | - scipy >=0.9.0 28 | - matplotlib >=1.1.1 29 | - uncertainties >=2.0.0 30 | - yeadon >=1.1.0 31 | - dynamicisttoolkit >=0.1.0 32 | 33 | test: 34 | imports: 35 | - bicycleparameters 36 | - bicycleparameters.bicycle 37 | - bicycleparameters.com 38 | - bicycleparameters.geometry 39 | - bicycleparameters.inertia 40 | - bicycleparameters.io 41 | - bicycleparameters.main 42 | - bicycleparameters.period 43 | - bicycleparameters.plot 44 | - bicycleparameters.rider 45 | - bicycleparameters.tables 46 | 47 | about: 48 | summary: 'Generates and manipulates the physical parameters of a bicycle.' 49 | license: BSD-2-Clause 50 | license_file: LICENSE.txt 51 | home: http://github.com/moorepants/bicycleparameters 52 | doc_url: http://bicycleparameters.readthedocs.io/ 53 | dev_url: https://github.com/moorepants/bicycleparameters 54 | -------------------------------------------------------------------------------- /conda/bicycleparameters-dev-old.yml: -------------------------------------------------------------------------------- 1 | name: bicycleparameters-dev-old 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | # pins are versions in Ubuntu 22.04 6 | # main 7 | - dynamicisttoolkit ==0.5.* 8 | - matplotlib ==3.5.* 9 | - numpy ==1.21.* 10 | - pyyaml ==5.4.* 11 | - scipy ==1.8.* 12 | - uncertainties ==3.1.* 13 | - yeadon ==1.3.* 14 | # app 15 | - dash >=2 16 | - dash-bootstrap-components 17 | - pandas ==1.3.* 18 | - plotly 19 | # dev 20 | - ipython 21 | - nose 22 | - numpydoc ==1.2.* 23 | - pytest 24 | - sphinx ==4.3.* 25 | - sphinx-gallery 26 | - sphinx-reredirects 27 | -------------------------------------------------------------------------------- /conda/bicycleparameters-dev.yml: -------------------------------------------------------------------------------- 1 | name: bicycleparameters-dev 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | # pins are versions in Ubuntu 22.04 6 | # main 7 | - dynamicisttoolkit >=0.5.3 8 | - matplotlib >=3.5.1 9 | - numpy >=1.21.5 10 | - pyyaml >=5.4.1 11 | - scipy >=1.8.0 12 | - uncertainties >=3.1.5 13 | - yeadon >=1.3.0 14 | # app 15 | - dash >=2 16 | - dash-bootstrap-components 17 | - pandas >=1.3.5 18 | - plotly 19 | # dev 20 | - ipython 21 | - nose 22 | - numpydoc >=1.2 23 | - pytest 24 | - sphinx >=4.3.2 25 | - sphinx-gallery 26 | - sphinx-reredirects 27 | -------------------------------------------------------------------------------- /conda/cycle-app-environment.yml: -------------------------------------------------------------------------------- 1 | # navigate to the directory which contains this file and run `conda env create -f environment.yml` to build 2 | name: bp 3 | channels: 4 | - conda-forge 5 | - defaults 6 | dependencies: 7 | - dash >=2 8 | - dash-bootstrap-components 9 | - dynamicisttoolkit 10 | - matplotlib 11 | - pandas 12 | - uncertainties 13 | - yeadon 14 | -------------------------------------------------------------------------------- /data/bicycles/Balanceassistv1/Parameters/Balanceassistv1Benchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 1.120+/-0.018 2 | IBxz = 0.047+/-0.028 3 | IByy = 3.16+/-0.08 4 | IBzz = 2.119+/-0.030 5 | IFxx = 0.0995+/-0.0005 6 | IFyy = 0.1902+/-0.0009 7 | IHxx = 0.2984+/-0.0031 8 | IHxz = -0.038+/-0.007 9 | IHyy = 0.257+/-0.006 10 | IHzz = 0.0566+/-0.0033 11 | IRxx = 0.1023+/-0.0006 12 | IRyy = 0.1887+/-0.0007 13 | c = 0.042+/-0.010 14 | g = 9.80665 15 | lam = 0.255+/-0.026 16 | mB = 22.500+/-0.010 17 | mF = 2.235+/-0.010 18 | mH = 4.300+/-0.010 19 | mR = 4.085+/-0.010 20 | rF = 0.35231+/-0.00014 21 | rR = 0.34895+/-0.00014 22 | w = 1.113+/-0.008 23 | xB = 0.519+/-0.012 24 | xH = 0.921+/-0.016 25 | zB = -0.521+/-0.015 26 | zH = -0.860+/-0.006 27 | -------------------------------------------------------------------------------- /data/bicycles/Balanceassistv1/RawData/Balanceassistv1Measured.txt: -------------------------------------------------------------------------------- 1 | aB1 = -0.155+/-0.001 2 | aB2 = 0.480+/-0.001 3 | aB3 = 0.030+/-0.001 4 | aH1 = -0.57+/-0.001 5 | aH2 = 0.315+/-0.001 6 | aH3 = 0.055+/-0.001 7 | alphaB1 = 340.5+/-0.5 8 | alphaB2 = 65.4+/-0.5 9 | alphaB3 = 172.4+/-0.5 10 | alphaH1 = 173.6+/-0.5 11 | alphaH2 = 46.4+/-0.5 12 | alphaH3 = 80.0+/-0.5 13 | d = 1.02+/-0.005 14 | d1 = 0.0101+/-0.005 15 | d2 = 0.0+/-0.005 16 | d3 = 0.0+/-0.005 17 | d4 = 0.0286+/-0.005 18 | dF = 8.825+/-0.005, 8.884+/-0.005 19 | dP = 0.020+/-0.001 20 | dR = 8.77+/-0.005, 8.77+/-0.005 21 | g = 9.80665 22 | h1 = 1.035+/-0.001 23 | h2 = 0.0+/-0.001 24 | h3 = 0.0101+/-0.001 25 | h4 = 0.132+/-0.001 26 | h5 = 0.098+/-0.001 27 | lF = 0.297+/-0.001 28 | lP = 0.836+/-0.001 29 | lR = 0.295+/-0.001 30 | mB = 22.50+/-0.01 31 | mF = 2.235+/-0.01 32 | mH = 4.300+/-0.01 33 | mP = 2.045+/-0.01 34 | mR = 4.085+/-0.01 35 | nF = 4, 4 36 | nR = 4, 4 37 | # rider variables are from Balanceassistv2, which should be almost the same as v1 38 | lcs = 0.48+/-0.005 39 | hbb = 0.30+/-0.005 40 | lsp = 0.27+/-0.005 41 | lst = 0.54+/-0.005 42 | lamst = 1.2164944886400477+/-0.01 43 | whb = 0.53+/-0.005 44 | LhbF = 0.93+/-0.005 45 | LhbR = 1.11+/-0.005 46 | TcB1 = 1.79887+/-0.00005 47 | TcF1 = 1.532598+/-0.000021 48 | TcH1 = 1.621215+/-0.000033 49 | TcR1 = 1.348251+/-0.000011 50 | TtB1 = 3.29557+/-0.00020 51 | TtB2 = 3.71436+/-0.00019 52 | TtB3 = 3.09933+/-0.00015 53 | TtF1 = 0.881810+/-0.000017 54 | TtH1 = 1.51300+/-0.00013 55 | TtH2 = 1.24038+/-0.00015 56 | TtH3 = 0.73673+/-0.00005 57 | TtP1 = 0.964822+/-0.000034 58 | TtR1 = 0.893870+/-0.000021 59 | -------------------------------------------------------------------------------- /data/bicycles/Benchmark/Parameters/BenchmarkBenchmark.txt: -------------------------------------------------------------------------------- 1 | w = 1.02+/-0.0 2 | c = 0.08+/-0.0 3 | lam = 0.314159265358979323846+/-0.0 4 | g = 9.81+/-0.0 5 | rR = 0.3+/-0.0 6 | mR = 2.0+/-0.0 7 | IRxx = 0.0603+/-0.0 8 | IRyy = 0.12+/-0.0 9 | xB = 0.3+/-0.0 10 | zB = -0.9+/-0.0 11 | mB = 85.0+/-0.0 12 | IBxx = 9.2+/-0.0 13 | IByy = 11.0+/-0.0 14 | IBzz = 2.8+/-0.0 15 | IBxz = 2.4+/-0.0 16 | xH = 0.9+/-0.0 17 | zH = -0.7+/-0.0 18 | mH = 4.0+/-0.0 19 | IHxx = 0.05892+/-0.0 20 | IHyy = 0.06+/-0.0 21 | IHzz = 0.00708+/-0.0 22 | IHxz = -0.00756+/-0.0 23 | rF = 0.35+/-0.0 24 | mF = 3.0+/-0.0 25 | IFxx = 0.1405+/-0.0 26 | IFyy = 0.28+/-0.0 27 | -------------------------------------------------------------------------------- /data/bicycles/Browser/Parameters/BrowserBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 0.52962890621+/-0.00247550148476 2 | IBxz = -0.116285607878+/-0.00114783359707 3 | IByy = 1.3163960125+/-0.00400774617153 4 | IBzz = 0.756786895402+/-0.00330394515109 5 | IFxx = 0.0883826870796+/-0.00035969731805 6 | IFyy = 0.149221207336+/-0.00151585483097 7 | IHxx = 0.25335539588+/-0.00126852786611 8 | IHxz = -0.0720217263293+/-0.000790281755242 9 | IHyy = 0.245827908036+/-0.00299166644562 10 | IHzz = 0.0955686343473+/-0.000737521114809 11 | IRxx = 0.0904114316323+/-0.000367953786506 12 | IRyy = 0.152391250767+/-0.00113908424669 13 | c = 0.0685808540382+/-0.00169464113488 14 | g = 9.81+/-0.01 15 | lam = 0.399680398707+/-0.00349065850399 16 | mB = 9.86+/-0.02 17 | mF = 2.02+/-0.02 18 | mH = 3.22+/-0.02 19 | mR = 3.11+/-0.02 20 | rF = 0.34352982332+/-0.000122426879301 21 | rR = 0.340958858855+/-0.000122426879301 22 | w = 1.121+/-0.002 23 | xB = 0.275951285677+/-0.00309782583552 24 | xH = 0.866949640247+/-0.003842300035 25 | zB = -0.537842424305+/-0.00265022978777 26 | zH = -0.748236400835+/-0.00263543623177 27 | -------------------------------------------------------------------------------- /data/bicycles/Browser/RawData/BrowserMeasured.txt: -------------------------------------------------------------------------------- 1 | lF = 0.293+/-0.001 2 | lP = 1.05+/-0.001 3 | nF = 13 4 | lR = 0.29325+/-0.001 5 | nR = 13 6 | aB1 = 0.098+/-0.003 7 | aB2 = 0.169+/-0.003 8 | aB3 = -0.294+/-0.003 9 | aH1 = 0.474+/-0.003 10 | aH2 = 0.383+/-0.003 11 | aH3 = 0.215+/-0.003 12 | mF = 2.02+/-0.02 13 | mP = 5.56+/-0.02 14 | mB = 9.86+/-0.02 15 | mH = 3.22+/-0.02 16 | alphaB1 = 3.4+/-0.2 17 | alphaB2 = 138.7+/-0.2 18 | alphaB3 = 229.8+/-0.2 19 | mR = 3.11+/-0.02 20 | alphaH1 = 346.7+/-0.2 21 | alphaH2 = 28.1+/-0.2 22 | alphaH3 = 287.0+/-0.2 23 | f = 0.0705+/-0.001 24 | dF = 28.06+/-0.01 25 | dP = 0.03+/-0.0001 26 | w = 1.121+/-0.002 27 | dR = 27.85+/-0.01 28 | gamma = 67.1+/-0.2 29 | g = 9.81 +/- 0.01 30 | lcs = 0.46 31 | hbb = 0.295 32 | lsp = 0.24 33 | lst = 0.53 34 | lamst = 1.195550538 35 | whb = 0.58 36 | LhbF = 0.8930 37 | LhbR = 0.9213 38 | TcB1 = 1.71730688911+/-4.98313880734e-06 39 | TcF1 = 1.4811273727+/-7.31000200392e-06 40 | TcH1 = 1.60185105189+/-6.90549490599e-06 41 | TcR1 = 1.36108970039+/-3.90671672693e-06 42 | TtB1 = 2.09957410356+/-8.09275635443e-05 43 | TtB2 = 2.37671750273+/-2.4333984297e-05 44 | TtB3 = 1.83976940999+/-1.02546435087e-05 45 | TtF1 = 0.787577011406+/-1.46269721914e-06 46 | TtH1 = 1.36879552035+/-5.95874853641e-06 47 | TtH2 = 1.29527226157+/-6.44254076091e-06 48 | TtH3 = 0.760950957261+/-2.80094376959e-06 49 | TtP1 = 1.89399317145+/-5.93377589066e-06 50 | TtR1 = 0.796564786052+/-1.16766813788e-06 51 | -------------------------------------------------------------------------------- /data/bicycles/Browserins/Parameters/BrowserinsBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 1.04508307817+/-0.00504180663254 2 | IBxz = -0.112576216156+/-0.00342792103562 3 | IByy = 2.40302606561+/-0.00678076158267 4 | IBzz = 1.85009284121+/-0.0076900136829 5 | IFxx = 0.0883826870796+/-0.00035969731805 6 | IFyy = 0.149221207336+/-0.00151585483097 7 | IHxx = 0.25335539588+/-0.00126852786611 8 | IHxz = -0.0720217263293+/-0.000790281755242 9 | IHyy = 0.245827908036+/-0.00299166644562 10 | IHzz = 0.0955686343473+/-0.000737521114809 11 | IRxx = 0.0904114316323+/-0.000367953786506 12 | IRyy = 0.152391250767+/-0.00113908424669 13 | c = 0.0681671329298+/-0.00169155184938 14 | g = 9.81+/-0.01 15 | lam = 0.399680398707+/-0.00349065850399 16 | mB = 14.71+/-0.02 17 | mF = 2.02+/-0.02 18 | mH = 3.22+/-0.02 19 | mR = 3.11+/-0.02 20 | rF = 0.342550408285+/-0.000122426879301 21 | rR = 0.340775218536+/-0.000122426879301 22 | w = 1.121+/-0.002 23 | xB = 0.217194662529+/-0.00260084278255 24 | xH = 0.866949640247+/-0.003842300035 25 | zB = -0.622313629343+/-0.00294167899872 26 | zH = -0.7472569858+/-0.00263543623177 27 | -------------------------------------------------------------------------------- /data/bicycles/Browserins/RawData/BrowserinsMeasured.txt: -------------------------------------------------------------------------------- 1 | lF = 0.293+/-0.001 2 | lP = 1.05+/-0.001 3 | nF = 13 4 | lR = 0.29325+/-0.001 5 | nR = 13 6 | aB1 = -0.018+/-0.003 7 | aB2 = -0.355+/-0.003 8 | aB3 = -0.242+/-0.003 9 | aH1 = 0.474+/-0.003 10 | aH2 = 0.383+/-0.003 11 | aH3 = 0.215+/-0.003 12 | mF = 2.02+/-0.02 13 | mP = 5.56+/-0.02 14 | mB = 14.71+/-0.02 15 | mH = 3.22+/-0.02 16 | alphaB1 = 154.1+/-0.2 17 | alphaB2 = 230.8+/-0.2 18 | alphaB3 = 286.9+/-0.2 19 | mR = 3.11+/-0.02 20 | alphaH1 = 346.7+/-0.2 21 | alphaH2 = 28.1+/-0.2 22 | alphaH3 = 287.0+/-0.2 23 | f = 0.0705+/-0.001 24 | dF = 27.98+/-0.01 25 | dP = 0.03+/-0.0001 26 | w = 1.121+/-0.002 27 | dR = 27.835+/-0.01 28 | gamma = 67.1+/-0.2 29 | g = 9.81 +/- 0.01 30 | lcs = 0.46 31 | hbb = 0.295 32 | lsp = 0.24 33 | lst = 0.53 34 | lamst = 1.195550538 35 | whb = 0.58 36 | LhbF = 0.8930 37 | LhbR = 0.9213 38 | TcB1 = 1.81102206555+/-7.19257359379e-06 39 | TcF1 = 1.4811273727+/-7.31000200392e-06 40 | TcH1 = 1.60185105189+/-6.90549490599e-06 41 | TcR1 = 1.36108970039+/-3.90671672693e-06 42 | TtB1 = 3.36393077723+/-3.53092798904e-05 43 | TtB2 = 2.81390615887+/-6.53051953916e-05 44 | TtB3 = 3.57185136181+/-8.77815156866e-05 45 | TtF1 = 0.787577011406+/-1.46269721914e-06 46 | TtH1 = 1.36879552035+/-5.95874853641e-06 47 | TtH2 = 1.29527226157+/-6.44254076091e-06 48 | TtH3 = 0.760950957261+/-2.80094376959e-06 49 | TtP1 = 1.89399317145+/-5.93377589066e-06 50 | TtR1 = 0.796564786052+/-1.16766813788e-06 51 | -------------------------------------------------------------------------------- /data/bicycles/Crescendo/Parameters/CrescendoBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 0.499733285449+/-0.00218886827509 2 | IBxz = -0.0148407505732+/-0.0011316149926 3 | IByy = 1.11746960046+/-0.00350925696921 4 | IBzz = 0.73927170227+/-0.00309105815486 5 | IFxx = 0.0954028662773+/-0.000388267862788 6 | IFyy = 0.165623459942+/-0.00117747774467 7 | IHxx = 0.3840330428+/-0.0017423135025 8 | IHxz = -0.0777986089409+/-0.00114110113858 9 | IHyy = 0.363142461888+/-0.00410499482239 10 | IHzz = 0.166357442859+/-0.00132747251116 11 | IRxx = 0.0966455697105+/-0.000393325323081 12 | IRyy = 0.143776919744+/-0.00112425225803 13 | c = 0.0832912572138+/-0.0016907620071 14 | g = 9.81+/-0.01 15 | lam = 0.366519142919+/-0.00349065850399 16 | mB = 9.18+/-0.02 17 | mF = 3.545+/-0.02 18 | mH = 4.57+/-0.02 19 | mR = 3.96+/-0.02 20 | rF = 0.342550408285+/-0.000122426879301 21 | rR = 0.339954958444+/-0.000122426879301 22 | w = 1.101+/-0.002 23 | xB = 0.312073833522+/-0.00284415365691 24 | xH = 0.906569561251+/-0.00503272487149 25 | zB = -0.525854751698+/-0.00341340590315 26 | zH = -0.802835004591+/-0.00253087563355 27 | -------------------------------------------------------------------------------- /data/bicycles/Crescendo/RawData/CrescendoMeasured.txt: -------------------------------------------------------------------------------- 1 | lF = 0.301+/-0.001 2 | lP = 1.05+/-0.001 3 | nF = 13 4 | lR = 0.2975+/-0.001 5 | nR = 13 6 | aB1 = 0.248+/-0.003 7 | aB2 = 0.075+/-0.003 8 | aB3 = -0.289+/-0.003 9 | aH1 = 0.496+/-0.003 10 | aH2 = 0.466+/-0.003 11 | aH3 = 0.301+/-0.003 12 | mF = 3.545+/-0.02 13 | mP = 5.56+/-0.02 14 | mB = 9.18+/-0.02 15 | mH = 4.57+/-0.02 16 | alphaB1 = 127.6+/-0.2 17 | alphaB2 = 158.0+/-0.2 18 | alphaB3 = 223.9+/-0.2 19 | mR = 3.96+/-0.02 20 | alphaH1 = 358.4+/-0.2 21 | alphaH2 = 20.6+/-0.2 22 | alphaH3 = 303.8+/-0.2 23 | f = 0.045+/-0.001 24 | dF = 27.98+/-0.01 25 | dP = 0.03+/-0.0001 26 | w = 1.101+/-0.002 27 | dR = 27.768+/-0.01 28 | gamma = 69.0+/-0.2 29 | g = 9.81 +/- 0.01 30 | lcs = 0.465 31 | hbb = 0.29 32 | lsp = 0.28 33 | lst = 0.49 34 | lamst = 1.2356931104119853 35 | whb = 0.56 36 | LhbF = 0.81 37 | LhbR = 1.08 38 | TcB1 = 1.67642832801+/-2.66725495016e-06 39 | TcF1 = 1.35497433248+/-4.2826118253e-06 40 | TcH1 = 1.62812554335+/-4.68103195851e-06 41 | TcR1 = 1.29936975217+/-7.90958016657e-06 42 | TtB1 = 2.26011002034+/-1.29833697844e-05 43 | TtB2 = 2.09594600471+/-2.4151188464e-05 44 | TtB3 = 1.92016974517+/-1.38000936541e-05 45 | TtF1 = 0.818257777294+/-1.61681772917e-06 46 | TtH1 = 1.69026378117+/-0.000113142614477 47 | TtH2 = 1.6439972228+/-0.00012665270655 48 | TtH3 = 1.21589993871+/-2.00027916365e-05 49 | TtP1 = 1.89399317145+/-5.93377589066e-06 50 | TtR1 = 0.823569786469+/-1.34542549293e-06 51 | -------------------------------------------------------------------------------- /data/bicycles/Fisher/Parameters/FisherBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 0.282523843228+/-0.00127383578938 2 | IBxz = 0.0559047839186+/-0.00032406554195 3 | IByy = 0.469714069753+/-0.00284777713914 4 | IBzz = 0.267736477961+/-0.00118544629608 5 | IFxx = 0.0631442259272+/-0.000256982558173 6 | IFyy = 0.106223925049+/-0.00143256408253 7 | IHxx = 0.114653255231+/-0.00096842589825 8 | IHxz = -0.0182419196924+/-0.00120624722635 9 | IHyy = 0.099999037681+/-0.00368850446069 10 | IHzz = 0.022649063255+/-0.00059383598588 11 | IRxx = 0.0630220804753+/-0.000256485390265 12 | IRyy = 0.100831563132+/-0.00107522785415 13 | c = 0.0723512958768+/-0.00162907266827 14 | g = 9.81+/-0.01 15 | lam = 0.329867228627+/-0.00349065850399 16 | mB = 4.48+/-0.02 17 | mF = 1.5+/-0.02 18 | mH = 2.52+/-0.02 19 | mR = 1.94+/-0.02 20 | rF = 0.330178297654+/-0.000113682102208 21 | rR = 0.338636246059+/-0.000113682102208 22 | w = 1.07+/-0.002 23 | xB = 0.367006269532+/-0.00248108393213 24 | xH = 0.959729631021+/-0.00631607383256 25 | zB = -0.499035032101+/-0.0030479185727 26 | zH = -0.719194693301+/-0.00351009078132 27 | -------------------------------------------------------------------------------- /data/bicycles/Fisher/RawData/FisherMeasured.txt: -------------------------------------------------------------------------------- 1 | lF = 0.26425+/-0.001 2 | lP = 1.05+/-0.001 3 | nF = 14 4 | lR = 0.2645+/-0.001 5 | nR = 14 6 | aB1 = 0.304+/-0.003 7 | aB2 = 0.395+/-0.003 8 | aB3 = -0.107+/-0.003 9 | aH1 = 0.341+/-0.003 10 | aH2 = 0.277+/-0.003 11 | aH3 = -0.008+/-0.003 12 | mF = 1.5+/-0.02 13 | mP = 5.56+/-0.02 14 | mB = 4.48+/-0.02 15 | mH = 2.52+/-0.02 16 | alphaB1 = 125.9+/-0.2 17 | alphaB2 = 75.7+/-0.2 18 | alphaB3 = 190.8+/-0.2 19 | mR = 1.94+/-0.02 20 | alphaH1 = 35.3+/-0.2 21 | alphaH2 = 50.0+/-0.2 22 | alphaH3 = 93.8+/-0.2 23 | f = 0.0385+/-0.001 24 | dF = 29.044+/-0.01 25 | dP = 0.03+/-0.0001 26 | w = 1.07+/-0.002 27 | dR = 29.788+/-0.01 28 | gamma = 71.1+/-0.2 29 | g = 9.81 +/- 0.01 30 | TcB1 = 1.63257241686+/-3.78747584928e-06 31 | TcF1 = 1.46351942388+/-4.28638104612e-06 32 | TcH1 = 1.42202097519+/-2.2216868942e-06 33 | TcR1 = 1.36206307943+/-6.67576162311e-06 34 | TtB1 = 1.29169390711+/-2.86110211063e-06 35 | TtB2 = 1.50653379762+/-4.55323430036e-06 36 | TtB3 = 1.36793873901+/-3.6230026194e-06 37 | TtF1 = 0.665696467328+/-1.25628007094e-06 38 | TtH1 = 0.826935810516+/-2.3491329007e-06 39 | TtH2 = 0.72050280427+/-1.0717013253e-06 40 | TtH3 = 0.371985554643+/-3.00453790372e-07 41 | TtP1 = 1.89399317145+/-5.93377589066e-06 42 | TtR1 = 0.66505229793+/-8.14417802793e-07 43 | -------------------------------------------------------------------------------- /data/bicycles/Gyro/RawData/GyroMeasured.txt: -------------------------------------------------------------------------------- 1 | aB1 = 0.153+/-0.001 2 | aB2 = -0.1945+/-0.001 3 | aB3 = -0.105+/-0.001 4 | aB4 = 0.192+/-0.001 5 | aH1 = 0.238+/-0.001 6 | aH2 = 0.2875+/-0.001 7 | aH3 = 0.0975+/-0.001 8 | aH4 = -0.008+/-0.001 9 | alphaB1 = 134.1+/-0.1 10 | alphaB2 = 219+/-0.1 11 | alphaB3 = 192.8+/-0.1 12 | alphaH1 = 323.5+/-0.1 13 | alphaH2 = 342.8+/-0.1 14 | alphaH3 = 292.5+/-0.1 15 | alphaH4 = 272.1+/-0.1 16 | d = 0.5413375+/-0.00008 17 | d1 = 0.045737018+/-0.00004 18 | d2 = 0.0094488+/-0.00004 19 | d3 = 0.0+/-0.0 20 | d4 = 0.0+/-0.0 21 | dF = 21.3055708+/-0.001, 21.2509227+/-0.001 22 | dP = 0.03009+/-0.00001, 0.0301+/-0.00001, 0.03012+/-0.00001 23 | dR = 21.6818591+/-0.001, 21.6917524+/-0.001 24 | g = 9.81+/-0.01 25 | h1 = 0.56515+/-0.00008 26 | h2 = 0.0311023+/-0.00008 27 | h3 = 0.09246235+/-0.00008 28 | h4 = 0.0+/-0.0 29 | h5 = 0.0+/-0.0 30 | lF = 0.10082+/-0.00008 31 | lP = 0.8355+/-0.00008 32 | lR = 0.0925115+/-0.001 33 | mB = 3.03906888+/-0.01 34 | mD = 3.85553515+/-0.01 35 | mF = 1.40613635+/-0.01 36 | mH = 1.36077711+/-0.01 37 | mP = 4.65+/-0.01 38 | mR = 1.54221406+/-0.01 39 | nF = 23 40 | nR = 23 41 | lsp = 0.0381 42 | lst = 0.238125 43 | lamst = 1.23394778 44 | hbb = 0.1905 45 | LhbR = 0.67945 46 | LhbF = 0.6096 47 | lcs = 0.2413 48 | whb = 0.42275 49 | TcB1 = 1.17360779985+/-0.000113325016711 50 | TcD1 = 0.796227679118+/-2.35973826654e-05 51 | TcF1 = 0.887466425789+/-1.20258105068e-05 52 | TcH1 = 1.28884191208+/-5.94220032645e-06 53 | TcR1 = 0.812587406213+/-9.98791668268e-06 54 | TtB1 = 0.346847556321+/-2.46601833704e-05 55 | TtB2 = 0.382250779462+/-7.66435210087e-06 56 | TtB3 = 0.356724884192+/-1.58323788552e-05 57 | TtD1 = 0.216570012201+/-4.0384345771e-06 58 | TtF1 = 0.169795337684+/-3.77334600399e-06 59 | TtH1 = 0.360973192519+/-1.92081666977e-05 60 | TtH2 = 0.39498048318+/-1.15257598507e-06 61 | TtH3 = 0.22540708698+/-7.90585820999e-07 62 | TtH4 = 0.209330171024+/-1.01829628026e-06 63 | TtP1 = 0.95691904392+/-2.0352369725e-06 64 | TtR1 = 0.156524202115+/-3.91621199646e-06 65 | -------------------------------------------------------------------------------- /data/bicycles/MeasuredTemplate.txt: -------------------------------------------------------------------------------- 1 | dF= 2 | dR= 3 | nF= 4 | nR= 5 | h1= 6 | h2= 7 | h3= 8 | h4= 9 | h5= 10 | d1= 11 | d2= 12 | d3= 13 | d4= 14 | d= 15 | mR= 16 | mF= 17 | mH= 18 | mB= 19 | mS= 20 | fo= 21 | lambdaHT= 22 | w= 23 | alphaB= 24 | alphaH= 25 | alphaS= 26 | aB= 27 | aH= 28 | aS= 29 | tB= 30 | tH= 31 | tS= 32 | tF= 33 | tR= 34 | cF= 35 | cR= 36 | cH= 37 | cS= 38 | cB= 39 | lF= 40 | lR= 41 | -------------------------------------------------------------------------------- /data/bicycles/Pista/Parameters/PistaBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 0.289968529291+/-0.00157896728396 2 | IBxz = 0.0502317583637+/-0.00104541145109 3 | IByy = 0.475817094274+/-0.00928289658533 4 | IBzz = 0.249418014295+/-0.0012401842031 5 | IFxx = 0.0553476418952+/-0.000225252175919 6 | IFyy = 0.106185287785+/-0.00137178526192 7 | IHxx = 0.0979884309288+/-0.000400797112661 8 | IHxz = -0.00440828467861+/-0.000293006332405 9 | IHyy = 0.0691907586693+/-0.00207906543331 10 | IHzz = 0.0396107377431+/-0.000166321860227 11 | IRxx = 0.0552268228143+/-0.000224760513182 12 | IRyy = 0.0764034890242+/-0.00113609058577 13 | c = 0.0617300113263+/-0.00160776211474 14 | g = 9.81+/-0.01 15 | lam = 0.275762021815+/-0.00349065850399 16 | mB = 4.49+/-0.02 17 | mF = 1.58+/-0.02 18 | mH = 2.27+/-0.02 19 | mR = 1.38+/-0.02 20 | rF = 0.333838861345+/-0.000113682102208 21 | rR = 0.332088156971+/-0.000113682102208 22 | w = 0.989+/-0.002 23 | xB = 0.382963782674+/-0.0167166513945 24 | xH = 0.906321313298+/-0.00453451662332 25 | zB = -0.476798507146+/-0.00737825561617 26 | zH = -0.732376356772+/-0.00234292942429 27 | -------------------------------------------------------------------------------- /data/bicycles/Pista/RawData/PistaMeasured.txt: -------------------------------------------------------------------------------- 1 | lF = 0.297+/-0.001 2 | lP = 1.05+/-0.001 3 | nF = 14 4 | lR = 0.2975+/-0.001 5 | nR = 14 6 | aB1 = 0.329+/-0.003 7 | aB2 = 0.293+/-0.003 8 | aB3 = -0.267+/-0.003 9 | aH1 = 0.337+/-0.003 10 | aH2 = 0.4+/-0.003 11 | aH3 = -0.063+/-0.003 12 | mF = 1.58+/-0.02 13 | mP = 5.56+/-0.02 14 | mB = 4.49+/-0.02 15 | mH = 2.27+/-0.02 16 | alphaB1 = 120.2+/-0.2 17 | alphaB2 = 40.7+/-0.2 18 | alphaB3 = 215.9+/-0.2 19 | mR = 1.38+/-0.02 20 | alphaH1 = 38.8+/-0.2 21 | alphaH2 = 12.4+/-0.2 22 | alphaH3 = 102.2+/-0.2 23 | f = 0.0315+/-0.001 24 | dF = 29.366+/-0.01 25 | dP = 0.03+/-0.0001 26 | w = 0.989+/-0.002 27 | dR = 29.212+/-0.01 28 | gamma = 74.2+/-0.2 29 | g = 9.81 +/- 0.01 30 | TcB1 = 1.63988549098+/-6.09223646174e-06 31 | TcF1 = 1.45115377659+/-4.69484368201e-06 32 | TcH1 = 1.39260570372+/-2.32445158601e-06 33 | TcR1 = 1.39504641486+/-3.88159278246e-06 34 | TtB1 = 1.26420151317+/-1.1020359906e-05 35 | TtB2 = 1.50127863596+/-7.05511778386e-06 36 | TtB3 = 1.49296965795+/-5.09800881475e-06 37 | TtF1 = 0.623245270589+/-6.38102543609e-07 38 | TtH1 = 0.776458345085+/-1.36048360723e-06 39 | TtH2 = 0.830610406763+/-2.77744026616e-06 40 | TtH3 = 0.525099469331+/-5.29469164537e-07 41 | TtP1 = 1.89399317145+/-5.93377589066e-06 42 | TtR1 = 0.622564653887+/-1.01113109619e-06 43 | -------------------------------------------------------------------------------- /data/bicycles/Rigid/Parameters/RigidBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 2.63751918806+/-0.011141147301 2 | IBxz = 0.65355108991+/-0.00257157016663 3 | IByy = 4.27679806219+/-0.0117267758886 4 | IBzz = 1.94277851254+/-0.0194143157306 5 | IFxx = 0.0524475128396+/-0.000168690908608 6 | IFyy = 0.0983720589324+/-0.000678080004122 7 | IGxx = 0.0497187764522+/-0.000174455202321 8 | IGxz = 0.00493851583989+/-2.83090548638e-05 9 | IGyy = 0.0174089850654+/-0.000197222100405 10 | IGzz = 0.0621995279809+/-0.000224153263826 11 | IHxx = 0.343873849682+/-0.00300081291905 12 | IHxz = -0.0918999164196+/-0.00137845404385 13 | IHyy = 0.339925043172+/-0.00401223893069 14 | IHzz = 0.10310836332+/-0.000713162568858 15 | IRxx = 0.0700963804567+/-0.000225450850594 16 | IRyy = 0.12934189355+/-0.000591786942138 17 | ISxx = 0.0827160331984+/-0.00029149825545 18 | ISxz = -0.0350687985221+/-0.000126243191633 19 | ISyy = 0.0930316861848+/-0.00108855640875 20 | ISzz = 0.0228635034478+/-0.000125326498665 21 | c = 0.0599399125715+/-0.000144359307346 22 | g = 9.81+/-0.01 23 | lam = 0.317489078499+/-0.000324568695876 24 | mB = 22.9+/-0.01 25 | mF = 1.55+/-0.01 26 | mG = 3.35+/-0.01 27 | mH = 5.4+/-0.0141421356237 28 | mR = 4.9+/-0.01 29 | mS = 2.05+/-0.01 30 | rF = 0.335572561302+/-9.1888149237e-06 31 | rR = 0.332528026978+/-9.1888149237e-06 32 | w = 1.06378677685+/-0.000166142163674 33 | xB = 0.334844476225+/-0.00690189995787 34 | xG = 0.773175453165+/-0.00204578962755 35 | xH = 0.818396445062+/-0.00132894376927 36 | xS = 0.892294163528+/-0.000835322896001 37 | zB = -0.735628402212+/-0.00476533104829 38 | zG = -1.14064934606+/-0.00231836644684 39 | zH = -0.98585673135+/-0.00164933184028 40 | zS = -0.732902946335+/-0.00155310201047 41 | -------------------------------------------------------------------------------- /data/bicycles/Rigid/RawData/RigidMeasured.txt: -------------------------------------------------------------------------------- 1 | dF = 21.0780313+/-0.001, 21.0859688+/-0.001, 21.0899375+/-0.001 2 | dR = 20.8907063+/-0.001, 20.8938813+/-0.001, 20.8954688+/-0.001 3 | nF = 10, 10, 10 4 | nR = 10, 10, 10 5 | h1 = 0.9158732+/-0.00008, 0.915924+/-0.00008, 0.9158732+/-0.00008, 0.9153144+/-0.00008, 0.9153398+/-0.00008, 0.9153144+/-0.00008 6 | h2 = 0.1016+/-0.00001 7 | h3 = 0.0674243+/-0.00008, 0.067043+/-0.00008, 0.0669925+/-0.00008, 0.0668528+/-0.00008 8 | h4 = 0.1221486+/-0.00008, 0.1220724+/-0.00008 9 | h5 = 0.0835533+/-0.00008, 0.0835406+/-0.00008 10 | h6 = 0.15369+/-0.00001 11 | h7 = 0.14833+/-0.00001 12 | d1 = 0.0370713+/-0.00004, 0.03703574+/-0.00004 13 | d2 = 0.00979424+/-0.00004, 0.00980186+/-0.00004 14 | d3 = 0.0100457+/-0.00004, 0.0100457+/-0.00004 15 | d4 = 0.0285496+/-0.00004, 0.0285496+/-0.00004 16 | d5 = 0.01001+/-0.00001 17 | d6 = 0.02217+/-0.00001 18 | d = 0.96338263+/-0.00008 19 | l = 0.962406+/-0.002 20 | mR = 4.90+/-0.01 21 | mF = 1.55+/-0.01 22 | mG = 3.35+/-0.01 23 | mB = 22.90+/-0.01 24 | mS = 2.05+/-0.01 25 | alphaB1 = 233.0+/-0.1 26 | alphaB2 = 180.2+/-0.1 27 | alphaB3 = 55.7+/-0.1 28 | alphaB4 = 342.5+/-0.1 29 | alphaB5 = 51.8+/-0.1 30 | aB1 = -0.5215+/-0.001 31 | aB2 = -0.295+/-0.001 32 | aB3 = 0.51825+/-0.001 33 | aB4 = 0.1395+/-0.001 34 | aB5 = 0.51625+/-0.001 35 | alphaG1 = 57.3+/-0.1 36 | alphaG2 = 224.4+/-0.1 37 | alphaG3 = 332.3+/-0.1 38 | aG1 = -0.059+/-0.001 39 | aG2 = 0.07525+/-0.001 40 | aG3 = -0.069+/-0.001 41 | alphaS1 = 252.6+/-0.1 42 | alphaS2 = 156.2+/-0.1 43 | alphaS3 = 127.6+/-0.1 44 | alphaS4 = 20.9+/-0.1 45 | alphaS5 = 301.0+/-0.1 46 | aS1 = -0.0925+/-0.001 47 | aS2 = -0.407+/-0.001 48 | aS3 = -0.2965+/-0.001 49 | aS4 = 0.3855+/-0.001 50 | aS5 = 0.255+/-0.001 51 | lF = 0.2957195+/-0.00008 52 | lR = 0.2802763+/-0.00008 53 | mP = 4.65+/-0.01 54 | dP = 0.03009+/-0.00001, 0.03010+/-0.00001, 0.03012+/-0.00001 55 | lP = 0.8355+/-0.001 56 | g = 9.81+/-0.01 57 | lst = 0.5476875 58 | lsp = 0.2032 59 | whb = 0.535 60 | LhbR = 1.0795 61 | LhbF = 0.90805 62 | hbb = 0.291 63 | lcs = 0.423 64 | lamst = 1.267109037 65 | xcl = 0.1984375 66 | zcl = -0.942975 67 | # ds1 and ds3 may not be that accurate of measurements 68 | ds1 = 0.1349375 69 | ds3 = -0.3603625 70 | TcB1 = 1.88230886153+/-8.82988138885e-05 71 | TcF1 = 1.43308791869+/-1.97417909435e-05 72 | TcG1 = 0.772670557802+/-2.17067624182e-05 73 | TcR1 = 1.22756837985+/-2.40589529543e-05 74 | TcS1 = 1.47090629433+/-3.02321660553e-05 75 | TtB1 = 3.42292311327+/-0.000150565484833 76 | TtB2 = 2.70613266739+/-2.2322886352e-05 77 | TtB3 = 3.07592110787+/-2.13922869876e-05 78 | TtB4 = 2.46588489403+/-5.25155976704e-05 79 | TtB5 = 3.08044654264+/-0.000119024683742 80 | TtF1 = 0.421156995746+/-7.35568080827e-06 81 | TtG1 = 0.448653508209+/-7.67889476368e-06 82 | TtG2 = 0.435446584274+/-1.16575745512e-05 83 | TtG3 = 0.416187252636+/-1.16264285315e-05 84 | TtP1 = 0.95691904392+/-2.0352369725e-06 85 | TtR1 = 0.486888331488+/-6.53327016652e-06 86 | TtS1 = 0.15191473471+/-0.000173154041374 87 | TtS2 = 0.535663629365+/-2.44654339388e-06 88 | TtS3 = 0.438209054995+/-5.88172139429e-06 89 | TtS4 = 0.529938720663+/-2.47108255048e-05 90 | TtS5 = 0.372150409705+/-5.11947455436e-06 91 | -------------------------------------------------------------------------------- /data/bicycles/Rigidcl/RawData/RigidclMeasured.txt: -------------------------------------------------------------------------------- 1 | # The differences in the Rigid bicycle and the Rigidcl bicycle are as follows: 2 | # - The rigid rider harness is set for the position that Luke and Charlie both 3 | # used during the experiments. 4 | # - The seat height is set for the position that Luke and Charlie both used 5 | # during the experiments. 6 | # - The wheel speed motor is mounted slightly different than the original 7 | # design (this should be pretty neglible). This only matters inertially for 8 | # these measurements. The wheel speed calculations should be defined through 9 | # the sensor calibrations. 10 | # - A small angular piece of the chest beam was removed to allow for more 11 | # adjustability in the harness (also pretty neglible). 12 | # - The seat now has the mounting point for the lateral force rod. (negligible) 13 | # So only the frame mass and pendulum measurements are different than the Rigid 14 | # bicycle. Otherwise they are the same. 15 | dF = 21.0780313+/-0.001, 21.0859688+/-0.001, 21.0899375+/-0.001 16 | dR = 20.8907063+/-0.001, 20.8938813+/-0.001, 20.8954688+/-0.001 17 | nF = 10, 10, 10 18 | nR = 10, 10, 10 19 | h1 = 0.9158732+/-0.00008, 0.915924+/-0.00008, 0.9158732+/-0.00008, 0.9153144+/-0.00008, 0.9153398+/-0.00008, 0.9153144+/-0.00008 20 | h2 = 0.1016+/-0.00001 21 | h3 = 0.0674243+/-0.00008, 0.067043+/-0.00008, 0.0669925+/-0.00008, 0.0668528+/-0.00008 22 | h4 = 0.1221486+/-0.00008, 0.1220724+/-0.00008 23 | h5 = 0.0835533+/-0.00008, 0.0835406+/-0.00008 24 | h6 = 0.15369+/-0.00001 25 | h7 = 0.14833+/-0.00001 26 | d1 = 0.0370713+/-0.00004, 0.03703574+/-0.00004 27 | d2 = 0.00979424+/-0.00004, 0.00980186+/-0.00004 28 | d3 = 0.0100457+/-0.00004, 0.0100457+/-0.00004 29 | d4 = 0.0285496+/-0.00004, 0.0285496+/-0.00004 30 | d5 = 0.01001+/-0.00001 31 | d6 = 0.02217+/-0.00001 32 | d = 0.96338263+/-0.00008 33 | l = 0.962406+/-0.002 34 | mR = 4.90+/-0.01 35 | mF = 1.55+/-0.01 36 | mG = 3.35+/-0.01 37 | mB = 22.9971332+/-0.01 38 | mS = 2.05+/-0.01 39 | alphaB1 = 228.2+/-0.1 40 | alphaB2 = 176.0+/-0.1 41 | alphaB3 = 54.4+/-0.1 42 | alphaB4 = 344.1+/-0.1 43 | aB1 = -0.50725+/-0.001 44 | aB2 = -0.2445+/-0.001 45 | aB3 = 0.5105+/-0.001 46 | aB4 = 0.1490+/-0.001 47 | alphaG1 = 57.3+/-0.1 48 | alphaG2 = 224.4+/-0.1 49 | alphaG3 = 332.3+/-0.1 50 | aG1 = -0.059+/-0.001 51 | aG2 = 0.07525+/-0.001 52 | aG3 = -0.069+/-0.001 53 | alphaS1 = 252.6+/-0.1 54 | alphaS2 = 156.2+/-0.1 55 | alphaS3 = 127.6+/-0.1 56 | alphaS4 = 20.9+/-0.1 57 | alphaS5 = 301.0+/-0.1 58 | aS1 = -0.0925+/-0.001 59 | aS2 = -0.407+/-0.001 60 | aS3 = -0.2965+/-0.001 61 | aS4 = 0.3855+/-0.001 62 | aS5 = 0.255+/-0.001 63 | lF = 0.2957195+/-0.00008 64 | lR = 0.2802763+/-0.00008 65 | mP = 4.65+/-0.01 66 | dP = 0.03009+/-0.00001, 0.03010+/-0.00001, 0.03012+/-0.00001 67 | lP = 0.8355+/-0.001 68 | g = 9.81+/-0.01 69 | lst = 0.5476875 70 | lsp = 0.1524 71 | whb = 0.535 72 | LhbR = 1.0795 73 | LhbF = 0.90805 74 | hbb = 0.291 75 | lcs = 0.423 76 | lamst = 1.267109037 77 | xcl = 0.20955 78 | zcl = -0.9017 79 | # ds1 and ds3 may not be that accurate of measurements 80 | ds1 = 0.1349375 81 | ds3 = -0.3603625 82 | TcB1 = 1.86669679749+/-3.80656155241e-05 83 | TcF1 = 1.43308791869+/-1.97417909435e-05 84 | TcG1 = 0.772670557802+/-2.17067624182e-05 85 | TcR1 = 1.22756837985+/-2.40589529543e-05 86 | TcS1 = 1.47090629433+/-3.02321660553e-05 87 | TtB1 = 3.02521246125+/-4.74835945006e-05 88 | TtB2 = 2.5589495205+/-2.62686893038e-05 89 | TtB3 = 3.03204989469+/-5.13438470958e-05 90 | TtB4 = 2.4171363178+/-4.10832893763e-05 91 | TtF1 = 0.421156995746+/-7.35568080827e-06 92 | TtG1 = 0.448653508209+/-7.67889476368e-06 93 | TtG2 = 0.435446584274+/-1.16575745512e-05 94 | TtG3 = 0.416187252636+/-1.16264285315e-05 95 | TtP1 = 0.95691904392+/-2.0352369725e-06 96 | TtR1 = 0.486888331488+/-6.53327016652e-06 97 | TtS1 = 0.15191473471+/-0.000173154041374 98 | TtS2 = 0.535663629365+/-2.44654339388e-06 99 | TtS3 = 0.438209054995+/-5.88172139429e-06 100 | TtS4 = 0.529938720663+/-2.47108255048e-05 101 | TtS5 = 0.372150409705+/-5.11947455436e-06 102 | -------------------------------------------------------------------------------- /data/bicycles/Silver/Parameters/SilverBenchmark.txt: -------------------------------------------------------------------------------- 1 | w = 1.010+/-0.0 2 | c = 0.190+/-0.0 3 | lam = 0.366519143+/-0.0 4 | g = 9.81+/-0.0 5 | rR = 0.35+/-0.0 6 | mR = 2.56+/-0.0 7 | IRxx = 0.078+/-0.0 8 | IRyy = 0.156+/-0.0 9 | IRzz = 0.078+/-0.0 10 | xB = 0.32+/-0.0 11 | yB = 0.0+/-0.0 12 | zB = -0.627+/-0.0 13 | mB = 12.06+/-0.0 14 | IBxx = 0.8155+/-0.0 15 | IBxz = 0.0327+/-0.0 16 | IByy = 1.2+/-0.0 17 | IBzz = 1.0825+/-0.0 18 | xH = 0.907+/-0.0 19 | yH = 0.0+/-0.0 20 | zH = -0.8+/-0.0 21 | mH = 2.54+/-0.0 22 | IHxx = 0.0860+/-0.0 23 | IHxz = -0.0311+/-0.0 24 | IHyy = 0.1+/-0.0 25 | IHzz = 0.0169+/-0.0 26 | rF = 0.3485+/-0.0 27 | mF = 2.05+/-0.0 28 | IFxx = 0.081+/-0.0 29 | IFyy = 0.162+/-0.0 30 | IFzz = 0.081+/-0.0 31 | -------------------------------------------------------------------------------- /data/bicycles/Silver/RawData/SilverMeasured.txt: -------------------------------------------------------------------------------- 1 | lcs = 0.46 2 | hbb = 0.315 3 | lsp = 0.2 4 | lst = 0.51 5 | lamst = 1.2391837689159739 6 | whb = 0.5 7 | LhbF = 0.75 8 | LhbR = 1.105 9 | -------------------------------------------------------------------------------- /data/bicycles/Stratos/RawData/StratosMeasured.txt: -------------------------------------------------------------------------------- 1 | lF = 0.297+/-0.001 2 | lP = 1.05+/-0.001 3 | nF = 13 4 | lR = 0.2965+/-0.001 5 | nR = 14 6 | aB1 = 0.249+/-0.003 7 | aB2 = -0.267+/-0.003 8 | aB3 = -0.071+/-0.003 9 | aH1 = 0.329+/-0.003 10 | aH2 = -0.038+/-0.003 11 | aH3 = 0.4+/-0.003 12 | mF = 3.334+/-0.02 13 | mP = 5.56+/-0.02 14 | mB = 7.22+/-0.02 15 | mH = 3.04+/-0.02 16 | alphaB1 = 128.9+/-0.2 17 | alphaB2 = 221.6+/-0.2 18 | alphaB3 = 184.5+/-0.2 19 | mR = 3.96+/-0.02 20 | alphaH1 = 36.0+/-0.2 21 | alphaH2 = 94.0+/-0.2 22 | alphaH3 = 347.3+/-0.2 23 | f = 0.045+/-0.001 24 | dF = 27.772+/-0.01 25 | dP = 0.03+/-0.0001 26 | w = 1.037+/-0.002 27 | dR = 29.774+/-0.01 28 | gamma = 73.1+/-0.2 29 | g = 9.81 +/- 0.01 30 | lcs = 0.445 31 | hbb = 0.290 32 | lst = 0.480 33 | lsp = 0.195 34 | lamst = 1.308996939 35 | whb = 0.58 36 | LhbF=0.6552 37 | LhbR=1.1014 38 | TcB1 = 1.59880197567+/-6.3096072159e-06 39 | TcF1 = 1.35366619175+/-5.30396954785e-06 40 | TcH1 = 1.45406634451+/-1.95301826402e-05 41 | TcR1 = 1.31217723331+/-7.33295949904e-06 42 | TtB1 = 1.815949139+/-1.36701497554e-05 43 | TtB2 = 1.58519804957+/-9.16825068389e-06 44 | TtB3 = 1.66019943538+/-8.06563293967e-06 45 | TtF1 = 0.801625248455+/-1.12728802487e-06 46 | TtH1 = 1.01149389309+/-4.48284908821e-06 47 | TtH2 = 0.525350778277+/-2.21244434089e-06 48 | TtH3 = 1.08603695606+/-5.66372430716e-06 49 | TtP1 = 1.89399317145+/-5.93377589066e-06 50 | TtR1 = 0.811662317594+/-9.30058972579e-07 51 | -------------------------------------------------------------------------------- /data/bicycles/Tms/Parameters/TmsBenchmark.txt: -------------------------------------------------------------------------------- 1 | w = 1.0 2 | c = 0.0 3 | lam = 0.0872664626 4 | g = 9.81 5 | rR = 0.0 6 | mR = 0.0 7 | IRxx = 0.0 8 | IRyy = 0.0 9 | xB = 1.2 10 | zB = -0.4 11 | mB = 10.0 12 | IBxx = 0.0 13 | IByy = 0.0 14 | IBzz = 0.0 15 | IBxz = 0.0 16 | xH = 1.02 17 | zH = -0.2 18 | mH = 1.0 19 | IHxx = 0.0 20 | IHyy = 0.0 21 | IHzz = 0.0 22 | IHxz = 0.0 23 | rF = 0.0 24 | mF = 0.0 25 | IFxx = 0.0 26 | IFyy = 0.0 27 | -------------------------------------------------------------------------------- /data/bicycles/Yellow/Parameters/YellowBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 0.224032534273+/-0.000924337136702 2 | IBxz = 0.0182183890667+/-0.000123765736234 3 | IByy = 0.387875498968+/-0.00457262650146 4 | IBzz = 0.216034304161+/-0.000899957967889 5 | IFxx = 0.0851500332546+/-0.000346541216905 6 | IFyy = 0.146642875064+/-0.00158129157014 7 | IHxx = 0.145204096638+/-0.000640851479448 8 | IHxz = -0.0193850131223+/-0.000517327473538 9 | IHyy = 0.120010862686+/-0.00250714868146 10 | IHzz = 0.0292310723185+/-0.00034384832588 11 | IRxx = 0.0876699101307+/-0.000356796414278 12 | IRyy = 0.148661417202+/-0.0012536133519 13 | c = 0.0473057207886+/-0.00162727102983 14 | g = 9.81+/-0.01 15 | lam = 0.301941960595+/-0.00349065850399 16 | mB = 3.31+/-0.02 17 | mF = 1.9+/-0.02 18 | mH = 2.45+/-0.02 19 | mR = 2.57+/-0.02 20 | rF = 0.341877060449+/-0.000122426879301 21 | rR = 0.341375110244+/-0.000122426879301 22 | w = 1.089+/-0.002 23 | xB = 0.422298296643+/-0.00384241188261 24 | xH = 0.947882088454+/-0.00438045273196 25 | zB = -0.602532173969+/-0.00365196117253 26 | zH = -0.788217049637+/-0.00232630323345 27 | -------------------------------------------------------------------------------- /data/bicycles/Yellow/RawData/YellowMeasured.txt: -------------------------------------------------------------------------------- 1 | lF = 0.3045+/-0.001 2 | lP = 1.05+/-0.001 3 | nF = 13 4 | lR = 0.302+/-0.001 5 | nR = 13 6 | aB1 = 0.22+/-0.003 7 | aB2 = 0.0+/-0.003 8 | aB3 = -0.379+/-0.003 9 | aH1 = 0.468+/-0.003 10 | aH2 = 0.396+/-0.003 11 | aH3 = 0.015+/-0.003 12 | mF = 1.9+/-0.02 13 | mP = 5.56+/-0.02 14 | mB = 3.31+/-0.02 15 | mH = 2.45+/-0.02 16 | alphaB1 = 139.5+/-0.2 17 | alphaB2 = 345.4+/-0.2 18 | alphaB3 = 215.9+/-0.2 19 | mR = 2.57+/-0.02 20 | alphaH1 = 0.3+/-0.2 21 | alphaH2 = 32.0+/-0.2 22 | alphaH3 = 87.9+/-0.2 23 | f = 0.0565+/-0.001 24 | dF = 27.925+/-0.01 25 | dP = 0.03+/-0.0001 26 | w = 1.089+/-0.002 27 | dR = 27.884+/-0.01 28 | gamma = 72.7+/-0.2 29 | g = 9.81 +/- 0.01 30 | lcs = 0.45 31 | hbb = 0.27658035936203973 32 | lsp = 0.21 33 | lst = 0.515 34 | lamst = 1.265363707695889 35 | whb = 0.24 36 | LhbF = 0.7 37 | LhbR = 1.145 38 | TcB1 = 1.71695407687+/-1.14328081025e-05 39 | TcF1 = 1.49847435147+/-1.92446763795e-05 40 | TcH1 = 1.5182064062+/-8.21997804456e-06 41 | TcR1 = 1.40930922435+/-1.56725622373e-05 42 | TtB1 = 1.1902858275+/-1.83136678217e-05 43 | TtB2 = 1.20078455321+/-6.47320664177e-06 44 | TtB3 = 1.28213595378+/-7.91264846696e-06 45 | TtF1 = 0.773039777241+/-1.71000972081e-06 46 | TtH1 = 1.01269794864+/-2.62213889754e-06 47 | TtH2 = 0.948609384275+/-2.41380261892e-06 48 | TtH3 = 0.457928910447+/-5.65787520945e-07 49 | TtP1 = 1.89399317145+/-5.93377589066e-06 50 | TtR1 = 0.784394809361+/-1.09500982313e-06 51 | -------------------------------------------------------------------------------- /data/bicycles/Yellowrev/Parameters/YellowrevBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 0.225356076528+/-0.00092916150614 2 | IBxz = 0.0178765751912+/-0.000129627296249 3 | IByy = 0.387875498968+/-0.00457262650146 4 | IBzz = 0.214710761906+/-0.000893315075898 5 | IFxx = 0.0851500332546+/-0.000346541216905 6 | IFyy = 0.146642875064+/-0.00158129157014 7 | IHxx = 0.147496786888+/-0.000640700256464 8 | IHxz = -0.0171836655309+/-0.000527993839439 9 | IHyy = 0.119511786484+/-0.00245444440384 10 | IHzz = 0.0293793112718+/-0.000366277717216 11 | IRxx = 0.0876699101307+/-0.000356796414278 12 | IRyy = 0.148661417202+/-0.0012536133519 13 | c = 0.180294938773+/-0.00176864639495 14 | g = 9.81+/-0.01 15 | lam = 0.338593874887+/-0.00349065850399 16 | mB = 3.31+/-0.02 17 | mF = 1.9+/-0.02 18 | mH = 2.45+/-0.02 19 | mR = 2.57+/-0.02 20 | rF = 0.341877060449+/-0.000122426879301 21 | rR = 0.341375110244+/-0.000122426879301 22 | w = 0.985+/-0.002 23 | xB = 0.41244491511+/-0.00379563686367 24 | xH = 0.918984961179+/-0.00455107965017 25 | zB = -0.61783135503+/-0.00370055269932 26 | zH = -0.816256856812+/-0.00225140598256 27 | -------------------------------------------------------------------------------- /data/bicycles/Yellowrev/RawData/YellowrevMeasured.txt: -------------------------------------------------------------------------------- 1 | lF = 0.3045+/-0.001 2 | lP = 1.05+/-0.001 3 | nF = 13 4 | lR = 0.302+/-0.001 5 | nR = 13 6 | aB1 = 0.22+/-0.003 7 | aB2 = 0.0+/-0.003 8 | aB3 = -0.379+/-0.003 9 | aH1 = 0.099+/-0.003 10 | aH2 = 0.445+/-0.003 11 | aH3 = 0.474+/-0.003 12 | mF = 1.9+/-0.02 13 | mP = 5.56+/-0.02 14 | mB = 3.31+/-0.02 15 | mH = 2.45+/-0.02 16 | alphaB1 = 139.5+/-0.2 17 | alphaB2 = 345.4+/-0.2 18 | alphaB3 = 215.9+/-0.2 19 | mR = 2.57+/-0.02 20 | alphaH1 = 89.3+/-0.2 21 | alphaH2 = 33.5+/-0.2 22 | alphaH3 = 4.3+/-0.2 23 | f = -0.0565+/-0.001 24 | dF = 27.925+/-0.01 25 | dP = 0.03+/-0.0001 26 | w = 0.985+/-0.002 27 | dR = 27.884+/-0.01 28 | gamma = 70.6+/-0.2 29 | g = 9.81 +/- 0.01 30 | lcs = 0.45 31 | hbb = 0.27660203113555454 32 | lsp = 0.21 33 | lst = 0.515 34 | lamst = 1.265363707695889 35 | whb = 0.24 36 | LhbF = 0.7 37 | LhbR = 1.145 38 | TcB1 = 1.71695407687+/-1.14328081025e-05 39 | TcF1 = 1.49847435147+/-1.92446763795e-05 40 | TcH1 = 1.52882728039+/-5.6354789354e-06 41 | TcR1 = 1.40930922435+/-1.56725622373e-05 42 | TtB1 = 1.1902858275+/-1.83136678217e-05 43 | TtB2 = 1.20078455321+/-6.47320664177e-06 44 | TtB3 = 1.28213595378+/-7.91264846696e-06 45 | TtF1 = 0.773039777241+/-1.71000972081e-06 46 | TtH1 = 0.475655737231+/-9.1103021502e-07 47 | TtH2 = 0.963825869257+/-2.72469191528e-06 48 | TtH3 = 1.01958456493+/-2.74691185862e-06 49 | TtP1 = 1.89399317145+/-5.93377589066e-06 50 | TtR1 = 0.784394809361+/-1.09500982313e-06 51 | -------------------------------------------------------------------------------- /data/riders/Aurelia/RawData/AureliaYeadonMeas.txt: -------------------------------------------------------------------------------- 1 | measurementconversionfactor: 0.01 2 | Ls1L: 15.2 3 | La2L: 25.7 4 | Lb2L: 26.2 5 | Ls2L: 19.3 6 | La3L: 29.5 7 | Lb3L: 30.4 8 | Ls3L: 31.7 9 | La4L: 47.9 10 | Lb4L: 49.5 11 | Ls4L: 47.9 12 | La5L: 3.5 13 | Lb5L: 3.0 14 | Ls5L: 51.4 15 | La6L: 8.3 16 | Lb6L: 8.5 17 | Ls6L: 11.5 18 | La7L: 14.0 19 | Lb7L: 14.0 20 | Ls7L: 16.3 21 | Ls8L: 29.2 22 | La0p: 31.3 23 | Lb0p: 30.6 24 | La1p: 25.0 25 | Lb1p: 25.6 26 | Ls0p: 87.6 27 | La2p: 23.5 28 | Lb2p: 22.9 29 | Ls1p: 73.7 30 | La3p: 23.2 31 | Lb3p: 23.4 32 | Ls2p: 65.6 #86.6 33 | La4p: 14.5 34 | Lb4p: 15 #14.6 35 | Ls3p: 83 #84.0 36 | La5p: 16.5 37 | Lb5p: 18.5 38 | Ls5p: 34.0 39 | La6p: 19.5 40 | Lb6p: 19.3 41 | Ls6p: 44.0 42 | La7p: 10.0 43 | Lb7p: 11.5 #10.8 44 | Ls7p: 54.0 45 | La4w: 5.5 46 | Lb4w: 5 #14.1 47 | Ls0w: 31.4 48 | La5w: 6.3 49 | Lb5w: 6.0 50 | Ls1w: 24.2 51 | La6w: 8.3 52 | Lb6w: 8.5 53 | Ls2w: 23.1 #22.5 54 | La7w: 4.5 55 | Lb7w: 4.8 #10.7 56 | Ls3w: 28.5 #26.6 57 | Ls4w: 27.6 58 | Lj1L: 11.0 59 | Lk1L: 11.0 60 | Ls4d: 14.8 61 | Lj3L: 40.8 62 | Lk3L: 36.6 63 | Lj4L: 50.7 64 | Lk4L: 53.9 65 | Lj5L: 75.9 66 | Lk5L: 72.2 67 | Lj6L: 3.2 68 | Lk6L: 3.2 69 | Lj8L: 10.8 70 | Lk8L: 10.8 71 | Lj9L: 15.6 72 | Lk9L: 15.6 73 | totalmass: -1 74 | Lj1p: 57.3 75 | Lk1p: 57.6 76 | Lj2p: 51.0 77 | Lk2p: 52.6 78 | Lj3p: 34.5 79 | Lk3p: 36.5 80 | Lj4p: 36.6 81 | Lk4p: 37.0 82 | Lj5p: 23.1 83 | Lk5p: 22.0 84 | Lj6p: 28.8 85 | Lk6p: 28.7 86 | Lj7p: 22.8 87 | Lk7p: 22.7 88 | Lj8p: 20.5 89 | Lk8p: 20.7 90 | Lj9p: 15.4 #17.5 91 | Lk9p: 14.5 #17.5 92 | Lj8w: 7.3 93 | Lk8w: 7.3 94 | Lj9w: 7 #5.2 95 | Lk9w: 6.9 # 5.2 96 | Lj6d: 11.0 97 | Lk6d: 11.0 98 | -------------------------------------------------------------------------------- /data/riders/Charlie/RawData/CharlieRigidclYeadonCFG.txt: -------------------------------------------------------------------------------- 1 | somersault: 0.148352986 # hunch angle of 81.5 degrees 2 | tilt: 0.0 3 | twist: 0.0 4 | PTsagittalFlexion: 0.0 5 | PTbending: 0.0 6 | TCspinalTorsion: 0.0 7 | TCsagittalSpinalFlexion: 0.0 8 | CA1extension: 0.0 9 | CA1adduction: 0.0 10 | CA1rotation: 0.0 11 | CB1extension: 0.0 12 | CB1abduction: 0.0 13 | CB1rotation: 0.0 14 | A1A2extension: 0.0 15 | B1B2extension: 0.0 16 | PJ1extension: 0.0 17 | PJ1adduction: 0.0 18 | PK1extension: 0.0 19 | PK1abduction: 0.0 20 | J1J2flexion: 0.0 21 | K1K2flexion: 0.0 22 | -------------------------------------------------------------------------------- /data/riders/Charlie/RawData/CharlieYeadonMeas.txt: -------------------------------------------------------------------------------- 1 | # Notes on Charlies measurements: 2 | # - Measured on September 28th, 2011 3 | # - Used the body calipers and the circumference tape 4 | # - We measured the acromium level at the base of the neck instead of the top 5 | # of the acromium (mostly the same as what we did for previous people). 6 | # - We measured the width of Ls4 to the outside of the shoulders. 7 | measurementconversionfactor: 0.01 8 | Ls1L: 20.0 9 | La2L: 25.2 10 | Lb2L: 26.2 11 | Ls2L: 24.5 12 | La3L: 30.7 13 | Lb3L: 31.0 14 | Ls3L: 36.9 15 | La4L: 57.6 16 | Lb4L: 57.5 17 | Ls4L: 57.1 18 | La5L: 5.2 19 | Lb5L: 4.9 20 | Ls5L: 59.6 21 | La6L: 13.2 22 | Lb6L: 13.8 23 | Ls6L: 10.5 24 | La7L: 18.0 25 | Lb7L: 18.2 26 | Ls7L: 15.5 27 | Ls8L: 26.3 28 | La0p: 39.6 29 | Lb0p: 37.6 30 | La1p: 27.9 31 | Lb1p: 28.7 32 | Ls0p: 98.0 33 | La2p: 26.5 34 | Lb2p: 27.1 35 | Ls1p: 87.4 36 | La3p: 27.8 37 | Lb3p: 28.7 38 | Ls2p: 85.8 39 | La4p: 17.6 40 | Lb4p: 17.9 41 | Ls3p: 97.2 42 | La5p: 25.2 43 | Lb5p: 24.8 44 | Ls5p: 38.7 45 | La6p: 16.5 46 | Lb6p: 17.6 47 | Ls6p: 49.1 48 | La7p: 11.9 49 | Lb7p: 12.7 50 | Ls7p: 57.2 51 | La4w: 5.8 52 | Lb4w: 6.0 53 | Ls0w: 32.6 54 | La5w: 10.0 55 | Lb5w: 10.1 56 | Ls1w: 29.8 57 | La6w: 7.0 58 | Lb6w: 7.3 59 | Ls2w: 28.6 60 | La7w: 4.9 61 | Lb7w: 5.1 62 | Ls3w: 31.5 63 | Ls4w: 45.8 64 | Lj1L: 10.3 65 | Lk1L: 10.6 66 | Ls4d: 18.4 67 | Lj3L: 41.0 68 | Lk3L: 40.6 69 | Lj4L: 54.4 70 | Lk4L: 55.5 71 | Lj5L: 82.9 72 | Lk5L: 81.8 73 | Lj6L: 2.0 74 | Lk6L: 3.0 75 | Lj8L: 13.9 76 | Lk8L: 15.2 77 | Lj9L: 19.6 78 | Lk9L: 21.3 79 | # The following mass included the clothes, helmet and shoes worn during the bicycle 80 | # experiments. 81 | totalmass: 78.745 82 | Lj1p: 57.4 83 | Lk1p: 59.9 84 | Lj2p: 48.6 85 | Lk2p: 51.2 86 | Lj3p: 39.5 87 | Lk3p: 40.4 88 | Lj4p: 37.8 89 | Lk4p: 37.6 90 | Lj5p: 26.7 91 | Lk5p: 26.8 92 | Lj6p: 33.8 93 | Lk6p: 33.9 94 | Lj7p: 25.5 95 | Lk7p: 24.7 96 | Lj8p: 24.7 97 | Lk8p: 24.6 98 | Lj9p: 21.8 99 | Lk9p: 22.5 100 | Lj8w: 9.1 101 | Lk8w: 9.2 102 | Lj9w: 9.4 103 | Lk9w: 9.2 104 | Lj6d: 12.3 105 | Lk6d: 12.7 106 | -------------------------------------------------------------------------------- /data/riders/Child/RawData/ChildGyroYeadonCFG.txt: -------------------------------------------------------------------------------- 1 | somersault: 0.148352986 # hunch angle of 81.5 degrees 2 | tilt: 0.0 3 | twist: 0.0 4 | PTsagittalFlexion: 0.0 5 | PTbending: 0.0 6 | TCspinalTorsion: 0.0 7 | TCsagittalSpinalFlexion: 0.0 8 | CA1extension: 0.0 9 | CA1adduction: 0.0 10 | CA1rotation: 0.0 11 | CB1extension: 0.0 12 | CB1abduction: 0.0 13 | CB1rotation: 0.0 14 | A1A2extension: 0.0 15 | B1B2extension: 0.0 16 | PJ1extension: 0.0 17 | PJ1adduction: 0.0 18 | PK1extension: 0.0 19 | PK1abduction: 0.0 20 | J1J2flexion: 0.0 21 | K1K2flexion: 0.0 22 | -------------------------------------------------------------------------------- /data/riders/Child/RawData/ChildYeadonMeas.txt: -------------------------------------------------------------------------------- 1 | # These are Charlie's measurements scaled to be the size of an average 5 year 2 | # old male child. Charlie's height is 175.8 cm (1.758 m) and an average child is 3 | # 1.016 m tall, giving a scaling factor of 0.5779294653014789. 4 | # experiments. 5 | measurementconversionfactor: 0.01 6 | totalmass: 18.96 # average weight of 5 year old male 7 | Ls1L: 11.558589306 8 | La2L: 14.5638225256 9 | Lb2L: 15.1417519909 10 | Ls2L: 14.1592718999 11 | La3L: 17.7424345848 12 | Lb3L: 17.9158134243 13 | Ls3L: 21.3255972696 14 | La4L: 33.2887372014 15 | Lb4L: 33.2309442548 16 | Ls4L: 32.9997724687 17 | La5L: 3.00523321957 18 | Lb5L: 2.83185437998 19 | Ls5L: 34.444596132 20 | La6L: 7.62866894198 21 | Lb6L: 7.97542662116 22 | Ls6L: 6.06825938567 23 | La7L: 10.4027303754 24 | Lb7L: 10.5183162685 25 | Ls7L: 8.95790671217 26 | Ls8L: 15.1995449374 27 | La0p: 22.8860068259 28 | Lb0p: 21.7301478953 29 | La1p: 16.1242320819 30 | Lb1p: 16.5865756542 31 | Ls0p: 56.6370875995 32 | La2p: 15.3151308305 33 | Lb2p: 15.6618885097 34 | Ls1p: 50.5110352673 35 | La3p: 16.0664391354 36 | Lb3p: 16.5865756542 37 | Ls2p: 49.5863481229 38 | La4p: 10.1715585893 39 | Lb4p: 10.3449374289 40 | Ls3p: 56.1747440273 41 | La5p: 14.5638225256 42 | Lb5p: 14.3326507395 43 | Ls5p: 22.3658703072 44 | La6p: 9.53583617747 45 | Lb6p: 10.1715585893 46 | Ls6p: 28.3763367463 47 | La7p: 6.87736063709 48 | Lb7p: 7.33970420933 49 | Ls7p: 33.0575654152 50 | La4w: 3.35199089875 51 | Lb4w: 3.46757679181 52 | Ls0w: 18.8405005688 53 | La5w: 5.77929465301 54 | Lb5w: 5.83708759954 55 | Ls1w: 17.222298066 56 | La6w: 4.04550625711 57 | Lb6w: 4.2188850967 58 | Ls2w: 16.5287827076 59 | La7w: 2.83185437998 60 | Lb7w: 2.94744027304 61 | Ls3w: 18.204778157 62 | Ls4w: 26.4691695108 63 | Lj1L: 5.95267349261 64 | Lk1L: 6.1260523322 65 | Ls4d: 10.6339021615 66 | Lj3L: 23.6951080774 67 | Lk3L: 23.4639362912 68 | Lj4L: 31.4393629124 69 | Lk4L: 32.0750853242 70 | Lj5L: 47.9103526735 71 | Lk5L: 47.2746302617 72 | Lj6L: 1.1558589306 73 | Lk6L: 1.7337883959 74 | Lj8L: 8.03321956769 75 | Lk8L: 8.78452787258 76 | Lj9L: 11.3274175199 77 | Lk9L: 12.3098976109 78 | Lj1p: 33.1731513083 79 | Lk1p: 34.6179749716 80 | Lj2p: 28.0873720137 81 | Lk2p: 29.5899886234 82 | Lj3p: 22.8282138794 83 | Lk3p: 23.3483503982 84 | Lj4p: 21.8457337884 85 | Lk4p: 21.7301478953 86 | Lj5p: 15.4307167235 87 | Lk5p: 15.4885096701 88 | Lj6p: 19.5340159272 89 | Lk6p: 19.5918088737 90 | Lj7p: 14.7372013652 91 | Lk7p: 14.2748577929 92 | Lj8p: 14.2748577929 93 | Lk8p: 14.2170648464 94 | Lj9p: 12.5988623436 95 | Lk9p: 13.0034129693 96 | Lj8w: 5.25915813424 97 | Lk8w: 5.31695108077 98 | Lj9w: 5.43253697383 99 | Lk9w: 5.31695108077 100 | Lj6d: 7.10853242321 101 | Lk6d: 7.33970420933 102 | -------------------------------------------------------------------------------- /data/riders/Child/RawData/convert.py: -------------------------------------------------------------------------------- 1 | # this simply scales Charlie's input file with respect to the average height of 2 | # a five year old male. 3 | scale = 1.016 / 1.758; 4 | 5 | f = open('CharlieYeadonMeas.txt', 'r') 6 | n = open('ChildYeadonMeasScaled.txt', 'w') 7 | 8 | for line in f: 9 | if line.startswith('L'): 10 | var, val = line.strip().split(':') 11 | scaled = scale * float(val) 12 | n.write(var + ': ' + str(scaled) + '\n') 13 | else: 14 | n.write(line) 15 | 16 | f.close() 17 | n.close() 18 | -------------------------------------------------------------------------------- /data/riders/Chris/RawData/ChrisYeadonMeas.txt: -------------------------------------------------------------------------------- 1 | # yeadon. (cld72@cornell.edu) 2 | # Measurement input template. 3 | # Lines beginning with pound are comment lines. 4 | # There are 95 measurements, consisting of lengths, perimeters, widths, and 5 | # depths. 6 | # 7 | # For details about how the measurements are to be taken, consult the 8 | # journal article Yeadon 1989-ii or the documentation of this python package. 9 | # 10 | # CONVERSION FACTOR to convert measurements INTO meters 11 | # (set to 1 if measurements are in meters, 0.001 if measurements are in mm, 12 | # 0.0254 if measurements are in inches) 13 | measurementconversionfactor : .01 14 | # 15 | ############################################################################## 16 | # TORSO 17 | # Ls0 hip joint centre 18 | # Ls1 umbilicus 19 | # Ls2 lowest front rib 20 | # Ls3 nipple 21 | # Ls4 shoulder joint centre 22 | # Ls5 acromion 23 | # Ls6 beneath nose 24 | # Ls7 above ear 25 | # Ls8 top of head 26 | # 27 | # lengths to levels 1 through 5 are measured from Ls0, the hip centre: 28 | Ls1L: 4.9 29 | Ls2L: 18.8 30 | Ls3L: 33.4 31 | Ls4L: 47.2 32 | Ls5L: 50.2 33 | # lengths to levels 6 through 8 are measured from Ls5, the acromion: 34 | Ls6L: 14.9 35 | Ls7L: 19 36 | Ls8L: 29.2 37 | # 38 | # stadium parameters: 39 | Ls0p: 86.9 40 | Ls1p: 75 41 | Ls2p: 73.9 42 | Ls3p: 80.6 43 | Ls5p: 37.5 44 | Ls6p: 49.8 45 | Ls7p: 57 46 | # 47 | # stadium widths: 48 | # width nor depth are measured for Ls5, acromion, because its shape is set by 49 | # estimates from Ls4, shoulder joint centre. 50 | Ls0w: 32.4 51 | Ls1w: 27.4 52 | Ls2w: 25.1 53 | Ls3w: 28 54 | Ls4w: 30.3 55 | # 56 | # depth: the presence of the shoulder joint at Ls4, the shoulder joint centre, 57 | # makes it difficult to measure the width of the Ls4 stadium. Therefore the 58 | # depth (: 2r) of the stadium is measured instead. 59 | Ls4d: 15.1 60 | # torso (s) levels 5 through 8 do not have widths because they are circles EDIT. 61 | # 62 | ############################################################################## 63 | # LEFT ARM 64 | # 65 | # lenghts measured from La0, shoulder joint centre: 66 | # La1L is not measured because it is set to be .5 * La2L. 67 | # Accordingly, La1p should be measured at the location .5 * La2L 68 | La2L: 26.1 69 | La3L: 33 70 | La4L: 50.8 71 | # lengths measured from La4, wrist joint centre: 72 | La5L: 3 73 | La6L: 8.8 74 | La7L: 17.7 75 | # 76 | # stadium perimeters: 77 | La0p: 28.5 78 | La1p: 24.2 79 | La2p: 23 80 | La3p: 23.5 81 | La4p: 15.4 82 | La5p: 21 83 | La6p: 21.5 84 | La7p: 10.7 85 | # 86 | # stadium widths: 87 | # arm levels 0-3 are do not have widths because they are circles 88 | La4w: 5 89 | La5w: 7.3 90 | La6w: 9.8 91 | La7w: 4.9 92 | # 93 | ############################################################################## 94 | # RIGHT ARM 95 | # 96 | # lengths measured from Lb0, shoulder joint centre: 97 | # Lb1L is not measured because it is set to be .5 * Lb2L. 98 | # Accordingly, Lb1p should be measured at the location .5 * Lb2L 99 | Lb2L: 26.6 100 | Lb3L: 32.4 101 | Lb4L: 51.9 102 | # lengths measured from Lb4, wrist joint centre: 103 | Lb5L: 1.5 104 | Lb6L: 7.2 105 | Lb7L: 16.6 106 | # 107 | # stadium perimeters: 108 | Lb0p: 29 109 | Lb1p: 24.2 110 | Lb2p: 22.7 111 | Lb3p: 23.4 112 | Lb4p: 15.2 113 | Lb5p: 20.9 114 | Lb6p: 22.4 115 | Lb7p: 11 116 | # 117 | # stadium widths: 118 | # arm levels 0-3 are do not have widths because they are circles 119 | Lb4w: 5.2 120 | Lb5w: 7.2 121 | Lb6w: 9.6 122 | Lb7w: 5 123 | # 124 | ############################################################################## 125 | # LEFT LEG 126 | # 127 | # lengths measured from Lj0, hip joint centre: 128 | Lj1L: 10.1 129 | # Lj2L is not measured because it is set as the average of Lj1L and Lj3L. 130 | Lj3L: 42.6 131 | Lj4L: 56.5 132 | Lj5L: 81.6 133 | # lengths measured from Lj5, ankle joint centre: 134 | Lj6L: 2.5 135 | # Lj7L is not measured because it is set as the average of Lj6L and Lj8L. 136 | Lj8L: 14.9 137 | Lj9L: 21 138 | # 139 | # stadium perimeters: 140 | # Lj0p is not measured because it is set by Ls0p and Ls0w. 141 | Lj1p: 52 142 | Lj2p: 48.9 143 | Lj3p: 35.1 144 | Lj4p: 35.2 145 | Lj5p: 25.5 146 | Lj6p: 30.2 147 | Lj7p: 23.3 148 | Lj8p: 22.8 149 | Lj9p: 18.5 150 | # 151 | # stadium widths: 152 | # leg levels 0-5 and 7 do not have widths because they are circles 153 | Lj8w: 8.7 154 | Lj9w: 8.2 155 | # 156 | # stadium depths: 157 | # this stadium is rotated 90 degrees from the other, so that its longitudinal 158 | # axis is oriented anterior-posteriorly (from back to front) 159 | Lj6d: 11.4 160 | # 161 | ############################################################################## 162 | # RIGHT LEG 163 | # 164 | # lengths measured from Lk0, hip joint centre: 165 | Lk1L: 9.7 166 | # Lk2L is not measured because it is set as the average of Lk1L and Lk3L. 167 | Lk3L: 42.2 168 | Lk4L: 55.8 169 | Lk5L: 80.6 170 | # lengths measured from Lk5, ankle joint centre: 171 | Lk6L: 2.5 172 | # Lk7L is not measured because it is set as the average of Lk6L and Lk8L. 173 | Lk8L: 14.5 174 | Lk9L: 20.8 175 | # 176 | # stadium perimeters: 177 | # Lk0p is not measured because it is set by Ls0p and Ls0w. 178 | Lk1p: 55 179 | Lk2p: 50 180 | Lk3p: 34.8 181 | Lk4p: 34.9 182 | Lk5p: 23 183 | Lk6p: 31 184 | Lk7p: 23.7 185 | Lk8p: 22.2 186 | Lk9p: 19.5 187 | # 188 | # stadium widths: 189 | # leg levels 0-5 and 7 do not have widths because they are circles 190 | Lk8w: 8.6 191 | Lk9w: 8.3 192 | # 193 | # stadium depths: 194 | # this stadium is rotated 90 degrees from the other, so that its longitudinal 195 | # axis is oriented anterior-posteriorly (from back to front) 196 | Lk6d: 11.1 197 | -------------------------------------------------------------------------------- /data/riders/Jason/Parameters/JasonBalanceassistv1Benchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 11.738504483083279 2 | IBxz = -1.5443190146856498 3 | IByy = 12.110105514155187 4 | IBzz = 2.2823416202457905 5 | mB = 83.50000000000001 6 | xB = 0.3352609184222891 7 | yB = 0.0 8 | zB = -1.1408922158792676 9 | -------------------------------------------------------------------------------- /data/riders/Jason/Parameters/JasonBrowserBenchmark.txt: -------------------------------------------------------------------------------- 1 | mB = 72.0+/-2.0 2 | xB = 0.2909+/-0.0 3 | yB = 0.0+/-0.0 4 | zB = -1.1091+/-0.0 5 | IBxx = 7.9985+/-0.0 6 | IBxz = -1.9272+/-0.0 7 | IByy = 8.0689+/-0.0 8 | IBzz = 2.3624+/-0.0 9 | -------------------------------------------------------------------------------- /data/riders/Jason/Parameters/JasonRigidBenchmark.txt: -------------------------------------------------------------------------------- 1 | IBxx = 9.57707087143 2 | IBxz = -1.02983731033 3 | IByy = 9.71438946103 4 | IBzz = 2.16361764694 5 | mB = 83.5 6 | xB = 0.352471843075 7 | yB = 2.77335755173e-08 8 | zB = -1.10674939861 9 | -------------------------------------------------------------------------------- /data/riders/Jason/RawData/JasonBalanceassistv1YeadonCFG.txt: -------------------------------------------------------------------------------- 1 | # When Jason sat on the bicycle the estimated somersault angle was 0 deg, but 2 | # this over extends the arms in the model. 9.74 deg is the first somersault 3 | # angle that results in a valid arm position. 4 | somersault: 0.17 # 9.74 deg 5 | tilt: 0.0 6 | twist: 0.0 7 | PTsagittalFlexion: 0.0 8 | PTbending: 0.0 9 | TCspinalTorsion: 0.0 10 | TCsagittalSpinalFlexion: 0.0 11 | CA1extension: 0.0 12 | CA1adduction: 0.0 13 | CA1rotation: 0.0 14 | CB1extension: 0.0 15 | CB1abduction: 0.0 16 | CB1rotation: 0.0 17 | A1A2extension: 0.0 18 | B1B2extension: 0.0 19 | PJ1extension: 0.0 20 | PJ1adduction: 0.0 21 | PK1extension: 0.0 22 | PK1abduction: 0.0 23 | J1J2flexion: 0.0 24 | K1K2flexion: 0.0 25 | -------------------------------------------------------------------------------- /data/riders/Jason/RawData/JasonBrowserYeadonCFG.txt: -------------------------------------------------------------------------------- 1 | # A hunch angle of 0.123918377 (82.9 degrees) was the original measurement when 2 | # I was at Delft but it doesn't work with the newer handlebar measurements, so 3 | # I lean the rider forward a bit more. 4 | somersault: 0.175 5 | tilt: 0.0 6 | twist: 0.0 7 | PTsagittalFlexion: 0.0 8 | PTbending: 0.0 9 | TCspinalTorsion: 0.0 10 | TCsagittalSpinalFlexion: 0.0 11 | CA1extension: 0.0 12 | CA1adduction: 0.0 13 | CA1rotation: 0.0 14 | CB1extension: 0.0 15 | CB1abduction: 0.0 16 | CB1rotation: 0.0 17 | A1A2extension: 0.0 18 | B1B2extension: 0.0 19 | PJ1extension: 0.0 20 | PJ1adduction: 0.0 21 | PK1extension: 0.0 22 | PK1abduction: 0.0 23 | J1J2flexion: 0.0 24 | K1K2flexion: 0.0 25 | -------------------------------------------------------------------------------- /data/riders/Jason/RawData/JasonBrowserinsYeadonCFG.txt: -------------------------------------------------------------------------------- 1 | # A hunch angle of 0.123918377 (82.9 degrees) was the original measurement when 2 | # I was at Delft but it doesn't work with the newer handlebar measurements, so 3 | # I lean the rider forward a bit more. 4 | somersault: 0.175 5 | tilt: 0.0 6 | twist: 0.0 7 | PTsagittalFlexion: 0.0 8 | PTbending: 0.0 9 | TCspinalTorsion: 0.0 10 | TCsagittalSpinalFlexion: 0.0 11 | CA1extension: 0.0 12 | CA1adduction: 0.0 13 | CA1rotation: 0.0 14 | CB1extension: 0.0 15 | CB1abduction: 0.0 16 | CB1rotation: 0.0 17 | A1A2extension: 0.0 18 | B1B2extension: 0.0 19 | PJ1extension: 0.0 20 | PJ1adduction: 0.0 21 | PK1extension: 0.0 22 | PK1abduction: 0.0 23 | J1J2flexion: 0.0 24 | K1K2flexion: 0.0 25 | -------------------------------------------------------------------------------- /data/riders/Jason/RawData/JasonRigidYeadonCFG.txt: -------------------------------------------------------------------------------- 1 | somersault: 0.284488668 # hunch angle of 73.7 degrees 2 | tilt: 0.0 3 | twist: 0.0 4 | PTsagittalFlexion: 0.0 5 | PTbending: 0.0 6 | TCspinalTorsion: 0.0 7 | TCsagittalSpinalFlexion: 0.0 8 | CA1extension: 0.0 9 | CA1adduction: 0.0 10 | CA1rotation: 0.0 11 | CB1extension: 0.0 12 | CB1abduction: 0.0 13 | CB1rotation: 0.0 14 | A1A2extension: 0.0 15 | B1B2extension: 0.0 16 | PJ1extension: 0.0 17 | PJ1adduction: 0.0 18 | PK1extension: 0.0 19 | PK1abduction: 0.0 20 | J1J2flexion: 0.0 21 | K1K2flexion: 0.0 22 | -------------------------------------------------------------------------------- /data/riders/Jason/RawData/JasonStratosYeadonCFG.txt: -------------------------------------------------------------------------------- 1 | somersault: 0.455530935 2 | tilt: 0.0 3 | twist: 0.0 4 | PTsagittalFlexion: 0.0 5 | PTbending: 0.0 6 | TCspinalTorsion: 0.0 7 | TCsagittalSpinalFlexion: 0.0 8 | CA1extension: 0.0 9 | CA1adduction: 0.0 10 | CA1rotation: 0.0 11 | CB1extension: 0.0 12 | CB1abduction: 0.0 13 | CB1rotation: 0.0 14 | A1A2extension: 0.0 15 | B1B2extension: 0.0 16 | PJ1extension: 0.0 17 | PJ1adduction: 0.0 18 | PK1extension: 0.0 19 | PK1abduction: 0.0 20 | J1J2flexion: 0.0 21 | K1K2flexion: 0.0 22 | -------------------------------------------------------------------------------- /data/riders/Jason/RawData/JasonYeadonMeas.txt: -------------------------------------------------------------------------------- 1 | # yeadon. (cld72@cornell.edu) 2 | # Measurement input template. 3 | # Lines beginning with pound are comment lines. 4 | # There are 95 measurements, consisting of lengths, perimeters, widths, and 5 | # depths. 6 | # 7 | # For details about how the measurements are to be taken, consult the 8 | # journal article Yeadon 1989-ii or the documentation of this python package. 9 | # 10 | # CONVERSION FACTOR to convert measurements INTO meters 11 | # (set to 1 if measurements are in meters, 0.001 if measurements are in mm, 12 | # 0.003937 : 1/2.54/100 if measurements are in inches) 13 | measurementconversionfactor : .01 14 | # 15 | totalmass: 83.5 # This Jason's total mass including the clothes, helmet, and shoes worn during the experiments. 16 | ############################################################################## 17 | # TORSO 18 | # Ls0 hip joint centre 19 | # Ls1 umbilicus 20 | # Ls2 lowest front rib 21 | # Ls3 nipple 22 | # Ls4 shoulder joint centre 23 | # Ls5 acromion 24 | # Ls6 beneath nose 25 | # Ls7 above ear 26 | # Ls8 top of head 27 | # 28 | # lengths to levels 1 through 5 are measured from Ls0, the hip centre: 29 | Ls1L: 17.6 30 | Ls2L: 27.7 31 | Ls3L: 38.8 32 | Ls4L: 49.3 33 | Ls5L: 54.5 34 | # lengths to levels 6 through 8 are measured from Ls5, the acromion: 35 | Ls6L: 15.2 36 | Ls7L: 20.8 37 | Ls8L: 30.8 38 | # 39 | # stadium parameters: 40 | Ls0p: 97 41 | Ls1p: 86.5 42 | Ls2p: 84.5 43 | Ls3p: 90.5 44 | # Ls5p is really measured around the neck at the acromion level (base of neck). 45 | Ls5p: 37.5 46 | Ls6p: 53 47 | Ls7p: 60 48 | # 49 | # stadium widths: 50 | # width nor depth are measured for Ls5, acromion, because its shape is set by 51 | # estimates from Ls4, shoulder joint centre. 52 | Ls0w: 34.7 53 | Ls1w: 31.7 54 | Ls2w: 28.5 55 | Ls3w: 29.6 56 | Ls4w: 34.3 57 | # 58 | # depth: the presence of the shoulder joint at Ls4, the shoulder joint centre, 59 | # makes it difficult to measure the width of the Ls4 stadium. Therefore the 60 | # depth (: 2r) of the stadium is measured instead. 61 | Ls4d: 21.5 62 | # torso (s) levels 5 through 8 do not have widths because they are circles EDIT. 63 | # 64 | ############################################################################## 65 | # LEFT ARM 66 | # 67 | # lenghts measured from La0, shoulder joint centre: 68 | # La1L is not measured because it is set to be .5 * La2L. 69 | # Accordingly, La1p should be measured at the location .5 * La2L 70 | La2L: 29.6 71 | La3L: 35.3 72 | La4L: 55.3 73 | # lengths measured from La4, wrist joint centre: 74 | La5L: 4.8 75 | La6L: 7.6 76 | La7L: 14.8 77 | # 78 | # stadium perimeters: 79 | La0p: 32.9 80 | La1p: 29 81 | La2p: 27.6 82 | La3p: 28 83 | La4p: 16.7 84 | La5p: 24 85 | La6p: 22.5 86 | La7p: 11.6 87 | # 88 | # stadium widths: 89 | # arm levels 0-3 are do not have widths because they are circles 90 | La4w: 5.6 91 | La5w: 9.5 92 | La6w: 9.3 93 | La7w: 4.5 94 | # 95 | ############################################################################## 96 | # RIGHT ARM 97 | # 98 | # lengths measured from Lb0, shoulder joint centre: 99 | # Lb1L is not measured because it is set to be .5 * Lb2L. 100 | # Accordingly, Lb1p should be measured at the location .5 * Lb2L 101 | Lb2L: 30.3 102 | Lb3L: 34.7 103 | Lb4L: 57.5 104 | # lengths measured from Lb4, wrist joint centre: 105 | Lb5L: 5 106 | Lb6L: 8.5 107 | Lb7L: 16.1 108 | # 109 | # stadium perimeters: 110 | Lb0p: 34.5 111 | Lb1p: 29.3 112 | Lb2p: 28 113 | Lb3p: 28.6 114 | Lb4p: 16.5 115 | Lb5p: 24 116 | Lb6p: 24 117 | Lb7p: 12.5 118 | # 119 | # stadium widths: 120 | # arm levels 0-3 are do not have widths because they are circles 121 | Lb4w: 5.5 122 | Lb5w: 10 123 | Lb6w: 10.2 124 | Lb7w: 4.9 125 | # 126 | ############################################################################## 127 | # LEFT LEG 128 | # 129 | # lengths measured from Lj0, hip joint centre: 130 | Lj1L: 6.4 131 | # Lj2L is not measured because it is set as the average of Lj1L and Lj3L. 132 | Lj3L: 44.1 133 | Lj4L: 54.7 134 | Lj5L: 88.1 135 | # lengths measured from Lj5, ankle joint centre: 136 | Lj6L: 4 137 | # Lj7L is not measured because it is set as the average of Lj6L and Lj8L. 138 | Lj8L: 14.2 139 | Lj9L: 19.7 140 | # 141 | # stadium perimeters: 142 | # Lj0p is not measured because it is set by Ls0p and Ls0w. 143 | Lj1p: 61.4 144 | Lj2p: 59 145 | Lj3p: 40 146 | Lj4p: 28.8 147 | Lj5p: 23.5 148 | Lj6p: 35.5 149 | Lj7p: 25.4 150 | Lj8p: 24 151 | Lj9p: 22.5 152 | # 153 | # stadium widths: 154 | # leg levels 0-5 and 7 do not have widths because they are circles 155 | Lj8w: 10.2 156 | Lj9w: 10.4 157 | # 158 | # stadium depths: 159 | # this stadium is rotated 90 degrees from the other, so that its longitudinal 160 | # axis is oriented anterior-posteriorly (from back to front) 161 | Lj6d: 12.4 162 | # 163 | ############################################################################## 164 | # RIGHT LEG 165 | # 166 | # lengths measured from Lk0, hip joint centre: 167 | Lk1L: 6 168 | # Lk2L is not measured because it is set as the average of Lk1L and Lk3L. 169 | Lk3L: 45.7 170 | Lk4L: 57.1 171 | Lk5L: 87.5 172 | # lengths measured from Lk5, ankle joint centre: 173 | Lk6L: 6 174 | # Lk7L is not measured because it is set as the average of Lk6L and Lk8L. 175 | Lk8L: 16.5 176 | Lk9L: 23.9 177 | # 178 | # stadium perimeters: 179 | # Lk0p is not measured because it is set by Ls0p and Ls0w. 180 | Lk1p: 62 181 | Lk2p: 57.2 182 | Lk3p: 38.3 183 | Lk4p: 39.2 184 | Lk5p: 26 185 | Lk6p: 33.5 186 | Lk7p: 25 187 | Lk8p: 25 188 | Lk9p: 20.5 189 | # 190 | # stadium widths: 191 | # leg levels 0-5 and 7 do not have widths because they are circles 192 | Lk8w: 10.1 193 | Lk9w: 8.9 194 | # 195 | # stadium depths: 196 | # this stadium is rotated 90 degrees from the other, so that its longitudinal 197 | # axis is oriented anterior-posteriorly (from back to front) 198 | Lk6d: 12 199 | -------------------------------------------------------------------------------- /data/riders/Luke/RawData/LukeRigidclYeadonCFG.txt: -------------------------------------------------------------------------------- 1 | somersault: 0.148352986 # hunch angle of 81.5 degrees 2 | tilt: 0.0 3 | twist: 0.0 4 | PTsagittalFlexion: 0.0 5 | PTbending: 0.0 6 | TCspinalTorsion: 0.0 7 | TCsagittalSpinalFlexion: 0.0 8 | CA1extension: 0.0 9 | CA1adduction: 0.0 10 | CA1rotation: 0.0 11 | CB1extension: 0.0 12 | CB1abduction: 0.0 13 | CB1rotation: 0.0 14 | A1A2extension: 0.0 15 | B1B2extension: 0.0 16 | PJ1extension: 0.0 17 | PJ1adduction: 0.0 18 | PK1extension: 0.0 19 | PK1abduction: 0.0 20 | J1J2flexion: 0.0 21 | K1K2flexion: 0.0 22 | -------------------------------------------------------------------------------- /data/riders/Luke/RawData/LukeYeadonMeas.txt: -------------------------------------------------------------------------------- 1 | # yeadon python module (cld72@cornell.edu) 2 | # Measurement input template. 3 | # Lines beginning with pound (#) are comment lines. 4 | # There are 95 distance measurements, consisting of lengths, 5 | # perimeters, widths, and 6 | # depths. 7 | # 8 | # For details about how the measurements are to be taken, consult the 9 | # journal article Yeadon 1989-ii or the documentation of this python package. 10 | # 11 | # CONVERSION FACTOR to convert measurements INTO meters 12 | # (set to 1 if measurements are in meters, 0.001 if measurements are in mm, 13 | # 0.0254 if measurements are in inches) 14 | measurementconversionfactor : .01 15 | # 16 | # DENSITY CORRECTION 17 | # the mass of the human can be set to a measured mass (by scaling the densities 18 | # used) if the totalmass field below is set to a a value greater than 0. 19 | # Alternatively, the next line can be deleted from the input file. 20 | totalmass: 84.273 21 | ############################################################################## 22 | # TORSO 23 | # Ls0 hip joint centre 24 | # Ls1 umbilicus 25 | # Ls2 lowest front rib 26 | # Ls3 nipple 27 | # Ls4 shoulder joint centre 28 | # Ls5 acromion 29 | # Ls6 beneath nose 30 | # Ls7 above ear 31 | # Ls8 top of head 32 | # 33 | # lengths to levels 1 through 5 are measured from Ls0, the hip centre: 34 | Ls1L: 14.8 35 | Ls2L: 21.6 36 | Ls3L: 35.7 37 | Ls4L: 50.2 38 | Ls5L: 55.7 39 | # lengths to levels 6 through 8 are measured from Ls5, the acromion: 40 | Ls6L: 13.9 41 | Ls7L: 17.4 42 | Ls8L: 28.9 43 | # 44 | # stadium parameters: 45 | Ls0p: 102.1 46 | Ls1p: 90.9 47 | Ls2p: 85.8 48 | Ls3p: 96.5 49 | Ls5p: 41 50 | Ls6p: 53.5 51 | Ls7p: 58.1 52 | # 53 | # stadium widths: 54 | # width nor depth are measured for Ls5, acromion, because its shape is set by 55 | # estimates from Ls4, shoulder joint centre. 56 | Ls0w: 34.8 57 | Ls1w: 31.8 58 | Ls2w: 28.6 59 | Ls3w: 31.0 60 | Ls4w: 36.1 61 | # 62 | # depth: the presence of the shoulder joint at Ls4, the shoulder joint centre, 63 | # makes it difficult to measure the width of the Ls4 stadium. Therefore the 64 | # depth (: 2r) of the stadium is measured instead. 65 | Ls4d: 21.6 66 | # torso (s) levels 5 through 8 do not have widths because they are circles. 67 | # 68 | ############################################################################## 69 | # LEFT ARM 70 | # La0 shoulder joint centre 71 | # La1 mid-arm 72 | # La2 elbow joint centre 73 | # La3 maximum forearm perimeter 74 | # La4 wrist joint centre 75 | # La5 base of thumb 76 | # La6 knuckles 77 | # La7 fingernails 78 | # 79 | # lenghts measured from La0, shoulder joint centre: 80 | # La1L is not measured because it is set to be .5 * La2L. 81 | # Accordingly, La1p should be measured at the location .5 * La2L 82 | La2L: 28 83 | La3L: 32.7 84 | La4L: 52.5 85 | # lengths measured from La4, wrist joint centre: 86 | La5L: 4 87 | La6L: 8.6 88 | La7L: 16.7 89 | # 90 | # stadium perimeters: 91 | La0p: 39.1 92 | La1p: 31.4 93 | La2p: 29 94 | La3p: 29.6 95 | La4p: 18 96 | La5p: 23.5 97 | La6p: 24.7 98 | La7p: 13 99 | # 100 | # stadium widths: 101 | # arm levels 0-3 are do not have widths because they are circles 102 | La4w: 6.1 103 | La5w: 7.9 104 | La6w: 11.1 105 | La7w: 5.3 106 | # 107 | ############################################################################## 108 | # RIGHT ARM 109 | # 110 | # lengths measured from Lb0, shoulder joint centre: 111 | # Lb1L is not measured because it is set to be .5 * Lb2L. 112 | # Accordingly, Lb1p should be measured at the location .5 * Lb2L 113 | Lb2L: 27.7 114 | Lb3L: 32.4 115 | Lb4L: 53.6 116 | # lengths measured from Lb4, wrist joint centre: 117 | Lb5L: 5.5 118 | Lb6L: 10 119 | Lb7L: 17.8 120 | # 121 | # stadium perimeters: 122 | Lb0p: 40.5 123 | Lb1p: 31.2 124 | Lb2p: 29.9 125 | Lb3p: 30.7 126 | Lb4p: 18.3 127 | Lb5p: 25.4 128 | Lb6p: 25.4 129 | Lb7p: 13.2 130 | # 131 | # stadium widths: 132 | # arm levels 0-3 are do not have widths because they are circles 133 | Lb4w: 6.2 134 | Lb5w: 8.1 135 | Lb6w: 11.1 136 | Lb7w: 5.6 137 | # 138 | ############################################################################## 139 | # LEFT LEG 140 | # Lj0 hip joint centre 141 | # Lj1 crotch 142 | # Lj2 mid-thigh 143 | # Lj3 knee joint centre 144 | # Lj4 maximum calf perimeter 145 | # Lj5 ankle joint centre 146 | # Lj6 heel 147 | # Lj7 arch 148 | # Lj8 ball 149 | # Lj9 toe nails 150 | # 151 | # lengths measured from Lj0, hip joint centre: 152 | Lj1L: 14 153 | # Lj2L is not measured because it is set as the average of Lj1L and Lj3L. 154 | Lj3L: 42.4 155 | Lj4L: 54.4 156 | Lj5L: 78.6 157 | # lengths measured from Lj5, ankle joint centre: 158 | Lj6L: 9.4 159 | # Lj7L is not measured because it is set as the average of Lj6L and Lj8L. 160 | Lj8L: 18.4 161 | Lj9L: 23.5 162 | # 163 | # stadium perimeters: 164 | # Lj0p is not measured because it is set by Ls0p and Ls0w. 165 | Lj1p: 63.4 166 | Lj2p: 55.1 167 | Lj3p: 38.9 168 | Lj4p: 38.3 169 | Lj5p: 22.2 170 | Lj6p: 33.8 171 | Lj7p: 25.4 172 | Lj8p: 23.4 173 | Lj9p: 15.7 174 | # 175 | # stadium widths: 176 | # leg levels 0-5 and 7 do not have widths because they are circles 177 | Lj8w: 8.8 178 | Lj9w: 6.3 179 | # 180 | # stadium depths: 181 | # this stadium is rotated 90 degrees from the other, so that its longitudinal 182 | # axis is oriented anterior-posteriorly (from back to front) 183 | Lj6d: 13.5 184 | # 185 | ############################################################################## 186 | # RIGHT LEG 187 | # 188 | # lengths measured from Lk0, hip joint centre: 189 | Lk1L: 14 190 | # Lk2L is not measured because it is set as the average of Lk1L and Lk3L. 191 | Lk3L: 36.5 192 | Lk4L: 50 193 | Lk5L: 70.2 194 | # lengths measured from Lk5, ankle joint centre: 195 | Lk6L: 6.8 196 | # Lk7L is not measured because it is set as the average of Lk6L and Lk8L. 197 | Lk8L: 16.7 198 | Lk9L: 20.7 199 | # 200 | # stadium perimeters: 201 | # Lk0p is not measured because it is set by Ls0p and Ls0w. 202 | Lk1p: 63.5 203 | Lk2p: 59.4 204 | Lk3p: 39.1 205 | Lk4p: 38.6 206 | Lk5p: 22.7 207 | Lk6p: 34.3 208 | Lk7p: 25.5 209 | Lk8p: 24.5 210 | Lk9p: 18.8 211 | # 212 | # stadium widths: 213 | # leg levels 0-5 and 7 do not have widths because they are circles 214 | Lk8w: 9.8 215 | Lk9w: 6.7 216 | # 217 | # stadium depths: 218 | # this stadium is rotated 90 degrees from the other, so that its longitudinal 219 | # axis is oriented anterior-posteriorly (from back to front) 220 | Lk6d: 12 221 | -------------------------------------------------------------------------------- /data/riders/Mont/RawData/MontYeadonMeas.txt: -------------------------------------------------------------------------------- 1 | # yeadon. (cld72@cornell.edu) 2 | # Measurement input template. 3 | # Lines beginning with pound are comment lines. 4 | # There are 95 measurements, consisting of lengths, perimeters, widths, and 5 | # depths. 6 | # 7 | # For details about how the measurements are to be taken, consult the 8 | # journal article Yeadon 1989-ii or the documentation of this python package. 9 | # 10 | # CONVERSION FACTOR to convert measurements INTO meters 11 | # (set to 1 if measurements are in meters, 0.001 if measurements are in mm, 12 | # 0.0254 if measurements are in inches) 13 | measurementconversionfactor : .01 14 | # 15 | ############################################################################## 16 | # TORSO 17 | # Ls0 hip joint centre 18 | # Ls1 umbilicus 19 | # Ls2 lowest front rib 20 | # Ls3 nipple 21 | # Ls4 shoulder joint centre 22 | # Ls5 acromion 23 | # Ls6 beneath nose 24 | # Ls7 above ear 25 | # Ls8 top of head 26 | # 27 | # lengths to levels 1 through 5 are measured from Ls0, the hip centre: 28 | Ls1L: 19.9 29 | Ls2L: 28.4 30 | Ls3L: 42.8 31 | Ls4L: 53.9 32 | Ls5L: 60.5 33 | # lengths to levels 6 through 8 are measured from Ls5, the acromion: 34 | Ls6L: 14.9 35 | Ls7L: 20 36 | Ls8L: 30.3 37 | # 38 | # stadium parameters: 39 | Ls0p: 109.8 40 | Ls1p: 105.1 41 | Ls2p: 103 42 | Ls3p: 106.3 43 | Ls5p: 40 44 | Ls6p: 51.7 45 | Ls7p: 59 46 | # 47 | # stadium widths: 48 | # width nor depth are measured for Ls5, acromion, because its shape is set by 49 | # estimates from Ls4, shoulder joint centre. 50 | Ls0w: 38.6 51 | Ls1w: 35.4 52 | Ls2w: 33.6 53 | Ls3w: 35.2 54 | Ls4w: 34.8 55 | # 56 | # depth: the presence of the shoulder joint at Ls4, the shoulder joint centre, 57 | # makes it difficult to measure the width of the Ls4 stadium. Therefore the 58 | # depth (: 2r) of the stadium is measured instead. 59 | Ls4d: 21.6 60 | # torso (s) levels 5 through 8 do not have widths because they are circles EDIT. 61 | # 62 | ############################################################################## 63 | # LEFT ARM 64 | # 65 | # lenghts measured from La0, shoulder joint centre: 66 | # La1L is not measured because it is set to be .5 * La2L. 67 | # Accordingly, La1p should be measured at the location .5 * La2L 68 | La2L: 30.6 69 | La3L: 38.7 70 | La4L: 59.1 71 | # lengths measured from La4, wrist joint centre: 72 | La5L: 3.5 73 | La6L: 8.1 74 | La7L: 17.4 75 | # 76 | # stadium perimeters: 77 | La0p: 39 78 | La1p: 32 79 | La2p: 27.5 80 | La3p: 27.6 81 | La4p: 16.9 82 | La5p: 21.7 83 | La6p: 24.9 84 | La7p: 12.6 85 | # 86 | # stadium widths: 87 | # arm levels 0-3 are do not have widths because they are circles 88 | La4w: 6 89 | La5w: 6.9 90 | La6w: 9.8 91 | La7w: 5.4 92 | # 93 | ############################################################################## 94 | # RIGHT ARM 95 | # 96 | # lengths measured from Lb0, shoulder joint centre: 97 | # Lb1L is not measured because it is set to be .5 * Lb2L. 98 | # Accordingly, Lb1p should be measured at the location .5 * Lb2L 99 | Lb2L: 29.3 100 | Lb3L: 36.1 101 | Lb4L: 59.6 102 | # lengths measured from Lb4, wrist joint centre: 103 | Lb5L: 2 104 | Lb6L: 6.9 105 | Lb7L: 17.3 106 | # 107 | # stadium perimeters: 108 | Lb0p: 38.8 109 | Lb1p: 32.6 110 | Lb2p: 28.3 111 | Lb3p: 28.3 112 | Lb4p: 18.7 113 | Lb5p: 24.3 114 | Lb6p: 24.6 115 | Lb7p: 13.7 116 | # 117 | # stadium widths: 118 | # arm levels 0-3 are do not have widths because they are circles 119 | Lb4w: 5.7 120 | Lb5w: 7.9 121 | Lb6w: 9.7 122 | Lb7w: 5.2 123 | # 124 | ############################################################################## 125 | # LEFT LEG 126 | # 127 | # lengths measured from Lj0, hip joint centre: 128 | Lj1L: 3.2 129 | # Lj2L is not measured because it is set as the average of Lj1L and Lj3L. 130 | Lj3L: 41.8 131 | Lj4L: 58.5 132 | Lj5L: 89.1 133 | # lengths measured from Lj5, ankle joint centre: 134 | Lj6L: 4 135 | # Lj7L is not measured because it is set as the average of Lj6L and Lj8L. 136 | Lj8L: 18.2 137 | Lj9L: 22.9 138 | # 139 | # stadium perimeters: 140 | # Lj0p is not measured because it is set by Ls0p and Ls0w. 141 | Lj1p: 63.1 142 | Lj2p: 58.9 143 | Lj3p: 41.5 144 | Lj4p: 31.6 145 | Lj5p: 26.6 146 | Lj6p: 36.2 147 | Lj7p: 23.9 148 | Lj8p: 22.3 149 | Lj9p: 20.5 150 | # 151 | # stadium widths: 152 | # leg levels 0-5 and 7 do not have widths because they are circles 153 | Lj8w: 8.5 154 | Lj9w: 8.3 155 | # 156 | # stadium depths: 157 | # this stadium is rotated 90 degrees from the other, so that its longitudinal 158 | # axis is oriented anterior-posteriorly (from back to front) 159 | Lj6d: 13.7 160 | # 161 | ############################################################################## 162 | # RIGHT LEG 163 | # 164 | # lengths measured from Lk0, hip joint centre: 165 | Lk1L: 3.1 166 | # Lk2L is not measured because it is set as the average of Lk1L and Lk3L. 167 | Lk3L: 39.8 168 | Lk4L: 53.8 169 | Lk5L: 86.1 170 | # lengths measured from Lk5, ankle joint centre: 171 | Lk6L: 2.7 172 | # Lk7L is not measured because it is set as the average of Lk6L and Lk8L. 173 | Lk8L: 19.3 174 | Lk9L: 24.5 175 | # 176 | # stadium perimeters: 177 | # Lk0p is not measured because it is set by Ls0p and Ls0w. 178 | Lk1p: 63.2 179 | Lk2p: 55.5 180 | Lk3p: 41.7 181 | Lk4p: 37.3 182 | Lk5p: 27.9 183 | Lk6p: 34.6 184 | Lk7p: 24.7 185 | Lk8p: 23.6 186 | Lk9p: 22.4 187 | # 188 | # stadium widths: 189 | # leg levels 0-5 and 7 do not have widths because they are circles 190 | Lk8w: 9.3 191 | Lk9w: 8.5 192 | # 193 | # stadium depths: 194 | # this stadium is rotated 90 degrees from the other, so that its longitudinal 195 | # axis is oriented anterior-posteriorly (from back to front) 196 | Lk6d: 12.8 197 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | 15 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest 16 | 17 | help: 18 | @echo "Please use \`make ' where is one of" 19 | @echo " html to make standalone HTML files" 20 | @echo " dirhtml to make HTML files named index.html in directories" 21 | @echo " singlehtml to make a single large HTML file" 22 | @echo " pickle to make pickle files" 23 | @echo " json to make JSON files" 24 | @echo " htmlhelp to make HTML files and a HTML help project" 25 | @echo " qthelp to make HTML files and a qthelp project" 26 | @echo " devhelp to make HTML files and a Devhelp project" 27 | @echo " epub to make an epub" 28 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 29 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 30 | @echo " text to make text files" 31 | @echo " man to make manual pages" 32 | @echo " changes to make an overview of all changed/added/deprecated items" 33 | @echo " linkcheck to check all external links for integrity" 34 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 35 | 36 | clean: 37 | -rm -rf $(BUILDDIR)/* 38 | -rm -rf gallery/ 39 | -rm -rf sg_execution_times.rst 40 | -rm -rf tmpz_*.html 41 | 42 | html: 43 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 44 | @echo 45 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 46 | 47 | dirhtml: 48 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 49 | @echo 50 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 51 | 52 | singlehtml: 53 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 54 | @echo 55 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 56 | 57 | pickle: 58 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 59 | @echo 60 | @echo "Build finished; now you can process the pickle files." 61 | 62 | json: 63 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 64 | @echo 65 | @echo "Build finished; now you can process the JSON files." 66 | 67 | htmlhelp: 68 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 69 | @echo 70 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 71 | ".hhp project file in $(BUILDDIR)/htmlhelp." 72 | 73 | qthelp: 74 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 75 | @echo 76 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 77 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 78 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/BicycleParameters.qhcp" 79 | @echo "To view the help file:" 80 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/BicycleParameters.qhc" 81 | 82 | devhelp: 83 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 84 | @echo 85 | @echo "Build finished." 86 | @echo "To view the help file:" 87 | @echo "# mkdir -p $$HOME/.local/share/devhelp/BicycleParameters" 88 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/BicycleParameters" 89 | @echo "# devhelp" 90 | 91 | epub: 92 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 93 | @echo 94 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 95 | 96 | latex: 97 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 98 | @echo 99 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 100 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 101 | "(use \`make latexpdf' here to do that automatically)." 102 | 103 | latexpdf: 104 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 105 | @echo "Running LaTeX files through pdflatex..." 106 | make -C $(BUILDDIR)/latex all-pdf 107 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 108 | 109 | text: 110 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 111 | @echo 112 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 113 | 114 | man: 115 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 116 | @echo 117 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 118 | 119 | changes: 120 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 121 | @echo 122 | @echo "The overview file is in $(BUILDDIR)/changes." 123 | 124 | linkcheck: 125 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 126 | @echo 127 | @echo "Link check complete; look for any errors in the above output " \ 128 | "or in $(BUILDDIR)/linkcheck/output.txt." 129 | 130 | doctest: 131 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 132 | @echo "Testing of doctests in the sources finished, look at the " \ 133 | "results in $(BUILDDIR)/doctest/output.txt." 134 | -------------------------------------------------------------------------------- /docs/api/bicycle.rst: -------------------------------------------------------------------------------- 1 | :mod:`bicycle` Module 2 | ===================== 3 | 4 | .. automodule:: bicycleparameters.bicycle 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/api/com.rst: -------------------------------------------------------------------------------- 1 | :mod:`com` Module 2 | ================= 3 | 4 | .. automodule:: bicycleparameters.com 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | 9 | -------------------------------------------------------------------------------- /docs/api/geometry.rst: -------------------------------------------------------------------------------- 1 | :mod:`geometry` Module 2 | ====================== 3 | 4 | .. automodule:: bicycleparameters.geometry 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/api/inertia.rst: -------------------------------------------------------------------------------- 1 | :mod:`inertia` Module 2 | ===================== 3 | 4 | .. automodule:: bicycleparameters.inertia 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/api/io.rst: -------------------------------------------------------------------------------- 1 | :mod:`io` Module 2 | ================ 3 | 4 | .. automodule:: bicycleparameters.io 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/api/main.rst: -------------------------------------------------------------------------------- 1 | :mod:`main` Module 2 | ================== 3 | 4 | .. automodule:: bicycleparameters.main 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/api/models.rst: -------------------------------------------------------------------------------- 1 | :mod:`models` Module 2 | ==================== 3 | 4 | .. automodule:: bicycleparameters.models 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | :inherited-members: 9 | -------------------------------------------------------------------------------- /docs/api/parameter_sets.rst: -------------------------------------------------------------------------------- 1 | :mod:`parameter_sets` Module 2 | ============================ 3 | 4 | .. automodule:: bicycleparameters.parameter_sets 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | :inherited-members: 9 | -------------------------------------------------------------------------------- /docs/api/period.rst: -------------------------------------------------------------------------------- 1 | :mod:`period` Module 2 | ==================== 3 | 4 | .. automodule:: bicycleparameters.period 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/api/plot.rst: -------------------------------------------------------------------------------- 1 | :mod:`plot` Module 2 | ================== 3 | 4 | .. automodule:: bicycleparameters.plot 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/api/rider.rst: -------------------------------------------------------------------------------- 1 | :mod:`rider` Module 2 | =================== 3 | 4 | .. automodule:: bicycleparameters.rider 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/api/tables.rst: -------------------------------------------------------------------------------- 1 | :mod:`tables` Module 2 | ==================== 3 | 4 | .. automodule:: bicycleparameters.tables 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/app.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | Bicycle Dynamics Analysis App 3 | ============================= 4 | 5 | The Bicycle Dynamics Analysis App provides a GUI for using the 6 | BicycleParameters Python program on the web. Using Dash, we transform Python 7 | code into HTML/CSS/JS which is nicely rendered within a web browser. The 8 | application is available at https://bicycle-dynamics.onrender.com/. 9 | 10 | Directory Structure 11 | =================== 12 | 13 | Within the ``BicycleParameters/bicycleparameters/`` directory, the primary 14 | module for the application is ``app.py`` and it is written entirely in Python. 15 | The ``/assets/`` folder contains files which are to be displayed by the app, 16 | and the ``/data/`` folder contains raw bicycle measurement data. Some custom 17 | CSS is contained within ``/assets/styles.css``, but most of the CSS can be 18 | written directly in ``app.py`` using ``dash-bootstrap-components``. You can 19 | read more about the purpose of the ``/assets/`` folder on the `Dash 20 | documentation `__. 21 | 22 | Development 23 | =========== 24 | 25 | To develop the application, you need to have an environment which contains all 26 | the necessary dependencies for running ``app.py``. If you are using ``conda``, 27 | you can use the ``cycle-app-environment.yml`` located in the top-level 28 | ``BicycleParameters/conda/`` directory to `build a conda environment 29 | `__ 30 | which contains all the packages you need to develop and run this code. 31 | Alternatively, you can simply view the contents of 32 | ``cycle-app-environment.yml`` and install those packages accordingly or use the 33 | ``requirements.txt`` file available in the top level directory. 34 | 35 | To run ``app.py`` and view the contents locally, navigate to the 36 | ``BicycleParameters/`` directory and run:: 37 | 38 | python -m bicycleparameters.app 39 | 40 | This command calls python and passes the file ``bicycleparameters.app`` (this 41 | is like ``/bicycleparameters/app.py``) using the ``-m`` flag as if we were 42 | simply running a python script. If you instead navigate to 43 | ``/bicycleparameters/`` and run ``python app.py``, the plot images will not 44 | appear in your browser. Stick to the first command above. 45 | 46 | If ``app.py`` has been executed properly, you should see an output similar to 47 | the following; 48 | 49 | :: 50 | 51 | (bp) user@host:~/BicycleParameters/bicycleparameters$ python -m bicycleparameters.app 52 | Dash is running on http://127.0.0.1:8050/ 53 | 54 | Warning: This is a development server. Do not use app.run_server 55 | in production, use a production WSGI server like gunicorn instead. 56 | 57 | * Serving Flask app "app" (lazy loading) 58 | * Environment: production 59 | WARNING: This is a development server. Do not use it in a production deployment. 60 | Use a production WSGI server instead. 61 | * Debug mode: on 62 | 63 | Now if you navigate to http://127.0.0.1:8050/, you should see your local 64 | version of the app displayed in your browser. Congratulations! As you play with 65 | the application online you should see feedback within your terminal window. 66 | Debug information will also display here. In addition, I recommend using the 67 | inspect element tool available with most browsers to debug things live within 68 | your browser. 69 | 70 | Additional Resources 71 | ==================== 72 | 73 | Here are some resources that I found very useful when first developing this 74 | application: 75 | 76 | - The offical `Dash documentation `__. Just 77 | about every single link on this page will have useful information for 78 | you. 79 | - `Dash Bootstrap Components 80 | documentation `__. 81 | This is used to write `CSS 82 | Bootstraps `__ using the 83 | Python language. 84 | - The `Mozilla Web Development 85 | guide `__. I highly 86 | recommened this guide for learning about HTML, CSS, and general web 87 | development. 88 | - The `example 89 | usage `__ 90 | page for Bicycle Parameters. Useful for understanding how the backend 91 | code works. 92 | - `w3schools.com `__. Has great HTML/CSS 93 | reference pages as well as tutorials. Also has some for 94 | `Python `__. 95 | - This `Software 96 | Carpentery `__ 97 | site. Has nice general programming tutorials as well as an in-depth 98 | `git 99 | tutorial `__. 100 | 101 | Feel free to extend this list as you develop and learn. Overall, I ended up 102 | needing to learn and use web development skills far more than I needed to 103 | really understand Python itself. Program in whichever way brings you the most 104 | joy. I wish you the best, future devs! 105 | -------------------------------------------------------------------------------- /docs/bicycleparameters.rst: -------------------------------------------------------------------------------- 1 | API reference for the bicycleparameters Package 2 | =============================================== 3 | 4 | .. toctree:: 5 | 6 | api/bicycle.rst 7 | api/com.rst 8 | api/geometry.rst 9 | api/inertia.rst 10 | api/io.rst 11 | api/main.rst 12 | api/models.rst 13 | api/parameter_sets.rst 14 | api/period.rst 15 | api/plot.rst 16 | api/rider.rst 17 | api/tables.rst 18 | -------------------------------------------------------------------------------- /docs/description.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | Description 3 | =========== 4 | 5 | This is code based off of the work done to measure the physical parameters of a 6 | bicycle and rider at both the `UCD Sports Biomechanics Lab`_ and the `TU Delft 7 | Bicycle Dynamics Lab`_. Physical parameters include but are not limited to the 8 | geometry, mass, mass location and mass distribution of the bicycle rider 9 | system. The code is structured around the Carvallo-Whipple bicycle model and 10 | fundamentally works with and produces the parameters presented in 11 | [Meijaard2007]_, due to the fact that these parameters have been widely adopted 12 | as a benchmark. But the software is also capable of generating parameter sets 13 | for more complex rider biomechanical models. More detail can be found in our 14 | papers and the website_ and in :ref:`references`. 15 | 16 | .. _UCD Sports Biomechanics Lab: http://biosport.ucdavis.edu 17 | .. _TU Delft Bicycle Dynamics Lab: http://bicycle.tudelft.nl 18 | .. _website: http://biosport.ucdavis.edu/research-projects/bicycle/bicycle-parameter-measurement 19 | 20 | Features 21 | ======== 22 | 23 | Parameter Manipulation 24 | ---------------------- 25 | 26 | - Loads bicycle parameter sets from a text file into a python object. 27 | - Generates the benchmark parameter set for a real bicycle from experimental 28 | data. 29 | - Generates the rider parameter set from human measurements based on the Yeadon 30 | model configured to sit on the bicycle. 31 | - Plots a descriptive drawing of the bicycle and/or rider. 32 | - Generates publication quality tables of parameters. 33 | 34 | Basic Linear Analysis 35 | --------------------- 36 | 37 | - Calculates the A and B matrices for the Whipple bicycle model linearized 38 | about the upright configuration. 39 | - Calculates the canonical matrices for the Whipple bicycle model linearized 40 | about the upright configuration. 41 | - Calculates the eigenvalues for the Whipple bicycle model linearized about the 42 | upright configuration. 43 | - Plots the eigenvalue root loci as a function of speed as eigenvalue vs speed. 44 | - Plots Bode diagrams of the open loop transfer functions. 45 | 46 | Refer to :ref:`usage` for examples of the features. 47 | 48 | Upcoming Features 49 | ================= 50 | 51 | - Converts benchmark parameters to other parametrizations. 52 | - Calculates the transfer functions of the open loop system. 53 | 54 | Example Code 55 | ============ 56 | 57 | :: 58 | 59 | >>> import bicycleparameters as bp 60 | >>> import numpy as np 61 | >>> rigid = bp.Bicycle('Rigid') 62 | >>> par = rigid.parameters['Benchmark'] 63 | >>> rigid.plot_bicycle_geometry() 64 | >>> speeds = np.linspace(0., 10., num=100) 65 | >>> rigid.plot_eigenvalues_vs_speed(speeds, show=True) 66 | 67 | .. _references: 68 | 69 | References 70 | ========== 71 | 72 | The methods associated with this software were built upon these previous works, 73 | among others. 74 | 75 | .. [Carvallo1899] Carvallo, E. (1899). Théorie du mouvement du monocycle et de 76 | la bicyclette. Gauthier- Villars. 77 | 78 | .. [Whipple1899] Whipple, F. J. W. (1899). The stability of the motion of a 79 | bicycle. Quarterly Journal of Pure and Applied Mathematics, 30, 312–348. 80 | 81 | .. [Roland1971] Roland J R ., R. D., and Massing , D. E. A digital computer simulation of 82 | bicycle dynamics. Calspan Report YA-3063-K-1, Cornell Aeronautical 83 | Laboratory, Inc., Buffalo, NY, 14221, Jun 1971. Prepared for Schwinn Bicycle 84 | Company, Chicago, IL 60639. 85 | 86 | .. [Meijaard2007] Meijaard, J. P.; Papadopoulos, J. M.; Ruina, A. & Schwab, A. 87 | L. Linearized dynamics equations for the balance and steer of a bicycle: A 88 | benchmark and review Proceedings of the Royal Society A: Mathematical, Physical 89 | and Engineering Sciences, 2007, 463, 1955-1982 90 | 91 | .. [Kooijman2006] Kooijman, J. D. G. (2006). Experimental validation of a model for the motion 92 | of an uncontrolled bicycle. MSc thesis, Delft University of Technology. 93 | 94 | .. [Kooijman2008] Kooijman, J. D. G., Schwab, A. L., and Meijaard, J. P. (2008). Experimental 95 | validation of a model of an uncontrolled bicycle. Multibody System Dynamics, 96 | 19:115–132. 97 | 98 | .. [Moore2009] Moore, J. K., Kooijman, J. D. G., Hubbard, M., and Schwab, A. L. (2009). A 99 | Method for Estimating Physical Properties of a Combined Bicycle and Rider. 100 | In Proceedings of the ASME 2009 International Design Engineering Technical 101 | Conferences & Computers and Information in Engineering Conference, 102 | IDETC/CIE 2009, San Diego, CA, USA. ASME. 103 | 104 | .. [Moore2010] Moore, J. K., Hubbard, M., Peterson, D. L., Schwab, A. L., and Kooijman, J. 105 | D. G. (2010). An accurate method of measuring and comparing a bicycle's 106 | physical parameters. In Bicycle and Motorcycle Dynamics: Symposium on the 107 | Dynamics and Control of Single Track Vehicles, Delft, Netherlands. 108 | 109 | .. [Moore2012] Moore, J. K. (2012). Human Control of a Bicycle. University of 110 | California, Davis PhD Thesis. http://moorepants.github.io/dissertation 111 | 112 | .. [Dembia2014] Dembia C, Moore JK and Hubbard M. An object oriented 113 | implementation of the Yeadon human inertia model [v1; ref status: awaiting 114 | peer review, http://f1000r.es/4cr] F1000Research 2014, 3:223 (doi: 115 | 10.12688/f1000research.5292.1) 116 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. BicycleParameters documentation master file, created by 2 | sphinx-quickstart on Wed Jun 29 15:30:42 2011. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | ================================== 7 | BicycleParameters's Documentation! 8 | ================================== 9 | 10 | **BicycleParameters** is a Python program designed to produce and manipulate 11 | the basic parameters needed for bicycle dynamic models. 12 | 13 | .. list-table:: Example Bicycle Inertia Plot and Corresponding Eigenvalue Speed 14 | Plot 15 | 16 | * - .. image:: _images/sphx_glr_plot_benchmark_001.png 17 | - .. image:: _images/sphx_glr_plot_benchmark_002.png 18 | 19 | .. figure:: https://objects-us-east-1.dream.io/mechmotum/bicycleparameters-app.png 20 | :target: https://bicycle-dynamics.onrender.com/ 21 | 22 | `Bicycle Dynamics Analysis App `_ Powered by BicycleParameters 23 | 24 | Table of Contents 25 | ================= 26 | 27 | .. toctree:: 28 | :maxdepth: 2 29 | 30 | description.rst 31 | installation.rst 32 | data.rst 33 | examples.rst 34 | gallery/index.rst 35 | app.rst 36 | bicycleparameters.rst 37 | 38 | * :ref:`genindex` 39 | * :ref:`modindex` 40 | * :ref:`search` 41 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Installation 3 | ============ 4 | 5 | Dependencies 6 | ============ 7 | 8 | Required 9 | -------- 10 | 11 | - `DynamicistToolKit >= 0.5.3 `_ 12 | - `Matplotlib >= 3.5.1 `_ 13 | - `NumPy >= 1.21.5 `_ 14 | - `Python >= 3.8 `_ 15 | - `SciPy >= 1.8.0 `_ 16 | - `Uncertainties >= 3.1.5 `_ 17 | - `yeadon >= 1.3.0 `_ 18 | 19 | Optional 20 | -------- 21 | 22 | These are required to run the Dash web application: 23 | 24 | - `Dash >= 2.0 `_ 25 | - `dash-bootstrap-components `_ 26 | - `Pandas >= 1.3.5 `_ 27 | 28 | These are required to build the documentation: 29 | 30 | - `Sphinx >= 4.3.2 `_ 31 | - `Numpydoc >= 1.2 `_ 32 | - `sphinx-reredirects `_ 33 | - `Sphinx-Gallery `_ 34 | 35 | Installation 36 | ============ 37 | 38 | We recommend installing BicycleParameters with conda_ or pip_. 39 | 40 | .. _conda: https://docs.conda.io 41 | .. _pip: https://pip.pypa.io 42 | 43 | For conda:: 44 | 45 | $ conda install -c conda-forge bicycleparameters 46 | 47 | For pip:: 48 | 49 | $ pip install BicycleParameters 50 | 51 | The package can also be installed from the source code. The options for getting 52 | the source code are: 53 | 54 | 1. Clone the source code with Git: ``git clone 55 | git://github.com/moorepants/BicycleParameters.git`` 56 | 2. `Download the source from Github`__. 57 | 3. Download the source from pypi__. 58 | 59 | .. __: https://github.com/moorepants/BicycleParameters 60 | .. __: http://pypi.python.org/pypi/BicycleParameters 61 | 62 | Once you have the source code navigate to the directory and run:: 63 | 64 | >>> python setup.py install 65 | 66 | This will install the software into your system. You can check if it installs 67 | with:: 68 | 69 | $ python -c "import bicycleparameters" 70 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | if NOT "%PAPER%" == "" ( 11 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 12 | ) 13 | 14 | if "%1" == "" goto help 15 | 16 | if "%1" == "help" ( 17 | :help 18 | echo.Please use `make ^` where ^ is one of 19 | echo. html to make standalone HTML files 20 | echo. dirhtml to make HTML files named index.html in directories 21 | echo. singlehtml to make a single large HTML file 22 | echo. pickle to make pickle files 23 | echo. json to make JSON files 24 | echo. htmlhelp to make HTML files and a HTML help project 25 | echo. qthelp to make HTML files and a qthelp project 26 | echo. devhelp to make HTML files and a Devhelp project 27 | echo. epub to make an epub 28 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 29 | echo. text to make text files 30 | echo. man to make manual pages 31 | echo. changes to make an overview over all changed/added/deprecated items 32 | echo. linkcheck to check all external links for integrity 33 | echo. doctest to run all doctests embedded in the documentation if enabled 34 | goto end 35 | ) 36 | 37 | if "%1" == "clean" ( 38 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 39 | del /q /s %BUILDDIR%\* 40 | goto end 41 | ) 42 | 43 | if "%1" == "html" ( 44 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 45 | if errorlevel 1 exit /b 1 46 | echo. 47 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 48 | goto end 49 | ) 50 | 51 | if "%1" == "dirhtml" ( 52 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 53 | if errorlevel 1 exit /b 1 54 | echo. 55 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 56 | goto end 57 | ) 58 | 59 | if "%1" == "singlehtml" ( 60 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 61 | if errorlevel 1 exit /b 1 62 | echo. 63 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 64 | goto end 65 | ) 66 | 67 | if "%1" == "pickle" ( 68 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 69 | if errorlevel 1 exit /b 1 70 | echo. 71 | echo.Build finished; now you can process the pickle files. 72 | goto end 73 | ) 74 | 75 | if "%1" == "json" ( 76 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 77 | if errorlevel 1 exit /b 1 78 | echo. 79 | echo.Build finished; now you can process the JSON files. 80 | goto end 81 | ) 82 | 83 | if "%1" == "htmlhelp" ( 84 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 85 | if errorlevel 1 exit /b 1 86 | echo. 87 | echo.Build finished; now you can run HTML Help Workshop with the ^ 88 | .hhp project file in %BUILDDIR%/htmlhelp. 89 | goto end 90 | ) 91 | 92 | if "%1" == "qthelp" ( 93 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 94 | if errorlevel 1 exit /b 1 95 | echo. 96 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 97 | .qhcp project file in %BUILDDIR%/qthelp, like this: 98 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\BicycleParameters.qhcp 99 | echo.To view the help file: 100 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\BicycleParameters.ghc 101 | goto end 102 | ) 103 | 104 | if "%1" == "devhelp" ( 105 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 106 | if errorlevel 1 exit /b 1 107 | echo. 108 | echo.Build finished. 109 | goto end 110 | ) 111 | 112 | if "%1" == "epub" ( 113 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 114 | if errorlevel 1 exit /b 1 115 | echo. 116 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 117 | goto end 118 | ) 119 | 120 | if "%1" == "latex" ( 121 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 122 | if errorlevel 1 exit /b 1 123 | echo. 124 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 125 | goto end 126 | ) 127 | 128 | if "%1" == "text" ( 129 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 130 | if errorlevel 1 exit /b 1 131 | echo. 132 | echo.Build finished. The text files are in %BUILDDIR%/text. 133 | goto end 134 | ) 135 | 136 | if "%1" == "man" ( 137 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 138 | if errorlevel 1 exit /b 1 139 | echo. 140 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 141 | goto end 142 | ) 143 | 144 | if "%1" == "changes" ( 145 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 146 | if errorlevel 1 exit /b 1 147 | echo. 148 | echo.The overview file is in %BUILDDIR%/changes. 149 | goto end 150 | ) 151 | 152 | if "%1" == "linkcheck" ( 153 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 154 | if errorlevel 1 exit /b 1 155 | echo. 156 | echo.Link check complete; look for any errors in the above output ^ 157 | or in %BUILDDIR%/linkcheck/output.txt. 158 | goto end 159 | ) 160 | 161 | if "%1" == "doctest" ( 162 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 163 | if errorlevel 1 exit /b 1 164 | echo. 165 | echo.Testing of doctests in the sources finished, look at the ^ 166 | results in %BUILDDIR%/doctest/output.txt. 167 | goto end 168 | ) 169 | 170 | :end 171 | -------------------------------------------------------------------------------- /gallery/README.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | Example Usage 3 | ============= 4 | 5 | Getting Started 6 | =============== 7 | -------------------------------------------------------------------------------- /gallery/examples/README.rst: -------------------------------------------------------------------------------- 1 | Examples 2 | ======== 3 | -------------------------------------------------------------------------------- /gallery/examples/plot_balanceassistv1.py: -------------------------------------------------------------------------------- 1 | """ 2 | =========================================================== 3 | Balance Assist E-Bike with Roll Rate Feedback Steer Control 4 | =========================================================== 5 | 6 | This example shows how to work with a model that includes a feedback controller 7 | and how to use a simple derivative control with it. The TU Delft Bicycle Lab 8 | developed a bicycle with a steer motor that can be controlled based on sensor 9 | measurements from an inertial measurement unit mounted on the rear frame, a 10 | steer angle sensor, and a speed sensor. The bicycle is based on an e-bike model 11 | from Royal Dutch Gazelle: 12 | 13 | .. figure:: https://objects-us-east-1.dream.io/mechmotum/balance-assist-bicycle-400x400.jpg 14 | :align: center 15 | 16 | Gazelle Grenoble/Arroyo E-Bike modified with a steering motor. Battery in 17 | the downtube and electronics box on the rear rack. 18 | 19 | """ 20 | import numpy as np 21 | 22 | from bicycleparameters.main import Bicycle 23 | from bicycleparameters.io import remove_uncertainties 24 | from bicycleparameters.parameter_sets import Meijaard2007ParameterSet 25 | from bicycleparameters.models import Meijaard2007WithFeedbackModel 26 | 27 | # %% 28 | # Set Up a Model 29 | # ============== 30 | # 31 | # First, load the physical parameter measurements of the bicycle from a file 32 | # and create a 33 | # :class:`~bicycleparameters.parameter_sets.Meijaard2007ParameterSet`. 34 | 35 | data_dir = "../../data" 36 | 37 | bicycle = Bicycle("Balanceassistv1", pathToData=data_dir) 38 | par = remove_uncertainties(bicycle.parameters['Benchmark']) 39 | par['v'] = 1.0 40 | par_set = Meijaard2007ParameterSet(par, False) 41 | par_set 42 | 43 | # %% 44 | # The following plot depicts the geometry and inertial parameters with the 45 | # inertia of the rider included. 46 | par_set.plot_all() 47 | 48 | # %% 49 | # Create a :class:`~bicycleparameters.models.Meijaard2007WithFeedbackModel`. 50 | # The parameter set does not include the feedback gain parameters, but 51 | # :meth:`~bicycleparameters.parameter_sets.Meijaard2007WithFeedbackParameterSet.to_parameterization` 52 | # will be used to convert the parameter set into one with the gains. 53 | model = Meijaard2007WithFeedbackModel(par_set) 54 | model.parameter_set 55 | 56 | # %% 57 | # The model shows a small self-stable speed range. 58 | speeds = np.linspace(0.0, 10.0, num=501) 59 | ax = model.plot_eigenvalue_parts(v=speeds) 60 | ax.set_ylim((-10.0, 10.0)) 61 | 62 | # %% 63 | # Add a Rider 64 | # =========== 65 | # 66 | # If the data files for a rider are present in the data directory, you can add 67 | # a rider and the package Yeadon will be used to configure a rider to sit on 68 | # the bicycle. You can check if a rider is properly configured by plotting the 69 | # geometry which will now include a stick figure depiction of the rider. 70 | bicycle.add_rider('Jason', reCalc=True) 71 | bicycle.plot_bicycle_geometry(inertiaEllipse=False) 72 | 73 | # %% 74 | # The inertia representation now reflects the larger inertia of the rear frame 75 | # due to the rigid rider addition. 76 | par = remove_uncertainties(bicycle.parameters['Benchmark']) 77 | par['v'] = 1.0 78 | par_set = Meijaard2007ParameterSet(par, True) 79 | par_set.plot_all() 80 | 81 | # %% 82 | # The self-stable speed range begins at a higher speed and becomes wider. 83 | model = Meijaard2007WithFeedbackModel(par_set) 84 | ax = model.plot_eigenvalue_parts(v=speeds) 85 | ax.set_ylim((-10.0, 10.0)) 86 | 87 | # %% 88 | # Add Control 89 | # =========== 90 | # 91 | # It turns out that controlling the steer torque with a positive feedback on 92 | # roll angular rate, the bicycle can be stabilized over a large speed range. 93 | # For example, setting :math:`k_{T_\delta \dot{\phi}}=-50` gives this effect: 94 | ax = model.plot_eigenvalue_parts(v=speeds, kTdel_phid=-50.0) 95 | ax.set_ylim((-10.0, 10.0)) 96 | 97 | # %% 98 | # The eigenvectors at low speed show that the weave mode has a steer dominated 99 | # high frequency natural motion. This may not be so favorable. 100 | speed = 2.0 101 | ax = model.plot_eigenvectors(v=speed, kTdel_phid=-50.0) 102 | 103 | # %% 104 | # You can also gain schedule with respect to speed. A linear variation in the 105 | # roll rate gain can make the weave eigenfrequency have lower magnitude than 106 | # using simply a constant gain. 107 | vmin, vmin_idx = 1.5, np.argmin(np.abs(speeds - 1.5)) 108 | vmax, vmax_idx = 4.7, np.argmin(np.abs(speeds - 4.7)) 109 | kappa = 10.0 110 | kphidots = -kappa*(vmax - speeds) 111 | kphidots[:vmin_idx] = -kappa*(vmax - vmin)/vmin*speeds[:vmin_idx] 112 | kphidots[vmax_idx:] = 0.0 113 | model.plot_gains(v=speeds, kTdel_phid=kphidots) 114 | 115 | # %% 116 | # Using the gain scheduling gives this effect to the dynamics: 117 | ax = model.plot_eigenvalue_parts(v=speeds, kTdel_phid=kphidots) 118 | ax.set_ylim((-10.0, 10.0)) 119 | 120 | # %% 121 | kphidot = kphidots[np.argmin(np.abs(speeds - speed))] 122 | ax = model.plot_eigenvectors(v=speed, kTdel_phid=kphidot) 123 | 124 | # %% 125 | # We can then simulate the system at a specific low speed and see the effect 126 | # control has. First, without control: 127 | times = np.linspace(0.0, 2.0, num=201) 128 | x0 = np.array([0.0, 0.0, 0.5, 0.0]) 129 | ax = model.plot_simulation(times, x0, v=speed) 130 | 131 | # %% 132 | # And with control: 133 | times = np.linspace(0.0, 5.0, num=501) 134 | ax = model.plot_simulation(times, x0, v=speed, kTdel_phid=kphidot) 135 | -------------------------------------------------------------------------------- /gallery/examples/plot_benchmark.py: -------------------------------------------------------------------------------- 1 | r""" 2 | ================================ 3 | Benchmark Carvallo-Whipple Model 4 | ================================ 5 | 6 | Meijaard et al. presents a benchmark minimal linear Carvallo-Whipple bicycle 7 | model ([Meijaard2007]_, [Carvallo1899]_, [Whipple1899]_) with 27 unique 8 | constant parameters and two coordinates: roll angle :math:`\phi` and steer 9 | angle :math:`\delta`. 10 | 11 | """ 12 | import numpy as np 13 | 14 | from bicycleparameters import Bicycle 15 | from bicycleparameters.io import remove_uncertainties 16 | from bicycleparameters.parameter_sets import Meijaard2007ParameterSet 17 | from bicycleparameters.models import Meijaard2007Model 18 | 19 | data_dir = "../../data" 20 | 21 | # %% 22 | # Benchmark Parameter Values 23 | # ========================== 24 | # 25 | # First, create a :class:`~bicycleparameters.main.Bicycle` object from the 26 | # parameter file in the data directory. 27 | bicycle = Bicycle("Benchmark", pathToData=data_dir) 28 | 29 | # %% 30 | # Strip the uncertainties from the parameters and add a speed parameter 31 | # :math:`v`, then create a 32 | # :class:`~bicycleparameters.parameter_sets.Meijaard2007ParameterSet` set from 33 | # the parameter values. 34 | par = remove_uncertainties(bicycle.parameters['Benchmark']) 35 | par['v'] = 4.6 36 | par_set = Meijaard2007ParameterSet(par, True) 37 | par_set 38 | 39 | # %% 40 | # The bicycle geometry and representations of the inertia of the four rigid 41 | # bodies (B: rear frame, F: front wheel, H: front frame, R: rear wheel) can be 42 | # visualized with the parameter set plot methods. 43 | ax = par_set.plot_all() 44 | 45 | # %% 46 | # Linear Carvallo-Whipple Model 47 | # ============================= 48 | # 49 | # Create a :class:`~bicycleparameters.models.Meijaard2007Model` that represents 50 | # linear Carvallo-Whipple model presented in [Meijaard2007]_ and populate it 51 | # with the parameter values in the parameter set. 52 | model = Meijaard2007Model(par_set) 53 | 54 | # %% 55 | # This model can be written in this form: 56 | # 57 | # .. math:: 58 | # 59 | # \mathbf{M}\ddot{\vec{q}} + 60 | # v\mathbf{C}_1\dot{\vec{q}} + 61 | # \left[ g \mathbf{K}_0 + v^2 \mathbf{K}_2 \right] \vec{q} = 62 | # \vec{F} 63 | # 64 | # where the essential coordinates are the roll angle :math:`\phi` and steer 65 | # angle :math:`\delta`, respectively: 66 | # 67 | # .. math:: 68 | # 69 | # \vec{q} = [\phi \quad \delta]^T 70 | # 71 | # and the forcing terms are: 72 | # 73 | # .. math:: 74 | # 75 | # \vec{F} = [T_\phi \quad T_\delta]^T 76 | # 77 | # The model can calculate the mass, damping, and stiffness coefficient matrices, 78 | # which should match the paper's results when using the matching parameter 79 | # values: 80 | M, C1, K0, K2 = model.form_reduced_canonical_matrices() 81 | M 82 | 83 | # %% 84 | C1 85 | 86 | # %% 87 | K0 88 | 89 | # %% 90 | K2 91 | 92 | # %% 93 | # The root locus can be plotted as a function of any model parameter. This plot 94 | # is most often used to show how stability is dependent on the speed 95 | # parameter.The blue lines indicate the weave eigenmode, the green the capsize 96 | # eigenmode, and the orange the caster eigenmode. Vertical dashed lines 97 | # indicate speeds that are examined further below. 98 | v = np.linspace(0.0, 10.0, num=401) 99 | ax = model.plot_eigenvalue_parts(v=v, 100 | colors=['C0', 'C0', 'C1', 'C2'], 101 | hide_zeros=True) 102 | for vi in [0.0, 2.0, 5.0, 8.0]: 103 | ax.axvline(vi, color='k', linestyle='--') 104 | ax.set_ylim((-10.0, 10.0)) 105 | 106 | # %% 107 | # Modes of Motion 108 | # =============== 109 | # 110 | # When populated with realistic parameter values the linear Carvallo-Whipple 111 | # model exhibits four characteristic eigenmodes that transition into three 112 | # eigenmodes when two roots bifurcate into an imaginary pair. 113 | # 114 | # Low Speed, Unstable Inverted Pendulum 115 | # ------------------------------------- 116 | # 117 | # Before the bifurcation point into the weave mode, there are four real 118 | # eigenvalues that describe the motion. 119 | ax = model.plot_eigenvectors(v=0.0) 120 | 121 | # %% 122 | # The unstable eigenmodes dominate the motion and this results in the steer 123 | # angle growing rapidly and the roll angle following suite, but slower. 124 | times = np.linspace(0.0, 1.0) 125 | ax = model.plot_mode_simulations(times, v=0.0) 126 | 127 | # %% 128 | # The total motion shows that the bicycle falls over, as expected. 129 | ax = model.plot_simulation(times, [0.01, 0.0, 0.0, 0.0], v=0.0) 130 | 131 | # %% 132 | # Low Speed, Unstable Weave 133 | # ------------------------- 134 | # 135 | # Moving up in speed past the bifurcation, the bicycle has an unstable 136 | # oscillatory eigenmode that is called "weave". The steer angle has about twice 137 | # the magnitude as the roll angle and they both grow together with close to 90 138 | # degrees phase. The other two stable real valued eigenmodes are called 139 | # "capsize" and "caster", with capsize being primarily a roll motion and caster 140 | # a steer motion. 141 | ax = model.plot_eigenvectors(v=2.0) 142 | # %% 143 | times = np.linspace(0.0, 1.0) 144 | ax = model.plot_mode_simulations(times, v=2.0) 145 | 146 | # %% 147 | # Stable Eigenmodes 148 | # ----------------- 149 | # 150 | # Increasing speed further shows that the weave eigenmode becomes stable, 151 | # making all eigenmodes stable, and thus the total motion is stable. The speed 152 | # regime where this is true is called the "self-stable" speed range given that 153 | # stability arises with no active control. The weave steer-roll phase is almost 154 | # aligned and the caster time constant is becoming very fast. 155 | ax = model.plot_eigenvectors(v=5.0) 156 | # %% 157 | times = np.linspace(0.0, 5.0, num=501) 158 | ax = model.plot_mode_simulations(times, v=5.0) 159 | 160 | # %% 161 | # High Speed, Unstable Capsize 162 | # ---------------------------- 163 | # 164 | # If the speed is increased further, the system becomes unstable due to the 165 | # capsize mode. The weave steer and roll are mostly aligned in phase but the 166 | # roll dominated capsize shows that the bicycle slowly falls over. 167 | ax = model.plot_eigenvectors(v=8.0) 168 | 169 | # %% 170 | ax = model.plot_mode_simulations(times, v=8.0) 171 | 172 | # %% 173 | # Total Motion Simulation 174 | # ----------------------- 175 | # 176 | # The following plot shows the total motion with the same initial conditions 177 | # used in [Meijaard2007]_ within the stable speed range at 4.6 m/s. 178 | x0 = [0.0, 0.0, 0.5, 0.0] 179 | ax = model.plot_simulation(times, x0) 180 | 181 | # %% 182 | # A constant steer torque puts the model into a turn. 183 | times = np.linspace(0.0, 10.0, num=1001) 184 | ax = model.plot_simulation(times, x0, 185 | input_func=lambda t, x: [0.0, 1.0]) 186 | -------------------------------------------------------------------------------- /gallery/examples/plot_lqr.py: -------------------------------------------------------------------------------- 1 | """ 2 | ==================================== 3 | Full State Feedback Control With LQR 4 | ==================================== 5 | 6 | We have a :py:class:`~bicycleparameters.models.Meijaard2007WithFeedbackModel` 7 | that applies full state feedback to the 8 | :py:class:`~bicycleparameters.models.Meijaard2007Model` using eight feedback 9 | gains. These feedback gains can be chosen with a variety of methods to 10 | stabilize the system. This example shows how to apply LQR control. 11 | """ 12 | import numpy as np 13 | from scipy.linalg import solve_continuous_are 14 | 15 | from bicycleparameters.models import Meijaard2007WithFeedbackModel 16 | from bicycleparameters.parameter_sets import Meijaard2007ParameterSet 17 | 18 | # %% 19 | # Create the model and plot the eigenvalues versus speed. This should be 20 | # identical to the model without feedback given that the gains are all set to 21 | # zero. 22 | par = { 23 | 'IBxx': 11.3557360401, 24 | 'IBxz': -1.96756380745, 25 | 'IByy': 12.2177848012, 26 | 'IBzz': 3.12354397008, 27 | 'IFxx': 0.0904106601579, 28 | 'IFyy': 0.149389340425, 29 | 'IHxx': 0.253379594731, 30 | 'IHxz': -0.0720452391817, 31 | 'IHyy': 0.246138810935, 32 | 'IHzz': 0.0955770796289, 33 | 'IRxx': 0.0883819364527, 34 | 'IRyy': 0.152467620286, 35 | 'c': 0.0685808540382, 36 | 'g': 9.81, 37 | 'lam': 0.399680398707, 38 | 'mB': 81.86, 39 | 'mF': 2.02, 40 | 'mH': 3.22, 41 | 'mR': 3.11, 42 | 'rF': 0.34352982332, 43 | 'rR': 0.340958858855, 44 | 'v': 1.0, 45 | 'w': 1.121, 46 | 'xB': 0.289099434117, 47 | 'xH': 0.866949640247, 48 | 'zB': -1.04029228321, 49 | 'zH': -0.748236400835, 50 | } 51 | par_set = Meijaard2007ParameterSet(par, True) 52 | model = Meijaard2007WithFeedbackModel(par_set) 53 | 54 | speeds = np.linspace(0.0, 10.0, num=1001) 55 | ax = model.plot_eigenvalue_parts(v=speeds, 56 | colors=['C0', 'C0', 'C1', 'C2'], 57 | hide_zeros=True) 58 | ax.set_ylim((-10.0, 10.0)) 59 | 60 | # %% 61 | # It is well known that a simple proportional positive feedback of roll angular 62 | # rate to control steer torque can stabilize a bicycle at lower speeds. So set 63 | # the :math:`k_{T_{\delta}\dot{\phi}}` to a larger negative value. 64 | 65 | ax = model.plot_eigenvalue_parts(v=speeds, 66 | kTdel_phid=-50.0, 67 | colors=['C0', 'C0', 'C1', 'C1'], 68 | hide_zeros=True) 69 | ax.set_ylim((-10.0, 10.0)) 70 | 71 | # %% 72 | # The stable speed range is significantly increased, but the weave mode 73 | # eigenfrequency is increased as a consequence. 74 | # 75 | # This can also be used to model adding springy training wheels by including a 76 | # negative feedback of roll angle to roll torque with damping. 77 | ax = model.plot_eigenvalue_parts(v=speeds, 78 | kTphi_phi=3000.0, 79 | kTphi_phid=600.0, 80 | hide_zeros=True) 81 | ax.set_ylim((-10.0, 10.0)) 82 | 83 | # %% 84 | times = np.linspace(0.0, 5.0, num=1001) 85 | model.plot_mode_simulations(times, v=2.0, kTphi_phi=3000.0, 86 | kTphi_phid=600.0) 87 | 88 | # %% 89 | # A more general method to control the bicycle is to create gain scheduling 90 | # with continuous Ricatti equation. If the system is controllable, this 91 | # guarantees a respect to speed using LQR optimal control. Assuming we only 92 | # control steer so we will only apply control at speeds greater than 0.8 m/s. 93 | # stable closed loop system. There is an uncontrollable speed just below 0.8 94 | # m/s, torque via feedback of all four states, the 4 gains can be found by 95 | # solving the 96 | As, Bs = model.form_state_space_matrices(v=speeds) 97 | Ks = np.zeros((len(speeds), 2, 4)) 98 | Q = np.eye(4) 99 | R = np.eye(1) 100 | 101 | for i, (vi, Ai, Bi) in enumerate(zip(speeds, As, Bs)): 102 | if vi >= 0.8: 103 | S = solve_continuous_are(Ai, Bi[:, 1:2], Q, R) 104 | Ks[i, 1, :] = (np.linalg.inv(R) @ Bi[:, 1:2].T @ S).squeeze() 105 | 106 | ax = model.plot_gains(v=speeds, 107 | kTphi_phi=Ks[:, 0, 0], 108 | kTphi_del=Ks[:, 0, 1], 109 | kTphi_phid=Ks[:, 0, 2], 110 | kTphi_deld=Ks[:, 0, 3], 111 | kTdel_phi=Ks[:, 1, 0], 112 | kTdel_del=Ks[:, 1, 1], 113 | kTdel_phid=Ks[:, 1, 2], 114 | kTdel_deld=Ks[:, 1, 3]) 115 | 116 | # %% 117 | # Now use the computed gains to check for closed loop stability: 118 | ax = model.plot_eigenvalue_parts(v=speeds, 119 | kTphi_phi=Ks[:, 0, 0], 120 | kTphi_del=Ks[:, 0, 1], 121 | kTphi_phid=Ks[:, 0, 2], 122 | kTphi_deld=Ks[:, 0, 3], 123 | kTdel_phi=Ks[:, 1, 0], 124 | kTdel_del=Ks[:, 1, 1], 125 | kTdel_phid=Ks[:, 1, 2], 126 | kTdel_deld=Ks[:, 1, 3]) 127 | ax.set_ylim((-10.0, 10.0)) 128 | 129 | # %% 130 | # This is stable over a wide speed range and retains the weave eigenfrequency 131 | # of the uncontrolled system. 132 | x0 = np.deg2rad([5.0, -3.0, 0.0, 0.0]) 133 | 134 | 135 | def input_func(t, x): 136 | if (t > 2.5 and t < 2.8): 137 | return np.array([50.0, 0.0]) 138 | else: 139 | return np.zeros(2) 140 | 141 | 142 | times = np.linspace(0.0, 5.0, num=1001) 143 | 144 | idx = 90 145 | ax = model.plot_simulation( 146 | times, 147 | x0, 148 | input_func=input_func, 149 | v=speeds[idx], 150 | kTphi_phi=Ks[idx, 0, 0], 151 | kTphi_del=Ks[idx, 0, 1], 152 | kTphi_phid=Ks[idx, 0, 2], 153 | kTphi_deld=Ks[idx, 0, 3], 154 | kTdel_phi=Ks[idx, 1, 0], 155 | kTdel_del=Ks[idx, 1, 1], 156 | kTdel_phid=Ks[idx, 1, 2], 157 | kTdel_deld=Ks[idx, 1, 3], 158 | ) 159 | ax[0].set_title('$v$ = {} m/s'.format(speeds[idx])) 160 | -------------------------------------------------------------------------------- /gallery/examples/plot_mooreriderlean2012.py: -------------------------------------------------------------------------------- 1 | """ 2 | =================== 3 | Leaning Rider Model 4 | =================== 5 | 6 | The Carvallo-Whipple bicycle model assumes that the rider is rigidly fixed to 7 | the rear frame of the bicycle. Here the model is extended to include a rigid 8 | body representing the rider's upper body (torso, arms, head) which can lean 9 | relative to the rear frame through a single additional degree of freedom. The 10 | model is defined in [Moore2012]_ chapter "Extensions of the Whipple Model", 11 | section `Leaning rider extension 12 | `_. 13 | 14 | """ 15 | import numpy as np 16 | import matplotlib.pyplot as plt 17 | 18 | from bicycleparameters.parameter_dicts import mooreriderlean2012_browser_jason 19 | from bicycleparameters.parameter_sets import MooreRiderLean2012ParameterSet 20 | from bicycleparameters.models import MooreRiderLean2012Model 21 | 22 | np.set_printoptions(precision=3, suppress=True) 23 | 24 | # %% 25 | # Load Parameters 26 | # =============== 27 | # 28 | # These parameters include the inertia of the rider's lower body rigidly 29 | # affixed to the bicycle's rear frame :math:`C` and the inertia of the rider's 30 | # upper body is associated with the inverted compound pendulum :math:`G` that 31 | # leans relative to the rear frame of the bicycle :math:`C` through angle 32 | # :math:`q_9` and driven by torque :math:`T_9`. 33 | par_set = MooreRiderLean2012ParameterSet(mooreriderlean2012_browser_jason) 34 | par_set 35 | 36 | # %% 37 | # Construct Model and Inspect State Space 38 | # ======================================= 39 | model = MooreRiderLean2012Model(par_set) 40 | A, B = model.form_state_space_matrices() 41 | 42 | # %% 43 | model.state_vars 44 | 45 | # %% 46 | A 47 | 48 | # %% 49 | model.input_vars 50 | 51 | # %% 52 | B 53 | 54 | # %% 55 | # Eigenvalues and Eigenvectors 56 | # ============================ 57 | # The state space model is not reduced to the minimal dynamical set, i.e. 58 | # ignorable coordinates are present, so there are zero eigenvalues associated 59 | # with the rows :math:`q_1,q_2,q_3,q_6,q_8,u_6` being present. 60 | evals, evecs = model.calc_eigen() 61 | evals 62 | 63 | # %% 64 | # The eigenvalue parts plotted against speed :math:`v` show that the model is 65 | # always unstable due to the inverted pendulum eigenmode of the upper body. But 66 | # the classic weave, capsize, and caster modes are visible and look similar to 67 | # the rigid rider model. 68 | vs = np.linspace(0.0, 10.0, num=401) 69 | ax = model.plot_eigenvalue_parts(hide_zeros=True, sort_modes=False, v=vs) 70 | 71 | # %% 72 | # If the stiffness of the rider lean joint :math:`k_9` is increased, the 73 | # dynamics should approach that of the rigid rider model and the self-stability 74 | # can be brought back. Zoom in to see the where the model becomes stable. 75 | k9s = np.linspace(0.0, 300.0, num=301) 76 | ax = model.plot_eigenvalue_parts(hide_zeros=True, sort_modes=False, v=5.5, 77 | k9=k9s, c9=50.0) 78 | ax.set_ylim((-5.0, 5.0)) 79 | 80 | # %% 81 | # Selecting values for the passive stiffness and damping at the rider upper 82 | # body joint gives dynamics with a small stable speed range. 83 | ax = model.plot_eigenvalue_parts(hide_zeros=True, sort_modes=False, v=vs, 84 | k9=128.0, c9=50.0) 85 | 86 | # %% 87 | # Modes of Motion 88 | # =============== 89 | # 90 | # When populated with realistic parameter values the linear Carvallo-Whipple 91 | # model exhibits four characteristic eigenmodes that transition into three 92 | # eigenmodes when two roots bifurcate into an imaginary pair. The rider lean 93 | # degree of freedom adds two real modes at low speed and an additional 94 | # oscillatory mode at high speed. 95 | # 96 | # Low Speed, Unstable Inverted Pendulum 97 | # ------------------------------------- 98 | ax = model.plot_eigenvectors(hide_zeros=True, v=0.0, k9=128.0, c9=50.0) 99 | 100 | # %% 101 | times = np.linspace(0.0, 1.0) 102 | ax = model.plot_mode_simulations(times, hide_zeros=True, v=0.0, k9=128.0, 103 | c9=50.0) 104 | 105 | # %% 106 | # The total motion shows that the bicycle falls over. 107 | x0 = np.zeros(12) 108 | x0[3] = np.deg2rad(1.0) # q4 109 | ax = model.plot_simulation(times, x0, v=0.0, k9=128.0, c9=50.0) 110 | 111 | # %% 112 | # Low Speed, Unstable Weave 113 | # ------------------------- 114 | ax = model.plot_eigenvectors(hide_zeros=True, v=2.0, k9=128.0, c9=50.0) 115 | 116 | # %% 117 | times = np.linspace(0.0, 1.0) 118 | ax = model.plot_mode_simulations(times, hide_zeros=True, v=2.0, k9=128.0, 119 | c9=50.0) 120 | # %% 121 | # Stable Eigenmodes 122 | # ----------------- 123 | ax = model.plot_eigenvectors(hide_zeros=True, v=5.5, k9=128.0, c9=50.0) 124 | 125 | # %% 126 | times = np.linspace(0.0, 5.0, num=501) 127 | ax = model.plot_mode_simulations(times, hide_zeros=True, v=5.5, k9=128.0, 128 | c9=50.0) 129 | 130 | # %% 131 | # High Speed, Unstable Capsize 132 | # ---------------------------- 133 | ax = model.plot_eigenvectors(hide_zeros=True, v=8.0, k9=128.0, c9=50.0) 134 | 135 | # %% 136 | ax = model.plot_mode_simulations(times, hide_zeros=True, v=8.0, k9=128.0, 137 | c9=50.0) 138 | # %% 139 | # Total Motion Simulation 140 | # ----------------------- 141 | # 142 | # The following plot shows the total motion with an initially perturbed roll 143 | # rate at 5.5 m/s. 144 | x0 = np.zeros(12) 145 | x0[8] = 0.5 # u4 146 | ax = model.plot_simulation(times, x0, v=5.5, k9=128.0, c9=50.0) 147 | 148 | # %% 149 | # A constant steer torque puts the model into a turn, showing the step 150 | # response. 151 | times = np.linspace(0.0, 5.0, num=101) 152 | x0 = np.zeros(12) 153 | res, inputs = model.simulate(times, x0, 154 | input_func=lambda t, x: [0.0, 0.2, 0.0], 155 | v=5.5, k9=128.0, c9=50.0) 156 | fig, ax = plt.subplots() 157 | ax.plot(res[:, 0], res[:, 1]) 158 | ax.set_xlabel('$q_1$ [m]') 159 | ax.set_ylabel('$q_2$ [m]') 160 | ax.set_aspect('equal') 161 | ax.grid() 162 | 163 | # %% 164 | ax = model.plot_simulation(times, x0, 165 | input_func=lambda t, x: [0.0, 0.2, 0.0], 166 | v=5.5, k9=128.0, c9=50.0) 167 | -------------------------------------------------------------------------------- /gallery/plot_models.py: -------------------------------------------------------------------------------- 1 | """ 2 | Using Models 3 | ============ 4 | 5 | Parameter sets can be associated with a model and the model can be used to 6 | compute and visualize properties of the model's dynamics. 7 | """ 8 | import numpy as np 9 | from bicycleparameters.parameter_dicts import meijaard2007_browser_jason 10 | from bicycleparameters.parameter_sets import Meijaard2007ParameterSet 11 | from bicycleparameters.models import Meijaard2007Model 12 | 13 | np.set_printoptions(precision=3, suppress=True) 14 | 15 | # %% 16 | # Start with a parameter and construct a model with it: 17 | par_set = Meijaard2007ParameterSet(meijaard2007_browser_jason, True) 18 | model = Meijaard2007Model(par_set) 19 | 20 | # %% 21 | # Model Attributes 22 | # ---------------- 23 | # Models have a set of ordered state variables: 24 | model.state_vars 25 | 26 | # %% 27 | model.state_units 28 | 29 | # %% 30 | model.state_vars_latex 31 | 32 | # %% 33 | # Models have a set of ordered input variables: 34 | model.input_vars 35 | 36 | # %% 37 | model.input_units 38 | 39 | # %% 40 | model.input_vars_latex 41 | 42 | # %% 43 | # State Space 44 | # ----------- 45 | # All linear models have a method that generates the state and input matrices. 46 | # The rows and columns match the order of the state and input variables. 47 | A, B = model.form_state_space_matrices() 48 | A 49 | 50 | # %% 51 | B 52 | 53 | # %% 54 | # Most all methods on models accept override values for the parameters. So if 55 | # you want the state and input matrices with :math:`v=14,g=5.1` and :math:`w=2` 56 | # pass them in as keyword arguments: 57 | A, B = model.form_state_space_matrices(v=14.0, g=5.1, w=2.0) 58 | A 59 | 60 | # %% 61 | B 62 | 63 | # %% 64 | # Eigenmodes 65 | # ---------- 66 | # All linear models can produce its eigenvalues and eigenvectors: 67 | evals, evecs = model.calc_eigen() 68 | evals 69 | 70 | # %% 71 | evecs 72 | 73 | # %% 74 | # Parameters can be overridden as before, but the following line shows how you 75 | # can pass in an iterable of values for any parameter override and get back an 76 | # iterable of eigenvalues: 77 | evals, evecs = model.calc_eigen(v=[2.0, 5.0]) 78 | evals 79 | 80 | # %% 81 | # The root locus with respect to any parameter, for example here speed ``v``, 82 | # can be plotted, which uses the iterable of eigenvalues shown above: 83 | speeds = np.linspace(-10.0, 10.0, num=200) 84 | _ = model.plot_eigenvalue_parts(v=speeds) 85 | 86 | # %% 87 | # There are several common customization options available for this plot: 88 | speeds = np.linspace(0.0, 10.0, num=100) 89 | ax = model.plot_eigenvalue_parts(v=speeds, 90 | colors=['C0', 'C0', 'C1', 'C2'], 91 | show_stable_regions=False, 92 | hide_zeros=True) 93 | ax.set_ylim((-10.0, 10.0)) 94 | _ = ax.legend(['Weave Im', None, None, None, 95 | 'Weave Re', None, 'Caster', 'Capsize'], ncol=4) 96 | 97 | # %% 98 | # You can choose any parameter in the dictionary to generate the root locus and 99 | # also override other parameters. 100 | wheelbases = np.linspace(0.2, 5.0, num=50) 101 | _ = model.plot_eigenvalue_parts(v=6.0, w=wheelbases) 102 | 103 | # %% 104 | # It is also possible to pass iterables for multiple parameters as long as the 105 | # length is the same for all. Only the scale for the first will be shown. 106 | trails = np.linspace(-0.2, 0.2, num=50) 107 | wheelbases = np.linspace(0.2, 5.0, num=50) 108 | _ = model.plot_eigenvalue_parts(c=trails, w=wheelbases) 109 | 110 | # %% 111 | # The eigenvector components can be created for each mode and for a series of 112 | # parameter values: 113 | _ = model.plot_eigenvectors(v=[1.0, 3.0, 5.0, 7.0]) 114 | 115 | # %% 116 | # The eigenmodes can be simulated for specific parameter values: 117 | times = np.linspace(0.0, 5.0, num=100) 118 | _ = model.plot_mode_simulations(times, v=6.0) 119 | 120 | # %% 121 | # Simulation 122 | # ---------- 123 | # A general simulation from initial conditions can also be run: 124 | x0 = np.deg2rad([5.0, -3.0, 0.0, 0.0]) 125 | _ = model.plot_simulation(times, x0, v=6.0) 126 | 127 | # %% 128 | # Inputs can be applied in the simulation, for example a simple positive 129 | # feedback derivative controller on roll shows that the low speed bicycle can 130 | # be stabilized: 131 | x0 = np.deg2rad([5.0, -3.0, 0.0, 0.0]) 132 | _ = model.plot_simulation(times, x0, 133 | input_func=lambda t, x: np.array([0.0, 50.0*x[2]]), 134 | v=2.0) 135 | -------------------------------------------------------------------------------- /gallery/plot_parameter_set.py: -------------------------------------------------------------------------------- 1 | """ 2 | Using Parameter Sets 3 | ==================== 4 | 5 | Parameter sets represent a set of constants associated with a multibody 6 | dynamics model. These constants have a name and an associated floating point 7 | value. This mapping from name to value is stored in a dictionary and then 8 | passed to a :py:class:`~bicycleparameters.parameter_sets.ParameterSet` on 9 | creation. The docstring of the parameter set shows what values must be defined 10 | in the dictionary. This example will make use of the parameters associated with 11 | the model defined in [Meijaard2007]_. 12 | """ 13 | from bicycleparameters import parameter_sets 14 | from bicycleparameters.parameter_sets import Meijaard2007ParameterSet 15 | 16 | print(help(Meijaard2007ParameterSet)) 17 | 18 | # %% 19 | # Below are a dictionary with parameters for the linear Carvallo-Whipple model 20 | # with some realistic initial values. 21 | par = { 22 | 'IBxx': 11.3557360401, 23 | 'IBxz': -1.96756380745, 24 | 'IByy': 12.2177848012, 25 | 'IBzz': 3.12354397008, 26 | 'IFxx': 0.0904106601579, 27 | 'IFyy': 0.149389340425, 28 | 'IHxx': 0.253379594731, 29 | 'IHxz': -0.0720452391817, 30 | 'IHyy': 0.246138810935, 31 | 'IHzz': 0.0955770796289, 32 | 'IRxx': 0.0883819364527, 33 | 'IRyy': 0.152467620286, 34 | 'c': 0.0685808540382, 35 | 'g': 9.81, 36 | 'lam': 0.399680398707, 37 | 'mB': 81.86, 38 | 'mF': 2.02, 39 | 'mH': 3.22, 40 | 'mR': 3.11, 41 | 'rF': 0.34352982332, 42 | 'rR': 0.340958858855, 43 | 'v': 1.0, 44 | 'w': 1.121, 45 | 'xB': 0.289099434117, 46 | 'xH': 0.866949640247, 47 | 'zB': -1.04029228321, 48 | 'zH': -0.748236400835, 49 | } 50 | 51 | # %% 52 | # The associated parameter set can then be created with the dictionary: 53 | par_set = Meijaard2007ParameterSet(par, True) 54 | par_set 55 | 56 | # %% 57 | # The dictionary of parameters is stored in the ``parameters`` attribute: 58 | par_set.parameters 59 | 60 | # %% 61 | # The module :mod:`parameter_sets` includes different parameter sets and it may 62 | # be possible to convert from one parameter set to another if the conversion is 63 | # available. 64 | print(parameter_sets.__all__) 65 | 66 | # %% 67 | # For example, this parameter set can be converted to the one for the linear 68 | # Carvallo-Whipple model in [Moore2012]_: 69 | par_set_moore = par_set.to_parameterization('Moore2012') 70 | par_set_moore 71 | 72 | # %% 73 | # There is a unique label for each body embedded in the parameter variables, 74 | # e.g. :math:`B` in :math:`I_{Bxx}`, and these are used in some methods below. 75 | par_set.body_labels 76 | 77 | # %% 78 | # Many methods take one or more body labels as arguments. For example, the 79 | # location of the combined mass center of the rear and front wheels can be 80 | # found with: 81 | par_set.mass_center_of('R', 'F') 82 | 83 | # %% 84 | # Or for all of the rigid bodies: 85 | par_set.mass_center_of('B', 'H', 'F', 'R') 86 | 87 | # %% 88 | # The inertia tensor of a single body can be shown with: 89 | par_set.form_inertia_tensor('B') 90 | 91 | # %% 92 | # Once the parameter set is available there are various methods that help you 93 | # calculate and visualize the properties of this parameter set. This set 94 | # describes the geometry, mass, and inertia of a bicycle. You can plot the 95 | # geometry like so: 96 | _ = par_set.plot_geometry() 97 | 98 | # %% 99 | # You can then add symbols representing the mass centers of the four bodies 100 | # like so: 101 | ax = par_set.plot_geometry() 102 | _ = par_set.plot_mass_centers(ax=ax) 103 | 104 | # %% 105 | # You can then add symbols representing the radii of gyration of each rigid 106 | # body like so: 107 | ax = par_set.plot_geometry() 108 | _ = par_set.plot_principal_radii_of_gyration(ax=ax) 109 | 110 | # %% 111 | # And finally, you can then add symbols representing uniformly dense ellipsoids 112 | # with the same mass and inertia of each rigid body like so: 113 | ax = par_set.plot_geometry() 114 | _ = par_set.plot_principal_inertia_ellipsoids(ax=ax) 115 | 116 | # %% 117 | # All of the plot features can be shown with a single function call: 118 | _ = par_set.plot_all() 119 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # build dependencies for running the app on heroku or render 2 | DynamicistToolKit 3 | dash>=2 4 | dash-bootstrap-components 5 | gunicorn 6 | numpy 7 | pandas 8 | scipy 9 | uncertainties 10 | yeadon 11 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from setuptools import setup, find_packages 4 | 5 | exec(open('bicycleparameters/version.py').read()) 6 | 7 | setup( 8 | name='BicycleParameters', 9 | version=__version__, 10 | author='Jason K. Moore', 11 | author_email='moorepants@gmail.com', 12 | packages=find_packages(), 13 | url='https://bicycleparameters.readthedocs.io', 14 | license='LICENSE.txt', 15 | description='Generates and manipulates the physical parameters of a bicycle.', 16 | long_description=open('README.rst').read(), 17 | project_urls={ 18 | 'Documentation': 'http://bicycleparameters.readthedocs.io', 19 | 'Issue Tracker': 'https://github.com/moorepants/BicycleParameters/issues', 20 | 'Source Code': 'https://github.com/moorepants/BicycleParameters', 21 | 'Web Application': 'https://bicycle-dynamics.onrender.com', 22 | }, 23 | include_package_data=True, # includes things in MANIFEST.in 24 | install_requires=[ 25 | 'DynamicistToolKit>=0.5.3', 26 | 'matplotlib>=3.5.1', 27 | 'numpy>=1.21.5', 28 | 'pyyaml>=5.4.1', 29 | 'scipy>=1.8.0', 30 | 'uncertainties>=3.1.5', 31 | 'yeadon>=1.3.0', 32 | ], 33 | python_requires='>=3.9', 34 | extras_require={ 35 | 'doc': [ 36 | 'numpydoc>=1.2', 37 | 'sphinx-gallery', 38 | 'sphinx-reredirects', 39 | 'sphinx>=4.3.2', 40 | ], 41 | 'app': [ 42 | 'dash-bootstrap-components', 43 | 'dash>=2', 44 | 'pandas>=1.3.5' 45 | ], 46 | }, 47 | entry_points={'console_scripts': 48 | ['bicycleparameters = bicycleparameters.app:app.run_server']}, 49 | classifiers=['Programming Language :: Python', 50 | 'Programming Language :: Python :: 3.9', 51 | 'Programming Language :: Python :: 3.10', 52 | 'Programming Language :: Python :: 3.11', 53 | 'Programming Language :: Python :: 3.12', 54 | 'Programming Language :: Python :: 3.13', 55 | 'Operating System :: OS Independent', 56 | 'Development Status :: 5 - Production/Stable', 57 | 'Intended Audience :: Science/Research', 58 | 'License :: OSI Approved :: BSD License', 59 | 'Natural Language :: English', 60 | 'Topic :: Scientific/Engineering', 61 | 'Topic :: Scientific/Engineering :: Physics'] 62 | ) 63 | -------------------------------------------------------------------------------- /utils/create_bicycle_files.py: -------------------------------------------------------------------------------- 1 | '''Creates indivdual *Measured.txt files for all of the bicycles measured at TU 2 | Delft for use in the new program.''' 3 | import pickle 4 | import os 5 | from uncertainties import unumpy 6 | from numpy import ones 7 | 8 | f = open('../../data/udata.p', 'r') 9 | udata = pickle.load(f) 10 | f.close() 11 | 12 | shortnames = ['Browser', 13 | 'Browserins', 14 | 'Crescendo', 15 | 'Fisher', 16 | 'Pista', 17 | 'Stratos', 18 | 'Yellow', 19 | 'Yellowrev'] 20 | 21 | measuredFiles = [] 22 | bicyclesFolder = os.path.join('..', 'bicycles') 23 | # open the files for writing 24 | for i, bike in enumerate(shortnames): 25 | # create the directory if it doesn't exist 26 | bikeFolder = os.path.join(bicyclesFolder, bike) 27 | if not os.path.isdir(bikeFolder): 28 | os.system('mkdir ' + bikeFolder) 29 | pathToMeasuredFile = os.path.join(bikeFolder, 'RawData', 30 | bike + 'Measured.txt') 31 | # store the file handle 32 | measuredFiles.append(open(pathToMeasuredFile, 'w')) 33 | 34 | badKeys = ['frontWheelPressure', 35 | 'names', 36 | 'shortnames', 37 | 'totalMass', 38 | 'rearWheelPressure'] 39 | 40 | # go through the dictionary of raw data and write it to the individual files 41 | for k, v in udata.items(): 42 | print k, v 43 | isPeriod = k.startswith('T') 44 | isBad = k in badKeys 45 | # don't add the periods 46 | if (not isPeriod) and (not isBad): 47 | try: 48 | if v.shape[0] == 3: 49 | # v is a (3, 8) array 50 | vn = v.T 51 | print k, "is a 3x8 array" 52 | else: 53 | # v is a (8,) array 54 | vn = v 55 | print k, "is a 8x array" 56 | except AttributeError: 57 | # v isn't an array 58 | vn = v 59 | print k, "is not an array" 60 | if k == 'lC' or k == 'mC' or k == 'dC': 61 | # these are not arrays, so make them one 62 | vn = ones(8, dtype='object') * v 63 | print "Made", k, "into and array" 64 | # rename k 65 | k = k[0] + 'P' 66 | for i, val in enumerate(vn): 67 | if k == 'bikes': 68 | k = 'name' 69 | try: 70 | nom = val.nominal_value 71 | std = val.std_dev() 72 | line = k + ' = ' + str(nom) + '+/-' + str(std) + '\n' 73 | except AttributeError: 74 | try: 75 | nom = unumpy.nominal_values(val) 76 | line = '' 77 | for j, number in enumerate(nom): 78 | line += k + str(j + 1) + ' = ' + str(val[j]) + '\n' 79 | except ValueError: 80 | line = k + ' = ' + str(val) + '\n' 81 | #print shortnames[i], line 82 | measuredFiles[i].write(line) 83 | else: 84 | print "Did not add:", k 85 | print '\n' 86 | 87 | for openfile in measuredFiles: 88 | openfile.write('g = 9.81 +/- 0.01\n') 89 | openfile.close() 90 | -------------------------------------------------------------------------------- /utils/largest_eigenvalue_plot.py: -------------------------------------------------------------------------------- 1 | import bicycleparameters as bp 2 | import numpy as np 3 | 4 | bikeNames = ['Browserins', 'Browser', 'Pista', 5 | 'Fisher', 'Yellow', 'Yellowrev'] 6 | 7 | colors = ['k'] * 3 + ['gray'] * 3 8 | 9 | linestyles = ['-', '-.', '--'] * 2 10 | 11 | bikes = [] 12 | 13 | for name in bikeNames: 14 | bikes.append(bp.Bicycle(name, pathToData='../data')) 15 | 16 | speeds = np.linspace(0., 10., num=100) 17 | 18 | bp.plot_eigenvalues(bikes, speeds, colors=colors, 19 | linestyles=linestyles), largest=True) 20 | 21 | bp.plt.vlines([2.5, 5., 7.], -0.5, 4.) 22 | 23 | #bp.plt.savefig('../plots/largest.png') 24 | 25 | bp.plt.show() 26 | -------------------------------------------------------------------------------- /utils/package_data.py: -------------------------------------------------------------------------------- 1 | import os 2 | import tarfile 3 | import zipfile 4 | 5 | def package_data(pathToData): 6 | """Packages all the data for BicycleParameters for distribution.""" 7 | 8 | tar = tarfile.open('bicycleparameters-data.tar.bz2', 'w:bz2') 9 | zipFile = zipfile.ZipFile('bicycleparameters-data.zip', 'w') 10 | 11 | # get the bicycle data 12 | bicycles = ['Benchmark', 'Browser', 'Browserins', 'Crescendo', 'Fisher', 13 | 'Gyro', 'Pista', 'Rigid', 'Silver', 'Stratos', 'Yellow', 14 | 'Yellowrev'] 15 | pathToBicycles = os.path.join(pathToData, 'bicycles') 16 | for bike in bicycles: 17 | folders = ['RawData', 'Parameters', 'Photos'] 18 | def raw_file_check(fName, bike): 19 | return fName.endswith('.mat') or fName.endswith('Measured.txt') 20 | def par_file_check(fName, bike): 21 | return fName.startswith(bike) and fName.endswith('.txt') 22 | def photo_file_check(fName, bike): 23 | return fName.startswith(bike) and fName.endswith('.jpg') 24 | rules = [raw_file_check, par_file_check, photo_file_check] 25 | for folder, rule in zip(folders, rules): 26 | pathToFolder = os.path.join(pathToBicycles, bike, folder) 27 | try: 28 | filesInFolder = os.listdir(pathToFolder) 29 | print "Searching", pathToFolder 30 | except OSError: 31 | print "Did not find:", pathToFolder 32 | else: 33 | for f in filesInFolder: 34 | if rule(f, bike): 35 | pathToFile = os.path.join(pathToFolder, f) 36 | print "Added:", pathToFile 37 | tar.add(pathToFile, 38 | arcname=os.path.join('data', 'bicycles', 39 | pathToFile.split('bicycles')[1][1:])) 40 | zipFile.write(pathToFile, 41 | os.path.join('data', 'bicycles', 42 | pathToFile.split('bicycles')[1][1:])) 43 | # get the rider data 44 | riders = ['Aurelia', 'Chris', 'Jason', 'Luke', 'Mont'] 45 | pathToRiders = os.path.join(pathToData, 'riders') 46 | for rider in riders: 47 | folders = ['Parameters', 'RawData'] 48 | def par_file_check(fName, rider): 49 | return fName.startswith(rider) and fName.endswith('.txt') 50 | def raw_file_check(fName, rider): 51 | return fName.startswith(rider) and (fName.endswith('YeadonCFG.txt') or 52 | fName.endswith('YeadonMeas.txt')) 53 | rules = [par_file_check, raw_file_check] 54 | for folder, rule in zip(folders, rules): 55 | pathToFolder = os.path.join(pathToRiders, rider, folder) 56 | try: 57 | filesInFolder = os.listdir(pathToFolder) 58 | print "Searching", pathToFolder 59 | except OSError: 60 | print "Did not find:", pathToFolder 61 | else: 62 | for f in filesInFolder: 63 | if rule(f, rider): 64 | pathToFile = os.path.join(pathToFolder, f) 65 | print "Added:", pathToFile 66 | tar.add(pathToFile, arcname=os.path.join('data', 'riders', 67 | pathToFile.split('riders')[1][1:])) 68 | zipFile.write(pathToFile, 69 | os.path.join('data', 'riders', 70 | pathToFile.split('riders')[1][1:])) 71 | 72 | 73 | tar.close() 74 | zipFile.close() 75 | -------------------------------------------------------------------------------- /utils/time_eig.py: -------------------------------------------------------------------------------- 1 | import bicycleparameters as bp 2 | import timeit 3 | import profile 4 | 5 | stratos = bp.Bicycle('Stratos', pathToData='../data') 6 | 7 | par = stratos.parameters['Benchmark'] 8 | 9 | s = "M, C1, K0, K2 = bp.bicycle.benchmark_par_to_canonical(par)" 10 | profile.run(s) 11 | t = timeit.Timer(s, "from __main__ import bp, par") 12 | print("%.2f usec/pass" % (1000000 * t.timeit(number=100000)/100000)) 13 | --------------------------------------------------------------------------------