Skip to content
LIBRARY
RollingWheel.md

RollingWheel

Ideal rolling wheel (mass + inertia) on the flat plane y = 0.

A wheel rolling on the x-z plane of the world frame with 5 positional and 3 velocity degrees of freedom. The rolling contact is considered ideal (no slip). The wheel can not lift off the ground but can lean.

frame_a is placed at the wheel center and rotates with the wheel. To attach the wheel to an axle, connect frame_a to a Revolute joint rotating around n = [0, 1, 0] (vertical axis of the inertial frame).

The wheel's inertia tensor is diagonal in body coordinates: I_axis is the moment of inertia about the spin axis (z of frame_a), and I_long is the moment of inertia perpendicular to it.

Usage

MultibodyComponents.RollingWheel(render=true, color=[1, 0, 0, 1], radius=0.3, m=1, I_axis=0.06, I_long=0.12, width=0.035)

Parameters:

NameDescriptionUnitsDefault value
renderRender the wheeltrue
colorColor of the wheel in animations[1, 0, 0, 1]
radiusRadius of the wheelm0.3
mMass of the wheelkg1
I_axisMoment of inertia of the wheel about its spin axiskg.m20.06
I_longMoment of inertia of the wheel perpendicular to its spin axiskg.m20.12
widthWidth of the wheel0.035

Connectors

  • frame_a - Frame3D is the fundamental 3D connector used for 6DOF motion. Most components have one or several Frame

connectors that can be connected together (Frame3D)

Variables

NameDescriptionUnits
xx-position of the wheel axism
zz-position of the wheel axism
anglesAngles that rotate the world frame into frame_a around the y-, z-, x-axisrad
der_anglesTime derivatives of anglesrad/s

Behavior

Source

dyad
"""
Ideal rolling wheel (mass + inertia) on the flat plane y = 0.

A wheel rolling on the x-z plane of the world frame with 5 positional and
3 velocity degrees of freedom. The rolling contact is considered ideal
(no slip). The wheel can not lift off the ground but can lean.

`frame_a` is placed at the wheel center and rotates with the wheel. To
attach the wheel to an axle, connect `frame_a` to a `Revolute` joint
rotating around `n = [0, 1, 0]` (vertical axis of the inertial frame).

The wheel's inertia tensor is diagonal in body coordinates: `I_axis` is the
moment of inertia about the spin axis (z of `frame_a`), and `I_long` is the
moment of inertia perpendicular to it.
"""
component RollingWheel
  frame_a = Frame3D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 450, "x2": 550, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  wheeljoint = RollingWheelJoint(final radius = radius, final width = width, render = render, color = color)
  body = Body(final m = m, final I_11 = I_long, final I_22 = I_long, final I_33 = I_axis, r_cm = [0, 0, 0], render = false)
  "Render the wheel"
  parameter render::Boolean = true
  "Color of the wheel in animations"
  parameter color::Real[4] = [1, 0, 0, 1]
  "Radius of the wheel"
  parameter radius::Length = 0.3
  "Mass of the wheel"
  parameter m::Mass = 1
  "Moment of inertia of the wheel about its spin axis"
  parameter I_axis::Inertia = 0.06
  "Moment of inertia of the wheel perpendicular to its spin axis"
  parameter I_long::Inertia = 0.12
  "Width of the wheel"
  parameter width::Real = 0.035
  "x-position of the wheel axis"
  variable x::Length(statePriority = 20)
  "z-position of the wheel axis"
  variable z::Length(statePriority = 20)
  "Angles that rotate the world frame into `frame_a` around the y-, z-, x-axis"
  variable angles::Angle(statePriority = 30)[3]
  "Time derivatives of `angles`"
  variable der_angles::AngularVelocity(statePriority = 30)[3]
