PlanarMechanics.Cable
Planar cable / rope of total length l and mass m, modeled as n rigid BodyShape segments connected by Revolute joints. This is the planar (PlanarMechanics) analog of the 3D Cable, using 1-DOF revolute joints (rotation about the z-axis) in place of 3-DOF Spherical joints.
When end_joints = true (default), the topology uses n + 1 joints: frame_a → R₁ → link₁ → R₂ → … → Rₙ → linkₙ → Rₙ₊₁ → frame_b
When end_joints = false, only the n − 1 internal joints are kept and both ends attach rigidly to the adjacent frame: frame_a → link₁ → R₁ → link₂ → … → Rₙ₋₁ → linkₙ → frame_b
By default each Revolute joint transmits no torque (its rotational flange is left unconnected), so the cable swings freely. Setting hasdamping = true adds a viscous Damper of constant d_joint to every joint, dissipating energy as the cable flexes (the planar analog of the Rope's d_joint in Multibody.jl). Setting hasstiffness = true adds a rotational Spring of constant c_joint to every joint, giving the cable flexural stiffness (a restoring torque toward the straight configuration). The two are independent and may be combined.
The cable starts straight (along dir); seed an initial bend by setting a joint's angle as an initial condition, e.g. a 0.9 rad bend on the first joint: cable.joints[1].phi = 0.9.
This component extends from PartialTwoFrames This component extends from MultibodyComponents.Renderable
Usage
MultibodyComponents.PlanarMechanics.Cable(render=true, color=[0.5, 0.4, 0.4, 1], specular_coefficient=1.5, d_joint=0, c_joint=0, l=1, m=1, dir=[0, -1], radius=0.05, z_position=0, r_segment=(l / n) * (dir / norm(dir)), m_segment=m / n, I_segment=m_segment * (l / n) ^ 2 / 12)
Parameters:
| Name | Description | Units | Default value |
|---|---|---|---|
n | Number of rigid segments | – | 5 |
end_joints | Include Revolute joints at both ends (frame_a and frame_b) | – | true |
hasdamping | Add viscous damping in the joints between links (dissipates energy while the cable flexes) | – | false |
hasstiffness | Add rotational stiffness in the joints between links (the cable resists bending toward straight) | – | false |
nj | Number of joints | – | ifelse(end_...+ 1, n - 1) |
render | – | true | |
color | – | [0.5, 0.4, 0.4, 1] | |
specular_coefficient | – | 1.5 | |
d_joint | Viscous damping constant of each joint (used only if hasdamping = true) | N.m.s/rad | 0 |
c_joint | Rotational spring constant of each joint (used only if hasstiffness = true) | N.m/rad | 0 |
l | Total unstretched length of the rope | m | 1 |
m | Total mass of the rope (each segment gets m/n) | kg | 1 |
dir | Hanging direction in the plane; unit-normalized internally | – | [0, -1] |
radius | Rendering radius of each segment | – | 0.05 |
z_position | z-position of the cable segments 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)
Behavior
Source
"""
Planar cable / rope of total length `l` and mass `m`, modeled as `n` rigid
`BodyShape` segments connected by `Revolute` joints. This is the planar
(PlanarMechanics) analog of the 3D `Cable`, using 1-DOF revolute joints
(rotation about the z-axis) in place of 3-DOF `Spherical` joints.
When `end_joints = true` (default), the topology uses `n + 1` joints:
`frame_a → R₁ → link₁ → R₂ → … → Rₙ → linkₙ → Rₙ₊₁ → frame_b`
When `end_joints = false`, only the `n − 1` internal joints are kept and
both ends attach rigidly to the adjacent frame:
`frame_a → link₁ → R₁ → link₂ → … → Rₙ₋₁ → linkₙ → frame_b`
By default each `Revolute` joint transmits no torque (its rotational flange is
left unconnected), so the cable swings freely. Setting `hasdamping = true` adds
a viscous `Damper` of constant `d_joint` to every joint, dissipating energy as
the cable flexes (the planar analog of the `Rope`'s `d_joint` in Multibody.jl).
Setting `hasstiffness = true` adds a rotational `Spring` of constant `c_joint`
to every joint, giving the cable flexural stiffness (a restoring torque toward
the straight configuration). The two are independent and may be combined.
The cable starts straight (along `dir`); seed an initial bend by setting a
joint's angle as an initial condition, e.g. a 0.9 rad bend on the first joint:
`cable.joints[1].phi = 0.9`.
"""
component Cable
extends PartialTwoFrames
extends MultibodyComponents.Renderable(color = [0.5, 0.4, 0.4, 1])
joints = [Revolute(render = false, phi(initial = 0), w(initial = 0)) for i in 1:nj]
links = [BodyShape(r = r_segment, m = m_segment, I = I_segment, color = color, radius = radius, z_position = z_position) for i in 1:n]
dampers = [RotationalComponents.Components.Damper(d = d_joint) for i in 1:nj] if hasdamping
damper_ground = RotationalComponents.Components.Fixed() if hasdamping
springs = [RotationalComponents.Components.Spring(c = c_joint) for i in 1:nj] if hasstiffness
spring_ground = RotationalComponents.Components.Fixed() if hasstiffness
"Number of rigid segments"
structural parameter n::Integer = 5
"Include Revolute joints at both ends (frame_a and frame_b)"
structural parameter end_joints::Boolean = true
"Add viscous damping in the joints between links (dissipates energy while the cable flexes)"
structural parameter hasdamping::Boolean = false
"Viscous damping constant of each joint (used only if hasdamping = true)"
parameter d_joint::RotationalDampingConstant = 0
"Add rotational stiffness in the joints between links (the cable resists bending toward straight)"
structural parameter hasstiffness::Boolean = false
"Rotational spring constant of each joint (used only if hasstiffness = true)"
parameter c_joint::RotationalSpringConstant = 0
"Number of joints"
final structural parameter nj::Integer = ifelse(end_joints, n + 1, n - 1)
"Total unstretched length of the rope"
parameter l::Length = 1
"Total mass of the rope (each segment gets m/n)"
parameter m::Mass = 1
"Hanging direction in the plane; unit-normalized internally"
parameter dir::Real[2] = [0, -1]
"Rendering radius of each segment"
parameter radius::Real = 0.05
"z-position of the cable segments in animations"
parameter z_position::Real = 0
"Vector from frame_a to frame_b of one segment, resolved in segment frame_a"
final parameter r_segment::Length[2] = (l / n) * (dir / norm(dir))
"Mass of one segment"
final parameter m_segment::Mass = m / n
"Moment of inertia of one segment about its center of mass (thin rod)"
final parameter I_segment::MomentOfInertia = m_segment * (l / n) ^ 2 / 12
relations
if end_joints
connect(frame_a, joints[1].frame_a)
for i in 1:n
connect(joints[i].frame_b, links[i].frame_a)
connect(links[i].frame_b, joints[i + 1].frame_a)
end
connect(joints[nj].frame_b, frame_b)
else
connect(frame_a, links[1].frame_a)
for i in 1:nj
connect(links[i].frame_b, joints[i].frame_a)
connect(joints[i].frame_b, links[i + 1].frame_a)
end
connect(links[n].frame_b, frame_b)
end
# viscous joint damping: each joint flange is damped against a fixed reference,
# so the damper dissipates energy proportional to the joint's angular velocity
if hasdamping
for i in 1:nj
connect(joints[i].flange_a, dampers[i].spline_a)
connect(dampers[i].spline_b, damper_ground.spline)
end
end
# rotational joint stiffness: each joint flange is sprung against a fixed
# reference, so the spring applies a restoring torque toward the straight cable
if hasstiffness
for i in 1:nj
connect(joints[i].flange_a, springs[i].spline_a)
connect(springs[i].spline_b, spring_ground.spline)
end
end
metadata {
"Dyad": {
"icons": {"default": "dyad://MultibodyComponents/Cable.svg"},
"labels": [
{
"label": "$(instance)",
"x": 500,
"y": 150,
"rot": 0,
"attrs": {"font-size": "160"}
}
]
}
}
endFlattened Source
"""
Planar cable / rope of total length `l` and mass `m`, modeled as `n` rigid
`BodyShape` segments connected by `Revolute` joints. This is the planar
(PlanarMechanics) analog of the 3D `Cable`, using 1-DOF revolute joints
(rotation about the z-axis) in place of 3-DOF `Spherical` joints.
When `end_joints = true` (default), the topology uses `n + 1` joints:
`frame_a → R₁ → link₁ → R₂ → … → Rₙ → linkₙ → Rₙ₊₁ → frame_b`
When `end_joints = false`, only the `n − 1` internal joints are kept and
both ends attach rigidly to the adjacent frame:
`frame_a → link₁ → R₁ → link₂ → … → Rₙ₋₁ → linkₙ → frame_b`
By default each `Revolute` joint transmits no torque (its rotational flange is
left unconnected), so the cable swings freely. Setting `hasdamping = true` adds
a viscous `Damper` of constant `d_joint` to every joint, dissipating energy as
the cable flexes (the planar analog of the `Rope`'s `d_joint` in Multibody.jl).
Setting `hasstiffness = true` adds a rotational `Spring` of constant `c_joint`
to every joint, giving the cable flexural stiffness (a restoring torque toward
the straight configuration). The two are independent and may be combined.
The cable starts straight (along `dir`); seed an initial bend by setting a
joint's angle as an initial condition, e.g. a 0.9 rad bend on the first joint:
`cable.joints[1].phi = 0.9`.
"""
component Cable
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 = 1.5
joints = [Revolute(render = false, phi(initial = 0), w(initial = 0)) for i in 1:nj]
links = [BodyShape(r = r_segment, m = m_segment, I = I_segment, color = color, radius = radius, z_position = z_position) for i in 1:n]
dampers = [RotationalComponents.Components.Damper(d = d_joint) for i in 1:nj] if hasdamping
damper_ground = RotationalComponents.Components.Fixed() if hasdamping
springs = [RotationalComponents.Components.Spring(c = c_joint) for i in 1:nj] if hasstiffness
spring_ground = RotationalComponents.Components.Fixed() if hasstiffness
"Number of rigid segments"
structural parameter n::Integer = 5
"Include Revolute joints at both ends (frame_a and frame_b)"
structural parameter end_joints::Boolean = true
"Add viscous damping in the joints between links (dissipates energy while the cable flexes)"
structural parameter hasdamping::Boolean = false
"Viscous damping constant of each joint (used only if hasdamping = true)"
parameter d_joint::RotationalDampingConstant = 0
"Add rotational stiffness in the joints between links (the cable resists bending toward straight)"
structural parameter hasstiffness::Boolean = false
"Rotational spring constant of each joint (used only if hasstiffness = true)"
parameter c_joint::RotationalSpringConstant = 0
"Number of joints"
final structural parameter nj::Integer = ifelse(end_joints, n + 1, n - 1)
"Total unstretched length of the rope"
parameter l::Length = 1
"Total mass of the rope (each segment gets m/n)"
parameter m::Mass = 1
"Hanging direction in the plane; unit-normalized internally"
parameter dir::Real[2] = [0, -1]
"Rendering radius of each segment"
parameter radius::Real = 0.05
"z-position of the cable segments in animations"
parameter z_position::Real = 0
"Vector from frame_a to frame_b of one segment, resolved in segment frame_a"
final parameter r_segment::Length[2] = (l / n) * (dir / norm(dir))
"Mass of one segment"
final parameter m_segment::Mass = m / n
"Moment of inertia of one segment about its center of mass (thin rod)"
final parameter I_segment::MomentOfInertia = m_segment * (l / n) ^ 2 / 12
relations
if end_joints
connect(frame_a, joints[1].frame_a)
for i in 1:n
connect(joints[i].frame_b, links[i].frame_a)
connect(links[i].frame_b, joints[i + 1].frame_a)
end
connect(joints[nj].frame_b, frame_b)
else
connect(frame_a, links[1].frame_a)
for i in 1:nj
connect(links[i].frame_b, joints[i].frame_a)
connect(joints[i].frame_b, links[i + 1].frame_a)
end
connect(links[n].frame_b, frame_b)
end
# viscous joint damping: each joint flange is damped against a fixed reference,
# so the damper dissipates energy proportional to the joint's angular velocity
if hasdamping
for i in 1:nj
connect(joints[i].flange_a, dampers[i].spline_a)
connect(dampers[i].spline_b, damper_ground.spline)
end
end
# rotational joint stiffness: each joint flange is sprung against a fixed
# reference, so the spring applies a restoring torque toward the straight cable
if hasstiffness
for i in 1:nj
connect(joints[i].flange_a, springs[i].spline_a)
connect(springs[i].spline_b, spring_ground.spline)
end
end
metadata {
"Dyad": {
"icons": {"default": "dyad://MultibodyComponents/Cable.svg"},
"labels": [
{
"label": "$(instance)",
"x": 500,
"y": 150,
"rot": 0,
"attrs": {"font-size": "160"}
}
]
}
}
endTest Cases
No test cases defined.
Related
Examples
Experiments
Analyses
Tests