LIBRARY
PlanarMechanics.examples.ParallelKinematicRobot
Usage
MultibodyComponents.PlanarMechanics.examples.ParallelKinematicRobot(a_length=0.53, b_length=0.4374, c_length=0.5, d_length=0.15, link_mass=1.5, w0=-0.5, phi0=deg2rad(10), alpha_tf=0, link_radius=0.03, link_color=[0.9, 0.9, 0.9, 1.0])
Parameters:
| Name | Description | Units | Default value |
|---|---|---|---|
a_length | m | 0.53 | |
b_length | m | 0.4374 | |
c_length | m | 0.5 | |
d_length | m | 0.15 | |
link_mass | kg | 1.5 | |
w0 | rad/s | -0.5 | |
phi0 | Initial angle of the base->a revolute joint | rad | deg2rad(10) |
alpha_tf | rad | 0 | |
link_radius | – | 0.03 | |
link_color | – | [0.9, 0.9, 0.9, 1] |
Behavior
julia
using MultibodyComponents #hide
using ModelingToolkit #hide
@variables a_length #hide
@variables b_length #hide
@variables c_length #hide
@variables d_length #hide
@variables link_mass #hide
@variables w0 #hide
@variables phi0 #hide
@variables alpha_tf #hide
@variables link_radius #hide
@variables link_color #hide
@named sys = MultibodyComponents.PlanarMechanics.examples.ParallelKinematicRobot(a_length=a_length, b_length=b_length, c_length=c_length, d_length=d_length, link_mass=link_mass, w0=w0, phi0=phi0, alpha_tf=alpha_tf, link_radius=link_radius, link_color=link_color) #hide
full_equations(sys) #hide<< @example-block not executed in draft mode >>Source
dyad
example component ParallelKinematicRobot
base = MultibodyComponents.PlanarMechanics.Fixed(r = [0.0, 0.520]) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 260, "y1": 630, "x2": 460, "y2": 830, "rot": 0}
},
"tags": []
}
}
base2 = MultibodyComponents.PlanarMechanics.Fixed(r = [0.15, 0.525]) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 0, "y1": 240, "x2": 200, "y2": 440, "rot": 0}
},
"tags": []
}
}
base_a = MultibodyComponents.PlanarMechanics.Revolute(radius = 1.3 * link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 520, "y1": 630, "x2": 720, "y2": 830, "rot": 0}
},
"tags": []
}
}
base2_b = MultibodyComponents.PlanarMechanics.Revolute(radius = 1.3 * link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 260, "y1": 240, "x2": 460, "y2": 440, "rot": 0}
},
"tags": []
}
}
a_cd = MultibodyComponents.PlanarMechanics.Revolute(radius = 1.3 * link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 1040, "y1": 630, "x2": 1240, "y2": 830, "rot": 0}
},
"tags": []
}
}
b_d = MultibodyComponents.PlanarMechanics.Revolute(radius = 1.3 * link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 780, "y1": 240, "x2": 980, "y2": 440, "rot": 0}
},
"tags": []
}
}
upper_arm = MultibodyComponents.PlanarMechanics.BodyShape(m = link_mass, r = [0, a_length], radius = link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 780, "y1": 630, "x2": 980, "y2": 830, "rot": 0}
},
"tags": []
}
}
link_b = MultibodyComponents.PlanarMechanics.BodyShape(m = link_mass, r = [0, b_length], radius = link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 520, "y1": 240, "x2": 720, "y2": 440, "rot": 0}
},
"tags": []
}
}
link_c = MultibodyComponents.PlanarMechanics.BodyShape(m = link_mass, r = [-c_length, 0], radius = link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 1300, "y1": 630, "x2": 1500, "y2": 830, "rot": 0}
},
"tags": []
}
}
link_d = MultibodyComponents.PlanarMechanics.BodyShape(m = link_mass, r = [d_length, 0], radius = link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {
"iconName": "default",
"x1": 1170,
"y1": 380,
"x2": 1370,
"y2": 580,
"rot": 270
}
},
"tags": []
}
}
fixed_rotation_tf = MultibodyComponents.PlanarMechanics.FixedRotation(alpha = alpha_tf) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 1560, "y1": 630, "x2": 1760, "y2": 830, "rot": 0}
},
"tags": []
}
}
end_effector = EndEffector() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 1810, "y1": 630, "x2": 2010, "y2": 830, "rot": 0}
},
"tags": []
}
}
speed = RotationalComponents.Sources.SpeedSource() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 260, "y1": 860, "x2": 460, "y2": 1060, "rot": 0}
},
"tags": []
}
}
w0_const = BlockComponents.Sources.Constant(k = w0) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 0, "y1": 860, "x2": 200, "y2": 1060, "rot": 0}
},
"tags": []
}
}
world = MultibodyComponents.PlanarMechanics.World() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 0, "y1": 550, "x2": 200, "y2": 750, "rot": 0}
},
"tags": []
}
}
fixed = RotationalComponents.Components.Fixed() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 310, "y1": 1130, "x2": 410, "y2": 1230, "rot": 0}
},
"tags": []
}
}
parameter a_length::Length = 0.53
parameter b_length::Length = 0.4374
parameter c_length::Length = 0.5
parameter d_length::Length = 0.15
parameter link_mass::Dyad.Mass = 1.5
parameter w0::AngularVelocity = -0.5
"Initial angle of the base->a revolute joint"
parameter phi0::Angle = deg2rad(10)
parameter alpha_tf::Angle = 0
parameter link_radius::Real = 0.03
parameter link_color::Real[4] = [0.9, 0.9, 0.9, 1.0]
relations
guess link_d.body.phi = 0
guess link_d.translation.phi = 0
guess link_b.translation.frame_b.fx = 1e-10
guess end_effector.body.frame_a.tau = 1e-10
guess link_b.translation.frame_b.fy = 1e-10
guess link_b.body.phi = 1e-10
guess link_b.translation.phi = 1e-10
guess speed.phi = 1e-10
guess end_effector.body.alpha = 1e-10
initial base_a.phi = phi0
# First chain: base → upper_arm → elbow
connect(base.frame_b, base_a.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(base_a.frame_b, upper_arm.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(upper_arm.frame_b, a_cd.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(a_cd.frame_b, link_c.frame_a, link_d.frame_a) {
"Dyad": {
"edges": [
{"S": 1, "M": [], "E": -1},
{"S": -1, "M": [], "E": 2},
{"S": -1, "M": [], "E": 3}
],
"junctions": [{"x": 1270, "y": 730}],
"renderStyle": "standard"
}
}
# Second chain: base2 → link_b → link_d (closes the loop)
connect(base2.frame_b, base2_b.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(base2_b.frame_b, link_b.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(link_b.frame_b, b_d.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(b_d.frame_b, link_d.frame_b) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 1270, "y": 340}], "E": 2}],
"renderStyle": "standard"
}
}
# End-effector: on link_c via fixed rotation
connect(link_c.frame_b, fixed_rotation_tf.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(fixed_rotation_tf.frame_b, end_effector.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
# Drive the base revolute at constant angular velocity
connect(speed.spline, base_a.flange_a) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 620, "y": 960}], "E": 2}],
"renderStyle": "standard"
}
}
connect(w0_const.y, speed.w_ref) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(fixed.spline, speed.support) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
metadata {"Dyad": {"tests": {"case1": {"stop": 10}}}}
endFlattened Source
dyad
example component ParallelKinematicRobot
base = MultibodyComponents.PlanarMechanics.Fixed(r = [0.0, 0.520]) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 260, "y1": 630, "x2": 460, "y2": 830, "rot": 0}
},
"tags": []
}
}
base2 = MultibodyComponents.PlanarMechanics.Fixed(r = [0.15, 0.525]) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 0, "y1": 240, "x2": 200, "y2": 440, "rot": 0}
},
"tags": []
}
}
base_a = MultibodyComponents.PlanarMechanics.Revolute(radius = 1.3 * link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 520, "y1": 630, "x2": 720, "y2": 830, "rot": 0}
},
"tags": []
}
}
base2_b = MultibodyComponents.PlanarMechanics.Revolute(radius = 1.3 * link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 260, "y1": 240, "x2": 460, "y2": 440, "rot": 0}
},
"tags": []
}
}
a_cd = MultibodyComponents.PlanarMechanics.Revolute(radius = 1.3 * link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 1040, "y1": 630, "x2": 1240, "y2": 830, "rot": 0}
},
"tags": []
}
}
b_d = MultibodyComponents.PlanarMechanics.Revolute(radius = 1.3 * link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 780, "y1": 240, "x2": 980, "y2": 440, "rot": 0}
},
"tags": []
}
}
upper_arm = MultibodyComponents.PlanarMechanics.BodyShape(m = link_mass, r = [0, a_length], radius = link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 780, "y1": 630, "x2": 980, "y2": 830, "rot": 0}
},
"tags": []
}
}
link_b = MultibodyComponents.PlanarMechanics.BodyShape(m = link_mass, r = [0, b_length], radius = link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 520, "y1": 240, "x2": 720, "y2": 440, "rot": 0}
},
"tags": []
}
}
link_c = MultibodyComponents.PlanarMechanics.BodyShape(m = link_mass, r = [-c_length, 0], radius = link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 1300, "y1": 630, "x2": 1500, "y2": 830, "rot": 0}
},
"tags": []
}
}
link_d = MultibodyComponents.PlanarMechanics.BodyShape(m = link_mass, r = [d_length, 0], radius = link_radius, color = link_color) {
"Dyad": {
"placement": {
"diagram": {
"iconName": "default",
"x1": 1170,
"y1": 380,
"x2": 1370,
"y2": 580,
"rot": 270
}
},
"tags": []
}
}
fixed_rotation_tf = MultibodyComponents.PlanarMechanics.FixedRotation(alpha = alpha_tf) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 1560, "y1": 630, "x2": 1760, "y2": 830, "rot": 0}
},
"tags": []
}
}
end_effector = EndEffector() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 1810, "y1": 630, "x2": 2010, "y2": 830, "rot": 0}
},
"tags": []
}
}
speed = RotationalComponents.Sources.SpeedSource() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 260, "y1": 860, "x2": 460, "y2": 1060, "rot": 0}
},
"tags": []
}
}
w0_const = BlockComponents.Sources.Constant(k = w0) {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 0, "y1": 860, "x2": 200, "y2": 1060, "rot": 0}
},
"tags": []
}
}
world = MultibodyComponents.PlanarMechanics.World() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 0, "y1": 550, "x2": 200, "y2": 750, "rot": 0}
},
"tags": []
}
}
fixed = RotationalComponents.Components.Fixed() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 310, "y1": 1130, "x2": 410, "y2": 1230, "rot": 0}
},
"tags": []
}
}
parameter a_length::Length = 0.53
parameter b_length::Length = 0.4374
parameter c_length::Length = 0.5
parameter d_length::Length = 0.15
parameter link_mass::Dyad.Mass = 1.5
parameter w0::AngularVelocity = -0.5
"Initial angle of the base->a revolute joint"
parameter phi0::Angle = deg2rad(10)
parameter alpha_tf::Angle = 0
parameter link_radius::Real = 0.03
parameter link_color::Real[4] = [0.9, 0.9, 0.9, 1.0]
relations
guess link_d.body.phi = 0
guess link_d.translation.phi = 0
guess link_b.translation.frame_b.fx = 1e-10
guess end_effector.body.frame_a.tau = 1e-10
guess link_b.translation.frame_b.fy = 1e-10
guess link_b.body.phi = 1e-10
guess link_b.translation.phi = 1e-10
guess speed.phi = 1e-10
guess end_effector.body.alpha = 1e-10
initial base_a.phi = phi0
# First chain: base → upper_arm → elbow
connect(base.frame_b, base_a.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(base_a.frame_b, upper_arm.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(upper_arm.frame_b, a_cd.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(a_cd.frame_b, link_c.frame_a, link_d.frame_a) {
"Dyad": {
"edges": [
{"S": 1, "M": [], "E": -1},
{"S": -1, "M": [], "E": 2},
{"S": -1, "M": [], "E": 3}
],
"junctions": [{"x": 1270, "y": 730}],
"renderStyle": "standard"
}
}
# Second chain: base2 → link_b → link_d (closes the loop)
connect(base2.frame_b, base2_b.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(base2_b.frame_b, link_b.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(link_b.frame_b, b_d.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(b_d.frame_b, link_d.frame_b) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 1270, "y": 340}], "E": 2}],
"renderStyle": "standard"
}
}
# End-effector: on link_c via fixed rotation
connect(link_c.frame_b, fixed_rotation_tf.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(fixed_rotation_tf.frame_b, end_effector.frame_a) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
# Drive the base revolute at constant angular velocity
connect(speed.spline, base_a.flange_a) {
"Dyad": {
"edges": [{"S": 1, "M": [{"x": 620, "y": 960}], "E": 2}],
"renderStyle": "standard"
}
}
connect(w0_const.y, speed.w_ref) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
connect(fixed.spline, speed.support) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "renderStyle": "standard"}}
metadata {"Dyad": {"tests": {"case1": {"stop": 10}}}}
endTest 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.PlanarMechanics.examples.ParallelKinematicRobot()
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 = 1e+1, abstol=1e-6, reltol=1e-6)
sol_case1 = rebuild_sol(result_case1)<< @setup-block not executed in draft mode >>Related
Examples
Experiments
Analyses