Skip to content
LIBRARY
tests.Sensors3DTest.md

tests.Sensors3DTest

3D Sensors Test

A pendulum that exercises all seventeen 3D multibody sensors. A revolute joint about the world z-axis connects the world to a rigid bar carrying a body. Released from rest in the horizontal position, the pendulum swings under gravity.

The inline CutForce, CutTorque, CutForceAndTorque and Power sensors sit in the load path between the bar and the body, while the remaining sensors read the body pose/motion without exerting forces. Because the rotation is purely about z, the absolute and relative angle sequences reduce to [0, 0, phi], and the relative position traces the bar tip at unit radius.

Usage

MultibodyComponents.tests.Sensors3DTest()

Behavior

julia
using MultibodyComponents #hide
using ModelingToolkit #hide
@named sys = MultibodyComponents.tests.Sensors3DTest() #hide
let eqs = full_equations(sys); Base.length(eqs) > 25 ? nothing : eqs end #hide
<< @example-block not executed in draft mode >>

Source

dyad
"""
# 3D Sensors Test

A pendulum that exercises all seventeen 3D multibody sensors. A revolute joint
about the world z-axis connects the world to a rigid bar carrying a body.
Released from rest in the horizontal position, the pendulum swings under
gravity.

The inline `CutForce`, `CutTorque`, `CutForceAndTorque` and `Power` sensors sit
in the load path between the bar and the body, while the remaining sensors
read the body pose/motion without exerting forces. Because the rotation is
purely about z, the absolute and relative angle sequences reduce to
`[0, 0, phi]`, and the relative position traces the bar tip at unit radius.
"""
example component Sensors3DTest
  world = MultibodyComponents.World() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 10, "y1": 190, "x2": 110, "y2": 290, "rot": 0}
      },
      "tags": []
    }
  }
  revolute = MultibodyComponents.Revolute(n = [0, 0, 1], phi(initial = 0), w(initial = 0)) {
    "Dyad": {
      "placement": {
        "diagram": {
          "iconName": "default",
          "x1": 150.5,
          "y1": 443,
          "x2": 250.5,
          "y2": 543,
          "rot": 0
        }
      },
      "tags": []
    }
  }
  bar = MultibodyComponents.FixedTranslation(r = [1, 0, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 276, "y1": 443, "x2": 376, "y2": 543, "rot": 0}
      },
      "tags": []
    }
  }
  cut_force = MultibodyComponents.CutForce(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 401, "y1": 443, "x2": 501, "y2": 543, "rot": 0}
      },
      "tags": []
    }
  }
  cut_torque = MultibodyComponents.CutTorque(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 531, "y1": 443, "x2": 631, "y2": 543, "rot": 0}
      },
      "tags": []
    }
  }
  cut_ft = MultibodyComponents.CutForceAndTorque(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 661, "y1": 443, "x2": 761, "y2": 543, "rot": 0}
      },
      "tags": []
    }
  }
  power = MultibodyComponents.Power() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 791, "y1": 443, "x2": 891, "y2": 543, "rot": 0}
      },
      "tags": []
    }
  }
  body = MultibodyComponents.Body(m = 1, r_cm = [0, 0, 0], I_11 = 0.1, I_22 = 0.1, I_33 = 0.1) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 276, "y1": 190, "x2": 376, "y2": 290, "rot": 0}
      },
      "tags": []
    }
  }
  abs_angles = MultibodyComponents.AbsoluteAngles() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 310, "y1": 10, "x2": 410, "y2": 110, "rot": 0}
      },
      "tags": []
    }
  }
  rel_angles = MultibodyComponents.RelativeAngles() {
    "Dyad": {
      "placement": {
        "diagram": {
          "iconName": "default",
          "x1": 150.5,
          "y1": 190,
          "x2": 250.5,
          "y2": 290,
          "rot": 0
        }
      },
      "tags": []
    }
  }
  rel_pos = MultibodyComponents.RelativePosition(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {
          "iconName": "default",
          "x1": 150.5,
          "y1": 317,
          "x2": 250.5,
          "y2": 417,
          "rot": 0
        }
      },
      "tags": []
    }
  }
  abs_pos = MultibodyComponents.AbsolutePosition(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 10, "y1": 650, "x2": 110, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  abs_vel = MultibodyComponents.AbsoluteVelocity(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 140, "y1": 650, "x2": 240, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  abs_angvel_a = MultibodyComponents.AbsoluteAngularVelocity(resolve_in_frame = ResolveInFrame.FrameA()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 270, "y1": 650, "x2": 370, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  abs_angvel_w = MultibodyComponents.AbsoluteAngularVelocity(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 400, "y1": 650, "x2": 500, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  rel_vel = MultibodyComponents.RelativeVelocity(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 530, "y1": 650, "x2": 630, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  rel_angvel = MultibodyComponents.RelativeAngularVelocity(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 660, "y1": 650, "x2": 760, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  distance = MultibodyComponents.Distance() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 790, "y1": 650, "x2": 890, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  xform_v = MultibodyComponents.TransformAbsoluteVector(frame_r_in = ResolveInFrame.World(), frame_r_out = ResolveInFrame.FrameA()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 920, "y1": 650, "x2": 1020, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  abs_sensor = MultibodyComponents.AbsoluteSensor(resolve_in_frame = ResolveInFrame.World(), get_r = true, get_v = true, get_a = true, get_w = true, get_z = true, get_angles = true) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 10, "y1": 800, "x2": 110, "y2": 900, "rot": 0}
      },
      "tags": []
    }
  }
  rel_sensor = MultibodyComponents.RelativeSensor(resolve_in_frame = ResolveInFrame.World(), get_r_rel = true, get_v_rel = true, get_a_rel = true, get_w_rel = true, get_z_rel = true, get_angles = true) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 200, "y1": 800, "x2": 300, "y2": 900, "rot": 0}
      },
      "tags": []
    }
  }
  rel_sensor2 = MultibodyComponents.RelativeSensor(resolve_in_frame = ResolveInFrame.FrameA(), resolve_in_frame_after_differentiation = ResolveInFrame.World(), get_v_rel = true) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 800, "x2": 550, "y2": 900, "rot": 0}
      },
      "tags": []
    }
  }
