model SpringDamper "Linear 2D translational spring damper model"
extends BaseClasses.TwoConnectorShapes;
extends Modelica.Thermal.HeatTransfer.Interfaces.PartialElementaryConditionalHeatPort(final T = 293.15);
parameter StateSelect stateSelect = StateSelect.default "Priority to use phi, w and a as states"
annotation (
HideResult = true,
Dialog(tab = "Advanced"));
parameter SI.TranslationalSpringConstant c_x(final min = 0, start = 1) "Spring constant in x dir";
parameter SI.TranslationalSpringConstant c_y(final min = 0, start = 1) "Spring constant in y dir";
parameter SI.RotationalSpringConstant c_phi(final min = 0, start = 100000) "Spring constant in phi dir";
parameter SI.TranslationalDampingConstant d_x(final min = 0, start = 1) "Damping constant in x dir";
parameter SI.TranslationalDampingConstant d_y(final min = 0, start = 1) "Damping constant in y dir";
parameter SI.RotationalDampingConstant d_phi(final min = 0, start = 1) "Damping constant in phi dir";
parameter SI.Position s_relx0 = 0 "Unstretched spring length";
parameter SI.Position s_rely0 = 0 "Unstretched spring length";
parameter SI.Angle phi_rel0 = 0 "Unstretched spring angle";
SI.Velocity v_relx "Spring velocity";
SI.Velocity v_rely "Spring velocity";
SI.AngularVelocity w_rel(start = 0) "Spring anglular velocity"
annotation (Dialog(
group = "Initialization",
showStartAttribute = true));
SI.Position s_relx(final stateSelect = stateSelect) "Spring length";
SI.Position s_rely(final stateSelect = stateSelect) "Spring length";
SI.Angle phi_rel(start = 0, final stateSelect = stateSelect) "Spring angle"
annotation (Dialog(
group = "Initialization",
showStartAttribute = true));
SI.Force f_x "Force in x direction";
SI.Force f_y "Force in y direction";
SI.Torque tau "Torque between frames (= frame_b.f)";
parameter SI.Position s_small = 1e-10 "Prevent zero-division if distance between frame_a and frame_b is zero"
annotation (Dialog(tab = "Advanced"));
parameter Boolean enableAssert = true "Cause an assert when the distance between frame_a and frame_b < s_small"
annotation (Dialog(tab = "Advanced"));
parameter Integer numberOfWindings = 5 "Number of spring windings"
annotation (Dialog(
tab = "Animation",
group = "Spring coil (if animation = true)",
enable = animate));
input SI.Length width = planarWorld.defaultJointWidth "Width of spring"
annotation (Dialog(
tab = "Animation",
group = "Spring coil (if animation = true)",
enable = animate));
input SI.Length coilWidth = 0.1 * width "Width of spring coil"
annotation (Dialog(
tab = "Animation",
group = "Spring coil (if animation = true)",
enable = animate));
input MB.Types.Color color = Types.Defaults.SpringColor "Color of spring"
annotation (
HideResult = true,
Dialog(
tab = "Animation",
group = "Spring coil (if animation = true)",
enable = animate,
colorSelector = true));
parameter SI.Length length_a = planarWorld.defaultForceLength "Length of cylinder at frame_a side"
annotation (Dialog(
tab = "Animation",
group = "Damper cylinders (if animation = true)",
enable = animate));
input SI.Diameter diameter_a = planarWorld.defaultForceWidth "Diameter of cylinder at frame_a side"
annotation (Dialog(
tab = "Animation",
group = "Damper cylinders (if animation = true)",
enable = animate));
input SI.Diameter diameter_b = 0.6 * diameter_a "Diameter of cylinder at frame_b side"
annotation (Dialog(
tab = "Animation",
group = "Damper cylinders (if animation = true)",
enable = animate));
input MB.Types.Color color_a = {100, 100, 100} "Color of cylinder at frame_a side"
annotation (
HideResult = true,
Dialog(
tab = "Animation",
group = "Damper cylinders (if animation = true)",
enable = animate,
colorSelector = true));
input MB.Types.Color color_b = {155, 155, 155} "Color of cylinder at frame_b side"
annotation (
HideResult = true,
Dialog(
tab = "Animation",
group = "Damper cylinders (if animation = true)",
enable = animate,
colorSelector = true));
SI.Length length "Distance between the origin of frame_a and the origin of frame_b";
SI.Position r_rel_0[3] "Position vector (3D) from frame_a to frame_b resolved in multibody world frame";
Real e_rel_0[3](each final unit = "1") "Unit vector (3D) in direction from frame_a to frame_b, resolved in multibody world frame";
protected
MB.Visualizers.Advanced.Shape shapeCoil(shapeType = "spring", color = color, specularCoefficient = specularCoefficient, length = length, width = width, height = coilWidth * 2, lengthDirection = e_rel_0, widthDirection = {0, 1, 0}, extra = numberOfWindings, r = MB.Frames.resolve1(planarWorld.R, {frame_a.x, frame_a.y, zPosition}) + planarWorld.r_0, R = planarWorld.R) if planarWorld.enableAnimation and animate;
MB.Visualizers.Advanced.Shape cylinderDamper_a(shapeType = "cylinder", color = color_a, specularCoefficient = specularCoefficient, length = noEvent(min(length_a, length)), width = diameter_a, height = diameter_a, lengthDirection = {s_relx, s_rely, 0}, widthDirection = {0, 1, 0}, r = MB.Frames.resolve1(planarWorld.R, {frame_a.x, frame_a.y, zPosition}) + planarWorld.r_0, R = planarWorld.R) if planarWorld.enableAnimation and animate;
MB.Visualizers.Advanced.Shape cylinderDamper_b(shapeType = "cylinder", color = color_b, specularCoefficient = specularCoefficient, length = noEvent(max(length - length_a, 0)), width = diameter_b, height = diameter_b, lengthDirection = {s_relx, s_rely, 0}, widthDirection = {0, 1, 0}, r_shape = Modelica.Math.Vectors.normalize(r_rel_0) * noEvent(min(length_a, length)), r = MB.Frames.resolve1(planarWorld.R, {frame_a.x, frame_a.y, zPosition}) + planarWorld.r_0, R = planarWorld.R) if planarWorld.enableAnimation and animate;
equation
if enableAssert then
assert(noEvent(s_small < length), "\n The distance between the origin of frame_a and the origin of frame_b\n of a Spring component became smaller as parameter s_small\n (= a small number, defined in the \"Advanced\" menu). The distance is\n set to s_small, although it is smaller, to avoid a division by zero\n when computing the direction of the line force. Possible reasons\n for this situation:\n - At initial time the distance may already be zero: Change the initial\n positions of the bodies connected by this element.\n - Hardware stops are not modeled or are modeled not stiff enough.\n Include stops, e.g., stiff springs, or increase the stiffness\n if already present.\n - Another error in your model may lead to unrealistically large forces\n and torques that would in reality destroy the stops.\n - The flange_b connector might be defined by a pre-defined motion,\n e.g., with Modelica.Mechanics.Translational.Position and the\n predefined flange_b.s is zero or negative.\n", level = AssertionLevel.warning);
end if;
e_rel_0 = r_rel_0 / MB.Frames.Internal.maxWithoutEvent(length, s_small);
f_x = c_x * (s_relx - s_relx0) + d_x * v_relx;
f_y = c_y * (s_rely - s_rely0) + d_y * v_rely;
length = Modelica.Math.Vectors.length(r_rel_0);
lossPower = d_x * v_relx * v_relx + d_y * v_rely * v_rely;
phi_rel = frame_b.phi - frame_a.phi;
r_rel_0 = {s_relx, s_rely, 0};
s_relx = frame_b.x - frame_a.x;
s_rely = frame_b.y - frame_a.y;
tau = c_phi * (phi_rel - phi_rel0) + d_phi * w_rel;
v_relx = der(s_relx);
v_rely = der(s_rely);
w_rel = der(phi_rel);
frame_a.t = -tau;
frame_a.fx = -f_x;
frame_a.fy = -f_y;
frame_b.t = tau;
frame_b.fx = f_x;
frame_b.fy = f_y;
annotation (
Documentation(
revisions = "<html>\n<p>\n<img src=\"modelica://PlanarMechanics/Resources/Images/dlr_logo.png\" alt=\"DLR logo\">\n<strong>Developed 2010 at the DLR Institute of System Dynamics and Control</strong>\n</p>\n</html>",
info = "<html>\n<p>\nA <em>linear translational spring-damper</em>. x- and y direction stiffness and\ndamping can be parameterized.\n</p>\n</html>"),
Icon(
coordinateSystem(
preserveAspectRatio = true,
extent = {
{-100, -100},
{100, 100}},
grid = {2, 2}),
graphics = {
Line(
points = {
{-80, 40},
{-58, 40},
{-43, 10},
{-13, 70},
{17, 10},
{47, 70},
{62, 40},
{80, 40}},
color = {0, 0, 0}),
Line(
points = {
{-70, -106},
{-70, -41}},
color = {128, 128, 128}),
Line(
points = {
{70, -106},
{70, -41}},
color = {128, 128, 128}),
Line(
points = {
{-70, -100},
{70, -100}},
color = {128, 128, 128}),
Polygon(
points = {
{60, -97},
{70, -100},
{60, -103},
{60, -97}},
lineColor = {128, 128, 128},
fillColor = {128, 128, 128},
fillPattern = FillPattern.Solid),
Text(
extent = {
{-40, -96},
{40, -76}},
textColor = {128, 128, 128},
textString = "phi_rel"),
Rectangle(
extent = {
{-50, -10},
{40, -70}},
fillColor = {192, 192, 192},
fillPattern = FillPattern.Solid),
Line(points = {
{-50, -70},
{54, -70}}),
Line(points = {
{-50, -10},
{54, -10}}),
Line(points = {
{40, -40},
{80, -40}}),
Line(points = {
{-80, -40},
{-50, -40}}),
Line(points = {
{-80, 40},
{-80, -40}}),
Line(points = {
{80, 40},
{80, -40}}),
Line(points = {
{-96, 0},
{-80, 0}}),
Line(points = {
{96, 0},
{80, 0}}),
Text(
extent = {
{-150, 120},
{150, 80}},
textString = "%name",
textColor = {0, 0, 255}),
Line(
visible = useHeatPort,
points = {
{-100, -100},
{-100, -60},
{-40, -60},
{-20, -40}},
color = {191, 0, 0},
pattern = LinePattern.Dot)}),
Diagram(
coordinateSystem(
preserveAspectRatio = true,
extent = {
{-100, -100},
{100, 100}},
grid = {2, 2}),
graphics = {
Line(
points = {
{-80, 32},
{-58, 32},
{-43, 2},
{-13, 62},
{17, 2},
{47, 62},
{62, 32},
{80, 32}},
thickness = 0.5),
Line(
points = {
{-68, 32},
{-68, 97}},
color = {128, 128, 128}),
Line(
points = {
{72, 32},
{72, 97}},
color = {128, 128, 128}),
Line(
points = {
{-68, 92},
{72, 92}},
color = {128, 128, 128}),
Polygon(
points = {
{62, 95},
{72, 92},
{62, 89},
{62, 95}},
lineColor = {128, 128, 128},
fillColor = {128, 128, 128},
fillPattern = FillPattern.Solid),
Text(
extent = {
{-20, 72},
{20, 97}},
textColor = {0, 0, 255},
textString = "phi_rel"),
Rectangle(
extent = {
{-50, -20},
{40, -80}},
fillColor = {192, 192, 192},
fillPattern = FillPattern.Solid),
Line(points = {
{-50, -80},
{68, -80}}),
Line(points = {
{-50, -20},
{68, -20}}),
Line(points = {
{40, -50},
{80, -50}}),
Line(points = {
{-80, -50},
{-50, -50}}),
Line(points = {
{-80, 32},
{-80, -50}}),
Line(points = {
{80, 32},
{80, -50}}),
Line(points = {
{-100, 0},
{-80, 0}}),
Line(points = {
{100, 0},
{80, 0}})}));
end SpringDamper;