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)"
    parameter Modelica.SIunits.TranslationalSpringConstant c(final min = Modelica.Constants.small, start = 100000) "Spring constant (c > 0 required)";
    parameter Modelica.SIunits.TranslationalDampingConstant d(final min = 0, start = 0) "Damping constant";
    parameter Modelica.SIunits.Position b(final min = 0, displayUnit = "mm") = 0 "Total backlash";
    parameter Modelica.SIunits.Position s_rel0(displayUnit = "mm") = 0 "Unstretched spring length";

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

protected
    final parameter Modelica.SIunits.Position bMax = 0.5 * b "Backlash in range bMin <= s_rel - s_rel0 <= bMax";
    final parameter Modelica.SIunits.Position bMin = -bMax "Backlash in range bMin <= s_rel - s_rel0 <= bMax";
    Modelica.SIunits.Force f_c;
    Modelica.SIunits.Force f_d;
    Modelica.SIunits.Position s_diff = s_rel - s_rel0;
    constant Modelica.SIunits.Position bEps = 1e-8 "Minimum backlash";
equation
    if initial() then 
        f_c = if 1.5 * bMax < s_diff then c * (s_diff - bMax) else if s_diff < 1.5 * bMin then c * (s_diff - bMin) else 0.333333333333333 * c * s_diff;
        f_d = d * v_rel;
        f = f_c + f_d;
        lossPower = f_d * v_rel;
    else 
        f_c = if abs(b) <= bEps then c * s_diff else if bMax < s_diff then c * (s_diff - bMax) else if s_diff < bMin then c * (s_diff - bMin) else 0;
        f_d = d * v_rel;
        f = if abs(b) <= bEps then f_c + f_d else if bMax < s_diff then if f_c + f_d <= 0 then 0 else f_c + f_d else if s_diff < bMin then if 0 <= f_c + f_d then 0 else f_c + f_d else 0;
        lossPower = if abs(b) <= bEps then f_d * v_rel else if bMax < s_diff then if f_c + f_d <= 0 then 0 else f_d * v_rel else if s_diff < bMin then if 0 <= f_c + f_d then 0 else f_d * v_rel else 0;
    end if;

    annotation (
        defaultComponentName = "elastoBacklash",
        Documentation(info = "<html>\n            <p>\n                This element consists of a <strong>backlash</strong> element <strong>connected in series</strong>\n                to a <strong>spring</strong> and <strong>damper</strong> element which are <strong>connected in parallel</strong>.\n                The spring constant shall be non-zero, otherwise the component cannot be used.\n            </p>\n            <p>\n                During initialization, the backlash characteristic is replaced by a continuous\n                approximation in the backlash region, in order to reduce problems during\n                initialization, especially for inverse models.\n            </p>\n            <p>\n                If the backlash b is smaller as 1e-8 m (especially, if b=0),\n                then the backlash is ignored and the component reduces to a spring/damper\n                element in parallel.\n            </p>\n            <p>\n                In the backlash region (-b/2 &le; flange_b.s - flange_a.s - s_rel0 &le; b/2) no force\n                is exerted (flange_b.f = 0). Outside of this region, contact is present and\n                the contact force is basically computed with a linear\n                spring/damper characteristic:\n            </p>\n            <pre>\n            desiredContactTorque = c*s_contact + d*<strong>der</strong>(s_contact)\n\n                    s_contact = s_rel - s_rel0 - b/2 <strong>if</strong> s_rel - s_rel0 &gt;  b/2\n                              = s_rel - s_rel0 + b/2 <strong>if</strong> s_rel - s_rel0 &lt; -b/2\n\n                    s_rel     = flange_b.s - flange_a.s;\n            </pre>\n\n            <p>\n                This force characteristic leads to the following difficulty:\n            </p>\n            <ul>\n                <li> If the damper force becomes larger as the spring force and with opposite sign,\n                 the contact force would be \"pulling/sticking\" which is unphysical, since during\n                 contact only pushing torques can occur.</li>\n            </ul>\n            <p>\n                In the literature this issue seems to be not discussed. For this reason, the most simple\n                approach is used in the ElastoBacklash2 model, by slightly changing\n                the linear spring/damper characteristic to:\n            </p>\n            <pre>\n                // Force characteristic when s_rel > s_rel0\n                <strong>if</strong> s_rel - s_rel0 &lt; b/2 <strong>then</strong>\n                   f_c = 0;          // spring force\n                   f_d = 0;          // damper force\n                   flange_b.f = 0;\n                <strong>else</strong>\n                   f_c = c*(s_rel - s_rel0);    // spring force\n                   f_d = d*<strong>der</strong>(s_rel);            // damper force\n                   flange_b.f = <strong>if</strong> f_c + f_d &le; 0 <strong>then</strong> 0 <strong>else</strong> f_c + f_d;\n                <strong>end if</strong>;\n            </pre>\n            <p>\n                Note, when sticking would occur (f_c + f_d &le; 0), then the contact force\n                is explicitly set to zero.\n            </p>\n            <p>\n                This model of backlash is slightly different to the\n                <a href=\"modelica://Modelica.Mechanics.Rotational.Components.ElastoBacklash\">ElastoBacklash</a>\n                component:\n            </p>\n            <ul>\n                <li> An event occurs when contact occurs or when contact is released.</li>\n                <li> When contact occurs, the force changes discontinuously, due to the damping.</li>\n            </ul>\n            <p>\n                See also the discussion\n                <a href=\"modelica://Modelica.Mechanics.Rotational.UsersGuide.StateSelection\">State Selection</a>\n                in the User's Guide of the Rotational library.\n            </p>\n            </html>"),
        Icon(graphics = {
            Line(
                visible = useHeatPort,
                points = {
                    {-100, -100}, 
                    {-100, -43}, 
                    {-34, -43}},
                color = {191, 0, 0},
                pattern = LinePattern.Dot), 
            Line(
                points = {
                    {-12, -38}, 
                    {-12, 36}},
                color = {0, 127, 0}), 
            Line(
                points = {
                    {-12, -28}, 
                    {70, -28}, 
                    {70, 24}},
                color = {0, 127, 0}), 
            Line(
                points = {
                    {70, 0}, 
                    {98, 0}},
                color = {0, 127, 0}), 
            Line(
                points = {
                    {-12, 24}, 
                    {0, 24}, 
                    {6, 34}, 
                    {18, 14}, 
                    {30, 34}, 
                    {42, 14}, 
                    {54, 34}, 
                    {60, 24}, 
                    {70, 24}},
                color = {0, 127, 0}), 
            Rectangle(
                lineColor = {0, 127, 0},
                fillColor = {192, 192, 192},
                fillPattern = FillPattern.Solid,
                extent = {
                    {10, -6}, 
                    {50, -50}}), 
            Line(
                points = {
                    {-52, -70}, 
                    {28, -70}},
                color = {95, 127, 95}), 
            Polygon(
                lineColor = {95, 127, 95},
                fillColor = {95, 127, 95},
                fillPattern = FillPattern.Solid,
                points = {
                    {58, -70}, 
                    {28, -60}, 
                    {28, -80}, 
                    {58, -70}}), 
            Line(
                visible = useHeatPort,
                points = {
                    {-100, -100}, 
                    {-100, -44}, 
                    {22, -44}, 
                    {22, -28}},
                color = {191, 0, 0},
                pattern = LinePattern.Dot), 
            Line(
                points = {
                    {0, -50}, 
                    {50, -50}, 
                    {50, -6}, 
                    {0, -6}},
                color = {0, 127, 0}), 
            Line(
                origin = {-120, 0},
                points = {
                    {108, 0}, 
                    {80, 0}},
                color = {0, 127, 0}), 
            Line(
                origin = {-120, 0},
                points = {
                    {20, 0}, 
                    {60, 0}, 
                    {60, -30}},
                color = {0, 127, 0}), 
            Line(
                origin = {-120, 0},
                points = {
                    {40, -12}, 
                    {40, -40}, 
                    {80, -40}, 
                    {80, 0}},
                color = {0, 127, 0}), 
            Text(
                extent = {
                    {-150, -125}, 
                    {150, -95}},
                textString = "c=%c"), 
            Text(
                extent = {
                    {-150, -160}, 
                    {150, -130}},
                textString = "b=%b")}),
        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}}), 
                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(
                    lineColor = {128, 128, 128},
                    fillColor = {128, 128, 128},
                    fillPattern = FillPattern.Solid,
                    points = {
                        {70, 95}, 
                        {80, 92}, 
                        {70, 89}, 
                        {70, 95}}), 
                Text(
                    textColor = {128, 128, 128},
                    extent = {
                        {-34, 77}, 
                        {40, 90}},
                    textString = "s_rel"), 
                Rectangle(
                    fillColor = {192, 192, 192},
                    fillPattern = FillPattern.Solid,
                    lineThickness = 0.5,
                    extent = {
                        {-60, -20}, 
                        {-10, -80}}), 
                Line(
                    points = {
                        {-52, -80}, 
                        {0, -80}},
                    thickness = 0.5), 
                Line(points = {
                    {-52, -20}, 
                    {0, -20}}), 
                Line(
                    points = {
                        {-10, -50}, 
                        {20, -50}},
                    thickness = 0.5), 
                Line(points = {
                    {-80, -50}, 
                    {-60, -50}}), 
                Line(
                    points = {
                        {-80, 32}, 
                        {-80, -50}},
                    thickness = 0.5), 
                Line(points = {
                    {20, 30}, 
                    {20, -50}}), 
                Line(points = {
                    {-96, 0}, 
                    {-80, 0}}), 
                Line(points = {
                    {96, 0}, 
                    {80, 0}}), 
                Line(points = {
                    {20, 0}, 
                    {60, 0}, 
                    {60, -30}}), 
                Line(points = {
                    {40, -12}, 
                    {40, -40}, 
                    {80, -40}, 
                    {80, 0}}), 
                Line(
                    origin = {10, 0},
                    points = {
                        {30, 0}, 
                        {30, 64}},
                    color = {128, 128, 128}), 
                Line(
                    points = {
                        {40, 60}, 
                        {80, 60}},
                    color = {128, 128, 128}), 
                Polygon(
                    lineColor = {128, 128, 128},
                    fillColor = {128, 128, 128},
                    fillPattern = FillPattern.Solid,
                    points = {
                        {70, 63}, 
                        {80, 60}, 
                        {70, 57}, 
                        {70, 63}}), 
                Text(
                    textColor = {160, 160, 164},
                    extent = {
                        {39, 60}, 
                        {68, 46}},
                    textString = "b")}));
end ElastoBacklash2;