WorldForceAndTorque

model WorldForceAndTorque "External force and torque acting at frame_b, defined by 3+3 input signals and resolved in frame world, frame_b or in frame_resolve"
    import Modelica.Mechanics.MultiBody.Types;

    extends Interfaces.PartialOneFrame_b;

    Interfaces.Frame_resolve frame_resolve if resolveInFrame == Modelica.Mechanics.MultiBody.Types.ResolveInFrameB.frame_resolve "The input signals are optionally resolved in this frame"
        annotation (Placement(transformation(
            origin = {0, 100},
            extent = {
                {16, -16}, 
                {-16, 16}},
            rotation = 270)));
    Blocks.Interfaces.RealInput force[3](each final quantity = "Force", each final unit = "N") "x-, y-, z-coordinates of force resolved in frame defined by resolveInFrame"
        annotation (Placement(transformation(extent = {
            {-140, -80}, 
            {-100, -40}})));
    Blocks.Interfaces.RealInput torque[3](each final quantity = "Torque", each final unit = "N.m") "x-, y-, z-coordinates of torque resolved in frame defined by resolveInFrame"
        annotation (Placement(transformation(extent = {
            {-140, 40}, 
            {-100, 80}})));
    parameter Boolean animation = true "= true, if animation shall be enabled";
    parameter Modelica.Mechanics.MultiBody.Types.ResolveInFrameB resolveInFrame = Modelica.Mechanics.MultiBody.Types.ResolveInFrameB.world "Frame in which input force and torque are resolved (1: world, 2: frame_b, 3: frame_resolve)";
    parameter Real N_to_m(unit = "N/m") = world.defaultN_to_m "Force arrow scaling (length = force/N_to_m)"
        annotation (Dialog(
            group = "if animation = true",
            enable = animation));
    parameter Real Nm_to_m(unit = "N.m/m") = world.defaultNm_to_m "Torque arrow scaling (length = torque/Nm_to_m)"
        annotation (Dialog(
            group = "if animation = true",
            enable = animation));
    input SI.Diameter forceDiameter = world.defaultArrowDiameter "Diameter of force arrow"
        annotation (Dialog(
            group = "if animation = true",
            enable = animation));
    input SI.Diameter torqueDiameter = forceDiameter "Diameter of torque arrow"
        annotation (Dialog(
            group = "if animation = true",
            enable = animation));
    input Types.Color forceColor = Modelica.Mechanics.MultiBody.Types.Defaults.ForceColor "Color of force arrow"
        annotation (Dialog(
            colorSelector = true,
            group = "if animation = true",
            enable = animation));
    input Types.Color torqueColor = Modelica.Mechanics.MultiBody.Types.Defaults.TorqueColor "Color of torque arrow"
        annotation (Dialog(
            colorSelector = true,
            group = "if animation = true",
            enable = animation));
    input Types.SpecularCoefficient specularCoefficient = world.defaultSpecularCoefficient "Reflection of ambient light (= 0: light is completely absorbed)"
        annotation (Dialog(
            group = "if animation = true",
            enable = animation));
protected
    SI.Position f_in_m[3] = frame_b.f / N_to_m "Force mapped from N to m for animation";
    SI.Position t_in_m[3] = frame_b.t / Nm_to_m "Torque mapped from Nm to m for animation";
    Visualizers.Advanced.Arrow forceArrow(diameter = forceDiameter, color = forceColor, specularCoefficient = specularCoefficient, R = frame_b.R, r = frame_b.r_0, r_tail = f_in_m, r_head = -f_in_m) if world.enableAnimation and animation;
    Visualizers.Advanced.DoubleArrow torqueArrow(diameter = torqueDiameter, color = torqueColor, specularCoefficient = specularCoefficient, R = frame_b.R, r = frame_b.r_0, r_tail = t_in_m, r_head = -t_in_m) if world.enableAnimation and animation;
public
    Internal.BasicWorldForce basicWorldForce(resolveInFrame = resolveInFrame) annotation (Placement(transformation(extent = {
        {18, -50}, 
        {38, -70}})));
    Internal.BasicWorldTorque basicWorldTorque(resolveInFrame = resolveInFrame) annotation (Placement(transformation(extent = {
        {-10, 50}, 
        {10, 70}})));
protected
    Interfaces.ZeroPosition zeroPosition if not resolveInFrame == Modelica.Mechanics.MultiBody.Types.ResolveInFrameB.frame_resolve annotation (Placement(transformation(extent = {
        {58, 70}, 
        {78, 90}})));
