Skip to content
LIBRARY
PlanarMechanics.RelativeForce.md

PlanarMechanics.RelativeForce

Relative force and torque acting between frame_a and frame_b, defined by input signals.

Applies the input force to frame_b and the reaction (equal and opposite) to frame_a. The force inputs (force_x, force_y) and torque input are resolved in the frame selected by the structural parameter resolve_in_frame (world, frame_a, or frame_b).

This component extends from MultibodyComponents.Renderable

Usage

MultibodyComponents.PlanarMechanics.RelativeForce(render=true, color=[0, 1, 0, 0.5], specular_coefficient=0.7, scale=0.1, arrow_diameter=0.05, z_position=0)

Parameters:

NameDescriptionUnitsDefault value
resolve_in_frameMultibodyComponents.ResolveInFrame.FrameA()
rendertrue
color[0, 1, 0, 0.5]
specular_coefficient0.7
scaleScale factor for force visualization (length = force * scale)0.1
arrow_diameterDiameter of the force arrow shaft0.05
z_positionz-position of the arrow in animations0

Connectors

  • frame_a - Coordinate system (2-dim.) fixed to the component with one cut-force and cut-torque.

All variables are resolved in the planar world frame. (Frame2D)

  • frame_b - Coordinate system (2-dim.) fixed to the component with one cut-force and cut-torque.

All variables are resolved in the planar world frame. (Frame2D)

  • force_x - This connector represents a real signal as an input to a component (RealInput)

  • force_y - This connector represents a real signal as an input to a component (RealInput)

  • torque - This connector represents a real signal as an input to a component (RealInput)

Variables

NameDescriptionUnits
phiAngle of resolution framerad

Behavior

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

Source

dyad
"""
Relative force and torque acting between frame_a and frame_b, defined by input signals.

Applies the input force to frame_b and the reaction (equal and opposite) to frame_a.
The force inputs (force_x, force_y) and torque input are resolved in the frame
selected by the structural parameter `resolve_in_frame` (world, frame_a, or frame_b).
"""
component RelativeForce
  extends MultibodyComponents.Renderable(color = [0, 1, 0, 0.5])
  frame_a = Frame2D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": -50, "y1": 450, "x2": 50, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  frame_b = Frame2D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 950, "y1": 450, "x2": 1050, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  force_x = RealInput() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 90, "y1": -50, "x2": 190, "y2": 50, "rot": 90}
      },
      "tags": []
    }
  }
  force_y = RealInput() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": -50, "x2": 550, "y2": 50, "rot": 90}
      },
      "tags": []
    }
  }
  torque = RealInput() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 810, "y1": -50, "x2": 910, "y2": 50, "rot": 90}
      },
      "tags": []
    }
  }
  "Force arrow visualization at frame_b"
  force_arrow = MultibodyComponents.ArrowShape(render = render, color = color, head_at_origin = true, diameter = arrow_diameter)
  structural parameter resolve_in_frame::MultibodyComponents.ResolveInFrame = MultibodyComponents.ResolveInFrame.FrameA()
  "Scale factor for force visualization (length = force * scale)"
  parameter scale::Real = 0.1
  "Diameter of the force arrow shaft"
  parameter arrow_diameter::Real = 0.05
  "z-position of the arrow in animations"
  parameter z_position::Real = 0
  "Angle of resolution frame"
  variable phi::Angle
relations
  if resolve_in_frame == MultibodyComponents.ResolveInFrame.World()
    phi = 0
  end
  if resolve_in_frame == MultibodyComponents.ResolveInFrame.FrameA()
    phi = frame_a.phi
  end
  if resolve_in_frame == MultibodyComponents.ResolveInFrame.FrameB()
    phi = frame_b.phi
  end
  # Apply rotated force to frame_b
  frame_b.fx + cos(phi) * force_x - sin(phi) * force_y = 0
  frame_b.fy + sin(phi) * force_x + cos(phi) * force_y = 0
  frame_b.tau + torque = 0
  # Reaction forces on frame_a (equal and opposite)
  frame_a.fx + frame_b.fx = 0
  frame_a.fy + frame_b.fy = 0
  frame_a.tau + frame_b.tau = 0
  # Force arrow: display the applied force vector at frame_b
  force_arrow.r = [frame_b.x, frame_b.y, z_position]
  force_arrow.R = (MultibodyComponents.planar_rotation([0, 0, 1], phi, 0))
  force_arrow.r_shape = [0, 0, 0]
  force_arrow.length_direction = [force_x, force_y, 0]
  force_arrow.width_direction = [0, 0, 1]
  force_arrow.length = sqrt(force_x ^ 2 + force_y ^ 2) * scale
  force_arrow.width = arrow_diameter
  force_arrow.height = arrow_diameter
