model CutForceAndTorque "Measure cut force vector and cut torque"
import Modelica.Mechanics.MultiBody.Types;
Modelica.Blocks.Interfaces.RealOutput force[2](each final quantity = "Force", each final unit = "N") "Cut force resolved in frame defined by resolveInFrame"
annotation (Placement(transformation(
origin = {-80, -110},
extent = {
{10, -10},
{-10, 10}},
rotation = 90)));
Modelica.Blocks.Interfaces.RealOutput torque(final quantity = "Torque", final unit = "N.m") "Cut torque resolved in frame defined by resolveInFrame"
annotation (Placement(transformation(
origin = {0, -110},
extent = {
{10, -10},
{-10, 10}},
rotation = 90)));
parameter Boolean animation = true "= true, if animation shall be enabled (show force and torque arrow)";
parameter Boolean positiveSign = true "= true, if force and torque with positive sign is returned (= frame_a.f/.t), otherwise with negative sign (= frame_b.f/.t)";
input Real N_to_m(unit = "N/m") = planarWorld.defaultN_to_m "Force arrow scaling (length = force/N_to_m)"
annotation (Dialog(
group = "if animation = true",
enable = animation));
input Real Nm_to_m(unit = "N.m/m") = planarWorld.defaultNm_to_m "Torque arrow scaling (length = torque/Nm_to_m)"
annotation (Dialog(
group = "if animation = true",
enable = animation));
input SI.Diameter forceDiameter = planarWorld.defaultArrowDiameter "Has no longer an effect and is only kept for backwards compatibility (arrow visualization by Vector now)"
annotation (Dialog(
group = "if animation = true",
enable = animation));
input SI.Diameter torqueDiameter = forceDiameter "Has no longer an effect and is only kept for backwards compatibility (arrow visualization by Vector now)"
annotation (Dialog(
group = "if animation = true",
enable = animation));
input MB.Types.Color forceColor = Modelica.Mechanics.MultiBody.Types.Defaults.ForceColor "Color of force arrow"
annotation (
HideResult = true,
Dialog(
colorSelector = true,
group = "if animation = true",
enable = animation));
input MB.Types.Color torqueColor = Modelica.Mechanics.MultiBody.Types.Defaults.TorqueColor "Color of torque arrow"
annotation (
HideResult = true,
Dialog(
colorSelector = true,
group = "if animation = true",
enable = animation));
input MB.Types.SpecularCoefficient specularCoefficient = planarWorld.defaultSpecularCoefficient "Reflection of ambient light (= 0: light is completely absorbed)"
annotation (
HideResult = true,
Dialog(
group = "if animation = true",
enable = animation));
extends Internal.PartialCutForceSensor;
protected
parameter Integer csign = if positiveSign then 1 else -1;
SI.Position f_in_m[3] = {frame_a.fx, frame_a.fy, 0} * csign / N_to_m "Force mapped from N to m for animation";
SI.Position t_in_m[3] = {0, 0, frame_a.t} * csign / Nm_to_m "Torque mapped from Nm to m for animation";
MB.Visualizers.Advanced.Vector arrowForce(coordinates = f_in_m, color = forceColor, specularCoefficient = specularCoefficient, r = MB.Frames.resolve1(planarWorld.R, {frame_b.x, frame_b.y, 0}) + planarWorld.r_0, quantity = MB.Types.VectorQuantity.Force, headAtOrigin = true, R = planarWorld.R) if planarWorld.enableAnimation and animation;
MB.Visualizers.Advanced.Vector arrowTorque(coordinates = t_in_m, color = torqueColor, specularCoefficient = specularCoefficient, r = MB.Frames.resolve1(planarWorld.R, {frame_b.x, frame_b.y, 0}) + planarWorld.r_0, quantity = MB.Types.VectorQuantity.Torque, headAtOrigin = true, R = planarWorld.R) if planarWorld.enableAnimation and animation;
Internal.BasicCutForce cutForce(resolveInFrame = resolveInFrame, positiveSign = positiveSign) annotation (Placement(transformation(extent = {
{-60, -10},
{-40, 10}})));
Internal.BasicCutTorque cutTorque(positiveSign = positiveSign) annotation (Placement(transformation(extent = {
{40, -10},
{60, 10}})));
Interfaces.ZeroPosition zeroPosition if not resolveInFrame == Modelica.Mechanics.MultiBody.Types.ResolveInFrameA.frame_resolve annotation (Placement(transformation(extent = {
{-20, -40},
{0, -20}})));
equation
connect(cutForce.force,force) annotation (Line(
points = {
{-58, -11},
{-58, -60},
{-80, -60},
{-80, -110}},
color = {0, 0, 127}));
connect(cutForce.frame_a,frame_a) annotation (Line(
points = {
{-60, 0},
{-100, 0}},
color = {95, 95, 95},
thickness = 0.5));
connect(cutForce.frame_b,cutTorque.frame_a) annotation (Line(
points = {
{-40, 0},
{40, 0}},
color = {95, 95, 95},
thickness = 0.5));
connect(cutForce.frame_resolve,frame_resolve) annotation (Line(
points = {
{-42, -10},
{-42, -60},
{80, -60},
{80, -100}},
color = {95, 95, 95},
pattern = LinePattern.Dot));
connect(cutTorque.frame_b,frame_b) annotation (Line(
points = {
{60, 0},
{100, 0}},
color = {95, 95, 95},
thickness = 0.5));
connect(cutTorque.torque,torque) annotation (Line(
points = {
{42, -11},
{42, -79.75},
{0, -79.75},
{0, -110}},
color = {0, 0, 127}));
connect(zeroPosition.frame_resolve,cutForce.frame_resolve) annotation (Line(
points = {
{-20, -30},
{-42, -30},
{-42, -10}},
color = {95, 95, 95},
pattern = LinePattern.Dot));
annotation (
Icon(
coordinateSystem(
preserveAspectRatio = true,
extent = {
{-100, -100},
{100, 100}}),
graphics = {
Line(
points = {
{-80, -100},
{-80, 0}},
color = {0, 0, 127}),
Line(
points = {
{0, -100},
{0, -70}},
color = {0, 0, 127}),
Text(
extent = {
{-188, -70},
{-72, -96}},
textString = "force"),
Text(
extent = {
{-56, -70},
{60, -96}},
textString = "torque")}),
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>\nThe cut-force and cut-torque acting between the two frames to which this\nmodel is connected, are determined and provided at the output signal connectors\n<code>force</code> (= <code>frame_a.f</code>) and <code>torque</code>\n(= <code>frame_a.t</code>).\nIf parameter <code>positiveSign = false</code>, the negative\ncut-force and cut-torque is provided (= <code>frame_b.f</code>, <code>frame_b.t</code>).\n</p>\n<p>\nVia parameter <code>resolveInFrame</code> it is defined, in which frame\nthe <code>force</code> vector is resolved.\n</p>\n\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">\n <caption align=\"bottom\">Options of parameter <strong>resolveInFrame</strong></caption>\n <tr>\n <th>resolveInFrame = …</th>\n <th>Force vector resolved in</th>\n </tr>\n <tr>\n <td valign=\"top\">Types.ResolveInFrameAB.world</td>\n <td valign=\"top\">world frame</td>\n </tr>\n <tr>\n <td valign=\"top\">Types.ResolveInFrameAB.frame_a</td>\n <td valign=\"top\">frame_a</td>\n </tr>\n <tr>\n <td valign=\"top\">Types.ResolveInFrameAB.frame_b</td>\n <td valign=\"top\">frame_b</td>\n </tr>\n <tr>\n <td valign=\"top\">Types.ResolveInFrameAB.frame_resolve</td>\n <td valign=\"top\">frame_resolve (must be connected)</td>\n </tr>\n</table>\n\n<p>\nIf <code>resolveInFrame = Types.ResolveInFrameAB.frame_resolve</code>,\nthe conditional connector <code>frame_resolve</code> is enabled and\noutput <code>force</code> is resolved in the frame, to which\n<code>frame_resolve</code> is connected.\nNote, if this connector is enabled, it must be connected.\n</p>\n\n<p>\nIn the following figure the animation of the\nsensor is shown. The dark blue coordinate system is <code>frame_b</code>,\nand the green arrows are the cut force and the cut torque,\nrespectively, acting at <code>frame_b</code> and\nwith negative sign at <code>frame_a</code>.\n</p>\n\n<div>\n<img src=\"modelica://Modelica/Resources/Images/Mechanics/MultiBody/Sensors/CutForceAndTorque.png\" alt=\"CutForceAndTorque animation\">\n</div>\n</html>"));
end CutForceAndTorque;