# Equilibrium¶

## Introduction¶

This tutorial introduces the equilibrium module in Robotran. You should already be comfortable with the basics modelling features of the Getting started tutorial of Robotran.

Features summary

The programming language in this tutorial is Python. The same tutorial for C is available, but not for Matlab at the moment.

### Equilibrium principle¶

In the case of a closed-loop multibody system, the equilibrium is computed based on the reduced equations of motions (see Robotran Basics). Generalized accelerations $$\ddot{\mathbf{q}}_\mathbf{u}$$ are set to zero, the remaining reduced force term is then a set of non-linear equations which can be solved numerically to obtain the equilibrium configuration:

$$\mathbf{F_r}(\mathbf{q_u}, \dot{\mathbf{q}}_\mathbf{u}) = \mathbf{0}$$

This system of equations can be solved with the help of a Newton-Raphson method. If $$\mathbf{F}$$ denotes the equations to cancel, the Newton-Raphson algorithm iterates on the equilibrium variables $$\mathbf{x}$$ until the equilibrium state is obtained.

$$\mathbf{x}_{k+1} = \mathbf{x}_{k} - \left(\dfrac{\partial \mathbf{F} }{ \partial \mathbf{x} } \left( \mathbf{x}_{k} \right)\right)^{-1} \mathbf{F}\left( \mathbf{x}_{k} \right)$$

The equilibrium can either be static or quasistatic depending on the equilibrium variables considered. During an equilibrium process variables can be ignored, exchanged or added.

### Example - the cart pendulum with spring¶

For this tutorial, let us consider the pendulum from the “modelling features” tutorial. The complex pendulum (with its four bar mechanism and its spring) is mounted on a cart. The cart slides horizontally on the ground and the pendulum rotates with respect to the cart.

Illustration of the modified example with the four-bar pendulum mounted on a cart

To create the model use the simpleProject-Python template. Build your model by first adding a prismatic joint (along the first direction) between the base and the cart body (mass 5kg) and set it to independent. Use the data given in the “modelling features” tutorial to model the rest of the pendulum-spring mechanism. Finally, add a F sensor on the slider (i.e. the hanging mass).

The system contains a kinematic loop implying independent and dependent variables. There are three 3 independent variables: $$\mathbf{q_u} = \left[ q_1,q_2,q_3 \right]$$ and 2 dependent variables: $$\mathbf{q_v} = \left[ q_4,q_5 \right]$$

MBSysPad diagram of the four-bar pendulum mounted on a cart

REMARK:

• Do not forget to implement the constitutive law (spring-damper) for the joint force (between the pendulum and the slider) but also for the spring force (between the cart and the pendulum).

• It is possible to reuse your previous model (from the “modelling features”) by adding the cart and its translation d.o.f. (see section “MBsysPad 2D diagram manipulation” in “Tips and tricks”)

## Static Equilibrium¶

For static equilibrium, the generalized velocities $$\dot{\mathbf{q}}_{\mathbf{u}}$$ are set to zero. In that case, the equilibrium variables are the 3 independent coordinates, $$\mathbf{x} = \mathbf{q_u}$$ and the equilibrium equations are the set of reduced equations, $$\mathbf{F} = \mathbf{F}_\mathbf{r} = \mathbf{0}$$ .

REMARK:

By default, an equilibrium will be static with the free coordinates as equilibrium variables.

### Non-sensitive variables¶

An equilibrium variable $$x_i$$ can be non-sensitive with respect to the equilibrium equations $$\mathbf{F}$$. This means that the variable $$x_i$$ does not influence the equilibrium equations, hence its gradients is:

$$\dfrac{\partial \mathbf{F} }{ \partial x_i } = \mathbf{0}$$

The variable $$x_i$$ can be ignored in the equilibrium iteration process. Its value can then be chosen arbitrarily by the user before the equilibrium process and will not evolve.

Often the non-sensitive variables are absolute positions and/or orientations. For example, the positions and orientation of a car in the horizontal plane are non-sensitive and can be chosen arbitrary.

### Example - the cart pendulum with spring¶

Among the 3 free variables of the multibody system, the translation of the cart $$q_1$$ is non-sensitive: none of the equations $$\mathbf{F_r}=\mathbf{0}$$ are influenced by the cart position . Its value does not depend on the equilibrium process and can then be chosen arbitrary. However, the equilibrium state for the two remaining variables $$q_2$$,$$q_3$$ has to be determined.

The equilibrium module is based on a similar infrastructure to the direct dynamic module.

• Just after the partitioning in the main function, execute the static equilibrium by writing the following lines.