equation
    connect(basicWorldForce.force,force) annotation (Line(
        points = {
            {16, -60}, 
            {-120, -60}},
        color = {0, 0, 127}));
    connect(basicWorldForce.frame_b,frame_b) annotation (Line(
        points = {
            {38, -60}, 
            {60, -60}, 
            {60, 0}, 
            {100, 0}},
        color = {95, 95, 95},
        thickness = 0.5));
    connect(basicWorldForce.frame_resolve,frame_resolve) annotation (Line(
        points = {
            {28, -50}, 
            {28, 80}, 
            {0, 80}, 
            {0, 100}},
        color = {95, 95, 95},
        pattern = LinePattern.Dot));
    connect(basicWorldTorque.frame_b,frame_b) annotation (Line(
        points = {
            {10, 60}, 
            {60, 60}, 
            {60, 0}, 
            {100, 0}},
        color = {95, 95, 95},
        thickness = 0.5));
    connect(basicWorldTorque.torque,torque) annotation (Line(
        points = {
            {-12, 60}, 
            {-120, 60}},
        color = {0, 0, 127}));
    connect(basicWorldTorque.frame_resolve,frame_resolve) annotation (Line(
        points = {
            {0, 70}, 
            {0, 100}},
        color = {95, 95, 95},
        pattern = LinePattern.Dot));
    connect(zeroPosition.frame_resolve,basicWorldForce.frame_resolve) annotation (Line(
        points = {
            {58, 80}, 
            {40, 80}, 
            {40, -40}, 
            {28, -40}, 
            {28, -50}},
        color = {95, 95, 95},
        pattern = LinePattern.Dot));
    connect(zeroPosition.frame_resolve,basicWorldTorque.frame_resolve) annotation (Line(
        points = {
            {58, 80}, 
            {0, 80}, 
            {0, 70}},
        color = {95, 95, 95},
        pattern = LinePattern.Dot));

    annotation (
        defaultComponentName = "forceAndTorque",
        Icon(
            coordinateSystem(
                preserveAspectRatio = true,
                extent = {
                    {-100, -100}, 
                    {100, 100}}),
            graphics = {
                Text(
                    extent = {
                        {-63, 56}, 
                        {44, 19}},
                    lineColor = {192, 192, 192},
                    textString = "resolve"), 
                Text(
                    extent = {
                        {-150, -75}, 
                        {150, -115}},
                    textString = "%name",
                    lineColor = {0, 0, 255}), 
                Line(
                    points = {
                        {-100, 60}, 
                        {-86, 68}, 
                        {-80, 72}, 
                        {-70, 78}, 
                        {-64, 82}, 
                        {-46, 86}, 
                        {-34, 88}, 
                        {-16, 88}, 
                        {-2, 86}, 
                        {12, 80}, 
                        {24, 74}, 
                        {34, 68}, 
                        {46, 58}, 
                        {52, 54}, 
                        {58, 48}},
                    thickness = 0.5), 
                Polygon(
                    points = {
                        {89, 17}, 
                        {64, 76}, 
                        {30, 41}, 
                        {89, 17}},
                    fillPattern = FillPattern.Solid), 
                Line(
                    points = {
                        {0, 95}, 
                        {0, -26}},
                    color = {95, 95, 95},
                    pattern = LinePattern.Dot), 
                Line(
                    points = {
                        {0, 0}, 
                        {96, 0}},
                    color = {95, 95, 95},
                    pattern = LinePattern.Dot), 
                Polygon(
                    points = {
                        {-104, -48}, 
                        {54, 0}, 
                        {46, 20}, 
                        {96, 0}, 
                        {66, -42}, 
                        {60, -22}, 
                        {-96, -72}, 
                        {-104, -48}},
                    fillPattern = FillPattern.Solid)}),
        Documentation(info = "<html>\n<p>\nThe <strong>3</strong> signals of the <strong>force</strong> and <strong>torque</strong>\nconnector are interpreted\nas the x-, y- and z-coordinates of a <strong>force</strong> and\n<strong>torque</strong> acting at the frame\nconnector to which frame_b of this component is attached.\nVia parameter <strong>resolveInFrame</strong> it is defined, in which frame these\ncoordinates shall be resolved:\n</p>\n\n<table border=1 cellspacing=0 cellpadding=2>\n<tr><th><strong>Types.ResolveInFrameB.</strong></th><th><strong>Meaning</strong></th></tr>\n<tr><td>world</td>\n    <td>Resolve input force and torque in world frame (= default)</td></tr>\n\n<tr><td>frame_b</td>\n    <td>Resolve input force and torque in frame_b</td></tr>\n\n<tr><td>frame_resolve</td>\n    <td>Resolve input force and torque in frame_resolve\n                    (frame_resolve must be connected)</td></tr>\n</table>\n\n<p>\nIf resolveInFrame = Types.ResolveInFrameB.frame_resolve, the force and\ntorque coordinates\nare with respect to the frame, that is connected to <strong>frame_resolve</strong>.\n</p>\n\n<p>\nIf force={100,0,0}, and for all parameters the default setting is used,\nthen the interpretation is that a force of 100 N is acting along the positive\nx-axis of frame_b.\n</p>\n\n<p>\nConceptually, a force and torque acts on the world frame in such a way that\nthe force and torque balance between world.frame_b and frame_b is fulfilled.\nFor efficiency reasons, this reaction torque is, however, not computed.\n</p>\n\n<p>\nThe force and torque are by default visualized as an arrow (force)\nand as a double arrow (torque) acting at the connector to which\nthey are connected. The diameters\nand colors of the arrows can be defined via\nvariables <strong>forceDiameter</strong>, <strong>torqueDiameter</strong>,\n<strong>forceColor</strong> and <strong>torqueColor</strong>. The arrows\npoint in the directions defined by the\nforce and torque vectors. The lengths of the arrows are proportional\nto the length of the force and torque vectors, respectively, using parameters\n<strong>N_to_m</strong> and <strong>Nm_to_m</strong> as scaling factors. For example, if N_to_m = 100 N/m,\nthen a force of 350 N is displayed as an arrow of length 3.5 m.\n</p>\n<p>\nAn example how to use this model is given in the\nfollowing figure:\n</p>\n\n<p>\n<img src=\"modelica://Modelica/Resources/Images/Mechanics/MultiBody/Forces/WorldForceAndTorque1.png\">\n</p>\n\n<p>\nThis leads to the following animation\n</p>\n\n<p>\n<img src=\"modelica://Modelica/Resources/Images/Mechanics/MultiBody/Forces/WorldForceAndTorque2.png\">\n</p>\n\n</html>"));
end WorldForceAndTorque;