ElastoBacklash2

model ElastoBacklash2 "Backlash connected in series to linear spring and damper (backlash is modeled with elasticity; at start of contact the flange torque can jump, contrary to the ElastoBacklash model)"
    parameter Modelica.SIunits.RotationalSpringConstant c(final min = Modelica.Constants.small, start = 100000) "Spring constant (c > 0 required)";
    parameter Modelica.SIunits.RotationalDampingConstant d(final min = 0, start = 0) "Damping constant";
    parameter Modelica.SIunits.Angle b(final min = 0) = 0 "Total backlash";
    parameter Modelica.SIunits.Angle phi_rel0 = 0 "Unstretched spring angle";

    extends Modelica.Mechanics.Rotational.Interfaces.PartialCompliantWithRelativeStates;
    extends Modelica.Thermal.HeatTransfer.Interfaces.PartialElementaryConditionalHeatPortWithoutT;

protected
    final parameter Modelica.SIunits.Angle bMax = 0.5 * b "Backlash in range bMin <= phi_rel - phi_rel0 <= bMax";
    final parameter Modelica.SIunits.Angle bMin = -bMax "Backlash in range bMin <= phi_rel - phi_rel0 <= bMax";
    Modelica.SIunits.Torque tau_c;
    Modelica.SIunits.Torque tau_d;
    Modelica.SIunits.Angle phi_diff = phi_rel - phi_rel0;
    constant Modelica.SIunits.Angle bEps = 1e-10 "Minimum backlash";
