FreeCAD as pre-post processor for MBDyn

About the development of the FEM module/workbench.

Moderator: bernd

josegegas
Posts: 135
Joined: Sat Feb 11, 2017 12:54 am
Location: New Zealand

Re: FreeCAD as pre-post processor for MBDyn

Postby josegegas » Fri Apr 23, 2021 8:14 pm

Hi all.

I have made major changes to the code, mainly to allow the user manage drives, scalar function and constitutive laws using scripted objects. After these changes, most of the examples in Gitlab stopped working, but they have been fixed now.

I have also sorted the examples by difficulty....
josegegas
Posts: 135
Joined: Sat Feb 11, 2017 12:54 am
Location: New Zealand

Re: FreeCAD as pre-post processor for MBDyn

Postby josegegas » Thu Apr 29, 2021 10:29 pm

Playing with plugin variables. Most can now be created and used from the GUI. This allows a whole new range of simulations. Here´s an example:

phpBB [video]


I'll upload the new version of the workbench and some more closed-loop control examples soon...
josegegas
Posts: 135
Joined: Sat Feb 11, 2017 12:54 am
Location: New Zealand

Re: FreeCAD as pre-post processor for MBDyn

Postby josegegas » Sun May 02, 2021 3:30 am

Another example, probably the most complex so far. It would be a pain to put together this simulation by manually writing the input file, not to say to program the animation by hand. When I was at university I did the same simulation using Adams. I have to say it is harder to simulate this using my workbench than using Adams, but it´s not too bad. It took me a couple of hours to succesfully run it...

phpBB [video]


Here´s the input file, automatically generated by my workbench:

Code: Select all

 # [Data Block]

 begin: data;
     problem: initial value;
 end: data;

 #-----------------------------------------------------------------------------
 # [Problem Block]

 begin: initial value;
     initial time: 0.0;
     final time: 8.5;
     time step: 1.0e-2;
     max iterations: 100;
     tolerance: 1.0e-6;
     derivatives tolerance: 1.e-4;
     derivatives max iterations: 100;
     derivatives coefficient: auto;
 end: initial value;

 #-----------------------------------------------------------------------------
 # [Control Data Block]

 begin: control data;
     default orientation: euler321;
     initial stiffness: 1.0, 1.0;
     structural nodes: 15;
     rigid bodies: 10;
     joints: 25;
 end: control data;

 #-----------------------------------------------------------------------------
 # [Design Variables]

     #Gears
     #Generic
         #body 2: 
             set: real M2 = 1.734284692414788; #mass [kg]

         #body 3: 
             set: real M3 = 7.2895829792098406; #mass [kg]

         #body 4: 
             set: real M4 = 0.3185961366636442; #mass [kg]

         #body 5: 
             set: real M5 = 0.6074140116202709; #mass [kg]

         #body 7: 
             set: real M7 = 0.3185961366636442; #mass [kg]

         #body 8: 
             set: real M8 = 0.6074140116202709; #mass [kg]

         #body 10: 
             set: real M10 = 0.31859613666364456; #mass [kg]

         #body 11: 
             set: real M11 = 0.6074140116202708; #mass [kg]

         #body 13: 
             set: real M13 = 0.31859613666364456; #mass [kg]

         #body 14: 
             set: real M14 = 0.6074140116202709; #mass [kg]

     #Cylinders
 #-----------------------------------------------------------------------------
 # [Intermediate Variables]

     #Moments of Inertia
         #body 2: 
             set: real ixx2 = 0.003546755413323648; #moment of inertia [kg*m^2]
             set: real iyy2 = 0.000511201348538537; #moment of inertia [kg*m^2]
             set: real izz2 = 0.003566326865159791; #moment of inertia [kg*m^2]

         #body 3: 
             set: real ixx3 = 0.02049246802801171; #moment of inertia [kg*m^2]
             set: real iyy3 = 0.03477269870643375; #moment of inertia [kg*m^2]
             set: real izz3 = 0.01938881721268155; #moment of inertia [kg*m^2]

         #body 4: 
             set: real ixx4 = 6.62878756168934e-05; #moment of inertia [kg*m^2]
             set: real iyy4 = 6.630975401757898e-05; #moment of inertia [kg*m^2]
             set: real izz4 = 7.261834602712804e-05; #moment of inertia [kg*m^2]

         #body 5: 
             set: real ixx5 = 0.0010693315203476452; #moment of inertia [kg*m^2]
             set: real iyy5 = 0.00011592962471965935; #moment of inertia [kg*m^2]
             set: real izz5 = 0.0010693315130850495; #moment of inertia [kg*m^2]

         #body 7: 
             set: real ixx7 = 6.628787561689359e-05; #moment of inertia [kg*m^2]
             set: real iyy7 = 6.630975401757946e-05; #moment of inertia [kg*m^2]
             set: real izz7 = 7.261834602712852e-05; #moment of inertia [kg*m^2]

         #body 8: 
             set: real ixx8 = 0.001069331520347645; #moment of inertia [kg*m^2]
             set: real iyy8 = 0.00011592962471965935; #moment of inertia [kg*m^2]
             set: real izz8 = 0.0010693315130850475; #moment of inertia [kg*m^2]

         #body 10: 
             set: real ixx10 = 7.24779467838061e-05; #moment of inertia [kg*m^2]
             set: real iyy10 = 6.645015326089999e-05; #moment of inertia [kg*m^2]
             set: real izz10 = 6.628787561689365e-05; #moment of inertia [kg*m^2]

         #body 11: 
             set: real ixx11 = 0.0010693315203476465; #moment of inertia [kg*m^2]
             set: real iyy11 = 0.00011592962471965842; #moment of inertia [kg*m^2]
             set: real izz11 = 0.0010693315130850486; #moment of inertia [kg*m^2]

         #body 13: 
             set: real ixx13 = 7.247794678380563e-05; #moment of inertia [kg*m^2]
             set: real iyy13 = 6.645015326090045e-05; #moment of inertia [kg*m^2]
             set: real izz13 = 6.628787561689351e-05; #moment of inertia [kg*m^2]

         #body 14: 
             set: real ixx14 = 0.001069331520347646; #moment of inertia [kg*m^2]
             set: real iyy14 = 0.00011592962471965935; #moment of inertia [kg*m^2]
             set: real izz14 = 0.0010693315130850495; #moment of inertia [kg*m^2]

 #-----------------------------------------------------------------------------
 # [Scalar functions]

 scalar function: "function:1",
 cubicspline,
 do not extrapolate,
 0.0,    0., 
