Skip to content
LIBRARY
RollingWheelSetJoint.md

RollingWheelSetJoint

Idealized two-wheel rolling axle (wheelset) without bodies.

Two parallel-axis revolute joints provide each wheel's spin angle; each is constrained by a RollingConstraintVerticalWheel. The wheelset center (frame_middle) is mounted to ground via prismatic-x → prismatic-z → revolute (around y), exposing planar coordinates (x, z, phi) and the two wheel spin angles (theta1, theta2) as states.

  • frame_middle: between the two wheels (z-axis along the axle, y-axis up)

  • frame1/frame2: wheel-center frames, rotating with each wheel

  • axis1/axis2: 1-D rotational flanges driving each wheel

  • support: 1-D support flange (mounted to frame_middle)

Usage

MultibodyComponents.RollingWheelSetJoint(radius=0.3, track=1.0, width_wheel=0.15 * radius)

Parameters:

NameDescriptionUnitsDefault value
radiusm0.3
trackm1.0
width_wheelm0.15 * radius

Connectors

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

connectors that can be connected together (Frame3D)

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

connectors that can be connected together (Frame3D)

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

connectors that can be connected together (Frame3D)

  • axis1 - This connector represents a rotational spline with angle and torque as the potential and flow variables, respectively. (Spline)

  • axis2 - This connector represents a rotational spline with angle and torque as the potential and flow variables, respectively. (Spline)

  • support - This connector represents a rotational spline with angle and torque as the potential and flow variables, respectively. (Spline)

Variables

NameDescriptionUnits
xm
zm
phirad
theta1rad
theta2rad
der_theta1rad/s
der_theta2rad/s

Behavior

Source

dyad
"""
Idealized two-wheel rolling axle (wheelset) without bodies.

Two parallel-axis revolute joints provide each wheel's spin angle; each is
constrained by a `RollingConstraintVerticalWheel`. The wheelset center
(`frame_middle`) is mounted to ground via prismatic-x → prismatic-z →
revolute (around y), exposing planar coordinates `(x, z, phi)` and the two
wheel spin angles `(theta1, theta2)` as states.

- `frame_middle`: between the two wheels (z-axis along the axle, y-axis up)
- `frame1`/`frame2`: wheel-center frames, rotating with each wheel
- `axis1`/`axis2`: 1-D rotational flanges driving each wheel
- `support`: 1-D support flange (mounted to `frame_middle`)
"""
component RollingWheelSetJoint
  frame_middle = Frame3D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 450, "x2": 550, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  frame1 = Frame3D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": -50, "y1": 450, "x2": 50, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  frame2 = Frame3D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 950, "y1": 450, "x2": 1050, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  axis1 = Spline() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": -50, "y1": 20, "x2": 50, "y2": 120, "rot": 0}
      },
      "tags": []
    }
  }
  axis2 = Spline() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 950, "y1": 20, "x2": 1050, "y2": 120, "rot": 0}
      },
      "tags": []
    }
  }
  support = Spline() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 100, "x2": 550, "y2": 200, "rot": 0}
      },
      "tags": []
    }
  }
  fixed = MultibodyComponents.Fixed(final r = [0, radius, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 900, "x2": 550, "y2": 1000, "rot": 270}
      },
      "tags": []
    }
  }
  rod1 = MultibodyComponents.FixedTranslation(final r = [0, 0, track / 2], render = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 420, "y1": 450, "x2": 320, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  rod2 = MultibodyComponents.FixedTranslation(final r = [0, 0, -track / 2], render = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 590, "y1": 450, "x2": 690, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  prismatic1 = MultibodyComponents.Prismatic(final n = [1, 0, 0], render = false, statePriority = 10) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 830, "x2": 550, "y2": 930, "rot": 270}
      },
      "tags": []
    }
  }
  prismatic2 = MultibodyComponents.Prismatic(final n = [0, 0, 1], render = false, statePriority = 10) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 420, "y1": 760, "x2": 320, "y2": 860, "rot": 0}
      },
      "tags": []
    }
  }
  revolute = MultibodyComponents.Revolute(final n = [0, 1, 0], render = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 640, "x2": 550, "y2": 740, "rot": 270}
      },
      "tags": []
    }
  }
  revolute1 = MultibodyComponents.Revolute(final n = [0, 0, 1], render = false, radius = radius, cylinder_length = width_wheel, statePriority = 11) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 280, "y1": 450, "x2": 180, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  revolute2 = MultibodyComponents.Revolute(final n = [0, 0, 1], render = false, radius = radius, cylinder_length = width_wheel, statePriority = 11) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 730, "y1": 450, "x2": 830, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  rolling1 = MultibodyComponents.RollingConstraintVerticalWheel(final radius = radius, lateral_sliding_constraint = true) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 90, "y1": 580, "x2": 190, "y2": 680, "rot": 0}
      },
      "tags": []
    }
  }
  rolling2 = MultibodyComponents.RollingConstraintVerticalWheel(final radius = radius, lateral_sliding_constraint = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 830, "y1": 590, "x2": 930, "y2": 690, "rot": 0}
      },
      "tags": []
    }
  }
  mounting1D = MultibodyComponents.Mounting1D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 360, "x2": 550, "y2": 260, "rot": 0}
      },
      "tags": []
    }
  }
  parameter radius::Length = 0.3
  parameter track::Length = 1.0
  parameter width_wheel::Length = 0.15 * radius
  variable x::Length(statePriority = 100)
  variable z::Length(statePriority = 100)
  variable phi::Angle(statePriority = 100)
  variable theta1::Angle(statePriority = 100)
  variable theta2::Angle(statePriority = 100)
  variable der_theta1::AngularVelocity(statePriority = 100)
  variable der_theta2::AngularVelocity(statePriority = 100)
