Introduction to BRiM#

BRiM [SBM23] is a Python package to model bicycle-riders symbolically. It offers a modular and extendable framework that empowers users to easily compose a custom bicycle-rider model. These models are build from a library of components, such as knife-edge wheels or toroidal-shaped wheels. The components serve as the building blocks of the system. Leveraging the open-source Python package sympy [MSP+17], a computer algebra system, BRiM allows the usage of sympy’s bodies and joints interface to modify the model and other tools to manipulate the equations. The equations of motion (EOMs) for the system are derived using Kane’s method [KL85], which can be further analysed and used in simulation and optimization tasks.

For a more in-depth academic introduction to BRiM and its application in trajectory tracking problems, refer to [SBM23]. The rest of this page will focus on the practical usage of BRiM.

Defining a Model Using SymPy#

sympy is a Python library for symbolic mathematics, which has a separate module, sympy.physics.mechanics, for working with dynamical systems. This module provides an interface for defining systems and deriving their EOMs. It has an interface that uses reference frames, points, bodies and joints to describe a system. For a comprehensive guide on the low-level interface to describe dynamical systems, refer to [Moo22]. An example of defining a simple system, which follows a similar workflow as BRiM, can be found in the docstring of sympy.physics.mechanics.system.System.

Composing a Model#

BRiM divides the bicycle-rider system into smaller subsystems called submodels. Each submodel is modeled separately and aggregated to create the complete bicycle-rider. This results in a tree structure, where the root is the entire bicycle-rider system, and the bicycle and rider are its children. The bicycle model can be further divided as illustrated in the image below. This graphical representation shows the division of the bicycle model into a ground, rear frame, front frame, rear wheel, front wheel and two tire models.

Core Components#

BRiM makes use of three core components: models, connections and loads groups. The models are the main components, where each model describes a (sub)system following a tree structure. The connections can be seen as an utility of parent models to describe a modular and reusable interaction between submodels. The load groups are predefined sets of actuators and loads, which are commonly associated with a specific model or connection.

Defining a Model Using BRiM#

The default Whipple bicycle model [Whi99], also visualized as a tree in the image above, can be constructed as follows. The first step is to configure the model by choosing the components.

from sympy import symbols
from sympy.physics.mechanics._actuator import TorqueActuator
from sympy.physics.mechanics import dynamicsymbols
from brim import *

bicycle = WhippleBicycle("bicycle")
bicycle.rear_frame = RigidRearFrame("rear_frame")
bicycle.front_frame = RigidFrontFrame("front_frame")
bicycle.rear_wheel = KnifeEdgeWheel("rear_wheel")
bicycle.front_wheel = KnifeEdgeWheel("front_wheel")
bicycle.rear_tire = NonHolonomicTire("rear_tire")
bicycle.front_tire = NonHolonomicTire("front_tire")

With the model configured, the next step is to let BRiM construct all the relationships in the model by calling define_all(). After this, the model can be exported to a single sympy.physics.mechanics.system.System object.

bicycle.define_all()
system = bicycle.to_system()

The model can be extended by adding an actuator for steering and applying gravity:

g = symbols("g")
T = dynamicsymbols("T")
normal = bicycle.ground.get_normal(bicycle.ground.origin)
system.add_actuators(TorqueActuator(
    T, bicycle.rear_frame.steer_axis,
    bicycle.front_frame.frame, bicycle.rear_frame.frame))
system.apply_uniform_gravity(-g * normal)

The last step before forming the EOMs is to define which generalized coordinates and speeds are independent and which are dependent. In this case the generalized coordinate for the pitch of the rear frame is chosen to be dependent. As dependent generalized speeds we choose the velocities for the contact point of the rear wheel, the rotation rate of the rear wheel, and the yaw and pitch rate of the rear frame.

system.q_ind = [*bicycle.q[:4], *bicycle.q[5:]]
system.q_dep = [bicycle.q[4]]
system.u_ind = [bicycle.u[3], *bicycle.u[5:7]]
system.u_dep = [*bicycle.u[:3], bicycle.u[4], bicycle.u[7]]

The following code validates the system on its consistency using sympy.physics.mechanics.system.System.validate_system() and forms the EOMs with Kane’s method. CRAMER is chosen as the constraint solver, as it provides better numeric stability.

system.validate_system()
system.form_eoms(constraint_solver="CRAMER")

See Also#

Here are some useful reference to get started:

  • The Tutorials page contains a collection of tutorials to get started with BRiM.

  • The brim-bmd-2023-paper repository contains a src directory with various trajectory tracking examples discussed in [SBM23].

  • [Moo22] is a great place to learn more about the fundamental modeling concepts when using sympy.physics.mechanics.

  • The sympy.physics.mechanics module contains several examples and tutorials to get familiar with using sympy for modeling dynamical systems.

References#

[KL85]

Thomas R. Kane and David A. Levinson. Dynamics, Theory and Applications. McGraw Hill, 1985. ISBN 978-0-07-037846-9. URL: https://ecommons.cornell.edu/handle/1813/638 (visited on 2023-01-26).

[MSP+17]

Aaron Meurer, Christopher P. Smith, Mateusz Paprocki, Ondřej Čertík, Sergey B. Kirpichev, Matthew Rocklin, Amit Kumar, Sergiu Ivanov, Jason K. Moore, Sartaj Singh, Thilina Rathnayake, Sean Vig, Brian E. Granger, Richard P. Muller, Francesco Bonazzi, Shivam Gupta, Harsh andVats, Fredrik Johansson, Fabian Pedregosa, Matthew J. Curry, Andy R. Terrel, Štěpán Roučka, Ashutosh Saboo, Isuru Fernando, Sumith Kulal, Robert Cimrman, and Anthony Scopatz. SymPy: symbolic computing in python. PeerJ Computer Science, 3:e103, January 2017. URL: https://doi.org/10.7717/peerj-cs.103, doi:10.7717/peerj-cs.103.

[Moo22] (1,2)

Jason K. Moore. Learn multibody dynamics. 2022. URL: https://moorepants.github.io/learn-multibody-dynamics/index.html.

[SBM23] (1,2,3)

Timótheüs J. Stienstra, Samuel G. Brockie, and Jason K. Moore. Brim: a modular bicycle-rider modeling framework. In The Evolving Scholar - BMD 2023, 5th Edition. 2023. doi:10.59490/6504c5a765e8118fc7b106c3.

[Whi99]

Francis JW Whipple. The stability of the motion of a bicycle. Quarterly Journal of Pure and Applied Mathematics, 30(120):312–348, 1899.