0.5,    0.,
1.0,    pi/4.,
1.5,    pi/4.,
2.0,    pi/2.,
2.5,    pi/2.,
3.0,    pi/4.,
3.5,    pi/4.,
4.0,    0,
4.5,    0,
5.0,    -pi/4.,
5.5,    -pi/4.,
6.0,    -pi/2.,
6.5,    -pi/2.,
7.0,    -pi/4.,
7.5,    -pi/4.,
8.0,    0.,
8.5,    0.;

 #-----------------------------------------------------------------------------
 # [Drive callers]

 #-----------------------------------------------------------------------------
 # [Constitutive laws]

 #-----------------------------------------------------------------------------
 # [Nodes Block]

 begin: nodes;

     structural: 1,
                 static,
                 0.0064704761275630115, 0.0064704761275630115, 0.0064704761275630115, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 2,
                 dynamic,
                 0.0064704761275630115, -0.02414814565722667, 3.91e-17, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 3,
                 dynamic,
                 -0.007764571353075637, 0.028977774788672094, 3.3e-17, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 4,
                 dynamic,
                 0.08693001787994643, 0.022789999999999998, 0.0, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 5,
                 dynamic,
                 0.08693001787994646, 0.12279000000000005, -2.4e-17, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 6,
                 static,
                 0.08693000000000001, 0.08693000000000001, 0.08693000000000001, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 7,
                 dynamic,
                 -0.0869333064860695, -0.02279371405922688, -4.18e-16, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 8,
                 dynamic,
                 -0.08693330523621436, 0.07505057512854742, 2.2743392e-10, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 9,
                 static,
                 -0.0869333064860695, -0.0869333064860695, -0.0869333064860695, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 10,
                 dynamic,
                 0.00012940952255063108, -0.0004829629131445117, 0.08999998212005345, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 11,
                 dynamic,
                 0.0001294095225506595, 0.09951703708685554, 0.08999998212005342, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 12,
                 static,
                 0.001, 0.001, 0.001, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 13,
                 dynamic,
                 0.00012940952255084432, -0.0004829629131445259, -0.0900000178799464, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 14,
                 dynamic,
                 0.0001294095225508727, 0.09951703708685553, -0.09000001787994642, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

     structural: 15,
                 static,
                 0.001, 0.001, 0.001, #<absolute_position> [m]
                 euler, 0.0, 0.0, 0.0, #<absolute_orientation_matrix> [rad]
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

 end: nodes;

 #-----------------------------------------------------------------------------
 # [Elements Block]

 begin: elements;

     body: 2,
           2, #<node_label> 
           M2, #<mass> [kg]
           9.761543547536985e-05, -0.03399470557162631, -1.43344e-15, #<relative_center_of_mass> [m]
           diag, ixx2, iyy2, izz2; #<inertia_matrix> [kg*m^2]

     body: 3,
           3, #<node_label> 
           M3, #<mass> [kg]
           0.0077645710024342686, -0.02897777478867211, -3.5064135753e-10, #<relative_center_of_mass> [m]
           diag, ixx3, iyy3, izz3; #<inertia_matrix> [kg*m^2]

     body: 4,
           4, #<node_label> 
           M4, #<mass> [kg]
           -2.189133894992e-08, 0.0006121757419957977, 0.031992171068006545, #<relative_center_of_mass> [m]
           diag, ixx4, iyy4, izz4; #<inertia_matrix> [kg*m^2]

     body: 5,
           5, #<node_label> 
           M5, #<mass> [kg]
           -1.30663846409e-09, -0.07817398396007044, -4.4894219845e-10, #<relative_center_of_mass> [m]
           diag, ixx5, iyy5, izz5; #<inertia_matrix> [kg*m^2]

     body: 7,
           7, #<node_label> 
           M7, #<mass> [kg]
           -2.18913389638e-08, -0.0006121757419957907, -0.031992171068006545, #<relative_center_of_mass> [m]
           diag, ixx7, iyy7, izz7; #<inertia_matrix> [kg*m^2]

     body: 8,
           8, #<node_label> 
           M8, #<mass> [kg]
           -2.55649360015e-09, -0.07601827314784468, -6.7637655544e-10, #<relative_center_of_mass> [m]
           diag, ixx8, iyy8, izz8; #<inertia_matrix> [kg*m^2]

     body: 10,
           10, #<node_label> 
           M10, #<mass> [kg]
           -0.03106050701462356, -0.007688866807156445, 1.386855402741e-08, #<relative_center_of_mass> [m]
           diag, ixx10, iyy10, izz10; #<inertia_matrix> [kg*m^2]

     body: 11,
           11, #<node_label> 
           M11, #<mass> [kg]
           -1.30663846672e-09, -0.07817398396007044, -4.4894218898e-10, #<relative_center_of_mass> [m]
           diag, ixx11, iyy11, izz11; #<inertia_matrix> [kg*m^2]

     body: 13,
           13, #<node_label> 
           M13, #<mass> [kg]
           0.030801687969522082, 0.008654792633445449, 1.386855395802e-08, #<relative_center_of_mass> [m]
           diag, ixx13, iyy13, izz13; #<inertia_matrix> [kg*m^2]

     body: 14,
           14, #<node_label> 
           M14, #<mass> [kg]
           -0.0002588203517400274, -0.0772080581337816, 3.531095064957e-08, #<relative_center_of_mass> [m]
           diag, ixx14, iyy14, izz14; #<inertia_matrix> [kg*m^2]

     joint: 1,
            clamp,
            1, #<node_label>
            0.0064704761275630115, -0.02414814565722667 ,3.91e-17, #<absolute_position> [m]
            euler, 0.0, 0.0, 0.0; #<absolute_orientation_matrix> [rad]

     joint: 2,
            axial rotation,
            1,#<node_1>
                null, #<relative_offset_1> [m]
                hinge, 3, 0, 10, 0, 2, guess, #<relative_orientation_matrix_1>
            2, #<node_2>
                0.0, 0.0, -3e-20, #<relative_offset_2> [m]
                hinge, 3, 0, 10, 0, 2, guess, #<relative_orientation_matrix_2>
            string, "model::sf::function:1(Time) *10."; #<angular_velocity> [rad/s]

     joint: 3,
            in line,
            2, #<node_1_label>
                0, 0, 0, #<relative_line_position> [m]
                3, -14.23504731744338000000, 53.12592123095720000000, -6.10000e-15, 2, guess, #<relative_orientation>
            3, #<node_2_label>
                offset, 3.4852785546e-10, 9.338775442e-11, 0.0; #<relative_offset> [m]

     joint: 4,
            spherical hinge,
            3, #<node_1_label>
               0.01423504748063865, -0.05312592044589876, 6.1e-18, #<relative_offset_1> [m]
            2, #<node_2_label>
               null; #<relative_offset_2>

     joint: 5,
            prismatic,
            3, #<node_1_label>
            4; #<node_2_label>

     joint: 6,
            spherical hinge,
            4, #<node_1_label>
               -0.09469458923302207, 0.006187774788672094, 3.3e-17, #<relative_offset_1> [m]
            3, #<node_2_label>
               null; #<relative_offset_2>

     joint: 7, #joint label
            in plane,
            1, # node 1
                position,0., 0., 0., #<relative_plane_position> [m]
                0., 0., 1., #<relative_normal_direction>
            4, # node 2 
                offset, 0., 0., 0.; #<relative_offset> [m]

     joint: 8,
            spherical hinge,
            5, #<node_1_label>
               -2.842e-17, -0.10000000000000006, 2.4e-17, #<relative_offset_1> [m]
            4, #<node_2_label>
               null; #<relative_offset_2>

     joint: 9,
            clamp,
            6, #<node_label>
            0.08693000000000001, 0.15521000000000001 ,0.0, #<absolute_position> [m]
            euler, 0.0, 0.0, 0.0; #<absolute_orientation_matrix> [rad]

     joint: 10,
            in line,
            6, #<node_1_label>
                0, 0, 0, #<relative_line_position> [m]
                3, 0, 100, 0, 2, guess, #<relative_orientation>
            5, #<node_2_label>
                offset, -1.78799464976e-08, 0.0, 2.4e-17; #<relative_offset> [m]

     joint: 11,
            prismatic,
            3, #<node_1_label>
            7; #<node_2_label>

     joint: 12,
            spherical hinge,
            7, #<node_1_label>
               0.07916873513299387, 0.05177148884789897, 4.51e-16, #<relative_offset_1> [m]
            3, #<node_2_label>
               null; #<relative_offset_2>

     joint: 13,
            spherical hinge,
            8, #<node_1_label>
               -1.24985515981e-09, -0.09784428918777431, -2.27434338e-10, #<relative_offset_1> [m]
            7, #<node_2_label>
               null; #<relative_offset_2>

     joint: 14,
            clamp,
            9, #<node_label>
            -0.0869333064860695, 0.15520628594077318 ,-4.24e-16, #<absolute_position> [m]
            euler, 0.0, 0.0, 0.0; #<absolute_orientation_matrix> [rad]

     joint: 15,
            in line,
            9, #<node_1_label>
                0, 0, 0, #<relative_line_position> [m]
                3, 0, 100, 0, 2, guess, #<relative_orientation>
            8, #<node_2_label>
                offset, -1.24985510297e-09, 0.0, -2.27434344e-10; #<relative_offset> [m]

     joint: 16,
            prismatic,
            3, #<node_1_label>
            10; #<node_2_label>

     joint: 17,
            spherical hinge,
            10, #<node_1_label>
               -0.007893980875626268, 0.029460737701816606, -0.08999998212005342, #<relative_offset_1> [m]
            3, #<node_2_label>
               null; #<relative_offset_2>

     joint: 18,
            spherical hinge,
            11, #<node_1_label>
               -2.839e-17, -0.10000000000000006, 2.842e-17, #<relative_offset_1> [m]
            10, #<node_2_label>
               null; #<relative_offset_2>

     joint: 19,
            clamp,
            12, #<node_label>
            0.001, 0.15521000000000001 ,0.08693000000000001, #<absolute_position> [m]
            euler, 0.0, 0.0, 0.0; #<absolute_orientation_matrix> [rad]

     joint: 20,
            in line,
            12, #<node_1_label>
                0, 0, 0, #<relative_line_position> [m]
                3, 0, 100, 0, 2, guess, #<relative_orientation>
            11, #<node_2_label>
                offset, 0.000870590477449341, 0.0, -0.0030699821200533962; #<relative_offset> [m]

     joint: 21,
            prismatic,
            3, #<node_1_label>
            13; #<node_2_label>

     joint: 22,
            spherical hinge,
            13, #<node_1_label>
               -0.007893980875626481, 0.02946073770181662, 0.09000001787994642, #<relative_offset_1> [m]
            3, #<node_2_label>
               null; #<relative_offset_2>

     joint: 23,
            spherical hinge,
            14, #<node_1_label>
               -2.839e-17, -0.10000000000000006, 2.842e-17, #<relative_offset_1> [m]
            13, #<node_2_label>
               null; #<relative_offset_2>

     joint: 24,
            clamp,
            15, #<node_label>
            0.001, 0.15521000000000001 ,-0.08693000000000001, #<absolute_position> [m]
            euler, 0.0, 0.0, 0.0; #<absolute_orientation_matrix> [rad]

     joint: 25,
            in line,
            15, #<node_1_label>
                0, 0, 0, #<relative_line_position> [m]
                3, 0, 100, 0, 2, guess, #<relative_orientation>
            14, #<node_2_label>
                offset, 0.000870590477449127, 0.0, 0.0030700178799463913; #<relative_offset> [m]

     #-----------------------------------------------------------------------------
     # [Plugin variables]

     #-----------------------------------------------------------------------------
     # [Forces and couples]

 end: elements;