relations
  # Load path: world -> revolute -> bar -> cut_force -> cut_torque -> cut_ft -> power -> body
  connect(world.frame_b, revolute.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 135, "y": 493}], "E": 2}],
      "junctions": [{"x": 135, "y": 240}],
      "renderStyle": "standard"
    }
  }
  connect(revolute.frame_b, bar.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(bar.frame_b, cut_force.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(cut_force.frame_b, cut_torque.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(cut_torque.frame_b, cut_ft.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(cut_ft.frame_b, power.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(power.frame_b, body.frame_a) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 906, "y": 493}, {"x": 906, "y": 140}], "E": -1},
        {"S": -1, "M": [{"x": 266, "y": 240}], "E": 2}
      ],
      "junctions": [{"x": 266, "y": 140}],
      "renderStyle": "standard"
    }
  }
  # Read-only sensors on the body
  connect(body.frame_a, abs_angles.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 266, "y": 60}], "E": 2}],
      "junctions": [{"x": 266, "y": 240}],
      "renderStyle": "standard"
    }
  }
  connect(world.frame_b, rel_angles.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, rel_angles.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, rel_pos.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 135, "y": 240}], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 135, "y": 367}],
      "renderStyle": "standard"
    }
  }
  connect(body.frame_a, rel_pos.frame_b) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 266, "y": 240}, {"x": 266, "y": 367}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(body.frame_a, abs_pos.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, abs_vel.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, abs_angvel_a.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, abs_angvel_w.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, rel_vel.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, rel_vel.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, rel_angvel.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, rel_angvel.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, distance.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, distance.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, xform_v.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  xform_v.r_in_x = der(body.r_0[1])
  xform_v.r_in_y = der(body.r_0[2])
  xform_v.r_in_z = der(body.r_0[3])
  connect(body.frame_a, abs_sensor.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, rel_sensor.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, rel_sensor.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, rel_sensor2.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, rel_sensor2.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
metadata {"Dyad": {"tests": {"case1": {"stop": 2}}}}
end
Flattened Source
dyad
"""
# 3D Sensors Test

A pendulum that exercises all seventeen 3D multibody sensors. A revolute joint
about the world z-axis connects the world to a rigid bar carrying a body.
Released from rest in the horizontal position, the pendulum swings under
gravity.

The inline `CutForce`, `CutTorque`, `CutForceAndTorque` and `Power` sensors sit
in the load path between the bar and the body, while the remaining sensors
read the body pose/motion without exerting forces. Because the rotation is
purely about z, the absolute and relative angle sequences reduce to
`[0, 0, phi]`, and the relative position traces the bar tip at unit radius.
"""
example component Sensors3DTest
  world = MultibodyComponents.World() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 10, "y1": 190, "x2": 110, "y2": 290, "rot": 0}
      },
      "tags": []
    }
  }
  revolute = MultibodyComponents.Revolute(n = [0, 0, 1], phi(initial = 0), w(initial = 0)) {
    "Dyad": {
      "placement": {
        "diagram": {
          "iconName": "default",
          "x1": 150.5,
          "y1": 443,
          "x2": 250.5,
          "y2": 543,
          "rot": 0
        }
      },
      "tags": []
    }
  }
  bar = MultibodyComponents.FixedTranslation(r = [1, 0, 0]) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 276, "y1": 443, "x2": 376, "y2": 543, "rot": 0}
      },
      "tags": []
    }
  }
  cut_force = MultibodyComponents.CutForce(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 401, "y1": 443, "x2": 501, "y2": 543, "rot": 0}
      },
      "tags": []
    }
  }
  cut_torque = MultibodyComponents.CutTorque(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 531, "y1": 443, "x2": 631, "y2": 543, "rot": 0}
      },
      "tags": []
    }
  }
  cut_ft = MultibodyComponents.CutForceAndTorque(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 661, "y1": 443, "x2": 761, "y2": 543, "rot": 0}
      },
      "tags": []
    }
  }
  power = MultibodyComponents.Power() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 791, "y1": 443, "x2": 891, "y2": 543, "rot": 0}
      },
      "tags": []
    }
  }
  body = MultibodyComponents.Body(m = 1, r_cm = [0, 0, 0], I_11 = 0.1, I_22 = 0.1, I_33 = 0.1) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 276, "y1": 190, "x2": 376, "y2": 290, "rot": 0}
      },
      "tags": []
    }
  }
  abs_angles = MultibodyComponents.AbsoluteAngles() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 310, "y1": 10, "x2": 410, "y2": 110, "rot": 0}
      },
      "tags": []
    }
  }
  rel_angles = MultibodyComponents.RelativeAngles() {
    "Dyad": {
      "placement": {
        "diagram": {
          "iconName": "default",
          "x1": 150.5,
          "y1": 190,
          "x2": 250.5,
          "y2": 290,
          "rot": 0
        }
      },
      "tags": []
    }
  }
  rel_pos = MultibodyComponents.RelativePosition(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {
          "iconName": "default",
          "x1": 150.5,
          "y1": 317,
          "x2": 250.5,
          "y2": 417,
          "rot": 0
        }
      },
      "tags": []
    }
  }
  abs_pos = MultibodyComponents.AbsolutePosition(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 10, "y1": 650, "x2": 110, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  abs_vel = MultibodyComponents.AbsoluteVelocity(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 140, "y1": 650, "x2": 240, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  abs_angvel_a = MultibodyComponents.AbsoluteAngularVelocity(resolve_in_frame = ResolveInFrame.FrameA()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 270, "y1": 650, "x2": 370, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  abs_angvel_w = MultibodyComponents.AbsoluteAngularVelocity(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 400, "y1": 650, "x2": 500, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  rel_vel = MultibodyComponents.RelativeVelocity(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 530, "y1": 650, "x2": 630, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  rel_angvel = MultibodyComponents.RelativeAngularVelocity(resolve_in_frame = ResolveInFrame.World()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 660, "y1": 650, "x2": 760, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  distance = MultibodyComponents.Distance() {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 790, "y1": 650, "x2": 890, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  xform_v = MultibodyComponents.TransformAbsoluteVector(frame_r_in = ResolveInFrame.World(), frame_r_out = ResolveInFrame.FrameA()) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 920, "y1": 650, "x2": 1020, "y2": 750, "rot": 0}
      },
      "tags": []
    }
  }
  abs_sensor = MultibodyComponents.AbsoluteSensor(resolve_in_frame = ResolveInFrame.World(), get_r = true, get_v = true, get_a = true, get_w = true, get_z = true, get_angles = true) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 10, "y1": 800, "x2": 110, "y2": 900, "rot": 0}
      },
      "tags": []
    }
  }
  rel_sensor = MultibodyComponents.RelativeSensor(resolve_in_frame = ResolveInFrame.World(), get_r_rel = true, get_v_rel = true, get_a_rel = true, get_w_rel = true, get_z_rel = true, get_angles = true) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 200, "y1": 800, "x2": 300, "y2": 900, "rot": 0}
      },
      "tags": []
    }
  }
  rel_sensor2 = MultibodyComponents.RelativeSensor(resolve_in_frame = ResolveInFrame.FrameA(), resolve_in_frame_after_differentiation = ResolveInFrame.World(), get_v_rel = true) {
    "Dyad": {
      "placement": {
        "diagram": {"iconName": "default", "x1": 450, "y1": 800, "x2": 550, "y2": 900, "rot": 0}
      },
      "tags": []
    }
  }