equation
    if initial() then 
        tau_c = if 1.5 * bMax < phi_diff then c * (phi_diff - bMax) else if phi_diff < 1.5 * bMin then c * (phi_diff - bMin) else 0.333333333333333 * c * phi_diff;
        tau_d = d * w_rel;
        tau = tau_c + tau_d;
        lossPower = tau_d * w_rel;
    else 
        tau_c = if abs(b) <= bEps then c * phi_diff else if bMax < phi_diff then c * (phi_diff - bMax) else if phi_diff < bMin then c * (phi_diff - bMin) else 0;
        tau_d = d * w_rel;
        tau = if abs(b) <= bEps then tau_c + tau_d else if bMax < phi_diff then if tau_c + tau_d <= 0 then 0 else tau_c + tau_d else if phi_diff < bMin then if 0 <= tau_c + tau_d then 0 else tau_c + tau_d else 0;
        lossPower = if abs(b) <= bEps then tau_d * w_rel else if bMax < phi_diff then if tau_c + tau_d <= 0 then 0 else tau_d * w_rel else if phi_diff < bMin then if 0 <= tau_c + tau_d then 0 else tau_d * w_rel else 0;
    end if;

    annotation (
        defaultComponentName = "elastoBacklash",
        Documentation(info = "<html>\n<p>\nThis element consists of a <strong>backlash</strong> element <strong>connected in series</strong>\nto a <strong>spring</strong> and <strong>damper</strong> element which are <strong>connected in parallel</strong>.\nThe spring constant shall be non-zero, otherwise the component cannot be used.\n</p>\n\n<p>\nIn combination with components IdealGear, the ElastoBacklash2 model\ncan be used to model a gear box with backlash, elasticity and damping.\n</p>\n\n<p>\nDuring initialization, the backlash characteristic is replaced by a continuous\napproximation in the backlash region, in order to reduce problems during\ninitialization, especially for inverse models.\n</p>\n\n<p>\nIf the backlash b is smaller as 1e-10 rad (especially, if b=0),\nthen the backlash is ignored and the component reduces to a spring/damper\nelement in parallel.\n</p>\n\n<p>\nIn the backlash region (-b/2 &le; flange_b.phi - flange_a.phi - phi_rel0 &le; b/2) no torque\nis exerted (flange_b.tau = 0). Outside of this region, contact is present and\nthe contact torque is basically computed with a linear\nspring/damper characteristic:\n</p>\n\n<pre>\n   desiredContactTorque = c*phi_contact + d*<strong>der</strong>(phi_contact)\n\n            phi_contact = phi_rel - phi_rel0 - b/2 <strong>if</strong> phi_rel - phi_rel0 &gt;  b/2\n                        = phi_rel - phi_rel0 + b/2 <strong>if</strong> phi_rel - phi_rel0 &lt; -b/2\n\n            phi_rel     = flange_b.phi - flange_a.phi;\n</pre>\n\n<p>\nThis torque characteristic leads to the following difficulty:\n</p>\n\n<ul>\n<li> If the damper torque becomes larger as the spring torque and with opposite sign,\n     the contact torque would be \"pulling/sticking\" which is unphysical, since during\n     contact only pushing torques can occur.</li>\n</ul>\n\n<p>\nIn the literature this issue seems to be not discussed. For this reason, the most simple\napproach is used in the ElastoBacklash2 model, by slightly changing\nthe linear spring/damper characteristic to:\n</p>\n\n<pre>\n    // Torque characteristic when phi_rel > phi_rel0\n    <strong>if</strong> phi_rel - phi_rel0 &lt; b/2 <strong>then</strong>\n       tau_c = 0;          // spring torque\n       tau_d = 0;          // damper torque\n       flange_b.tau = 0;\n    <strong>else</strong>\n       tau_c = c*(phi_rel - phi_rel0);    // spring torque\n       tau_d = d*<strong>der</strong>(phi_rel);            // damper torque\n       flange_b.tau = <strong>if</strong> tau_c + tau_d &le; 0 <strong>then</strong> 0 <strong>else</strong> tau_c + tau_d;\n    <strong>end if</strong>;\n</pre>\n\n<p>\nNote, when sticking would occur (tau_c + tau_d &le; 0), then the contact torque\nis explicitly set to zero.\n</p>\n\n\n<p>\nThis model of backlash is slightly different to the\n<a href=\"modelica://Modelica.Mechanics.Rotational.Components.ElastoBacklash\">ElastoBacklash</a>\ncomponent:\n</p>\n\n<ul>\n<li> An event occurs when contact occurs or when contact is released (contrary to the ElastoBacklash component).</li>\n<li> When contact occurs, the torque changes discontinuously, due to the damping.\n     The damping is larger as for the ElastoBacklash component (for the same damping coefficient),\n    because the ElastoBacklash component has a heuristic to avoid the discontinuity of the torque when contact occurs.</li>\n<li> For some models, the ElastoBacklash2 component leads to faster simulations\n      (as compared when using the ElastBacklash component).</li>\n</ul>\n\n\n<p>\nSee also the discussion\n<a href=\"modelica://Modelica.Mechanics.Rotational.UsersGuide.StateSelection\">State Selection</a>\nin the User's Guide of the Rotational library.\n</p>\n</html>"),
        Icon(
            coordinateSystem(
                preserveAspectRatio = false,
                extent = {
                    {-100, -100}, 
                    {100, 100}}),
            graphics = {
                Line(points = {
                    {-80, 32}, 
                    {-58, 32}, 
                    {-48, 0}, 
                    {-34, 61}, 
                    {-20, 0}, 
                    {-8, 60}, 
                    {0, 30}, 
                    {20, 30}}), 
                Rectangle(
                    extent = {
                        {-60, -10}, 
                        {-10, -50}},
                    fillColor = {192, 192, 192},
                    fillPattern = FillPattern.Solid), 
                Line(points = {
                    {-60, -50}, 
                    {0, -50}}), 
                Line(points = {
                    {-60, -10}, 
                    {0, -10}}), 
                Line(points = {
                    {-10, -30}, 
                    {20, -30}}), 
                Line(points = {
                    {-80, -30}, 
                    {-60, -30}}), 
                Line(points = {
                    {-80, 32}, 
                    {-80, -30}}), 
                Line(points = {
                    {20, 30}, 
                    {20, -30}}), 
                Line(points = {
                    {-90, 0}, 
                    {-80, 0}}), 
                Line(points = {
                    {90, 0}, 
                    {80, 0}}), 
                Line(points = {
                    {20, 0}, 
                    {60, 0}, 
                    {60, -30}}), 
                Line(points = {
                    {40, -12}, 
                    {40, -40}, 
                    {80, -40}, 
                    {80, 0}}), 
                Text(
                    extent = {
                        {-150, -130}, 
                        {150, -90}},
                    textString = "b=%b"), 
                Text(
                    extent = {
                        {-150, 100}, 
                        {150, 60}},
                    lineColor = {0, 0, 255},
                    textString = "%name"), 
                Text(
                    extent = {
                        {-152, -92}, 
                        {148, -52}},
                    textString = "c=%c"), 
                Line(
                    visible = useHeatPort,
                    points = {
                        {-100, -100}, 
                        {-100, -43}, 
                        {-34, -43}},
                    color = {191, 0, 0},
                    pattern = LinePattern.Dot), 
                Text(
                    extent = {
                        {20, 48}, 
                        {80, 10}},
                    lineColor = {95, 95, 95},
                    textString = "2")}),
        Diagram(
            coordinateSystem(
                preserveAspectRatio = true,
                extent = {
                    {-100, -100}, 
                    {100, 100}}),
            graphics = {
                Line(
                    points = {
                        {-80, 32}, 
                        {-58, 32}, 
                        {-48, 0}, 
                        {-34, 60}, 
                        {-20, 0}, 
                        {-8, 60}, 
                        {0, 30}, 
                        {20, 30}},
                    thickness = 0.5), 
                Line(
                    points = {
                        {-68, 32}, 
                        {-68, 97}},
                    color = {128, 128, 128}), 
                Line(
                    points = {
                        {80, 0}, 
                        {80, 96}},
                    color = {128, 128, 128}), 
                Line(
                    points = {
                        {-68, 92}, 
                        {72, 92}},
                    color = {128, 128, 128}), 
                Polygon(
                    points = {
                        {70, 95}, 
                        {80, 92}, 
                        {70, 89}, 
                        {70, 95}},
                    lineColor = {128, 128, 128},
                    fillColor = {128, 128, 128},
                    fillPattern = FillPattern.Solid), 
                Text(
                    extent = {
                        {-34, 77}, 
                        {40, 90}},
                    lineColor = {128, 128, 128},
                    textString = "phi_rel"), 
                Rectangle(
                    extent = {
                        {-60, -20}, 
                        {-10, -80}},
                    lineThickness = 0.5,
                    fillColor = {192, 192, 192},
                    fillPattern = FillPattern.Solid), 
                Line(
                    points = {
                        {-52, -80}, 
                        {0, -80}},
                    thickness = 0.5), 
                Line(
                    points = {
                        {-52, -20}, 
                        {0, -20}},
                    thickness = 0.5), 
                Line(
                    points = {
                        {-10, -50}, 
                        {20, -50}},
                    thickness = 0.5), 
                Line(
                    points = {
                        {-80, -50}, 
                        {-60, -50}},
                    thickness = 0.5), 
                Line(
                    points = {
                        {-80, 32}, 
                        {-80, -50}},
                    thickness = 0.5), 
                Line(
                    points = {
                        {20, 30}, 
                        {20, -50}},
                    thickness = 0.5), 
                Line(points = {
                    {-96, 0}, 
                    {-80, 0}}), 
                Line(
                    points = {
                        {96, 0}, 
                        {80, 0}},
                    thickness = 0.5), 
                Line(
                    points = {
                        {20, 0}, 
                        {60, 0}, 
                        {60, -30}},
                    thickness = 0.5), 
                Line(
                    points = {
                        {40, -12}, 
                        {40, -40}, 
                        {80, -40}, 
                        {80, 0}},
                    thickness = 0.5), 
                Line(
                    points = {
                        {30, 0}, 
                        {30, 64}},
                    color = {128, 128, 128}), 
                Line(
                    points = {
                        {30, 60}, 
                        {80, 60}},
                    color = {128, 128, 128}), 
                Polygon(
                    points = {
                        {70, 63}, 
                        {80, 60}, 
                        {70, 57}, 
                        {70, 63}},
                    lineColor = {128, 128, 128},
                    fillColor = {128, 128, 128},
                    fillPattern = FillPattern.Solid), 
                Text(
                    extent = {
                        {39, 60}, 
                        {68, 46}},
                    lineColor = {160, 160, 164},
                    textString = "b")}));
end ElastoBacklash2;