Search code examples
modelicaopenmodelica

How can I model a rigid body with a spring mass attached in Modelica?


I am pretty new to modelica. I would like to model a rigid body (as a long cylinder), with a point mass attached to it via a spring.

Imagine the body-fixed frame of the rigid body, where the x-axis is the long axis of the cylinder. The slosh mass should be constrained to translate only in the y-z plane.

How can I model this system in modelica using the standard library?

For reference, here is my attempt (does not build). Thank you.

model RigidBody6DOFWithSpring
  // Parameters
  parameter Real mass_slosh = 90; // Mass of a single slosh mass
  parameter Real springStiffness = 1e4; // Spring stiffness
  parameter Real springRestLength = 1; // Spring rest length
  
  // Rigid body properties
  parameter Real mass_rigid = 10; // Mass of the rigid body
  parameter Modelica.Units.SI.Position r_CM[3](start={4,0,0});
  parameter Modelica.Units.SI.Inertia Ixx = 100;
  parameter Modelica.Units.SI.Inertia Iyy = 100;
  parameter Modelica.Units.SI.Inertia Izz = Iyy;

  // Model a world with no gravity
  inner Modelica.Mechanics.MultiBody.World world(g=0);

  // Rocket structure
  Modelica.Mechanics.MultiBody.Parts.Body rigidBody(m=mass_rigid,
                                                    r_CM = r_CM,
                                                    cylinderDiameter = 0.0, // Disable vis
                                                    sphereDiameter=0.5, // Disable vis
                                                    I_11 = Ixx,
                                                    I_22 = Iyy,
                                                    I_33 = Izz);
  
  // Joints to constrain point mass motion to body frame y-z motion only
  import Modelica.Mechanics.MultiBody.Joints;
  Joints.Constraints.Prismatic slosh1_constraint(
    x_locked=true,
    y_locked=false,
    z_locked=false);
  
  
  // Point masses
  parameter Real slosh1_x = 8;
  Modelica.Mechanics.MultiBody.Parts.Body sloshMass1(m=mass_slosh,
                                                     sphereDiameter=1);
  Modelica.Mechanics.MultiBody.Forces.Spring spring1(c=springStiffness,
                                                     s_unstretched=springRestLength);
  Modelica.Mechanics.MultiBody.Parts.FixedTranslation attachmentPoint1(
    r={slosh1_x,0,0}
  );
  
initial equation
  // Initial rigid body state
  rigidBody.w_0_start = {0, 0, 0};

  // Initial slosh positions in world space
  sloshMass1.r_0 = {slosh1_x, 0, 0};

  // Spring lengths
  spring1.length = 2;

equation
  // Define translation of spring mounting frame w.r.t rigid body frame
  connect(rigidBody.frame_a, attachmentPoint1.frame_a);
  connect(spring1.frame_a, attachmentPoint1.frame_b);
  connect(spring1.frame_b, sloshMass1.frame_a);
  
  connect(slosh1_constraint.frame_a, rigidBody.frame_a);
  connect(slosh1_constraint.frame_b, sloshMass1.frame_a);
  connect(slosh1_constraint.frame_b, attachmentPoint1.frame_b);
  connect(slosh1_constraint.frame_b, spring1.frame_b);
end RigidBody6DOFWithSpring;


Solution

  • I'm not sure if I correctly understood what you would want to build, but here are some remarks for your model:

    • Modelica.Mechanics.MultiBody.Joints.Constraints.Prismatic is not used to constrain the movement in one direction. It is rather used in "complex multibody systems with closed loops this may help to simplify the system of non-linear equations" (from the documentation of the model). Comparably simple examples can be found here: Modelica.Mechanics.MultiBody.Examples.Constraints.
    • `Spring.length' is a variable, setting it to a fixed value will likely break the system of equations. In any case it will undermine the function of the spring as it will fix the length during simulation.

    From you description I have built the following:
    Graphical description of suggested model

    The resulting animation is the this:
    Simulation Result

    Note that the point-mass is not constrained to a movement on the y-z-plane.

    Here is the code (including the annotations for graphical description etc.):

    model ZylinderSpringMass
      Modelica.Mechanics.MultiBody.Joints.Planar planar(
        animation=false,
        n(displayUnit="1") = {1,0,0},
        n_x(displayUnit="1") = {0,1,0}) annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
      Modelica.Mechanics.MultiBody.Parts.Fixed fixed annotation (Placement(transformation(extent={{-40,-10},{-20,10}})));
      Modelica.Mechanics.MultiBody.Parts.BodyCylinder bodyCylinder(
        r={0.5,0,0},
        r_shape={-0.5,0,0},
        r_0(start={0,-0.1,-0.1}, fixed=true)) annotation (Placement(transformation(extent={{40,-10},{60,10}})));
      inner Modelica.Mechanics.MultiBody.World world(n(displayUnit="1") = {-1,0,0})
        annotation (Placement(transformation(extent={{-40,40},{-20,60}})));
      Modelica.Mechanics.MultiBody.Parts.Body body(
        r_CM={0,0,0},
        m=3,
        r_0(fixed=true, start={0,0.1,0}),
        v_0(fixed=true, start={0,0,1})) annotation (Placement(transformation(extent={{40,30},{60,50}})));
      Modelica.Mechanics.MultiBody.Forces.Spring spring(c=100)
        annotation (Placement(transformation(
            extent={{-10,-10},{10,10}},
            rotation=90,
            origin={20,20})));
    equation 
      connect(fixed.frame_b, planar.frame_a)
        annotation (Line(
          points={{-20,0},{-10,0}},
          color={95,95,95},
          thickness=0.5));
      connect(bodyCylinder.frame_a, planar.frame_b)
        annotation (Line(
          points={{40,0},{10,0}},
          color={95,95,95},
          thickness=0.5));
      connect(spring.frame_a, planar.frame_b)
        annotation (Line(
          points={{20,10},{20,0},{10,0}},
          color={95,95,95},
          thickness=0.5));
      connect(spring.frame_b, body.frame_a)
        annotation (Line(
          points={{20,30},{20,40},{40,40}},
          color={95,95,95},
          thickness=0.5));
      annotation (
        Icon(coordinateSystem(preserveAspectRatio=false)),
        Diagram(coordinateSystem(preserveAspectRatio=false)),
        uses(Modelica(version="4.0.0")),
        experiment(
          StopTime=3,
          Interval=0.001,
          __Dymola_Algorithm="Dassl"));
    end ZylinderSpringMass;
    

    Not sure if that does what you need, but it should be a starting point at least.

    Note: I have built that using Dymola 2024x, assuming it will work in other tools as well, as it does only use standard components...