relations
  prismatic1.s = x
  prismatic2.s = z
  revolute.phi = phi
  revolute1.phi = theta1
  revolute2.phi = theta2
  der_theta1 = der(theta1)
  der_theta2 = der(theta2)
  connect(prismatic1.frame_a, fixed.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(prismatic1.frame_b, prismatic2.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 500, "y": 810}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(revolute2.axis, axis2) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 780, "y": 70}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(frame_middle, mounting1D.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(mounting1D.flange_b, support) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(frame2, revolute2.frame_b, rolling2.frame_a) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [], "E": -1},
        {"S": -1, "M": [], "E": 2},
        {"S": 3, "M": [], "E": -1}
      ],
      "junctions": [{"x": 880, "y": 500}],
      "renderStyle": "standard"
    }
  }
  connect(frame1, rolling1.frame_a, revolute1.frame_b) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [], "E": -1},
        {"S": -1, "M": [{"x": 140, "y": 500}], "E": 2},
        {"S": 3, "M": [], "E": -1}
      ],
      "junctions": [{"x": 140, "y": 500}],
      "renderStyle": "standard"
    }
  }
  connect(rod1.frame_b, revolute1.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(rod1.frame_a, frame_middle) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(rod2.frame_a, frame_middle) {"Dyad": {"renderStyle": "standard", "edges": [{"S": 1, "E": 2, "M": []}]}}
  connect(rod2.frame_b, revolute2.frame_a) {"Dyad": {"renderStyle": "standard", "edges": [{"S": 1, "E": 2, "M": []}]}}
  connect(axis1, revolute1.axis) {
    "Dyad": {
      "renderStyle": "standard",
      "edges": [{"S": 1, "M": [{"x": 230, "y": 70}], "E": 2}]
    }
  }
  connect(prismatic2.frame_b, revolute.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 320, "y": 750}, {"x": 500, "y": 750}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(revolute.frame_b, frame_middle) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
metadata {
  "Dyad": {
    "icons": {"default": "dyad://MultibodyComponents/RollingWheelSetJoint.svg"},
    "labels": [
      {
        "label": "$(instance)",
        "x": 500,
        "y": 1080,
        "rot": 0,
        "attrs": {"font-size": "120"}
      }
    ]
  }
}
end
Flattened Source
dyad
"""
Idealized two-wheel rolling axle (wheelset) without bodies.

Two parallel-axis revolute joints provide each wheel's spin angle; each is
constrained by a `RollingConstraintVerticalWheel`. The wheelset center
(`frame_middle`) is mounted to ground via prismatic-x → prismatic-z →
revolute (around y), exposing planar coordinates `(x, z, phi)` and the two
wheel spin angles `(theta1, theta2)` as states.

- `frame_middle`: between the two wheels (z-axis along the axle, y-axis up)
- `frame1`/`frame2`: wheel-center frames, rotating with each wheel
- `axis1`/`axis2`: 1-D rotational flanges driving each wheel
- `support`: 1-D support flange (mounted to `frame_middle`)
"""
component RollingWheelSetJoint
  frame_middle = Frame3D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 450, "x2": 550, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  frame1 = Frame3D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": -50, "y1": 450, "x2": 50, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  frame2 = Frame3D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 950, "y1": 450, "x2": 1050, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  axis1 = Spline() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": -50, "y1": 20, "x2": 50, "y2": 120, "rot": 0}
      },
      "tags": []
    }
  }
  axis2 = Spline() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 950, "y1": 20, "x2": 1050, "y2": 120, "rot": 0}
      },
      "tags": []
    }
  }
  support = Spline() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 100, "x2": 550, "y2": 200, "rot": 0}
      },
      "tags": []
    }
  }
  fixed = MultibodyComponents.Fixed(final r = [0, radius, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 900, "x2": 550, "y2": 1000, "rot": 270}
      },
      "tags": []
    }
  }
  rod1 = MultibodyComponents.FixedTranslation(final r = [0, 0, track / 2], render = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 420, "y1": 450, "x2": 320, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  rod2 = MultibodyComponents.FixedTranslation(final r = [0, 0, -track / 2], render = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 590, "y1": 450, "x2": 690, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  prismatic1 = MultibodyComponents.Prismatic(final n = [1, 0, 0], render = false, statePriority = 10) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 830, "x2": 550, "y2": 930, "rot": 270}
      },
      "tags": []
    }
  }
  prismatic2 = MultibodyComponents.Prismatic(final n = [0, 0, 1], render = false, statePriority = 10) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 420, "y1": 760, "x2": 320, "y2": 860, "rot": 0}
      },
      "tags": []
    }
  }
  revolute = MultibodyComponents.Revolute(final n = [0, 1, 0], render = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 640, "x2": 550, "y2": 740, "rot": 270}
      },
      "tags": []
    }
  }
  revolute1 = MultibodyComponents.Revolute(final n = [0, 0, 1], render = false, radius = radius, cylinder_length = width_wheel, statePriority = 11) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 280, "y1": 450, "x2": 180, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  revolute2 = MultibodyComponents.Revolute(final n = [0, 0, 1], render = false, radius = radius, cylinder_length = width_wheel, statePriority = 11) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 730, "y1": 450, "x2": 830, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  rolling1 = MultibodyComponents.RollingConstraintVerticalWheel(final radius = radius, lateral_sliding_constraint = true) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 90, "y1": 580, "x2": 190, "y2": 680, "rot": 0}
      },
      "tags": []
    }
  }
  rolling2 = MultibodyComponents.RollingConstraintVerticalWheel(final radius = radius, lateral_sliding_constraint = false) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 830, "y1": 590, "x2": 930, "y2": 690, "rot": 0}
      },
      "tags": []
    }
  }
  mounting1D = MultibodyComponents.Mounting1D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 360, "x2": 550, "y2": 260, "rot": 0}
      },
      "tags": []
    }
  }
  parameter radius::Length = 0.3
  parameter track::Length = 1.0
  parameter width_wheel::Length = 0.15 * radius
  variable x::Length(statePriority = 100)
  variable z::Length(statePriority = 100)
  variable phi::Angle(statePriority = 100)
  variable theta1::Angle(statePriority = 100)
  variable theta2::Angle(statePriority = 100)
  variable der_theta1::AngularVelocity(statePriority = 100)
  variable der_theta2::AngularVelocity(statePriority = 100)
