PlanarMechanics.CutForce
Measures the cut force between two rigidly connected frames.
This sensor is inserted between two frames in a kinematic chain. It constrains frame_a and frame_b to have identical position and orientation, and measures the reaction force needed to maintain this constraint. The measured force is output resolved in the frame selected by resolve_in_frame.
This is a sensor component: it does not alter the dynamics of the system.
This component extends from PartialTwoFrameSensor This component extends from MultibodyComponents.Renderable
Usage
MultibodyComponents.PlanarMechanics.CutForce(render=true, color=[0, 1, 0, 0.5], specular_coefficient=0.7, positive_sign=true, scale=0.1, arrow_diameter=0.03, z_position=0)
Parameters:
| Name | Description | Units | Default value |
|---|---|---|---|
resolve_in_frame | – | MultibodyComponents.ResolveInFrame.FrameA() | |
render | – | true | |
color | – | [0, 1, 0, 0.5] | |
specular_coefficient | – | 0.7 | |
positive_sign | Sign convention: true = force on frame_a, false = force on frame_b | – | true |
scale | Scale factor for force arrow visualization (length = force * scale) | – | 0.1 |
arrow_diameter | Diameter of the force arrow shaft | – | 0.03 |
z_position | z-position of the arrow in animations | – | 0 |
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 output from a component (RealOutput)force_y- This connector represents a real signal as an output from a component (RealOutput)
Variables
| Name | Description | Units |
|---|---|---|
f0x | Force in world frame before resolution | N |
f0y | N | |
phi_resolve | Angle of resolution frame | rad |
Behavior
Dict{MIME{Symbol("text/plain")}, String} with 1 entry: MIME type text/plain => "Error displaying result"
Source
# ── Cut sensors ──────────────────────────────────────────────────────────────
"""
Measures the cut force between two rigidly connected frames.
This sensor is inserted between two frames in a kinematic chain. It constrains
frame_a and frame_b to have identical position and orientation, and measures the
reaction force needed to maintain this constraint. The measured force is output
resolved in the frame selected by `resolve_in_frame`.
This is a sensor component: it does not alter the dynamics of the system.
"""
component CutForce
extends PartialTwoFrameSensor
extends MultibodyComponents.Renderable(color = [0, 1, 0, 0.5])
"x-component of the measured cut force"
force_x = RealOutput() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 190, "y1": 960, "x2": 290, "y2": 1060, "rot": 90}
},
"tags": []
}
}
"y-component of the measured cut force"
force_y = RealOutput() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 690, "y1": 960, "x2": 790, "y2": 1060, "rot": 90}
},
"tags": []
}
}
"Force arrow visualization"
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()
"Sign convention: true = force on frame_a, false = force on frame_b"
parameter positive_sign::Boolean = true
"Scale factor for force arrow visualization (length = force * scale)"
parameter scale::Real = 0.1
"Diameter of the force arrow shaft"
parameter arrow_diameter::Real = 0.03
"z-position of the arrow in animations"
parameter z_position::Real = 0
"Force in world frame before resolution"
variable f0x::Dyad.Force
variable f0y::Dyad.Force
"Angle of resolution frame"
variable phi_resolve::Angle
relations
# Rigid connection: identical position and orientation
frame_a.x = frame_b.x
frame_a.y = frame_b.y
frame_a.phi = frame_b.phi
# Force balance
frame_a.fx + frame_b.fx = 0
frame_a.fy + frame_b.fy = 0
# Torque balance
frame_a.tau + frame_b.tau = 0
# Cut force in world frame (sign convention)
f0x = ifelse(positive_sign, frame_a.fx, -frame_a.fx)
f0y = ifelse(positive_sign, frame_a.fy, -frame_a.fy)
# Resolution frame angle
if resolve_in_frame == MultibodyComponents.ResolveInFrame.World()
phi_resolve = 0
end
if resolve_in_frame == MultibodyComponents.ResolveInFrame.FrameA()
phi_resolve = frame_a.phi
end
if resolve_in_frame == MultibodyComponents.ResolveInFrame.FrameB()
phi_resolve = frame_b.phi
end
# Resolve force into chosen frame
force_x = cos(phi_resolve) * f0x + sin(phi_resolve) * f0y
force_y = -sin(phi_resolve) * f0x + cos(phi_resolve) * f0y
# Force arrow visualization at frame_b
force_arrow.r = [frame_b.x, frame_b.y, z_position]
force_arrow.R = MultibodyComponents.RR(MultibodyComponents.nullrotation())
force_arrow.r_shape = [0, 0, 0]
force_arrow.length_direction = [f0x, f0y, 0]
force_arrow.width_direction = [0, 0, 1]
force_arrow.length = sqrt(f0x ^ 2 + f0y ^ 2) * scale
force_arrow.width = arrow_diameter
force_arrow.height = arrow_diameter
metadata {
"Dyad": {
"icons": {"default": "dyad://MultibodyComponents/TwoFrameSensor.svg"},
"labels": [{"label": "cut force", "x": 500, "y": 680, "rot": 0}]
}
}
endFlattened Source
"""
Measures the cut force between two rigidly connected frames.
This sensor is inserted between two frames in a kinematic chain. It constrains
frame_a and frame_b to have identical position and orientation, and measures the
reaction force needed to maintain this constraint. The measured force is output
resolved in the frame selected by `resolve_in_frame`.
This is a sensor component: it does not alter the dynamics of the system.
"""
component CutForce
frame_a = Frame2D() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 50, "y1": 450, "x2": 150, "y2": 550, "rot": 0}
},
"tags": []
}
}
frame_b = Frame2D() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 850, "y1": 450, "x2": 950, "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 = 0.7
"x-component of the measured cut force"
force_x = RealOutput() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 190, "y1": 960, "x2": 290, "y2": 1060, "rot": 90}
},
"tags": []
}
}
"y-component of the measured cut force"
force_y = RealOutput() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 690, "y1": 960, "x2": 790, "y2": 1060, "rot": 90}
},
"tags": []
}
}
"Force arrow visualization"
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()
"Sign convention: true = force on frame_a, false = force on frame_b"
parameter positive_sign::Boolean = true
"Scale factor for force arrow visualization (length = force * scale)"
parameter scale::Real = 0.1
"Diameter of the force arrow shaft"
parameter arrow_diameter::Real = 0.03
"z-position of the arrow in animations"
parameter z_position::Real = 0
"Force in world frame before resolution"
variable f0x::Dyad.Force
variable f0y::Dyad.Force
"Angle of resolution frame"
variable phi_resolve::Angle
relations
# Rigid connection: identical position and orientation
frame_a.x = frame_b.x
frame_a.y = frame_b.y
frame_a.phi = frame_b.phi
# Force balance
frame_a.fx + frame_b.fx = 0
frame_a.fy + frame_b.fy = 0
# Torque balance
frame_a.tau + frame_b.tau = 0
# Cut force in world frame (sign convention)
f0x = ifelse(positive_sign, frame_a.fx, -frame_a.fx)
f0y = ifelse(positive_sign, frame_a.fy, -frame_a.fy)
# Resolution frame angle
if resolve_in_frame == MultibodyComponents.ResolveInFrame.World()
phi_resolve = 0
end
if resolve_in_frame == MultibodyComponents.ResolveInFrame.FrameA()
phi_resolve = frame_a.phi
end
if resolve_in_frame == MultibodyComponents.ResolveInFrame.FrameB()
phi_resolve = frame_b.phi
end
# Resolve force into chosen frame
force_x = cos(phi_resolve) * f0x + sin(phi_resolve) * f0y
force_y = -sin(phi_resolve) * f0x + cos(phi_resolve) * f0y
# Force arrow visualization at frame_b
force_arrow.r = [frame_b.x, frame_b.y, z_position]
force_arrow.R = MultibodyComponents.RR(MultibodyComponents.nullrotation())
force_arrow.r_shape = [0, 0, 0]
force_arrow.length_direction = [f0x, f0y, 0]
force_arrow.width_direction = [0, 0, 1]
force_arrow.length = sqrt(f0x ^ 2 + f0y ^ 2) * scale
force_arrow.width = arrow_diameter
force_arrow.height = arrow_diameter
metadata {
"Dyad": {
"icons": {"default": "dyad://MultibodyComponents/TwoFrameSensor.svg"},
"labels": [{"label": "cut force", "x": 500, "y": 680, "rot": 0}]
}
}
endTest Cases
No test cases defined.
Related
Examples
Experiments
Analyses
Tests