• Option senstol allows to adjust the criteria of sensitivity (default is 1e-6). A higher value (e.g., 1e-2) might lead to the detection of more non-sensitive variables.

• Option verbose displays the steps of the Newton-Raphson algorithm (values of $$\mathbf{F}$$ and $$\mathbf{x}$$).

• Results are available through the function print_equil.

• For more details of the parameters, we refer to the Documentation.

#...

#==============================================================================
#==============================================================================
try:
import MBsysPy as Robotran
except:
)

#...

#==============================================================================
# Static Equilibrium
#==============================================================================
mbs_data.process = 2
mbs_data.q[mbs_data.joint_id["R2_pendulum"]] = 0.2
mbs_equil = Robotran.MbsEquil(mbs_data)
mbs_equil.set_options(save_anim = 1, senstol = 1e-6, compute_uxd = 0, resfilename = "equil1")
mbs_equil.run()
mbs_equil.print_equil()

#...


There you can see the printout of the equilibrium process and results. The cart translation is detected as non-sensitive and is kept to its zero initial value. The pendulum is angled at an angle of about 10 degrees (0.1642 radian) due to the upper spring and the mass suspended from the pendulum.

Printout for a static equilibrium

In some cases, multiple equilibria are possible. The starting configuration provided by the user will decide which equilibrium is reached. For example, setting the starting value of the pendulum R2 rotation to 1.0 radian will end up with a different equilibrium configuration.

Remarks :

• The equilibrium process is computed based on the mbs_data structure.

• If not changed after loading, the initial values for $$\mathbf{q_u}$$ are the ones written in the .mbs from MBsysPad.

• After an equilibrium, the structure mbs_data is modified and contains the equilibrium configuration.

• For a static equilibrium performed on the generalized coordinates (i.e. the default setting), it is possible to visualize the iteration process of the equilibrium by loading the file equil_q.anim with MBSysPad. Each second corresponds to one iteration step of the Newton-Raphson Algorithm.

## Exchange of equilibrium variables¶

It is possible to replace some of the variables while performing an equilibrium. One of the free coordinates $$q_i$$ can be replaced by another quantity of the system denoted by $$x_{sub}$$ (e.g. a mass, a stiffness, a length, …). The equilibrium equations remain the reduced force term equalling zero, $$\mathbf{F_r} = \mathbf{0}$$. In that case, the replaced free coordinates $$q_i$$ are kept constant during the equilibrium process. It is important that the exchange makes sense and that the exchange variable (i.e. the new one) is sensitive to the equilibrium equations.

$$\mathbf{x} = \left[ \mathbf{q_u}\setminus \{ q_i \} , x_{sub} \right]$$

$$\mathbf{F} = \mathbf{F_r} = \mathbf{0}$$ such that the pendulum is vertical

Remarks:

The exchange is not limited to one variable but can be applied to several variables at the same time

### Example - the cart pendulum with spring¶

If we come back to the cart pendulum model, different variable exchanges can be performed. Here are some examples:

• The elongation of the lower spring $$q_3$$ can be set to a desired length and replaced by the spring stiffness $$k$$ or its free length $$z_0$$.

• The pendulum angular position can be set and replaced by

• the upper spring stiffness $$K$$ or its free length $$Z_0$$

• the joint torque applied along the pendulum $$Q_2$$ or the crank rotational axis $$Q_4$$.

• The crank angular position can be set and replaced by

• the length of the rod

• the distance between the pendulum the crank attachment point with the cart.

Remarks:

The exchange and the desired equilibrium configuration has to make sense otherwise the equilibrium results could be inconsistent from a physical point of view (negative mass or negative free length for a spring)

In this tutorial, The exchange consists of setting the angular position of the pendulum to 0 radian and replacing it by the upper spring free length. The algorithm will then determine the free length and the other variables values (i.e. cart position $$q_1$$ and the lower spring elongation $$q_3$$) such that the pendulum is vertical.

• Some additional lines of code are necessary in the equilibrium process:

• The pendulum rotation is set to zero in the mbs_data structure.

• Function add_exchange_um adds a user model as a new equilibrium variable that replaces the specified default one.

• For more details of the parameters, we refer to the Documentation.

#...

#==============================================================================
# Static Equilibrium
#==============================================================================
mbs_data.reset()
mbs_data.set_qa(mbs_data.joint_id["R2_pendulum"])
mbs_data.q[mbs_data.joint_id["R2_pendulum"]] = 0.0
mbs_equil = Robotran.MbsEquil(mbs_data)
mbs_equil.set_options(senstol = 1e-6, compute_uxd = 0, resfilename = "equil3")
mbs_equil.run()
mbs_equil.print_equil()
mbs_data.unset_qa(mbs_data.joint_id["R2_pendulum"])

