diff --git a/Modelica/Mechanics/MultiBody/Forces/Internal/ZeroForceAndTorque.mo b/Modelica/Mechanics/MultiBody/Forces/Internal/ZeroForceAndTorque.mo index 4a66927abd..b91bc2c25d 100644 --- a/Modelica/Mechanics/MultiBody/Forces/Internal/ZeroForceAndTorque.mo +++ b/Modelica/Mechanics/MultiBody/Forces/Internal/ZeroForceAndTorque.mo @@ -1,8 +1,7 @@ within Modelica.Mechanics.MultiBody.Forces.Internal; model ZeroForceAndTorque "Set force and torque to zero" - extends Modelica.Blocks.Icons.Block; - Interfaces.Frame_a frame_a - annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); + extends Modelica.Blocks.Icons.Block; + extends Interfaces.PartialOneFrame_a; equation frame_a.f = zeros(3); frame_a.t = zeros(3); diff --git a/Modelica/Mechanics/MultiBody/Interfaces/OneFrame_a.mo b/Modelica/Mechanics/MultiBody/Interfaces/OneFrame_a.mo new file mode 100644 index 0000000000..72b949305d --- /dev/null +++ b/Modelica/Mechanics/MultiBody/Interfaces/OneFrame_a.mo @@ -0,0 +1,18 @@ +within Modelica.Mechanics.MultiBody.Interfaces; +partial model OneFrame_a + "Base model for components providing one frame_a connector and outer world" + + Interfaces.Frame_a frame_a + "Coordinate system fixed to the component with one cut-force and cut-torque" + annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); +protected + outer Modelica.Mechanics.MultiBody.World world; + + annotation (Documentation(info=" +

+This partial model provides one frame_a connector and access to +the world object. +Therefore, inherit from this partial model if both is needed. +

+")); +end OneFrame_a; diff --git a/Modelica/Mechanics/MultiBody/Interfaces/PartialConstraint.mo b/Modelica/Mechanics/MultiBody/Interfaces/PartialConstraint.mo new file mode 100644 index 0000000000..40e501ab13 --- /dev/null +++ b/Modelica/Mechanics/MultiBody/Interfaces/PartialConstraint.mo @@ -0,0 +1,73 @@ +within Modelica.Mechanics.MultiBody.Interfaces; +partial model PartialConstraint + "Base model for elementary constraints" + extends PartialTwoFrames; + + parameter Boolean x_locked=true + "= true, if constraint force in x-direction, resolved in frame_a" + annotation (Dialog(group="Constrain translational motion"), choices(checkBox=true)); + parameter Boolean y_locked=true + "= true, if constraint force in y-direction, resolved in frame_a" + annotation (Dialog(group="Constrain translational motion"), choices(checkBox=true)); + parameter Boolean z_locked=true + "= true, if constraint force in z-direction, resolved in frame_a" + annotation (Dialog(group="Constrain translational motion"), choices(checkBox=true)); + +protected + SI.Position r_rel_a[3] + "Position vector from origin of frame_a to origin of frame_b, resolved in frame_a"; + Frames.Orientation R_rel + "Relative orientation object from frame_a to frame_b"; + SI.InstantaneousPower P "Instantaneous power"; + +equation + // Determine relative position and orientation + r_rel_a = Frames.resolve2(frame_a.R, frame_b.r_0 - frame_a.r_0); + R_rel = Frames.relativeRotation(frame_a.R, frame_b.R); + + // Constraint equations concerning translations + if x_locked then + r_rel_a[1]=0; + else + frame_a.f[1]=0; + end if; + + if y_locked then + r_rel_a[2]=0; + else + frame_a.f[2]=0; + end if; + + if z_locked then + r_rel_a[3]=0; + else + frame_a.f[3]=0; + end if; + + // Force and torque balance + zeros(3) = frame_a.f + Frames.resolve1(R_rel, frame_b.f); + zeros(3) = frame_a.t + Frames.resolve1(R_rel, frame_b.t) - cross(r_rel_a, frame_a.f); + // - cross(r_rel_a, frame_a.f) gives the same result like cross(r_rel_a, Frames.resolve1(R_rel, frame_b.f)) + + // Instantaneous power + P = frame_a.t * Frames.angularVelocity2(frame_a.R) + + frame_b.t * Frames.angularVelocity2(frame_b.R) + + frame_a.f * Frames.resolve2(frame_a.R, der(frame_a.r_0)) + + frame_b.f * Frames.resolve2(frame_b.R, der(frame_b.r_0)); + + annotation (Documentation(info=" +

+All elementary joints defined by constraints should inherit +from this base model, i.e., joints that are directly defined by constraint +equations between the two frames. +

+

+This partial model provides relative kinematic quantities r_rel_a +and R_rel between the two frame connectors frame_a +and frame_b, and basic equations constraining translational movement. +The inheriting class shall additionally provide corresponding equations +constraining rotational movement. +

+ +")); +end PartialConstraint; diff --git a/Modelica/Mechanics/MultiBody/Interfaces/PartialElementaryJoint.mo b/Modelica/Mechanics/MultiBody/Interfaces/PartialElementaryJoint.mo index 3c2a335d73..d7847b3c53 100644 --- a/Modelica/Mechanics/MultiBody/Interfaces/PartialElementaryJoint.mo +++ b/Modelica/Mechanics/MultiBody/Interfaces/PartialElementaryJoint.mo @@ -1,18 +1,11 @@ within Modelica.Mechanics.MultiBody.Interfaces; partial model PartialElementaryJoint "Base model for elementary joints (has two frames + outer world + assert to guarantee that the joint is connected)" + extends PartialTwoFrames; - Interfaces.Frame_a frame_a "Coordinate system fixed to the joint with one cut-force and cut-torque" annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); - Interfaces.Frame_b frame_b "Coordinate system fixed to the joint with one cut-force and cut-torque" annotation (Placement(transformation(extent={{84,-16},{116,16}}))); - -protected - outer Modelica.Mechanics.MultiBody.World world; equation Connections.branch(frame_a.R, frame_b.R); - assert(cardinality(frame_a) > 0, - "Connector frame_a of joint object is not connected"); - assert(cardinality(frame_b) > 0, - "Connector frame_b of joint object is not connected"); + annotation (Documentation(info="

All elementary joints should inherit from this base model, i.e., @@ -30,5 +23,6 @@ This partial model provides two frame connectors, a \"Connections.branch\" between frame_a and frame_b, access to the world object and an assert to check that both frame connectors are connected.

-")); + +")); end PartialElementaryJoint; diff --git a/Modelica/Mechanics/MultiBody/Interfaces/PartialOneFrame_a.mo b/Modelica/Mechanics/MultiBody/Interfaces/PartialOneFrame_a.mo index ce85c4e80d..3216508bf9 100644 --- a/Modelica/Mechanics/MultiBody/Interfaces/PartialOneFrame_a.mo +++ b/Modelica/Mechanics/MultiBody/Interfaces/PartialOneFrame_a.mo @@ -1,10 +1,8 @@ within Modelica.Mechanics.MultiBody.Interfaces; partial model PartialOneFrame_a "Base model for components providing one frame_a connector + outer world + assert to guarantee that the component is connected" + extends OneFrame_a; - Interfaces.Frame_a frame_a "Coordinate system fixed to the component with one cut-force and cut-torque" annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); -protected - outer Modelica.Mechanics.MultiBody.World world; equation assert(cardinality(frame_a) > 0, "Connector frame_a of component is not connected"); diff --git a/Modelica/Mechanics/MultiBody/Interfaces/PartialTwoFrames.mo b/Modelica/Mechanics/MultiBody/Interfaces/PartialTwoFrames.mo index 8ee6e05a13..cc0c0b12f6 100644 --- a/Modelica/Mechanics/MultiBody/Interfaces/PartialTwoFrames.mo +++ b/Modelica/Mechanics/MultiBody/Interfaces/PartialTwoFrames.mo @@ -1,11 +1,8 @@ within Modelica.Mechanics.MultiBody.Interfaces; partial model PartialTwoFrames "Base model for components providing two frame connectors + outer world + assert to guarantee that the component is connected" + extends TwoFrames; - Interfaces.Frame_a frame_a "Coordinate system a fixed to the component with one cut-force and cut-torque" annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); - Interfaces.Frame_b frame_b "Coordinate system b fixed to the component with one cut-force and cut-torque" annotation (Placement(transformation(extent={{84,-16},{116,16}}))); -protected - outer Modelica.Mechanics.MultiBody.World world; equation assert(cardinality(frame_a) > 0, "Connector frame_a of component is not connected"); diff --git a/Modelica/Mechanics/MultiBody/Interfaces/PartialTwoFramesDoubleSize.mo b/Modelica/Mechanics/MultiBody/Interfaces/PartialTwoFramesDoubleSize.mo index 73c32d9cdb..593557f289 100644 --- a/Modelica/Mechanics/MultiBody/Interfaces/PartialTwoFramesDoubleSize.mo +++ b/Modelica/Mechanics/MultiBody/Interfaces/PartialTwoFramesDoubleSize.mo @@ -2,8 +2,8 @@ within Modelica.Mechanics.MultiBody.Interfaces; partial model PartialTwoFramesDoubleSize "Base model for components providing two frame connectors + outer world + assert to guarantee that the component is connected (default icon size is factor 2 larger as usual)" - Interfaces.Frame_a frame_a "Coordinate system fixed to the component with one cut-force and cut-torque" annotation (Placement(transformation(extent={{-108,-8},{-92,8}}))); - Interfaces.Frame_b frame_b "Coordinate system fixed to the component with one cut-force and cut-torque" annotation (Placement(transformation(extent={{92,-8},{108,8}}))); + Interfaces.Frame_a frame_a "Coordinate system a fixed to the component with one cut-force and cut-torque" annotation (Placement(transformation(extent={{-108,-8},{-92,8}}))); + Interfaces.Frame_b frame_b "Coordinate system b fixed to the component with one cut-force and cut-torque" annotation (Placement(transformation(extent={{92,-8},{108,8}}))); protected outer Modelica.Mechanics.MultiBody.World world; diff --git a/Modelica/Mechanics/MultiBody/Interfaces/PartialVisualizer.mo b/Modelica/Mechanics/MultiBody/Interfaces/PartialVisualizer.mo index 064cef6666..3a6ea80610 100644 --- a/Modelica/Mechanics/MultiBody/Interfaces/PartialVisualizer.mo +++ b/Modelica/Mechanics/MultiBody/Interfaces/PartialVisualizer.mo @@ -1,13 +1,9 @@ within Modelica.Mechanics.MultiBody.Interfaces; partial model PartialVisualizer "Base model for visualizers (has a frame_a on the left side + outer world + assert to guarantee that the component is connected)" + extends PartialOneFrame_a( + frame_a "Coordinate system in which visualization data is resolved"); - Interfaces.Frame_a frame_a "Coordinate system in which visualization data is resolved" annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); -protected - outer Modelica.Mechanics.MultiBody.World world; -equation - assert(cardinality(frame_a) > 0, - "Connector frame_a of visualizer object is not connected"); annotation (Documentation(info="

This partial model provides one frame_a connector, access to the world diff --git a/Modelica/Mechanics/MultiBody/Interfaces/TwoFrames.mo b/Modelica/Mechanics/MultiBody/Interfaces/TwoFrames.mo new file mode 100644 index 0000000000..a5062e3c2f --- /dev/null +++ b/Modelica/Mechanics/MultiBody/Interfaces/TwoFrames.mo @@ -0,0 +1,36 @@ +within Modelica.Mechanics.MultiBody.Interfaces; +partial model TwoFrames + "Base model for components providing two frame connectors and outer world" + + Interfaces.Frame_a frame_a + "Coordinate system a fixed to the component with one cut-force and cut-torque" + annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); + Interfaces.Frame_b frame_b + "Coordinate system b fixed to the component with one cut-force and cut-torque" + annotation (Placement(transformation(extent={{84,-16},{116,16}}))); +protected + outer Modelica.Mechanics.MultiBody.World world; + + annotation ( + Icon( + coordinateSystem( + preserveAspectRatio=true, + extent={{-100,-100},{100,100}}), + graphics={ + Text( + extent={{-136,-25},{-100,-50}}, + textColor={128,128,128}, + textString="a"), + Text( + extent={{100,-25},{136,-50}}, + textColor={128,128,128}, + textString="b")}), + Documentation(info=" +

+This partial model provides two frame connectors and access to +the world object. +Therefore, inherit from this partial model if the two frame +connectors are needed. +

+")); +end TwoFrames; diff --git a/Modelica/Mechanics/MultiBody/Interfaces/package.order b/Modelica/Mechanics/MultiBody/Interfaces/package.order index f90accb778..c2d575dc4f 100644 --- a/Modelica/Mechanics/MultiBody/Interfaces/package.order +++ b/Modelica/Mechanics/MultiBody/Interfaces/package.order @@ -4,10 +4,13 @@ Frame_b Frame_resolve FlangeWithBearing FlangeWithBearingAdaptor -PartialTwoFrames -PartialTwoFramesDoubleSize +OneFrame_a PartialOneFrame_a PartialOneFrame_b +TwoFrames +PartialTwoFrames +PartialTwoFramesDoubleSize +PartialConstraint PartialElementaryJoint PartialForce LineForceBase diff --git a/Modelica/Mechanics/MultiBody/Joints/Constraints/Prismatic.mo b/Modelica/Mechanics/MultiBody/Joints/Constraints/Prismatic.mo index 3092c9e80d..ef1f30b2b8 100644 --- a/Modelica/Mechanics/MultiBody/Joints/Constraints/Prismatic.mo +++ b/Modelica/Mechanics/MultiBody/Joints/Constraints/Prismatic.mo @@ -1,17 +1,7 @@ within Modelica.Mechanics.MultiBody.Joints.Constraints; model Prismatic "Prismatic cut-joint and translational directions may be constrained or released" - extends Modelica.Mechanics.MultiBody.Interfaces.PartialTwoFrames; - - parameter Boolean x_locked=true - "= true: constraint force in x-direction, resolved in frame_a" - annotation (Dialog(group="Constraints"),choices(checkBox=true)); - parameter Boolean y_locked=true - "= true: constraint force in y-direction, resolved in frame_a" - annotation (Dialog(group="Constraints"),choices(checkBox=true)); - parameter Boolean z_locked=true - "= true: constraint force in z-direction, resolved in frame_a" - annotation (Dialog(group="Constraints"),choices(checkBox=true)); + extends Modelica.Mechanics.MultiBody.Interfaces.PartialConstraint; parameter Boolean animation=true "= true, if animation shall be enabled (show sphere)"; @@ -25,13 +15,6 @@ model Prismatic "Reflection of ambient light (= 0: light is completely absorbed)" annotation (Dialog(group="if animation = true", enable=animation)); -protected - Frames.Orientation R_rel - "Dummy or relative orientation object from frame_a to frame_b"; - SI.Position r_rel_a[3] - "Position vector from origin of frame_a to origin of frame_b, resolved in frame_a"; - SI.InstantaneousPower P; - public Visualizers.Advanced.Shape sphere( shapeType="sphere", @@ -46,40 +29,10 @@ public r=frame_a.r_0, R=frame_a.R) if world.enableAnimation and animation; equation - // Determine relative position vector resolved in frame_a - R_rel = Frames.relativeRotation(frame_a.R, frame_b.R); - r_rel_a = Frames.resolve2(frame_a.R, frame_b.r_0 - frame_a.r_0); - // Constraint equations concerning rotations // Same logic as for overdetermined connection graph loops to get good residuals. zeros(3)=Modelica.Mechanics.MultiBody.Frames.Orientation.equalityConstraint(frame_a.R, frame_b.R); - // Constraint equations concerning translations - if x_locked then - r_rel_a[1]=0; - else - frame_a.f[1]=0; - end if; - - if y_locked then - r_rel_a[2]=0; - else - frame_a.f[2]=0; - end if; - - if z_locked then - r_rel_a[3]=0; - else - frame_a.f[3]=0; - end if; - - zeros(3) = frame_a.t + Frames.resolve1(R_rel, frame_b.t) + cross(r_rel_a, - Frames.resolve1(R_rel, frame_b.f)); - zeros(3) = Frames.resolve1(R_rel, frame_b.f) + frame_a.f; - P = frame_a.t*Frames.angularVelocity2(frame_a.R) + frame_b.t* - Frames.angularVelocity2(frame_b.R) + frame_b.f*Frames.resolve2(frame_b.R, - der(frame_b.r_0)) + frame_a.f*Frames.resolve2(frame_a.R, der(frame_a.r_0)); - annotation ( defaultComponentName="constraint", Icon(coordinateSystem( diff --git a/Modelica/Mechanics/MultiBody/Joints/Constraints/Revolute.mo b/Modelica/Mechanics/MultiBody/Joints/Constraints/Revolute.mo index cc3bad276a..5b9f929126 100644 --- a/Modelica/Mechanics/MultiBody/Joints/Constraints/Revolute.mo +++ b/Modelica/Mechanics/MultiBody/Joints/Constraints/Revolute.mo @@ -1,17 +1,7 @@ within Modelica.Mechanics.MultiBody.Joints.Constraints; model Revolute "Revolute cut-joint and translational directions may be constrained or released" - extends Modelica.Mechanics.MultiBody.Interfaces.PartialTwoFrames; - - parameter Boolean x_locked=true - "= true: constraint force in x-direction, resolved in frame_a" - annotation (Dialog(group="Constraints in translational motion"),choices(checkBox=true)); - parameter Boolean y_locked=true - "= true: constraint force in y-direction, resolved in frame_a" - annotation (Dialog(group="Constraints in translational motion"),choices(checkBox=true)); - parameter Boolean z_locked=true - "= true: constraint force in z-direction, resolved in frame_a" - annotation (Dialog(group="Constraints in translational motion"),choices(checkBox=true)); + extends Modelica.Mechanics.MultiBody.Interfaces.PartialConstraint; parameter Boolean animation=true "= true, if animation shall be enabled (show sphere)"; @@ -30,21 +20,15 @@ model Revolute annotation (Dialog(group="if animation = true", enable=animation)); protected - Frames.Orientation R_rel - "Dummy or relative orientation object from frame_a to frame_b"; - SI.Position r_rel_a[3] - "Position vector from origin of frame_a to origin of frame_b, resolved in frame_a"; - SI.InstantaneousPower P; - parameter Real e[3](each final unit="1")=Modelica.Math.Vectors.normalizeWithAssert( - n) + parameter Real e[3](each final unit="1")=Modelica.Math.Vectors.normalizeWithAssert(n) "Unit vector in direction of rotation axis, resolved in frame_a (= same as in frame_b)"; - parameter Real nnx_a[3](each final unit="1")=if abs(e[1]) > 0.1 then {0,1,0} else (if abs(e[2]) - > 0.1 then {0,0,1} else {1,0,0}) + parameter Real nnx_a[3](each final unit="1")= + if abs(e[1]) > 0.1 then {0,1,0} else (if abs(e[2]) > 0.1 then {0,0,1} else {1,0,0}) "Arbitrary vector that is not aligned with rotation axis n" annotation (Evaluate=true); - parameter Real ey_a[3](each final unit="1")=Modelica.Math.Vectors.normalizeWithAssert( - cross(e, nnx_a)) + parameter Real ey_a[3](each final unit="1")= + Modelica.Math.Vectors.normalizeWithAssert(cross(e, nnx_a)) "Unit vector orthogonal to axis n of revolute joint, resolved in frame_a" annotation (Evaluate=true); parameter Real ex_a[3](each final unit="1")=cross(ey_a, e) @@ -65,43 +49,13 @@ public R=frame_a.R) if world.enableAnimation and animation; equation - // Determine relative position vector resolved in frame_a - R_rel = Frames.relativeRotation(frame_a.R, frame_b.R); - r_rel_a = Frames.resolve2(frame_a.R, frame_b.r_0 - frame_a.r_0); - - // Constraint equations concerning translations - if x_locked then - r_rel_a[1]=0; - else - frame_a.f[1]=0; - end if; - - if y_locked then - r_rel_a[2]=0; - else - frame_a.f[2]=0; - end if; - - if z_locked then - r_rel_a[3]=0; - else - frame_a.f[3]=0; - end if; - // Constraint equations concerning rotations 0 = ex_a*R_rel.T*e; 0 = ey_a*R_rel.T*e; frame_a.t*n=0; - zeros(3) = frame_a.f + Frames.resolve1(R_rel, frame_b.f); - zeros(3) = frame_a.t + Frames.resolve1(R_rel, frame_b.t) - cross(r_rel_a, - frame_a.f); - P = frame_a.t*Frames.angularVelocity2(frame_a.R) + frame_b.t* - Frames.angularVelocity2(frame_b.R) + Frames.resolve1(frame_b.R, frame_b.f) - *der(frame_b.r_0) + Frames.resolve1(frame_a.R, frame_a.f)*der(frame_a.r_0); - - annotation ( defaultComponentName="constraint", - Icon(coordinateSystem( + annotation ( defaultComponentName="constraint", + Icon(coordinateSystem( preserveAspectRatio=true, extent={{-100,-100},{100,100}}), graphics={ Text( @@ -137,7 +91,7 @@ equation extent={{-150,110},{150,70}}, textColor={0,0,255}, textString="%name")}), - Documentation(info=" + Documentation(info="

This model does not use explicit variables e.g. state variables in order to describe the relative motion of frame_b with respect to frame_a, but defines kinematic constraints between the frame_a and frame_b. The forces and torques at both frames are then evaluated in such a way that the constraints are satisfied. Sometimes this type of formulation is also called an implicit joint in literature.

As a consequence of the formulation the relative kinematics between frame_a and frame_b cannot be initialized.

In particular in complex multibody systems with closed loops this may help to simplify the system of non-linear equations. Please compare the translation log using the classical joint formulation and the alternative formulation used here in order to check whether this fact applies to the particular system under consideration.

diff --git a/Modelica/Mechanics/MultiBody/Joints/Constraints/Spherical.mo b/Modelica/Mechanics/MultiBody/Joints/Constraints/Spherical.mo index 83e7b39270..e8f3309e8f 100644 --- a/Modelica/Mechanics/MultiBody/Joints/Constraints/Spherical.mo +++ b/Modelica/Mechanics/MultiBody/Joints/Constraints/Spherical.mo @@ -1,18 +1,7 @@ within Modelica.Mechanics.MultiBody.Joints.Constraints; model Spherical "Spherical cut joint and translational directions may be constrained or released" - extends Modelica.Mechanics.MultiBody.Interfaces.PartialTwoFrames; - import MBS = Modelica.Mechanics.MultiBody; - - parameter Boolean x_locked=true - "= true: constraint force in x-direction, resolved in frame_a" - annotation (Dialog(group="Constraints"), choices(checkBox=true)); - parameter Boolean y_locked=true - "= true: constraint force in y-direction, resolved in frame_a" - annotation (Dialog(group="Constraints"), choices(checkBox=true)); - parameter Boolean z_locked=true - "= true: constraint force in z-direction, resolved in frame_a" - annotation (Dialog(group="Constraints"), choices(checkBox=true)); + extends Modelica.Mechanics.MultiBody.Interfaces.PartialConstraint; parameter Boolean animation=true "= true, if animation shall be enabled (show sphere)" @@ -20,10 +9,10 @@ model Spherical parameter SI.Distance sphereDiameter=world.defaultJointLength /3 "Diameter of sphere representing the spherical joint" annotation (Dialog(group="Animation", enable=animation)); - input MBS.Types.Color sphereColor=MBS.Types.Defaults.JointColor + input Types.Color sphereColor=Types.Defaults.JointColor "Color of sphere representing the spherical joint" annotation (Dialog(colorSelector=true, group="Animation", enable=animation)); - input MBS.Types.SpecularCoefficient specularCoefficient = world.defaultSpecularCoefficient + input Types.SpecularCoefficient specularCoefficient = world.defaultSpecularCoefficient "Reflection of ambient light (= 0: light is completely absorbed)" annotation (Dialog(group="Animation", enable=animation)); @@ -39,42 +28,11 @@ model Spherical r_shape={-0.5,0,0}*sphereDiameter, r=frame_a.r_0, R=frame_a.R) if world.enableAnimation and animation; -protected - MBS.Frames.Orientation R_rel - "Dummy or relative orientation object from frame_a to frame_b"; - SI.Position r_rel_a[3] - "Position vector from origin of frame_a to origin of frame_b, resolved in frame_a"; - SI.InstantaneousPower P; equation - // Determine relative position vector resolved in frame_a - R_rel = MBS.Frames.relativeRotation(frame_a.R, frame_b.R); - r_rel_a = MBS.Frames.resolve2(frame_a.R, frame_b.r_0 - frame_a.r_0); - - // Constraint equations concerning translation - if x_locked then - r_rel_a[1]=0; - else - frame_a.f[1]=0; - end if; - - if y_locked then - r_rel_a[2]=0; - else - frame_a.f[2]=0; - end if; - - if z_locked then - r_rel_a[3]=0; - else - frame_a.f[3]=0; - end if; - //frame_a.t = zeros(3); frame_b.t = zeros(3); - frame_b.f = -MBS.Frames.resolve2(R_rel, frame_a.f); - zeros(3) = frame_a.t + MBS.Frames.resolve1(R_rel, frame_b.t) - cross(r_rel_a, frame_a.f); - P= frame_a.t*MBS.Frames.angularVelocity2(frame_a.R)+frame_b.t*MBS.Frames.angularVelocity2(frame_b.R) + MBS.Frames.resolve1(frame_b.R,frame_b.f)*der(frame_b.r_0)+MBS.Frames.resolve1(frame_a.R,frame_a.f)*der(frame_a.r_0); + annotation ( defaultComponentName="constraint", Icon(coordinateSystem( @@ -155,7 +113,7 @@ equation textColor={0,0,255}, textString="%name")}), Documentation(info=" -

This model does not use explicit variables e.g. state variables in order to describe the relative motion of frame_b with to respect to frame_a, but defines kinematic constraints between the frame_a and frame_b. The forces and torques at both frames are then evaluated in such a way that the constraints are satisfied. Sometimes this type of formulation is also called an implicit joint in literature.

+

This model does not use explicit variables e.g. state variables in order to describe the relative motion of frame_b with respect to frame_a, but defines kinematic constraints between the frame_a and frame_b. The forces and torques at both frames are then evaluated in such a way that the constraints are satisfied. Sometimes this type of formulation is also called an implicit joint in literature.

As a consequence of the formulation the relative kinematics between frame_a and frame_b cannot be initialized.

In particular in complex multibody systems with closed loops this may help to simplify the system of non-linear equations. Please compare the translation log using the classical joint formulation and the alternative formulation used here in order to check whether this fact applies to the particular system under consideration.

In systems without closed loops the use of this implicit joint does not make sense or may even be disadvantageous.

diff --git a/Modelica/Mechanics/MultiBody/Joints/Constraints/Universal.mo b/Modelica/Mechanics/MultiBody/Joints/Constraints/Universal.mo index 9dce558fb0..829a213a22 100644 --- a/Modelica/Mechanics/MultiBody/Joints/Constraints/Universal.mo +++ b/Modelica/Mechanics/MultiBody/Joints/Constraints/Universal.mo @@ -1,79 +1,37 @@ within Modelica.Mechanics.MultiBody.Joints.Constraints; model Universal "Universal cut-joint and translational directions may be constrained or released" - extends Modelica.Mechanics.MultiBody.Interfaces.PartialTwoFrames; - import MBS = Modelica.Mechanics.MultiBody; + extends Modelica.Mechanics.MultiBody.Interfaces.PartialConstraint; - parameter MBS.Types.Axis n_a={1,0,0} + parameter Types.Axis n_a={1,0,0} "Axis of revolute joint 1 resolved in frame_a" annotation (Evaluate=true); - parameter MBS.Types.Axis n_b={0,1,0} + parameter Types.Axis n_b={0,1,0} "Axis of revolute joint 2 resolved in frame_b" annotation (Evaluate=true); - parameter Boolean x_locked=true - "= true: constraint force in x-direction, resolved in frame_a" - annotation (Dialog(group="Constraints in translational motion"), choices(checkBox=true)); - parameter Boolean y_locked=true - "= true: constraint force in y-direction, resolved in frame_a" - annotation (Dialog(group="Constraints in translational motion"), choices(checkBox=true)); - parameter Boolean z_locked=true - "= true: constraint force in z-direction, resolved in frame_a" - annotation (Dialog(group="Constraints in translational motion"), choices(checkBox=true)); - parameter Boolean animation=true "= true, if animation shall be enabled (show sphere)" annotation (Dialog(group="Animation")); parameter SI.Distance sphereDiameter=world.defaultJointLength /3 "Diameter of sphere representing the spherical joint" annotation (Dialog(group="Animation", enable=animation)); - input MBS.Types.Color sphereColor=MBS.Types.Defaults.JointColor + input Types.Color sphereColor=Types.Defaults.JointColor "Color of sphere representing the spherical joint" annotation (Dialog(colorSelector=true, group="Animation", enable=animation)); - input MBS.Types.SpecularCoefficient specularCoefficient = world.defaultSpecularCoefficient + input Types.SpecularCoefficient specularCoefficient = world.defaultSpecularCoefficient "Reflection of ambient light (= 0: light is completely absorbed)" annotation (Dialog(group="Animation", enable=animation)); protected - MBS.Frames.Orientation R_rel - "Dummy or relative orientation object from frame_a to frame_b"; Real w_rel[3]; - SI.Position r_rel_a[3] - "Position vector from origin of frame_a to origin of frame_b, resolved in frame_a"; - SI.InstantaneousPower P; equation - // Determine relative position vector resolved in frame_a - R_rel = MBS.Frames.relativeRotation(frame_a.R, frame_b.R); - w_rel = MBS.Frames.angularVelocity1(R_rel); - r_rel_a = MBS.Frames.resolve2(frame_a.R, frame_b.r_0 - frame_a.r_0); - - // Constraint equations concerning translations - if x_locked then - r_rel_a[1]=0; - else - frame_a.f[1]=0; - end if; - - if y_locked then - r_rel_a[2]=0; - else - frame_a.f[2]=0; - end if; - - if z_locked then - r_rel_a[3]=0; - else - frame_a.f[3]=0; - end if; + w_rel = Frames.angularVelocity1(R_rel); // Constraint equations concerning rotations - frame_a.t*n_a=0; - frame_b.t*n_b=0; - n_b*R_rel.T*n_a=0; + frame_a.t * n_a = 0; + frame_b.t * n_b = 0; + n_b * Frames.resolve2(R_rel, n_a) = 0; // Constraint: R_rel shall assure orthogonality of n_a and n_b assert(abs(n_a*n_b) < Modelica.Constants.eps, "The two axes that constitute the Constraints.Universal joint must be different"); - zeros(3)=frame_a.f + MBS.Frames.resolve1(R_rel, frame_b.f); - zeros(3) = frame_a.t+MBS.Frames.resolve1(R_rel, frame_b.t)- cross(r_rel_a, frame_a.f); - P = frame_a.t*MBS.Frames.angularVelocity2(frame_a.R)+frame_b.t*MBS.Frames.angularVelocity2(frame_b.R) + MBS.Frames.resolve1(frame_b.R,frame_b.f)*der(frame_b.r_0)+MBS.Frames.resolve1(frame_a.R,frame_a.f)*der(frame_a.r_0); - annotation ( defaultComponentName="constraint", Icon(coordinateSystem( diff --git a/Modelica/Mechanics/MultiBody/Joints/Revolute.mo b/Modelica/Mechanics/MultiBody/Joints/Revolute.mo index 640f58178a..25ed2fdcba 100644 --- a/Modelica/Mechanics/MultiBody/Joints/Revolute.mo +++ b/Modelica/Mechanics/MultiBody/Joints/Revolute.mo @@ -2,6 +2,7 @@ within Modelica.Mechanics.MultiBody.Joints; model Revolute "Revolute joint (1 rotational degree-of-freedom, 2 potential states, optional axis flange)" + extends Modelica.Mechanics.MultiBody.Interfaces.PartialElementaryJoint; Modelica.Mechanics.Rotational.Interfaces.Flange_a axis if useAxisFlange "1-dim. rotational flange that drives the joint" annotation (Placement(transformation(extent={{10,90},{-10,110}}))); @@ -9,13 +10,6 @@ model Revolute "1-dim. rotational flange of the drive support (assumed to be fixed in the world frame, NOT in the joint)" annotation (Placement(transformation(extent={{-70,90},{-50,110}}))); - Modelica.Mechanics.MultiBody.Interfaces.Frame_a frame_a - "Coordinate system fixed to the joint with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); - Modelica.Mechanics.MultiBody.Interfaces.Frame_b frame_b - "Coordinate system fixed to the joint with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{84,-16},{116,16}}))); - parameter Boolean useAxisFlange=false "= true, if axis flange is enabled" annotation(Evaluate=true, HideResult=true, choices(checkBox=true)); parameter Boolean animation=true @@ -58,7 +52,6 @@ Possible reasons: SI.Angle angle "= phi"; protected - outer Modelica.Mechanics.MultiBody.World world; parameter Real e[3](each final unit="1")=Modelica.Math.Vectors.normalizeWithAssert(n) "Unit vector in direction of rotation axis, resolved in frame_a (= same as in frame_b)"; Frames.Orientation R_rel @@ -85,13 +78,6 @@ protected Rotational.Sources.ConstantTorque constantTorque(tau_constant=0) if not useAxisFlange annotation (Placement(transformation(extent={{40,70},{20,90}}))); equation - Connections.branch(frame_a.R, frame_b.R); - - assert(cardinality(frame_a) > 0, - "Connector frame_a of revolute joint is not connected"); - assert(cardinality(frame_b) > 0, - "Connector frame_b of revolute joint is not connected"); - angle = phi; w = der(phi); a = der(w); diff --git a/Modelica/Mechanics/MultiBody/Joints/RevolutePlanarLoopConstraint.mo b/Modelica/Mechanics/MultiBody/Joints/RevolutePlanarLoopConstraint.mo index cf2b39ffbc..27ece3f186 100644 --- a/Modelica/Mechanics/MultiBody/Joints/RevolutePlanarLoopConstraint.mo +++ b/Modelica/Mechanics/MultiBody/Joints/RevolutePlanarLoopConstraint.mo @@ -1,17 +1,11 @@ within Modelica.Mechanics.MultiBody.Joints; model RevolutePlanarLoopConstraint "Revolute joint that is described by 2 positional constraints for usage in a planar loop (the ambiguous cut-force perpendicular to the loop and the ambiguous cut-torques are set arbitrarily to zero)" + extends Modelica.Mechanics.MultiBody.Interfaces.PartialTwoFrames; import T = Modelica.Mechanics.MultiBody.Frames.TransformationMatrices; import Modelica.Mechanics.MultiBody.Types; - Interfaces.Frame_a frame_a - "Coordinate system fixed to the joint with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); - Interfaces.Frame_b frame_b - "Coordinate system fixed to the joint with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{84,-16},{116,16}}))); - parameter Boolean animation=true "= true, if animation shall be enabled (show axis as cylinder)"; parameter Modelica.Mechanics.MultiBody.Types.Axis n={0,0,1} @@ -30,7 +24,6 @@ model RevolutePlanarLoopConstraint "Reflection of ambient light (= 0: light is completely absorbed)" annotation (Dialog(group="if animation = true", enable=animation)); protected - outer Modelica.Mechanics.MultiBody.World world; parameter Real e[3](each final unit="1")=Modelica.Math.Vectors.normalizeWithAssert(n) "Unit vector in direction of rotation axis, resolved in frame_a (= same as in frame_b)"; parameter Real nnx_a[3](each final unit="1")=if abs(e[1]) > 0.1 then {0,1,0} else (if abs(e[2]) @@ -64,11 +57,6 @@ protected r=frame_a.r_0, R=frame_a.R) if world.enableAnimation and animation; equation - assert(cardinality(frame_a) > 0, - "Connector frame_a of revolute joint is not connected"); - assert(cardinality(frame_b) > 0, - "Connector frame_b of revolute joint is not connected"); - // Determine relative position vector resolved in frame_a R_rel = Frames.relativeRotation(frame_a.R, frame_b.R); r_rel_a = Frames.resolve2(frame_a.R, frame_b.r_0 - frame_a.r_0); diff --git a/Modelica/Mechanics/MultiBody/Parts/Body.mo b/Modelica/Mechanics/MultiBody/Parts/Body.mo index b18e6ff678..d59d2e6321 100644 --- a/Modelica/Mechanics/MultiBody/Parts/Body.mo +++ b/Modelica/Mechanics/MultiBody/Parts/Body.mo @@ -1,14 +1,12 @@ within Modelica.Mechanics.MultiBody.Parts; model Body "Rigid body with mass, inertia tensor and one frame connector (12 potential states)" + extends Interfaces.OneFrame_a; import Modelica.Mechanics.MultiBody.Types; import Modelica.Mechanics.MultiBody.Frames; import Modelica.Units.Conversions.to_unit1; - Modelica.Mechanics.MultiBody.Interfaces.Frame_a frame_a - "Coordinate system fixed at body" annotation (Placement(transformation( - extent={{-116,-16},{-84,16}}))); parameter Boolean animation=true "= true, if animation shall be enabled (show cylinder and sphere)"; parameter SI.Position r_CM[3](start={0,0,0}) @@ -131,10 +129,8 @@ model Body "Absolute angular acceleration of frame_a resolved in frame_a"; SI.Acceleration g_0[3] "Gravity acceleration resolved in world frame"; -protected - outer Modelica.Mechanics.MultiBody.World world; - // Declarations for quaternions (dummies, if quaternions are not used) +protected parameter Frames.Quaternions.Orientation Q_start=Frames.to_Q(R_start) "Quaternion orientation object from world frame to frame_a at initial time"; Frames.Quaternions.Orientation Q(start=Q_start, each stateSelect=if diff --git a/Modelica/Mechanics/MultiBody/Parts/BodyBox.mo b/Modelica/Mechanics/MultiBody/Parts/BodyBox.mo index 1d57175827..dd8449d20d 100644 --- a/Modelica/Mechanics/MultiBody/Parts/BodyBox.mo +++ b/Modelica/Mechanics/MultiBody/Parts/BodyBox.mo @@ -1,17 +1,12 @@ within Modelica.Mechanics.MultiBody.Parts; model BodyBox "Rigid body with box shape. Mass and animation properties are computed from box data and density (12 potential states)" + extends Interfaces.TwoFrames; import Modelica.Mechanics.MultiBody.Types; import Modelica.Math.Vectors.normalizeWithAssert; import Modelica.Units.Conversions.to_unit1; - Interfaces.Frame_a frame_a - "Coordinate system fixed to the component with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); - Interfaces.Frame_b frame_b - "Coordinate system fixed to the component with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{84,-16},{116,16}}))); parameter Boolean animation=true "= true, if animation shall be enabled (show box between frame_a and frame_b)"; parameter SI.Position r[3](start={0.1,0,0}) @@ -149,8 +144,6 @@ model BodyBox specularCoefficient=specularCoefficient) annotation (Placement( transformation(extent={{-30,-20},{10,20}}))); -protected - outer Modelica.Mechanics.MultiBody.World world; equation r_0 = frame_a.r_0; v_0 = der(r_0); diff --git a/Modelica/Mechanics/MultiBody/Parts/BodyCylinder.mo b/Modelica/Mechanics/MultiBody/Parts/BodyCylinder.mo index 3289482161..61c55c791e 100644 --- a/Modelica/Mechanics/MultiBody/Parts/BodyCylinder.mo +++ b/Modelica/Mechanics/MultiBody/Parts/BodyCylinder.mo @@ -1,6 +1,7 @@ within Modelica.Mechanics.MultiBody.Parts; model BodyCylinder "Rigid body with cylinder shape. Mass and animation properties are computed from cylinder data and density (12 potential states)" + extends Interfaces.TwoFrames; import Modelica.Units.NonSI; import Modelica.Mechanics.MultiBody.Types; @@ -8,12 +9,6 @@ model BodyCylinder import Modelica.Units.Conversions.to_unit1; import Modelica.Constants.pi; - Interfaces.Frame_a frame_a - "Coordinate system fixed to the component with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); - Interfaces.Frame_b frame_b - "Coordinate system fixed to the component with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{84,-16},{116,16}}))); parameter Boolean animation=true "= true, if animation shall be enabled (show cylinder between frame_a and frame_b)"; parameter SI.Position r[3](start={0.1,0,0}) @@ -151,8 +146,6 @@ model BodyCylinder widthDirection={0,1,0}) annotation (Placement(transformation(extent={{-30, -20},{10,20}}))); -protected - outer Modelica.Mechanics.MultiBody.World world; equation r_0 = frame_a.r_0; v_0 = der(r_0); diff --git a/Modelica/Mechanics/MultiBody/Parts/BodyShape.mo b/Modelica/Mechanics/MultiBody/Parts/BodyShape.mo index 9fc242a377..46a464f278 100644 --- a/Modelica/Mechanics/MultiBody/Parts/BodyShape.mo +++ b/Modelica/Mechanics/MultiBody/Parts/BodyShape.mo @@ -1,17 +1,11 @@ within Modelica.Mechanics.MultiBody.Parts; model BodyShape "Rigid body with mass, inertia tensor, different shapes for animation, and two frame connectors (12 potential states)" + extends Interfaces.TwoFrames; import Modelica.Mechanics.MultiBody.Types; import Modelica.Units.Conversions.to_unit1; - Interfaces.Frame_a frame_a - "Coordinate system fixed to the component with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); - Interfaces.Frame_b frame_b - "Coordinate system fixed to the component with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{84,-16},{116,16}}))); - parameter Boolean animation=true "= true, if animation shall be enabled (show shape between frame_a and frame_b and optionally a sphere at the center of mass)"; parameter Boolean animateSphere=true @@ -180,7 +174,6 @@ model BodyShape enforceStates=false) annotation (Placement(transformation(extent={{-27.3333, -70.3333},{13,-30}}))); protected - outer Modelica.Mechanics.MultiBody.World world; Visualizers.Advanced.Shape shape1( shapeType=shapeType, color=color, diff --git a/Modelica/Mechanics/MultiBody/Parts/FixedRotation.mo b/Modelica/Mechanics/MultiBody/Parts/FixedRotation.mo index 1d9971b303..5d716e78e4 100644 --- a/Modelica/Mechanics/MultiBody/Parts/FixedRotation.mo +++ b/Modelica/Mechanics/MultiBody/Parts/FixedRotation.mo @@ -1,17 +1,11 @@ within Modelica.Mechanics.MultiBody.Parts; model FixedRotation "Fixed translation followed by a fixed rotation of frame_b with respect to frame_a" + extends Interfaces.TwoFrames; import Modelica.Mechanics.MultiBody.Frames; import Modelica.Units.Conversions.to_unit1; - Interfaces.Frame_a frame_a - "Coordinate system fixed to the component with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); - Interfaces.Frame_b frame_b - "Coordinate system fixed to the component with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{84,-16},{116,16}}))); - parameter Boolean animation=true "= true, if animation shall be enabled"; parameter SI.Position r[3]={0,0,0} "Vector from frame_a to frame_b resolved in frame_a"; @@ -117,17 +111,16 @@ model FixedRotation sequence, Cv.from_deg(angles), zeros(3)) "Fixed rotation object from frame_a to frame_b"; - /* +/* SI.Power totalPower "Total power flowing into this element, if checkTotalPower=true (otherwise dummy)"; */ -protected - outer Modelica.Mechanics.MultiBody.World world; - /* +/* parameter Frames.Orientation R_rel_inv= Frames.inverseRotation(R_rel) */ +protected parameter Frames.Orientation R_rel_inv=Frames.from_T(transpose(R_rel.T), zeros(3)) "Inverse of R_rel (rotate from frame_b to frame_a)"; Modelica.Mechanics.MultiBody.Visualizers.Advanced.Shape shape( diff --git a/Modelica/Mechanics/MultiBody/Parts/FixedTranslation.mo b/Modelica/Mechanics/MultiBody/Parts/FixedTranslation.mo index 3055d86ae3..2de59a3907 100644 --- a/Modelica/Mechanics/MultiBody/Parts/FixedTranslation.mo +++ b/Modelica/Mechanics/MultiBody/Parts/FixedTranslation.mo @@ -1,15 +1,10 @@ within Modelica.Mechanics.MultiBody.Parts; model FixedTranslation "Fixed translation of frame_b with respect to frame_a" + extends Interfaces.TwoFrames; + import Modelica.Mechanics.MultiBody.Types; import Modelica.Units.Conversions.to_unit1; - Interfaces.Frame_a frame_a - "Coordinate system fixed to the component with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); - Interfaces.Frame_b frame_b - "Coordinate system fixed to the component with one cut-force and cut-torque" - annotation (Placement(transformation(extent={{84,-16},{116,16}}))); - parameter Boolean animation=true "= true, if animation shall be enabled"; parameter SI.Position r[3](start={0,0,0}) "Vector from frame_a to frame_b resolved in frame_a"; @@ -70,7 +65,6 @@ model FixedTranslation "Fixed translation of frame_b with respect to frame_a" enable=animation)); protected - outer Modelica.Mechanics.MultiBody.World world; Visualizers.Advanced.Shape shape( shapeType=shapeType, color=color, diff --git a/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialAbsoluteBaseSensor.mo b/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialAbsoluteBaseSensor.mo index 77642943bf..90f95a7067 100644 --- a/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialAbsoluteBaseSensor.mo +++ b/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialAbsoluteBaseSensor.mo @@ -1,11 +1,7 @@ within Modelica.Mechanics.MultiBody.Sensors.Internal; model PartialAbsoluteBaseSensor "Base class for absolute sensor models defined by equations (frame_resolve must be connected exactly once)" - extends Modelica.Icons.RoundSensor; - - Modelica.Mechanics.MultiBody.Interfaces.Frame_a frame_a - "Coordinate system from which kinematic quantities are measured" annotation (Placement( - transformation(extent={{-116,-16},{-84,16}}))); + extends PartialAbsoluteSensor; Modelica.Mechanics.MultiBody.Interfaces.Frame_resolve frame_resolve "Coordinate system in which output vector(s) is optionally resolved" @@ -14,7 +10,6 @@ model PartialAbsoluteBaseSensor origin={0,-100}))); equation - assert(cardinality(frame_a) > 0, "Connector frame_a must be connected at least once"); assert(cardinality(frame_resolve) == 1, "Connector frame_resolve must be connected exactly once"); frame_a.f = zeros(3); frame_a.t = zeros(3); diff --git a/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialAbsoluteSensor.mo b/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialAbsoluteSensor.mo index 2efde157dc..22528e420b 100644 --- a/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialAbsoluteSensor.mo +++ b/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialAbsoluteSensor.mo @@ -3,7 +3,7 @@ partial model PartialAbsoluteSensor "Base class for absolute sensor models" extends Modelica.Icons.RoundSensor; Modelica.Mechanics.MultiBody.Interfaces.Frame_a frame_a - "Coordinate system a of which the absolute kinematic quantities are measured" annotation (Placement( + "Coordinate system of which the absolute kinematic quantities are measured" annotation (Placement( transformation(extent={{-116,-16},{-84,16}}))); equation diff --git a/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialRelativeBaseSensor.mo b/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialRelativeBaseSensor.mo index 15d33e9945..dd3acfb55d 100644 --- a/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialRelativeBaseSensor.mo +++ b/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialRelativeBaseSensor.mo @@ -1,22 +1,13 @@ within Modelica.Mechanics.MultiBody.Sensors.Internal; model PartialRelativeBaseSensor "Base class for relative sensor models defined by equations (frame_resolve must be connected exactly once)" - extends Modelica.Icons.RoundSensor; - - Modelica.Mechanics.MultiBody.Interfaces.Frame_a frame_a - "Coordinate system a (measurement is between frame_a and frame_b)" annotation (Placement( - transformation(extent={{-116,-16},{-84,16}}))); - Modelica.Mechanics.MultiBody.Interfaces.Frame_b frame_b - "Coordinate system b (measurement is between frame_a and frame_b)" annotation (Placement( - transformation(extent={{84,-16},{116,16}}))); + extends PartialRelativeSensor; Modelica.Mechanics.MultiBody.Interfaces.Frame_resolve frame_resolve "Coordinate system in which vector is optionally resolved" annotation (Placement(transformation(extent={{84,64},{116,96}}))); equation - assert(cardinality(frame_a) > 0, "Connector frame_a must be connected at least once"); - assert(cardinality(frame_b) > 0, "Connector frame_b must be connected at least once"); assert(cardinality(frame_resolve) == 1, "Connector frame_resolve must be connected exactly once"); frame_a.f = zeros(3); frame_a.t = zeros(3); diff --git a/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialRelativeSensor.mo b/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialRelativeSensor.mo index 81f942e3c9..9580ae1a53 100644 --- a/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialRelativeSensor.mo +++ b/Modelica/Mechanics/MultiBody/Sensors/Internal/PartialRelativeSensor.mo @@ -4,10 +4,10 @@ partial model PartialRelativeSensor extends Modelica.Icons.RoundSensor; Modelica.Mechanics.MultiBody.Interfaces.Frame_a frame_a - "Coordinate system a" annotation (Placement( + "Coordinate system a (measurement is between frame_a and frame_b)" annotation (Placement( transformation(extent={{-116,-16},{-84,16}}))); Modelica.Mechanics.MultiBody.Interfaces.Frame_b frame_b - "Coordinate system b" annotation (Placement( + "Coordinate system b (measurement is between frame_a and frame_b)" annotation (Placement( transformation(extent={{84,-16},{116,16}}))); equation diff --git a/Modelica/Mechanics/MultiBody/Sensors/TransformAbsoluteVector.mo b/Modelica/Mechanics/MultiBody/Sensors/TransformAbsoluteVector.mo index e2f8d77aa1..c0e1ae87b0 100644 --- a/Modelica/Mechanics/MultiBody/Sensors/TransformAbsoluteVector.mo +++ b/Modelica/Mechanics/MultiBody/Sensors/TransformAbsoluteVector.mo @@ -1,15 +1,10 @@ within Modelica.Mechanics.MultiBody.Sensors; model TransformAbsoluteVector "Transform absolute vector in to another frame" - extends Modelica.Icons.RoundSensor; + extends Internal.PartialAbsoluteSensor; - Modelica.Mechanics.MultiBody.Interfaces.Frame_a frame_a - "Coordinate system from which absolute kinematic quantities are measured" - annotation (Placement( - transformation(extent={{-116,-16},{-84,16}}))); - - Modelica.Mechanics.MultiBody.Interfaces.Frame_resolve frame_resolve if - (frame_r_in == Modelica.Mechanics.MultiBody.Types.ResolveInFrameA.frame_resolve) or - (frame_r_out == Modelica.Mechanics.MultiBody.Types.ResolveInFrameA.frame_resolve) + Modelica.Mechanics.MultiBody.Interfaces.Frame_resolve frame_resolve + if (frame_r_in == Modelica.Mechanics.MultiBody.Types.ResolveInFrameA.frame_resolve) + or (frame_r_out == Modelica.Mechanics.MultiBody.Types.ResolveInFrameA.frame_resolve) "Coordinate system in which r_in or r_out is optionally resolved" annotation (Placement(transformation(extent={{84,-16},{116,16}}))); @@ -35,8 +30,8 @@ protected Internal.BasicTransformAbsoluteVector basicTransformVector(frame_r_in= frame_r_in, frame_r_out=frame_r_out) annotation (Placement(transformation(extent={{-10,-10},{10,10}}))); - Modelica.Mechanics.MultiBody.Interfaces.ZeroPosition zeroPosition if - not (frame_r_in == Modelica.Mechanics.MultiBody.Types.ResolveInFrameA.frame_resolve or + Modelica.Mechanics.MultiBody.Interfaces.ZeroPosition zeroPosition + if not (frame_r_in == Modelica.Mechanics.MultiBody.Types.ResolveInFrameA.frame_resolve or frame_r_out == Modelica.Mechanics.MultiBody.Types.ResolveInFrameA.frame_resolve) annotation (Placement(transformation(extent={{40,18},{60,38}}))); diff --git a/Modelica/Mechanics/MultiBody/UsersGuide/Tutorial/ConnectionOfLineForces.mo b/Modelica/Mechanics/MultiBody/UsersGuide/Tutorial/ConnectionOfLineForces.mo index 44926f5f65..7fbb0aa56f 100644 --- a/Modelica/Mechanics/MultiBody/UsersGuide/Tutorial/ConnectionOfLineForces.mo +++ b/Modelica/Mechanics/MultiBody/UsersGuide/Tutorial/ConnectionOfLineForces.mo @@ -73,7 +73,7 @@ Here, spring3.frame_b.R is defined to be in parallel to the world frame. However, this is then also the orientation of fixedTranslation.frame_a, and this in turn means that the left part of the fixedTranslation object is always in parallel to the world frame. Since this is not correct, this model -will result in a wrong simulation result +will result in a wrong simulation result. This system is mathematically not well-defined and does not have a solution. The only way to model such a system is by providing a mass and an inertia tensor to fixedTranslation. Then, the flags are not needed, because the \"connection\" diff --git a/Modelica/Mechanics/MultiBody/Visualizers/FixedShape2.mo b/Modelica/Mechanics/MultiBody/Visualizers/FixedShape2.mo index cf05dba66b..3af99ae064 100644 --- a/Modelica/Mechanics/MultiBody/Visualizers/FixedShape2.mo +++ b/Modelica/Mechanics/MultiBody/Visualizers/FixedShape2.mo @@ -1,17 +1,12 @@ within Modelica.Mechanics.MultiBody.Visualizers; model FixedShape2 "Visualizing an elementary shape with dynamically varying shape attributes (has two frame connectors)" + extends Interfaces.TwoFrames; import Modelica.Mechanics.MultiBody.Frames; import Modelica.Mechanics.MultiBody.Types; import Modelica.Units.Conversions.to_unit1; - Interfaces.Frame_a frame_a - "Coordinate system a (all shape definition vectors are resolved in this frame)" - annotation (Placement(transformation(extent={{-116,-16},{-84,16}}))); - Interfaces.Frame_b frame_b "Coordinate system b" - annotation (Placement(transformation(extent={{84,-16},{116,16}}))); - parameter Boolean animation=true "= true, if animation shall be enabled"; parameter Types.ShapeType shapeType="box" "Type of shape" annotation (Dialog(group="if animation = true", enable=animation));