relations
  prismatic1.s = x
  prismatic2.s = z
  revolute.phi = phi
  revolute1.phi = theta1
  revolute2.phi = theta2
  der_theta1 = der(theta1)
  der_theta2 = der(theta2)
  connect(prismatic1.frame_a, fixed.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(prismatic1.frame_b, prismatic2.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 500, "y": 810}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(revolute2.axis, axis2) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 780, "y": 70}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(frame_middle, mounting1D.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(mounting1D.flange_b, support) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(frame2, revolute2.frame_b, rolling2.frame_a) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [], "E": -1},
        {"S": -1, "M": [], "E": 2},
        {"S": 3, "M": [], "E": -1}
      ],
      "junctions": [{"x": 880, "y": 500}],
      "renderStyle": "standard"
    }
  }
  connect(frame1, rolling1.frame_a, revolute1.frame_b) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [], "E": -1},
        {"S": -1, "M": [{"x": 140, "y": 500}], "E": 2},
        {"S": 3, "M": [], "E": -1}
      ],
      "junctions": [{"x": 140, "y": 500}],
      "renderStyle": "standard"
    }
  }
  connect(rod1.frame_b, revolute1.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(rod1.frame_a, frame_middle) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(rod2.frame_a, frame_middle) {"Dyad": {"renderStyle": "standard", "edges": [{"S": 1, "E": 2, "M": []}]}}
  connect(rod2.frame_b, revolute2.frame_a) {"Dyad": {"renderStyle": "standard", "edges": [{"S": 1, "E": 2, "M": []}]}}
  connect(axis1, revolute1.axis) {
    "Dyad": {
      "renderStyle": "standard",
      "edges": [{"S": 1, "M": [{"x": 230, "y": 70}], "E": 2}]
    }
  }
  connect(prismatic2.frame_b, revolute.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 320, "y": 750}, {"x": 500, "y": 750}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(revolute.frame_b, frame_middle) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
metadata {
  "Dyad": {
    "icons": {"default": "dyad://MultibodyComponents/RollingWheelSetJoint.svg"},
    "labels": [
      {
        "label": "$(instance)",
        "x": 500,
        "y": 1080,
        "rot": 0,
        "attrs": {"font-size": "120"}
      }
    ]
  }
}
end


Test Cases

No test cases defined.

  • Examples

  • Experiments

  • Analyses