#...


There you can see the printout of the equilibrium results. The cart position is again detected as non-sensitive and is kept to its zero initial value. The pendulum is angled at 0 radian (print mbs_data to verify) and the free length of the upper spring $$x_{2}$$ is found to be much longer it was than initially (the spring is now working in compression while working in extension initially). The slider elongation is slightly larger than initially.

Printout for an equilibrium with exchange

## Extra Equilibrium variables¶

Another feature of the equilibrium module is the addition of equilibrium variables and equations. One equation of equilibrium $$F_{e} = 0$$ can be added to the initial equations $$\mathbf{F_r} = \mathbf{0}$$ as far as one equilibrium variable $$x_{e}$$ is also added. This added variable has to be sensitive with respect to the added equation.

$$\mathbf{x} = \left[ \mathbf{q_u} , x_{e} \right]$$

$$\mathbf{F} = \left[ \mathbf{F_r} , F_e \right] = \mathbf{0}$$

Remarks:

The addition is not limited to one equation and one variable, several pairs of those can be added at the same time.

Such features can be practical for adjustments of any kind (geometry, … ) which would imply complex relationship between the variables. For example, the front wheels alignement for a car can be adjusted by varying the steering rod length. The 2 added equations are used to express that the toe of the wheels has to be equal to a given value. The 2 added variables are the steering rods lengths.

### Example - the cart pendulum with spring¶

If we come back to the cart pendulum example, several equation additions can be performed. Let us assume that the slider needs to be horizontally offset of 0.2 meter from the pendulum anchor point on the cart. This condition can be written as an additional equilibrium equation.

• The equation has to be written by the user in the function user_equil_fxe (in user_equil.py, the dedicated user file for equilibrium).

#...
def user_equil_fxe(mbs_data, f):
f[1] = np.sin(mbs_data.q[mbs_data.joint_id["R2_pendulum"]])*(mbs_data.dpt[3][3]+ mbs_data.q[mbs_data.joint_id["T3_slider"]]) - 0.4
return


Remarks:

The anchor point of the lower spring is hardcoded (0.5) but it could be retrieved from the mbs_data structure using the anchor point ID.

There are several ways to ensure a given horizontal position of the slider. One possible way is to apply a joint torque $$Q_{2}$$between the cart and the pendulum.

• Some additional lines of code are necessary in the equilibrium process:

• Function add_extra_variable adds a new equilibrium variable which is defined the variable contained in the array ptr at index index and renamed by the user if wanted.

• For more details of the parameters, we refer to the Documentation.

#...

#==============================================================================
# Static Equilibrium
#==============================================================================
mbs_data.reset()
mbs_data.set_qa(mbs_data.joint_id["R2_pendulum"])
mbs_equil = Robotran.MbsEquil(mbs_data)
mbs_equil.set_options(senstol = 1e-6, compute_uxd = 0)
mbs_equil.run()
mbs_equil.print_equil()
mbs_data.unset_qa(mbs_data.joint_id["R2_pendulum"])

#...


Remarks:

• It is also possible to replace an existing variable by the new equilibrium variable with the function replace_extra_variable.

There you can see the printout of the equilibrium results. There are 4 equilibrium variables. The pendulum orientation $$x_{2}$$is positive such that it is angled to the right. The 4th equilibrium variable $$x_{4}$$ corresponds to a positive joint torque $$Q_{2}$$ which acts against gravity and the upper spring to position the slider to the given horizontal position. From the mbs_data structure, you can verify the vertical position of the slider (combining $$q_{2}$$ and $$q_{3}$$ as in the user function)

Printout for a static equilibrium

## Quasistatic Equilibrium¶

A quasistatic equilibrium is a special type of equilibrium such that there is one joint i with a non-zero velocity $$\dot{q}_i$$. Forces (or torques) $$F_{qstc}$$ act against resistance forces (often friction) to maintain the vehicle in a continuous constant motion. There are two ways to compute the equilibrium:

• Fix the speed and determine the forces (or torques) necessary to maintain this speed.

• Fix the forces (or torques) applied on the system and determine the resulting speed.

Computing those equilibrium utilizes the notion of non-sensitive variable and exchange of variables. In quasistatic equilibrium, the position $$q_i$$ associated with the non-zero speed is not relevant and can then be considered non-sensitive. This variable can be removed from the set of equilibrium variables and exchanged for a sensitive variable. Depending on which approach is chosen, the exchange variable is the force or the speed $$\dot{q}_i$$

• Fixed speed

$$\dot{q}_i \rightarrow \mathbf{x} = \left[ \mathbf{q_u}\setminus \{ q_i \} , F_{qstc} \right] \phantom{.....} \mathbf{F}(\mathbf{x})=\mathbf{0}$$

