Joints

Joints in Solfec-1.0 are defined by FIX_POINT, FIX_DIRECTION, SET_DISPLACEMENT, SET_VELOCITY, SET_ACCELERATION, PUT_RIGID_LINK, and PUT_SPRING commands. Joints are also called bilateral constraints. They restrain absolute motion of individual points of individual bodies, or relative motion of pairs of points between two bodies.

Joints are implemented via suitably setting values of components of relative constraint velocities or constraint reactions. That is to say, the general implicit relation

(73)\[\mathbf{C}_{\alpha}\left(\mathbf{U}_{\alpha},\mathbf{R}_{\alpha}\right)=\mathbf{0}\]

for a bilateral constraint with index \(\alpha\) takes a particular shape. In order to work with components of relative velocities and forces it is convenient to introduce the following naming convention. Let every local frame be defined by a matrix \(\left\{ \mathbf{a}_{T1},\mathbf{a}_{T2},\mathbf{a}_{N}\right\}\) made of juxtaposed column vectors: \(\mathbf{a}_{T1}\) and \(\mathbf{a}_{T2}\), called tangent, and \(\mathbf{a}_{N}\), called normal. We also assume, that these vectors are mutually perpendicular: \(\mathbf{a}_{T1}\perp\mathbf{a}_{T2}\perp\mathbf{a}_{N}\). With this convenetion at hand, below we define particular versions of relation (73) for joint types available in Solfec-1.0.

Fixed point

Joint corresponding to the FIX_POINT command is realized by defining

\[\mathbf{C}\left(\mathbf{U},\mathbf{R}\right)=\mathbf{U}\]

and hence

\[\mathbf{U}=\mathbf{0}\]

imposes the fixed point constraint.

Fixed direction

Joint corresponding to the FIX_DIRECTION command is realized by defining

\[\begin{split}\mathbf{C}\left(\mathbf{U},\mathbf{R}\right)=\left[\begin{array}{c} R_{T1}\\ R_{T2}\\ U_{N} \end{array}\right]\end{split}\]

and hence

\[\mathbf{R}_{T}=\mathbf{0},\,\,\,U_{N}=0\]

imposes the fixed direction constraint. In this case the normal direction is taken to be the fixed direction, while the tangential plane is unused (hence zero tangential reaction, \(\mathbf{R}_{T}=\left[\begin{array}{c} R_{T1}\\ R_{T2} \end{array}\right]\))

Prescribed displacement

Joint corresponding to the SET_DISPLACEMENT command is realized by defining

\[\begin{split}\mathbf{C}\left(\mathbf{U},\mathbf{R}\right)=\left[\begin{array}{c} R_{T1}\\ R_{T2}\\ U_{N}-\frac{d}{dt}\text{disp}\left(t\right) \end{array}\right]\end{split}\]

and hence

\[\mathbf{R}_{T}=\mathbf{0},\,\,\,U_{N}=\frac{d}{dt}\text{disp}\left(t\right)\]

where the displacement signal \(\text{disp}\left(t\right)\) is provided by the user as a linear spline and differentiated numerically to obtain velocity. The tangential plane is unused, hence zero tangential reaction.

Prescribed velocity

Joint corresponding to the SET_VELOCITY command is realized by defining

\[\begin{split}\mathbf{C}\left(\mathbf{U},\mathbf{R}\right)=\left[\begin{array}{c} R_{T1}\\ R_{T2}\\ U_{N}-\text{velo}\left(t\right) \end{array}\right]\end{split}\]

and hence

\[\mathbf{R}_{T}=\mathbf{0},\,\,\,U_{N}=\text{velo}\left(t\right)\]

where the velocity signal \(\text{velo}\left(t\right)\) is provided by the user as a linear spline. The tangential plane is unused, hence zero tangential reaction.

Prescribed acceleration

Joint corresponding to the SET_ACCELERATION command is realized by defining

\[\begin{split}\mathbf{C}\left(\mathbf{U},\mathbf{R}\right)=\left[\begin{array}{c} R_{T1}\\ R_{T2}\\ U_{N}-\int_{0}^{t}\text{acc}\left(t\right) \end{array}\right]\end{split}\]

and hence

\[\mathbf{R}_{T}=\mathbf{0},\,\,\,U_{N}=\int_{0}^{t}\text{acc}\left(t\right)\]

where the acceleration signal \(\text{acc}\left(t\right)\) is provided by the user as a linear spline and integrated numerically to obtain velocity. The tangential plane is unused, hence zero tangential reaction.

Spring constraint

Joint corresponding to the PUT_SPRING command is realized by defining a stretch

\[d=\left\Vert \mathbf{x}_{1}\left(\mathbf{X}_{1},t\right)-\mathbf{x}_{2}\left(\mathbf{X}_{2},t\right)\right\Vert -\left\Vert \mathbf{X}_{1}-\mathbf{X}_{2}\right\Vert\]

a normal direction

\[\mathbf{a}_{N}=\frac{\mathbf{x}_{1}\left(\mathbf{X}_{1},t\right)-\mathbf{x}_{2}\left(\mathbf{X}_{2},t\right)}{\left\Vert \mathbf{x}_{1}-\mathbf{x}_{2}\right\Vert }\]

and tangential plane as orthogonal to this direction \(\mathbf{a}_{T1}\perp\mathbf{a}_{T2}\perp\mathbf{a}_{N}\), followed by imposing

\[\begin{split}\mathbf{C}\left(\mathbf{U},\mathbf{R}\right)=\left[\begin{array}{c} R_{T1}\\ R_{T2}\\ R_{N}=\text{user_force}\left(d,\dot{d}\right) \end{array}\right]\end{split}\]

and hence

\[\mathbf{R}_{T}=\mathbf{0},\,\,\,R_{N}=\text{user_force}\left(d,\dot{d}\right)\]

where the user force is prescribed as a Python subroutine. The tangential plane is unused, hence zero tangential reaction.

Implementation

Joints are implemented as a part of constraint solvers. For example, function dbs.c:DIAGONAL_BLOCK_Solver is a driver routine for all joint types solved within the Gauss–Seidel solver, invoked from within bgs.c:GAUSS_SEIDEL_Solve. Within the Projected Newton solver the routine nts.c:solve implements all joint types.