Skip to content
LIBRARY
Revolute.md

Revolute ​

Revolute joint: rotation about a single axis in 3D.

The rooted structural parameter determines which frame is closest to the base of the kinematic tree.

This component extends from PartialTwoFrames This component extends from Renderable This component extends from CutJoint

Usage ​

MultibodyComponents.Revolute(render=true, color=world_default_joint_color(), specular_coefficient=1.5, n=[0, 0, 1], n_sparse=[n[1] * n_nonzero[1], n[2] * n_nonzero[2], n[3] * n_nonzero[3]], radius=world_default_joint_width() / 2, cylinder_length=world_default_joint_length())

Parameters: ​

NameDescriptionUnitsDefault value
iscut–false
residual–zeros(3)
statePriority–4
rooted–MultibodyCo...me.FrameA()
n_nonzeroStructural sparsity mask for the rotation axis: element i is true if n[i] may be nonzero. Components marked false are assembled as literal zeros, so the compiler can rely on the sparsity (e.g. avoids forming a dense outer product axis*axis' that defeats codegen). Defaults to all-true (no sparsity assumption). Must be set consistently with n.–[true, true, true]
render–true
color–world_defau...int_color()
specular_coefficient–1.5
naxis of rotation–[0, 0, 1]
radiusRadius of the revolute cylinder in animations–world_defau...width() / 2
cylinder_lengthLength of the revolute cylinder in animations–world_defau...nt_length()

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)

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

connectors that can be connected together (Frame3D)

  • axis - 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
Rleaf–
Rroot–
phiRelative rotation angle from frame_a to frame_brad
wangular velocity (rad/s)rad/s
tauDriving torque in direction of axis of rotationN.m
R_rel–

Behavior ​

Dict{MIME{Symbol("text/plain")}, String} with 1 entry: MIME type text/plain => "Error displaying result"

Source ​

dyad
"""
Revolute joint: rotation about a single axis in 3D.

The `rooted` structural parameter determines which frame is closest to the base of the kinematic tree. 
"""
component Revolute
  extends PartialTwoFrames()
  extends Renderable(color = world_default_joint_color())
  extends CutJoint()
  axis = Spline() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 450, "x2": 550, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  support = Spline() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 100, "y1": 450, "x2": 200, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  # Visualization shape
  shape = CylinderShape(render = render, color = color, r = frame_a.r_0, R = transpose(frame_a.R), r_shape = n * (-cylinder_length / 2), length_direction = n, length = cylinder_length, width = 2 * radius, height = 2 * radius)
  structural parameter statePriority::Integer = 4 # One higher than prismatic
  structural parameter rooted::RootedFrame = MultibodyComponents.RootedFrame.FrameA()
  "axis of rotation"
  parameter n::Real[3] = [0, 0, 1]
  "Structural sparsity mask for the rotation axis: element i is true if n[i] may be nonzero. Components marked false are assembled as literal zeros, so the compiler can rely on the sparsity (e.g. avoids forming a dense outer product axis*axis' that defeats codegen). Defaults to all-true (no sparsity assumption). Must be set consistently with `n`."
  structural parameter n_nonzero::Boolean[3] = [true, true, true]
  "Rotation axis assembled with the declared sparsity (zeros are structural)."
  final parameter n_sparse::Real[3] = [n[1] * n_nonzero[1], n[2] * n_nonzero[2], n[3] * n_nonzero[3]]
  "Radius of the revolute cylinder in animations"
  parameter radius::Real = world_default_joint_width() / 2
  "Length of the revolute cylinder in animations"
  parameter cylinder_length::Real = world_default_joint_length()
  "Relative rotation angle from frame_a to frame_b"
  variable phi::Angle(statePriority = statePriority)
  "angular velocity (rad/s)"
  variable w::AngularVelocity(statePriority = statePriority)
  "Driving torque in direction of axis of rotation"
  variable tau::Dyad.Torque
  variable R_rel::Real[3, 3]
relations
  # Kinematics
  der(phi) = w
  frame_a.r_0 = frame_b.r_0
  # Relative rotation matrix (Rodrigues formula). Uses the sparsity-assembled
  # axis so structurally-zero components are literal zeros in axis*axis'.
  R_rel = RR(planar_rotation(n_sparse, phi, w))
  # Axisflange: axis drives the joint, support is grounded
  axis.phi = phi
  axis.tau = tau
  support.phi = 0
  tau = -dot(frame_b.tau, n_sparse)
  # Orientation propagation depends on which frame is rooted
  switch rooted
    case FrameA
      # frame_b.R = R_rel * frame_a.R
      Rleaf = frame_b.R
      Rroot = R_rel * frame_a.R
      frame_a.f = -transpose(R_rel) * frame_b.f
      frame_a.tau = -transpose(R_rel) * frame_b.tau
    case FrameB
      # frame_a.R = transpose(R_rel) * frame_b.R
      Rleaf = frame_a.R
      Rroot = transpose(R_rel) * frame_b.R
      frame_b.f = -R_rel * frame_a.f
      frame_b.tau = -R_rel * frame_a.tau
  end