• Fixed force

$$F_{qstc} \rightarrow \mathbf{x} = \left[ \mathbf{q_u}\setminus \{ q_i \} , \dot{q}_i \right] \phantom{.....} \mathbf{F}(\mathbf{x})=\mathbf{0}$$

It is important to notice that the exchange only concerns the joint i and that the other free independent variables from $$\mathbf{q_u}$$ are still part of the equilibrium process.

Remarks:

The quasistatic force $$F_{qstc}$$ can be of different natures, it can either be a joint force or an external force.

The main application of quasistatic equilibrium is in vehicule dynamics where equilibrium can be performed in straight line and in curves. Multiple wheels does however require good understanding of the module features: for a fixed speed, both forces and speeds need to be exchanged in the process.

### Example - the cart pendulum with spring¶

So far, the cart translation has not been subjected to any calculation as it was non-sensitive. A quasistatic equilibrium can be performed for the cart translation speed but it will make sense only if there is a resistive force (i.e. aerodynamic drag) . In this example, the quasistatic force $$F_{qstc}$$ can simply be a joint force $$Q_{1}$$ applied between the ground and the cart (i.e. a linear actuator).

• The first step is to implement an aerodynamic drag force on the slider.

• Add a Force sensor on the slider, name it and regenerate the equations with MBSysPad

• Implement the aerodynamic force as a function of the slider angle $$\theta$$ of attack and its horizontal velocity $$v$$ :

$$F_{aero} = - a v^2 \left(b - \sin(2\theta)(b-c) \right)$$

import numpy as np

def user_ExtForces(PxF, RxF, VxF, OMxF, AxF, OMPxF, mbs_data, tsim, ixF):

#...

#==============================================================================
# BEGIN OF USER CODE
#==============================================================================

# get the force id
F1 = mbs_data.extforce_id['aero_force']

if ixF == F1:
id = mbs_data.joint_id['R2_pendulum']
a = 0.5
b = 1.05
c = 0.80
v = VxF[1]
Fx = -a*v*v*(b-np.sin(mbs_data.q[id]*2)*(b-c))
#        if PxF[1] > gap:
#            Fx = -10000*(PxF[1]-gap)
#...

#==============================================================================
# END OF USER CODE
#==============================================================================

Swr=np.zeros(9+1)
Swr[1:]=np.r_[Fx,Fy,Fz,Mx,My,Mz,dxF] #concatenation...

return Swr


Remarks:

The external force is placed on the slider body rather than on the pendulum (as it was the case for the modelling features tutorial)

• To perform the quasistatic equilibrium, an exchange must be performed in the main.py file

• Option mode has to be set on 2 (or 3 if you also have non-zero accelerations).

• The desired speed for the cart is set to 5 m/s.

• Function add_exchange adds a new equilibrium variable that replaces the specified one.

• For more details of the parameters, we refer to the Documentation.

..

#...

#==============================================================================
# Static Equilibrium
#==============================================================================

#.. a static equilibrium to perform beforehand and get good initial conditions for the qstc equilibrium

#==============================================================================
# Quasistatic Equilibrium
#==============================================================================
mbs_data.reset()
mbs_data.set_qa(mbs_data.joint_id["T1_cart"])
mbs_equil = Robotran.MbsEquil(mbs_data)
mbs_data.qd[mbs_data.joint_id["T1_cart"]] = 5
mbs_equil.set_options(senstol = 1e-6, compute_uxd = 0, resfilename = "equil7")
mbs_equil.set_options(verbose = 1, grad_lpk = 1, mode = 2)
mbs_equil.run()
mbs_equil.print_equil()
mbs_data.unset_qa(mbs_data.joint_id["T1_cart"])

#...


There you can see the printout of the quasistatic equilibrium. The non-sensitive position of the cart $$x_{1}$$ is replaced by the active joint force $$Q_{1}$$ on the cart necessary to balance the aerodynamic drag. Note that if you are not comfortable with using the variable Qa, the active joint force can also be defined in the user_JointForces function with the help of a user model variable. The pendulum is slightly angled on the left with a negative value for $$x_{2}$$. The lower spring elongation is about 5 cm larger than initially because of the aerodynamic drag. Starting a direct dynamic simulation will correspond to a constant speed displacement of the overall system.

Printout for a quasistatic equilibrium

Remarks:

Limit yourself to speed less than 10 m/s for the cart. Otherwise, equilibrium might not converge or encounter undesired solution (reverse four-bar configuration)

Qa stands for actuated torques/forces, while Qq is the joint torques/forces.