relations
  # Solver guesses for the wheel's generalized coordinates
  guess x = 0
  guess z = 0
  guess angles = [0, 0, 0]
  guess der_angles = [0, 0, 0]
  wheeljoint.x = x
  wheeljoint.z = z
  wheeljoint.angles = angles
  # The derivative relation lives at THIS level (instead of an alias to
  # wheeljoint.der_angles, which is equivalent through the angles alias):
  # state selection only considers variables that carry a derivative chain, so
  # aliasing would make the high-statePriority `angles`/`der_angles` here
  # unselectable and the low-priority wheeljoint internals would end up as the
  # states.
  der_angles = der(angles)
  connect(body.frame_a, frame_a)
  connect(wheeljoint.frame_a, frame_a)
metadata {
  "Dyad": {
    "icons": {"default": "dyad://MultibodyComponents/RollingWheel.svg"},
    "labels": [
      {
        "label": "$(instance)",
        "x": 500,
        "y": 200,
        "rot": 0,
        "attrs": {"font-size": "160"}
      }
    ]
  }
}
end
Flattened Source
dyad
"""
Ideal rolling wheel (mass + inertia) on the flat plane y = 0.

A wheel rolling on the x-z plane of the world frame with 5 positional and
3 velocity degrees of freedom. The rolling contact is considered ideal
(no slip). The wheel can not lift off the ground but can lean.

`frame_a` is placed at the wheel center and rotates with the wheel. To
attach the wheel to an axle, connect `frame_a` to a `Revolute` joint
rotating around `n = [0, 1, 0]` (vertical axis of the inertial frame).

The wheel's inertia tensor is diagonal in body coordinates: `I_axis` is the
moment of inertia about the spin axis (z of `frame_a`), and `I_long` is the
moment of inertia perpendicular to it.
"""
component RollingWheel
  frame_a = Frame3D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 450, "x2": 550, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  wheeljoint = RollingWheelJoint(final radius = radius, final width = width, render = render, color = color)
  body = Body(final m = m, final I_11 = I_long, final I_22 = I_long, final I_33 = I_axis, r_cm = [0, 0, 0], render = false)
  "Render the wheel"
  parameter render::Boolean = true
  "Color of the wheel in animations"
  parameter color::Real[4] = [1, 0, 0, 1]
  "Radius of the wheel"
  parameter radius::Length = 0.3
  "Mass of the wheel"
  parameter m::Mass = 1
  "Moment of inertia of the wheel about its spin axis"
  parameter I_axis::Inertia = 0.06
  "Moment of inertia of the wheel perpendicular to its spin axis"
  parameter I_long::Inertia = 0.12
  "Width of the wheel"
  parameter width::Real = 0.035
  "x-position of the wheel axis"
  variable x::Length(statePriority = 20)
  "z-position of the wheel axis"
  variable z::Length(statePriority = 20)
  "Angles that rotate the world frame into `frame_a` around the y-, z-, x-axis"
  variable angles::Angle(statePriority = 30)[3]
  "Time derivatives of `angles`"
  variable der_angles::AngularVelocity(statePriority = 30)[3]
relations
  # Solver guesses for the wheel's generalized coordinates
  guess x = 0
  guess z = 0
  guess angles = [0, 0, 0]
  guess der_angles = [0, 0, 0]
  wheeljoint.x = x
  wheeljoint.z = z
  wheeljoint.angles = angles
  # The derivative relation lives at THIS level (instead of an alias to
  # wheeljoint.der_angles, which is equivalent through the angles alias):
  # state selection only considers variables that carry a derivative chain, so
  # aliasing would make the high-statePriority `angles`/`der_angles` here
  # unselectable and the low-priority wheeljoint internals would end up as the
  # states.
  der_angles = der(angles)
  connect(body.frame_a, frame_a)
  connect(wheeljoint.frame_a, frame_a)
metadata {
  "Dyad": {
    "icons": {"default": "dyad://MultibodyComponents/RollingWheel.svg"},
    "labels": [
      {
        "label": "$(instance)",
        "x": 500,
        "y": 200,
        "rot": 0,
        "attrs": {"font-size": "160"}
      }
    ]
  }
}
end


Test Cases

No test cases defined.

  • Examples

  • Experiments

  • Analyses