josegegas
Posts: 135
Joined: Sat Feb 11, 2017 12:54 am
Location: New Zealand

Re: FreeCAD as pre-post processor for MBDyn

Postby josegegas » Tue May 11, 2021 3:35 am

Hi.

I have a problem. To define the position of nodes, orientation of joints, etc, I take as reference lines, edges, faces, etc, that the user selects from the GUI, for example:

a = FreeCADGui.Selection.getSelectionEx()[0].SubObjects[0]
b = FreeCADGui.Selection.getSelectionEx()[1].SubObjects[0]

then I create, for instance, a revolute hinge or an axial rotation joint using a and b as reference... The revolute hinge, axial rotation, etc are just scripted objects.

The thing is that so far I am using exclusively non-parametric objects for my simulations. Now I would like to experiment using parametric bodies, which introduces a new complication: if the user changes the shape of the body, for instance by changing one of the sketches that define the body, then the joints, nodes, etc will have to be re-computed to addapt to the new shape of the body. In other words, the scripted objects have to somehow remember which lines, faces, edges, etc are a and b, even after the object´s shape has changed, so that they can be recomputed.

To say the same thing in other words, I do:

a = FreeCADGui.Selection.getSelectionEx()[0].SubObjects[0]
b = FreeCADGui.Selection.getSelectionEx()[1].SubObjects[0]