metadata {
  "Dyad": {
    "icons": {"default": "dyad://MultibodyComponents/Revolute.svg"},
    "labels": [
      {
        "label": "$(instance)",
        "x": 500,
        "y": 200,
        "rot": 0,
        "attrs": {"font-size": "160"}
      }
    ]
  }
}
end
Flattened Source
dyad
"""
Revolute joint: rotation about a single axis in 3D.

The `rooted` structural parameter determines which frame is closest to the base of the kinematic tree. 
"""
component Revolute
  frame_a = Frame3D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": -50, "y1": 450, "x2": 50, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  frame_b = Frame3D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 950, "y1": 450, "x2": 1050, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  parameter render::Boolean = true
  parameter color::Real[4] = [0.5, 0.5, 0.5, 1.0]
  parameter specular_coefficient::Real = 1.5
  structural parameter iscut::Boolean = false
  final structural parameter residual::Real[3] = zeros(3) if iscut
  variable Rleaf::Real[3, 3]
  variable Rroot::Real[3, 3]
  axis = Spline() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 450, "x2": 550, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  support = Spline() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 100, "y1": 450, "x2": 200, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  # Visualization shape
  shape = CylinderShape(render = render, color = color, r = frame_a.r_0, R = transpose(frame_a.R), r_shape = n * (-cylinder_length / 2), length_direction = n, length = cylinder_length, width = 2 * radius, height = 2 * radius)
  structural parameter statePriority::Integer = 4 # One higher than prismatic
  structural parameter rooted::RootedFrame = MultibodyComponents.RootedFrame.FrameA()
  "axis of rotation"
  parameter n::Real[3] = [0, 0, 1]
  "Structural sparsity mask for the rotation axis: element i is true if n[i] may be nonzero. Components marked false are assembled as literal zeros, so the compiler can rely on the sparsity (e.g. avoids forming a dense outer product axis*axis' that defeats codegen). Defaults to all-true (no sparsity assumption). Must be set consistently with `n`."
  structural parameter n_nonzero::Boolean[3] = [true, true, true]
  "Rotation axis assembled with the declared sparsity (zeros are structural)."
  final parameter n_sparse::Real[3] = [n[1] * n_nonzero[1], n[2] * n_nonzero[2], n[3] * n_nonzero[3]]
  "Radius of the revolute cylinder in animations"
  parameter radius::Real = world_default_joint_width() / 2
  "Length of the revolute cylinder in animations"
  parameter cylinder_length::Real = world_default_joint_length()
  "Relative rotation angle from frame_a to frame_b"
  variable phi::Angle(statePriority = statePriority)
  "angular velocity (rad/s)"
  variable w::AngularVelocity(statePriority = statePriority)
  "Driving torque in direction of axis of rotation"
  variable tau::Dyad.Torque
  variable R_rel::Real[3, 3]
relations
  if iscut
    residue(Rleaf, Rroot) = residual
  else
    Rleaf = Rroot
  end
  # Kinematics
  der(phi) = w
  frame_a.r_0 = frame_b.r_0
  # Relative rotation matrix (Rodrigues formula). Uses the sparsity-assembled
  # axis so structurally-zero components are literal zeros in axis*axis'.
  R_rel = RR(planar_rotation(n_sparse, phi, w))
  # Axisflange: axis drives the joint, support is grounded
  axis.phi = phi
  axis.tau = tau
  support.phi = 0
  tau = -dot(frame_b.tau, n_sparse)
  # Orientation propagation depends on which frame is rooted
  switch rooted
    case FrameA
      # frame_b.R = R_rel * frame_a.R
      Rleaf = frame_b.R
      Rroot = R_rel * frame_a.R
      frame_a.f = -transpose(R_rel) * frame_b.f
      frame_a.tau = -transpose(R_rel) * frame_b.tau
    case FrameB
      # frame_a.R = transpose(R_rel) * frame_b.R
      Rleaf = frame_a.R
      Rroot = transpose(R_rel) * frame_b.R
      frame_b.f = -R_rel * frame_a.f
      frame_b.tau = -R_rel * frame_a.tau
  end
metadata {
  "Dyad": {
    "icons": {"default": "dyad://MultibodyComponents/Revolute.svg"},
    "labels": [
      {
        "label": "$(instance)",
        "x": 500,
        "y": 200,
        "rot": 0,
        "attrs": {"font-size": "160"}
      }
    ]
  }
}
end


Test Cases ​

No test cases defined.