metadata {"Dyad": {"icons": {"default": "dyad://MultibodyComponents/RelativeForce.svg"}}}
end
Flattened Source
dyad
"""
Relative force and torque acting between frame_a and frame_b, defined by input signals.

Applies the input force to frame_b and the reaction (equal and opposite) to frame_a.
The force inputs (force_x, force_y) and torque input are resolved in the frame
selected by the structural parameter `resolve_in_frame` (world, frame_a, or frame_b).
"""
component RelativeForce
  parameter render::Boolean = true
  parameter color::Real[4] = [0.5, 0.5, 0.5, 1.0]
  parameter specular_coefficient::Real = 0.7
  frame_a = Frame2D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": -50, "y1": 450, "x2": 50, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  frame_b = Frame2D() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 950, "y1": 450, "x2": 1050, "y2": 550, "rot": 0}
      },
      "tags": []
    }
  }
  force_x = RealInput() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 90, "y1": -50, "x2": 190, "y2": 50, "rot": 90}
      },
      "tags": []
    }
  }
  force_y = RealInput() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": -50, "x2": 550, "y2": 50, "rot": 90}
      },
      "tags": []
    }
  }
  torque = RealInput() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 810, "y1": -50, "x2": 910, "y2": 50, "rot": 90}
      },
      "tags": []
    }
  }
  "Force arrow visualization at frame_b"
  force_arrow = MultibodyComponents.ArrowShape(render = render, color = color, head_at_origin = true, diameter = arrow_diameter)
  structural parameter resolve_in_frame::MultibodyComponents.ResolveInFrame = MultibodyComponents.ResolveInFrame.FrameA()
  "Scale factor for force visualization (length = force * scale)"
  parameter scale::Real = 0.1
  "Diameter of the force arrow shaft"
  parameter arrow_diameter::Real = 0.05
  "z-position of the arrow in animations"
  parameter z_position::Real = 0
  "Angle of resolution frame"
  variable phi::Angle
relations
  if resolve_in_frame == MultibodyComponents.ResolveInFrame.World()
    phi = 0
  end
  if resolve_in_frame == MultibodyComponents.ResolveInFrame.FrameA()
    phi = frame_a.phi
  end
  if resolve_in_frame == MultibodyComponents.ResolveInFrame.FrameB()
    phi = frame_b.phi
  end
  # Apply rotated force to frame_b
  frame_b.fx + cos(phi) * force_x - sin(phi) * force_y = 0
  frame_b.fy + sin(phi) * force_x + cos(phi) * force_y = 0
  frame_b.tau + torque = 0
  # Reaction forces on frame_a (equal and opposite)
  frame_a.fx + frame_b.fx = 0
  frame_a.fy + frame_b.fy = 0
  frame_a.tau + frame_b.tau = 0
  # Force arrow: display the applied force vector at frame_b
  force_arrow.r = [frame_b.x, frame_b.y, z_position]
  force_arrow.R = (MultibodyComponents.planar_rotation([0, 0, 1], phi, 0))
  force_arrow.r_shape = [0, 0, 0]
  force_arrow.length_direction = [force_x, force_y, 0]
  force_arrow.width_direction = [0, 0, 1]
  force_arrow.length = sqrt(force_x ^ 2 + force_y ^ 2) * scale
  force_arrow.width = arrow_diameter
  force_arrow.height = arrow_diameter
metadata {"Dyad": {"icons": {"default": "dyad://MultibodyComponents/RelativeForce.svg"}}}
end


Test Cases

No test cases defined.