then, the shapes of the bodies to which a and b are belong change, how can I automatically get a and b again, whithout asking the user to select them again?

Is there any "ID" an object of the type "FreeCADGui.Selection.getSelectionEx()[0].SubObjects[0]" has, so I can use it to retrieve the same object again?

Any help will be very welcome...

Cheers
josegegas
Posts: 135
Joined: Sat Feb 11, 2017 12:54 am
Location: New Zealand

Re: FreeCAD as pre-post processor for MBDyn

Postby josegegas » Mon May 17, 2021 12:59 am

Total joints can now be created from the GUI. I´ve uploaded a couple of examples to Gitlab, including an updated version of the RC car suspension example, in case anyone wants to have a look....

phpBB [video]
chrisb
Posts: 35351
Joined: Tue Mar 17, 2015 9:14 am

Re: FreeCAD as pre-post processor for MBDyn

Postby chrisb » Mon May 17, 2021 5:33 am

Impressive. What are the red arrows showing?
A Sketcher Lecture with in-depth information is available in English, auf Deutsch, en français, en español.
josegegas
Posts: 135
Joined: Sat Feb 11, 2017 12:54 am
Location: New Zealand

Re: FreeCAD as pre-post processor for MBDyn

Postby josegegas » Mon May 31, 2021 8:46 pm

