Rotor1D
Inertia with a 1D rotation axis that is embedded in a 3D mechanism.
J is the moment of inertia about the axis n (resolved in frame_a). flange_a/flange_b are the 1D drivetrain connections and frame_a is the bearing/carrier frame.
When drive_train_mechanics_3d = true the component adds the two effects a plain 1D inertia cannot represent:
the gyroscopic reaction
cross(w_a, nJ*w)that the spinning rotor exerts on its carrier, andthe correction
-e*dot(nJ, z_a), which returns the axial component of the carrier's angular acceleration to the carrier, because that axial torque is supplied through the flanges rather than through the frame.
Because of (2) this component models only the rotor's spin momentum. The rotor's mass and its full inertia tensor must still be present as an ordinary rigid body (e.g. a BodyCylinder) attached to the same frame; Rotor1D then adds the angular momentum J*e*w due to the relative spin. Using Rotor1D alone leaves the rotor massless in 3D.
exact = false drops the -dot(nJ, z_a) term from the rotor equation only (the carrier reaction is unchanged), neglecting the influence of the bearing on the rotor acceleration in order to break the resulting algebraic loop.
See Mounting1D for the meaning of drive_train_mechanics_3d.
This component extends from Renderable
Usage
MultibodyComponents.Rotor1D(render=true, color=world_default_rod_color(), specular_coefficient=1.5, J=1, n=[1, 0, 0], r_center=[0, 0, 0], cylinder_length=2 * world_default_joint_length(), cylinder_diameter=2 * world_default_joint_width(), e=normalize_(n), nJ=e * J)
Parameters:
| Name | Description | Units | Default value |
|---|---|---|---|
drive_train_mechanics_3d | Expose the carrier frame frame_a and apply the rotor's gyroscopic/axial reaction to it. Structural: when false, neither the connector nor any 3D term is emitted. | – | true |
exact | Include the influence of the carrier's angular acceleration on the rotor acceleration. Set false to neglect it and break the resulting algebraic loop. | – | true |
statePriority | State priority of the rotor's angle and speed | – | 10 |
render | – | true | |
color | – | world_default_rod_color() | |
specular_coefficient | – | 1.5 | |
J | Moment of inertia of the rotor about its axis | kg.m2 | 1 |
n | Axis of rotation, resolved in frame_a | – | [1, 0, 0] |
r_center | Position vector from frame_a to the rotor center, resolved in frame_a | m | [0, 0, 0] |
cylinder_length | Length of the rotor cylinder in animations | – | 2 * world_d...nt_length() |
cylinder_diameter | Diameter of the rotor cylinder in animations | – | 2 * world_d...int_width() |
Connectors
flange_a- This connector represents a rotational spline with angle and torque as the potential and flow variables, respectively. (Spline)flange_b- This connector represents a rotational spline with angle and torque as the potential and flow variables, respectively. (Spline)frame_a- Frame3D is the fundamental 3D connector used for 6DOF motion. Most components have one or severalFrame
connectors that can be connected together (Frame3D)
Variables
| Name | Description | Units |
|---|---|---|
phi | Rotation angle of the rotor relative to frame_a | rad |
w | Angular velocity of the rotor relative to frame_a | rad/s |
a | Angular acceleration of the rotor relative to frame_a | rad/s2 |
w_a | Absolute angular velocity of frame_a (the carrier), resolved in frame_a | rad/s |
z_a | Absolute angular acceleration of frame_a (the carrier), resolved in frame_a | rad/s2 |
Behavior
Dict{MIME{Symbol("text/plain")}, String} with 1 entry: MIME type text/plain => "Error displaying result"
Source
"""
Inertia with a 1D rotation axis that is embedded in a 3D mechanism.
`J` is the moment of inertia about the axis `n` (resolved in `frame_a`).
`flange_a`/`flange_b` are the 1D drivetrain connections and `frame_a` is the
bearing/carrier frame.
When `drive_train_mechanics_3d = true` the component adds the two effects a plain
1D inertia cannot represent:
1. the gyroscopic reaction `cross(w_a, nJ*w)` that the spinning rotor exerts on
its carrier, and
2. the correction `-e*dot(nJ, z_a)`, which returns the axial component of the
carrier's angular acceleration to the carrier, because that axial torque is
supplied through the *flanges* rather than through the frame.
Because of (2) this component models only the rotor's **spin momentum**. The
rotor's mass and its full inertia tensor must still be present as an ordinary
rigid body (e.g. a `BodyCylinder`) attached to the same frame; `Rotor1D` then adds
the angular momentum `J*e*w` due to the relative spin. Using `Rotor1D` alone
leaves the rotor massless in 3D.
`exact = false` drops the `-dot(nJ, z_a)` term from the rotor equation only (the
carrier reaction is unchanged), neglecting the influence of the bearing on the
rotor acceleration in order to break the resulting algebraic loop.
See `Mounting1D` for the meaning of `drive_train_mechanics_3d`.
"""
component Rotor1D
extends Renderable(color = world_default_rod_color())
flange_a = Spline() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": -50, "y1": 450, "x2": 50, "y2": 550, "rot": 180}
},
"tags": []
}
}
flange_b = Spline() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 950, "y1": 450, "x2": 1050, "y2": 550, "rot": 0}
},
"tags": []
}
}
frame_a = Frame3D() if drive_train_mechanics_3d {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 450, "y1": 950, "x2": 550, "y2": 1050, "rot": 90}
},
"tags": []
}
}
shape = CylinderShape(render = render, color = color, r = frame_a.r_0, R = transpose(frame_a.R), r_shape = r_center - e * (cylinder_length / 2), length_direction = e, length = cylinder_length, width = cylinder_diameter, height = cylinder_diameter) if drive_train_mechanics_3d {}
"Expose the carrier frame `frame_a` and apply the rotor's gyroscopic/axial reaction to it. Structural: when false, neither the connector nor any 3D term is emitted."
structural parameter drive_train_mechanics_3d::Boolean = true
"Include the influence of the carrier's angular acceleration on the rotor acceleration. Set false to neglect it and break the resulting algebraic loop."
structural parameter exact::Boolean = true
"State priority of the rotor's angle and speed"
structural parameter statePriority::Integer = 10
"Moment of inertia of the rotor about its axis"
parameter J::Inertia = 1
"Axis of rotation, resolved in frame_a"
parameter n::Real[3] = [1, 0, 0]
"Position vector from frame_a to the rotor center, resolved in frame_a"
parameter r_center::Length[3] = [0, 0, 0]
"Length of the rotor cylinder in animations"
parameter cylinder_length::Real = 2 * world_default_joint_length()
"Diameter of the rotor cylinder in animations"
parameter cylinder_diameter::Real = 2 * world_default_joint_width()
final parameter e::Real[3] = normalize_(n)
final parameter nJ::Real[3] = e * J
"Rotation angle of the rotor relative to frame_a"
variable phi::Angle(statePriority = statePriority)
"Angular velocity of the rotor relative to frame_a"
variable w::AngularVelocity(statePriority = statePriority)
"Angular acceleration of the rotor relative to frame_a"
variable a::AngularAcceleration
"Absolute angular velocity of frame_a (the carrier), resolved in frame_a"
variable w_a::AngularVelocity[3] if drive_train_mechanics_3d
"Absolute angular acceleration of frame_a (the carrier), resolved in frame_a"
variable z_a::AngularAcceleration[3] if drive_train_mechanics_3d
relations
phi = flange_a.phi
phi = flange_b.phi
w = der(phi)
a = der(w)
if drive_train_mechanics_3d
# Frame3D carries no angular velocity, so w_a is reconstructed from D(R) and
# z_a is a second derivative of R. Naming both (rather than inlining
# der(angular_velocity2(...))) is the idiom that MTK handles.
w_a = angular_velocity2(ori(frame_a))
z_a = der(w_a)
frame_a.f = [0, 0, 0]
frame_a.tau = cross(w_a, nJ * w) - e * dot(nJ, z_a)
if exact
J * a = flange_a.tau + flange_b.tau - dot(nJ, z_a)
else
J * a = flange_a.tau + flange_b.tau
end
else
J * a = flange_a.tau + flange_b.tau
end
metadata {
"Dyad": {
"icons": {"default": "dyad://MultibodyComponents/Rotor1D.svg"},
"labels": [
{
"label": "$(instance)",
"x": 500,
"y": 150,
"rot": 0,
"attrs": {"font-size": "140"}
}
]
}
}
endFlattened Source
"""
Inertia with a 1D rotation axis that is embedded in a 3D mechanism.
`J` is the moment of inertia about the axis `n` (resolved in `frame_a`).
`flange_a`/`flange_b` are the 1D drivetrain connections and `frame_a` is the
bearing/carrier frame.
When `drive_train_mechanics_3d = true` the component adds the two effects a plain
1D inertia cannot represent:
1. the gyroscopic reaction `cross(w_a, nJ*w)` that the spinning rotor exerts on
its carrier, and
2. the correction `-e*dot(nJ, z_a)`, which returns the axial component of the
carrier's angular acceleration to the carrier, because that axial torque is
supplied through the *flanges* rather than through the frame.
Because of (2) this component models only the rotor's **spin momentum**. The
rotor's mass and its full inertia tensor must still be present as an ordinary
rigid body (e.g. a `BodyCylinder`) attached to the same frame; `Rotor1D` then adds
the angular momentum `J*e*w` due to the relative spin. Using `Rotor1D` alone
leaves the rotor massless in 3D.
`exact = false` drops the `-dot(nJ, z_a)` term from the rotor equation only (the
carrier reaction is unchanged), neglecting the influence of the bearing on the
rotor acceleration in order to break the resulting algebraic loop.
See `Mounting1D` for the meaning of `drive_train_mechanics_3d`.
"""
component Rotor1D
parameter render::Boolean = true
parameter color::Real[4] = [0.5, 0.5, 0.5, 1.0]
parameter specular_coefficient::Real = 1.5
flange_a = Spline() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": -50, "y1": 450, "x2": 50, "y2": 550, "rot": 180}
},
"tags": []
}
}
flange_b = Spline() {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 950, "y1": 450, "x2": 1050, "y2": 550, "rot": 0}
},
"tags": []
}
}
frame_a = Frame3D() if drive_train_mechanics_3d {
"Dyad": {
"placement": {
"diagram": {"iconName": "default", "x1": 450, "y1": 950, "x2": 550, "y2": 1050, "rot": 90}
},
"tags": []
}
}
shape = CylinderShape(render = render, color = color, r = frame_a.r_0, R = transpose(frame_a.R), r_shape = r_center - e * (cylinder_length / 2), length_direction = e, length = cylinder_length, width = cylinder_diameter, height = cylinder_diameter) if drive_train_mechanics_3d {}
"Expose the carrier frame `frame_a` and apply the rotor's gyroscopic/axial reaction to it. Structural: when false, neither the connector nor any 3D term is emitted."
structural parameter drive_train_mechanics_3d::Boolean = true
"Include the influence of the carrier's angular acceleration on the rotor acceleration. Set false to neglect it and break the resulting algebraic loop."
structural parameter exact::Boolean = true
"State priority of the rotor's angle and speed"
structural parameter statePriority::Integer = 10
"Moment of inertia of the rotor about its axis"
parameter J::Inertia = 1
"Axis of rotation, resolved in frame_a"
parameter n::Real[3] = [1, 0, 0]
"Position vector from frame_a to the rotor center, resolved in frame_a"
parameter r_center::Length[3] = [0, 0, 0]
"Length of the rotor cylinder in animations"
parameter cylinder_length::Real = 2 * world_default_joint_length()
"Diameter of the rotor cylinder in animations"
parameter cylinder_diameter::Real = 2 * world_default_joint_width()
final parameter e::Real[3] = normalize_(n)
final parameter nJ::Real[3] = e * J
"Rotation angle of the rotor relative to frame_a"
variable phi::Angle(statePriority = statePriority)
"Angular velocity of the rotor relative to frame_a"
variable w::AngularVelocity(statePriority = statePriority)
"Angular acceleration of the rotor relative to frame_a"
variable a::AngularAcceleration
"Absolute angular velocity of frame_a (the carrier), resolved in frame_a"
variable w_a::AngularVelocity[3] if drive_train_mechanics_3d
"Absolute angular acceleration of frame_a (the carrier), resolved in frame_a"
variable z_a::AngularAcceleration[3] if drive_train_mechanics_3d
relations
phi = flange_a.phi
phi = flange_b.phi
w = der(phi)
a = der(w)
if drive_train_mechanics_3d
# Frame3D carries no angular velocity, so w_a is reconstructed from D(R) and
# z_a is a second derivative of R. Naming both (rather than inlining
# der(angular_velocity2(...))) is the idiom that MTK handles.
w_a = angular_velocity2(ori(frame_a))
z_a = der(w_a)
frame_a.f = [0, 0, 0]
frame_a.tau = cross(w_a, nJ * w) - e * dot(nJ, z_a)
if exact
J * a = flange_a.tau + flange_b.tau - dot(nJ, z_a)
else
J * a = flange_a.tau + flange_b.tau
end
else
J * a = flange_a.tau + flange_b.tau
end
metadata {
"Dyad": {
"icons": {"default": "dyad://MultibodyComponents/Rotor1D.svg"},
"labels": [
{
"label": "$(instance)",
"x": 500,
"y": 150,
"rot": 0,
"attrs": {"font-size": "140"}
}
]
}
}
endTest Cases
No test cases defined.
Related
Examples
Experiments
Analyses