relations
  # Load path: world -> revolute -> bar -> cut_force -> cut_torque -> cut_ft -> power -> body
  connect(world.frame_b, revolute.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 135, "y": 493}], "E": 2}],
      "junctions": [{"x": 135, "y": 240}],
      "renderStyle": "standard"
    }
  }
  connect(revolute.frame_b, bar.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(bar.frame_b, cut_force.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(cut_force.frame_b, cut_torque.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(cut_torque.frame_b, cut_ft.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(cut_ft.frame_b, power.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(power.frame_b, body.frame_a) {
    "Dyad": {
      "edges": [
        {"S": 1, "M": [{"x": 906, "y": 493}, {"x": 906, "y": 140}], "E": -1},
        {"S": -1, "M": [{"x": 266, "y": 240}], "E": 2}
      ],
      "junctions": [{"x": 266, "y": 140}],
      "renderStyle": "standard"
    }
  }
  # Read-only sensors on the body
  connect(body.frame_a, abs_angles.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [], "E": -1}, {"S": -1, "M": [{"x": 266, "y": 60}], "E": 2}],
      "junctions": [{"x": 266, "y": 240}],
      "renderStyle": "standard"
    }
  }
  connect(world.frame_b, rel_angles.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, rel_angles.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, rel_pos.frame_a) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 135, "y": 240}], "E": -1}, {"S": -1, "M": [], "E": 2}],
      "junctions": [{"x": 135, "y": 367}],
      "renderStyle": "standard"
    }
  }
  connect(body.frame_a, rel_pos.frame_b) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 266, "y": 240}, {"x": 266, "y": 367}], "E": 2}],
      "renderStyle": "standard"
    }
  }
  connect(body.frame_a, abs_pos.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, abs_vel.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, abs_angvel_a.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, abs_angvel_w.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, rel_vel.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, rel_vel.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, rel_angvel.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, rel_angvel.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, distance.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, distance.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, xform_v.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  xform_v.r_in_x = der(body.r_0[1])
  xform_v.r_in_y = der(body.r_0[2])
  xform_v.r_in_z = der(body.r_0[3])
  connect(body.frame_a, abs_sensor.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, rel_sensor.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, rel_sensor.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(world.frame_b, rel_sensor2.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
  connect(body.frame_a, rel_sensor2.frame_b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
metadata {"Dyad": {"tests": {"case1": {"stop": 2}}}}
end


Test Cases

julia
using MultibodyComponents
using DyadInterface: TransientAnalysis, rebuild_sol, ODEAlg
using ModelingToolkit: toggle_namespacing, get_initial_conditions, @named
using CSV, DataFrames, Plots

snapshotsdir = joinpath(dirname(dirname(pathof(MultibodyComponents))), "test", "snapshots")
<< @setup-block not executed in draft mode >>

Test Case case1

julia
@named model_case1 = MultibodyComponents.tests.Sensors3DTest()
model_case1 = toggle_namespacing(model_case1, false)

model_case1 = toggle_namespacing(model_case1, true)
result_case1 = TransientAnalysis(; model = model_case1, alg = ODEAlg.Auto(), start = 0e+0, stop = 2e+0, abstol=1e-6, reltol=1e-6)
sol_case1 = rebuild_sol(result_case1)
<< @setup-block not executed in draft mode >>
  • Examples

  • Experiments

  • Analyses

julia
<< @example-block not executed in draft mode >>