Hi.

Red arrows depict joint´s reaction forces...
josegegas
Posts: 135
Joined: Sat Feb 11, 2017 12:54 am
Location: New Zealand

Re: FreeCAD as pre-post processor for MBDyn

Postby josegegas » Tue Jun 01, 2021 3:36 am

Hi.

So far, I have been doing steady progress in integrating FreeCAD and MBDyn. The user can now:

Create rigid bodies starting from CAD objects.
Assign nodes to those bodies.
Connect the nodes through joints.
Apply forces, couples, gravity, etc...

The thing is that now I would like to make the MBD simulation parametric. So that, for instance, if the user changes the shape of the CAD bodies, the workbench will have to re-compute the nodes, rigid bodies and the joints so that the MBD simulation does not break after changing the CAD. And this is where I got stuck. So I´m asking for some help or ideas here...

Think of a revolute pin joint. To define such a joint in MBDyn I need to get the next information from the CAD model:

a) The location of the joint (X,Y,Z) relative to its node (in MBDYn they call this "relative offset").
b) The absolute orientation of the joint´s rotation axis. This is simply a unit vector.

So that, to create a revolute pin joint, the user has to select a node and two reference geometries. The joint will then be placed at the center of a line that has the center of mass of the first reference geometry and the center of mass of the second reference geometry as start and end points, respectively. The relative offset and the orientation are then calculated, and the joint is defined. A similar process applies basically to all the other joints. Here is the key part of the code for the "revolutepin" class:

