```{raw} latex \clearpage ``` (sec-item-objectconnectorcoordinatevector)= # ObjectConnectorCoordinateVector A constraint which constrains the coordinate vectors of two markers Marker[Node|Object|Body]Coordinates attached to nodes or bodies. The marker uses the objects {ref}`LTG `-lists to build the according coordinate mappings. ## Interface - Python names: `ObjectConnectorCoordinateVector` or `CoordinateVectorConstraint`, and `VCoordinateVectorConstraint` for its visualization - Markers it acts on: those providing `Coordinates`: [](#sec-item-markernodecoordinates), [](#sec-item-markerobjectode2coordinates) ## Parameters The parameters of the item; in a dictionary, its type is 'ConnectorCoordinateVector': | name | type | size | default | description | |---|---|---|---|---| | **name** | String | | '' | constraints's unique name | | **markerNumbers** | ArrayMarkerIndex | | [ invalid (-1), invalid (-1) ] | (symbol: $[m0,m1]\tp$) list of markers used in connector | | **scalingMarker0** | NumpyMatrix | | [] | (symbol: $\Xm_{m0} \in \Rcal^{n_{ae} \times n_{q_{m0}}}$) linear scaling matrix for coordinate vector of marker 0; matrix provided in Python numpy format | | **scalingMarker1** | NumpyMatrix | | [] | (symbol: $\Xm_{m1} \in \Rcal^{n_{ae} \times n_{q_{m1}}}$) linear scaling matrix for coordinate vector of marker 1; matrix provided in Python numpy format | | **quadraticTermMarker0** | NumpyMatrix | | [] | (symbol: $\Ym_{m0} \in \Rcal^{n_{ae} \times n_{q_{m0}}}$) quadratic scaling matrix for coordinate vector of marker 0; matrix provided in Python numpy format | | **quadraticTermMarker1** | NumpyMatrix | | [] | (symbol: $\Ym_{m0} \in \Rcal^{n_{ae} \times n_{q_{m0}}}$) quadratic scaling matrix for coordinate vector of marker 1; matrix provided in Python numpy format | | **offset** | NumpyVector | | [] | (symbol: $\vv_\mathrm{off} \in \Rcal^{n_{ae}}$) offset added to constraint equation; only active, if no userFunction is defined | | **velocityLevel** | Bool | | False | If true: connector constrains velocities (only works for {ref}`ODE2 ` coordinates!); offset is used between velocities; in this case, the offsetUserFunction_t is considered and offsetUserFunction is ignored | | **constraintUserFunction** | ObjectConnectorCoordinateVectorConstraintUserFunction | | 0 | (symbol: $\cv_{user} \in \Rcal^{n_{ae}}$) A Python user function which computes the constraint equations; to define the number of algebraic equations, set scalingMarker0 as a numpy.zeros((nAE,1)) array with nAE being the number algebraic equations; see description below | | **jacobianUserFunction** | ObjectConnectorCoordinateVectorJacobianUserFunction | | 0 | (symbol: $\Jm_{user} \in \Rcal^{(n_{q_{m0}}+n_{q_{m1}}) \times n_{ae}}$) A Python user function which computes the jacobian, i.e., the derivative of the left-hand-side object equation w.r.t. the coordinates (times $f_{ODE2}$) and w.r.t. the velocities (times $f_{ODE2_t}$). Terms on the RHS must be subtracted from the LHS equation; the respective terms for the stiffness matrix and damping matrix are automatically added; see description below | | **activeConnector** | Bool | | True | flag, which determines, if the connector is active; used to deactivate (temporarily) a connector or constraint | | **visualization** | VObjectConnectorCoordinateVector | | | parameters for visualization of item | ## Visualization parameters `VObjectConnectorCoordinateVector` has no parameters. ## Drawing The item draws nothing. ## Output variables Available as `OutputVariableType` in sensors, `Get...Output()` and other functions: ```{tabularcolumns} \Y{0.25}\Y{0.25}\Y{0.5} ``` | output variable | symbol | description | |---|---|---| | Displacement | $\Delta \qv$ | relative scalar displacement of marker coordinates, not including scaling matrices | | Velocity | $\Delta \vv$ | difference of scalar marker velocity coordinates, not including scaling matrices | | ConstraintEquation | $\cv$ | (residuum of) constraint equations | | Force | $\tlambda$ | constraint force vector (vector of Lagrange multipliers), resulting from action of constraint equations | (description-objectconnectorcoordinatevector)= ## Detailed description ### Definition of quantities | intermediate variables | symbol | description | |---|---|---| | marker m0 coordinate vector | $\qv_{m0} \in \Rcal^{n_{q_{m0}}}$ | coordinate vector provided by marker $m0$; depending on the marker, the coordinates may or may not include reference coordinates | | marker m1 coordinate vector | $\qv_{m1} \in \Rcal^{n_{q_{m1}}}$ | coordinate vector provided by marker $m1$; depending on the marker, the coordinates may or may not include reference coordinates | | marker m0 velocity coordinate vector | $\dot \qv_{m0} \in \Rcal^{n_{q_{m0}}}$ | velocity coordinate vector provided by marker $m0$ | | marker m1 velocity coordinate vector | $\dot \qv_{m1} \in \Rcal^{n_{q_{m1}}}$ | velocity coordinate vector provided by marker $m1$ | | number of algebraic equations | $n_{ae}$ | number of algebraic equations must be same as number of rows in $\Xm_{m0}$ and $\Xm_{m1}$ | | difference of coordinates | $\Delta \qv = \qv_{m1} - \qv_{m0}$ | Displacement between marker m0 to marker m1 coordinates | | difference of velocity coordinates | $\Delta \vv= \dot \qv_{m1} - \dot \qv_{m0}$ | | ### Remarks The number of algebraic equations depends on the maximum number of rows in $\Xm_{m0}$, $\Ym_{m0}$, $\Xm_{m1}$ and $\Ym_{m1}$. The number of rows of the latter matrices must either be zero or the maximum of these rows. The number of columns in $\Xm_{m0}$ (or $\Ym_{m0}$) must agree with the length of the coordinate vector $\qv_{m0}$ and the number of columns in $\Xm_{m1}$ (or $\Ym_{m1}$) must agree with the length of the coordinate vector $\qv_{m1}$, if these matrices are not empty matrices. If one marker $k$ is a ground marker (node/object), the length of $\qv_{m,k}$ is zero and also the according matrices $\Xm_{m,k}$, $\Ym_{m,k}$ have zero size and will not be considered in the computation of the constraint equations. ### Connector constraint equations If `activeConnector = True` and no `constraintUserFunction` is defined, the index 3 algebraic equations $$ \cv(\qv_{m0}, \qv_{m1}) = \Xm_{m1} \cdot \qv_{m1} + \Ym_{m1} \cdot \qv^2_{m1} - \Xm_{m0} \cdot\qv_{m0} - \Ym_{m0} \cdot\qv^2_{m0} - \vv_\mathrm{off} = 0 $$ Note that the squared coordinates are understood as $\qv^2_{m0} = [q^2_{0,m0}, \; q^2_{1,m0}, \; \ldots]\tp$, same for $\qv^2_{m1}$. The index 2 (velocity level) algebraic equation accordingly reads $$ \dot \cv(\dot \qv_{m0}, \dot \qv_{m1}) = \Xm_{m1} \cdot \dot \qv_{m1} + \Ym_{m1} \cdot \dot \qv^2_{m1} - \Xm_{m0} \cdot \dot \qv_{m0} - \Ym_{m0} \cdot \dot \qv^2_{m0} - \dv_\mathrm{off} = 0 $$ The vector $\dv$ in velocity level equations is zero, except if `parameters.velocityLevel = True`, then $\dv=\vv_\mathrm{off}$. Note that the index 2 equations are used, if the solver uses index 2 formulation OR if the flag `parameters.velocityLevel = True` (or both). However, the `constraintUserFunction` has to be chosen accordingly by the user, either as position or as velocity level. The user functions include dependency on time $t$, but this time dependency is not respected in the computation of initial accelerations. Therefore, If `activeConnector = False`, the (index 1) algebraic equation reads for ALL cases: $$ \cv(\tlambda) = \tlambda = 0 $$ If a `constraintUserFunction` is defined, it also requires an according `jacobianUserFunction` (and vice versa). **Userfunction**: `constraintUserFunction(mbs, t, itemNumber, q, q_t, velocityLevel)` A user function, which computes algebraic equations for the connector based on the marker coordinates stored in `q` and `q_t`. Depending on `velocityLevel`, the user function needs to compute either the position-level (`velocityLevel=False`) or the velocity level (`velocityLevel=True`) constraint equations. Note that for Index 2 solvers, the `constraintUserFunction` may be called with `velocityLevel=True` but `jacobianUserFunction` is called with `velocityLevel=False`. To define the number of algebraic equations, set `scalingMarker0` as a `numpy.zeros((nAE,1))` array with `nAE` being the number algebraic equations. The returned vector of `constraintUserFunction` must have size `nAE`. Note that itemNumber represents the index of the ObjectGenericODE2 object in mbs, which can be used to retrieve additional data from the object through `mbs.GetObjectParameter(itemNumber, ...)`, see the according description of `GetObjectParameter`. | arguments / return | type or size | description | |---|---|---| | `mbs` | MainSystem | provides MainSystem mbs to which object belongs to | | `t` | Real | current time in mbs | | `itemNumber` | Index | integer number $i_N$ of the object in mbs, allowing easy access to all object data via mbs.GetObjectParameter(itemNumber, ...) | | `q` | Vector $\in \Rcal^{(n_{q_{m0}}+n_{q_{m1}})}$ | connector coordinates, subsequently for marker $m0$ and marker $m1$, in current configuration | | `q_t` | Vector $\in \Rcal^{(n_{q_{m0}}+n_{q_{m1}})}$ | connector velocity coordinates in current configuration | | `velocityLevel` | Bool | velocityLevel as currently stored in connector | | **return value** | Vector $\in \Rcal^{n_{ae}}$ | returns vector (numpy array or list) of evaluated constraint equations for connector | **Userfunction**: `jacobianUserFunction(mbs, t, itemNumber, q, q_t, velocityLevel)` A user function, which computes the jacobian of the algebraic equations w.r.t. the ODE2 coordiantes (ODE2_t velocity coordinates if `velocityLevel=True`). The jacobian needs to exactly represent the derivative of the constraintUserFunction. The returned matrix of `jacobianUserFunction` must have `nAE` rows and `len(q)` columns. | arguments / return | type or size | description | |---|---|---| | `mbs` | MainSystem | provides MainSystem mbs to which object belongs to | | `t` | Real | current time in mbs | | `itemNumber` | Index | integer number $i_N$ of the object in mbs, allowing easy access to all object data via mbs.GetObjectParameter(itemNumber, ...) | | `q` | Vector $\in \Rcal^{(n_{q_{m0}}+n_{q_{m1}})}$ | connector coordinates, subsequently for marker $m0$ and marker $m1$, in current configuration | | `q_t` | Vector $\in \Rcal^{(n_{q_{m0}}+n_{q_{m1}})}$ | connector velocity coordinates in current configuration | | `velocityLevel` | Bool | velocityLevel as currently stored in connector | | **return value** | MatrixContainer $\in \Rcal^{(n_{q_{m0}}+n_{q_{m1}})\times n_{ae}}$ | returns special jacobian for connector, as exu.MatrixContainer, numpy array or list of lists; use MatrixContainer sparse format for larger matrices to speed up computations; sparse triplets MAY NOT contain zero values! | (miniexample-objectconnectorcoordinatevector)= ## Mini example ```python #all coordinates of two nodes, tied by a coordinate vector constraint X1 qB - X0 qA = offset; the #coordinates INCLUDE the reference values, so qB - qA = [1,0,0] keeps the two points where they are nA = mbs.AddNode(NodePoint(referenceCoordinates=[0,0,0])) nB = mbs.AddNode(NodePoint(referenceCoordinates=[1,0,0])) mbs.AddObject(ObjectMassPoint(nodeNumber=nA, mass=1)) mbs.AddObject(ObjectMassPoint(nodeNumber=nB, mass=1)) mA = mbs.AddMarker(MarkerNodeCoordinates(nodeNumber=nA)) mB = mbs.AddMarker(MarkerNodeCoordinates(nodeNumber=nB)) mbs.AddObject(ObjectConnectorCoordinateVector(markerNumbers=[mA, mB], scalingMarker0=np.eye(3), scalingMarker1=np.eye(3), offset=[1,0,0])) mbs.AddLoad(LoadForceVector(markerNumber=mbs.AddMarker(MarkerNodePosition(nodeNumber=nA)), loadVector=[2,0,0])) mbs.Assemble() mbs.SolveDynamic() #both masses move together: a = F/(2m) = 1, x = a/2*t^2 at t=1 exu.sys['testResult'] = mbs.GetNodeOutput(nB, exu.OutputVariableType.Displacement)[0] #0.5 ``` Relevant Examples (Ex) and TestModels (TM) with weblink to github: [`coordinateVectorConstraint.py`](https://github.com/jgerstmayr/EXUDYN/blob/master/python/TestModels/coordinateVectorConstraint.py) (TM), [`coordinateVectorConstraintGenericODE2.py`](https://github.com/jgerstmayr/EXUDYN/blob/master/python/TestModels/coordinateVectorConstraintGenericODE2.py) (TM), [`rigidBodyAsUserFunctionTest.py`](https://github.com/jgerstmayr/EXUDYN/blob/master/python/TestModels/rigidBodyAsUserFunctionTest.py) (TM)