Code: Select all

class Revolutepin:
    def __init__(self, obj, label, node, reference, reference1):             
        #Get the center of mass or the center of the two references
        try:
            x2 = FreeCAD.Units.Quantity(reference.Curve.Center[0],FreeCAD.Units.Unit('mm'))  
            y2 = FreeCAD.Units.Quantity(reference.Curve.Center[1],FreeCAD.Units.Unit('mm'))  
            z2 = FreeCAD.Units.Quantity(reference.Curve.Center[2],FreeCAD.Units.Unit('mm'))  
        except:    
            x2 = FreeCAD.Units.Quantity(reference.CenterOfMass[0],FreeCAD.Units.Unit('mm'))  
            y2 = FreeCAD.Units.Quantity(reference.CenterOfMass[1],FreeCAD.Units.Unit('mm'))  
            z2 = FreeCAD.Units.Quantity(reference.CenterOfMass[2],FreeCAD.Units.Unit('mm')) 
       
        try:
            x3 = FreeCAD.Units.Quantity(reference1.Curve.Center[0],FreeCAD.Units.Unit('mm'))  
            y3 = FreeCAD.Units.Quantity(reference1.Curve.Center[1],FreeCAD.Units.Unit('mm'))  
            z3 = FreeCAD.Units.Quantity(reference1.Curve.Center[2],FreeCAD.Units.Unit('mm')) 
        except:
            x3 = FreeCAD.Units.Quantity(reference1.CenterOfMass[0],FreeCAD.Units.Unit('mm'))  
            y3 = FreeCAD.Units.Quantity(reference1.CenterOfMass[1],FreeCAD.Units.Unit('mm'))  
            z3 = FreeCAD.Units.Quantity(reference1.CenterOfMass[2],FreeCAD.Units.Unit('mm')) 
        

        #Calculate the joint´s absolute position:
        x = (x2+x3)/2
        y = (y2+y3)/2
        z = (z2+z3)/2
            
        #Calculate the joint position relative to it's node (relative offset):        
        x1 = x-node.absolute_position_X
        y1 = y-node.absolute_position_Y
        z1 = z-node.absolute_position_Z
node, reference and reference1 are something like:

Code: Select all

        node = FreeCADGui.Selection.getSelection()[0]
        try:
            reference = FreeCADGui.Selection.getSelectionEx()[1].SubObjects[0]
            reference1 = FreeCADGui.Selection.getSelectionEx()[2].SubObjects[0]
        except:
            reference = FreeCADGui.Selection.getSelectionEx()[1].SubObjects[0]
            reference1 = FreeCADGui.Selection.getSelectionEx()[1].SubObjects[1]
Then, I create the joint:

Code: Select all

FreeCAD.ActiveDocument.addObject("Part::FeaturePython",obj)
Revolutepin(a,str(existingjoints),node, reference, reference1) 
Now, if the user changes the CAD model, the MBD model can be recomputed accordingly, but only as far as the names of the reference geometries that define the joints have not changed. If the names change, my code will refer to the wrong geometry while re-computing the joints and the joints will be broken or the initial assembly will fail. The only solution (not a very nice solution) I can think about is to ask the user to re-define the broken joint(s) every time the CAD model changes and faces or edges are added/removed from a body.

I guess it all comes back to the "topological naming problem"? After all, if the CAD body changes but the number of faces and edges remains constant, this is, if no faces or edges are created/removed, there is no problem to re-compute the MBD model.

I was wondering, how do the assembly workbenches deal with this? Is any of the assembly workbenches parametric? This is, if faces or edges are added/removed from a body, will the assembly still work? Or will the user be forced to apply the constraints again?

Any comment will be welcome....

Cheers!