/***************************************************************************** * DynaMechs: A Multibody Dynamic Simulation Library * * Copyright (C) 1994-2001 Scott McMillan All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ***************************************************************************** * File: dmRigidBody.hpp * Author: Scott McMillan * Summary: Class definition for dmRigidBody *****************************************************************************/ #ifndef _DM_RIGID_BODY_HPP #define _DM_RIGID_BODY_HPP #include #include #include #include //====================================================================== /** This class is the repository for all the dynamic parameters for rigid bodies (links) that are needed for the AB dynamics algorithm. It is subclassed from {\tt dmLink} and subclassed by all links that have degrees of freedom to be simulated. Remember: {\tt dmLink} is a misleading name as it specifies the API needed by the AB algorithm and could also correspond to non-variable transformations like the {\tt dmZScrewTxLink} class that is only used for kinematic manipulation (transformations), but do not have a physical manifestation. The {\tt setInertiaParameters} and {\tt getInertiaParameters} functions is used set and retrieve the inertial parameters. The first argument specifies the mass, $m$, of the body, the second specifies the $3\times 3$ inertia matrix, $\bar{\mbox{\boldmath $I$}}$, of the body with respect to the body's coordinate system, and the third specifies the position of the body's center of gravity, $\mbox{\boldmath $p$}_{cg}$, with respect to the body's coordinate system origin. Note that from these parameters, the {\tt setInertiaParameters} function constructs the the spatial inertial matrix from the mass, center of gravity and inertia tensor and verifies that it is positive definite: \begin{eqnarray*} {\bf I} & = & \left[ \begin{array}{cc} \bar{\mbox{\boldmath $I$}} & m\:\tilde{\mbox{\boldmath $p$}}_{cg} \\ m\:\tilde{\mbox{\boldmath $p$}}^T_{cg} & m{\bf 1}_3 \end{array} \right]. \end{eqnarray*} Note that $\bar{\mbox{\boldmath $I$}}$ is related to the body's inertia about its principle axes, $\bar{\mbox{\boldmath $I$}}_{cg}$, as follows: \begin{eqnarray*} \bar{\mbox{\boldmath $I$}} & = & \mbox{\boldmath $R$}^T \bar{\mbox{\boldmath $I$}}_{cg} \mbox{\boldmath $R$} + m \tilde{\mbox{\boldmath $p$}}_{cg} \tilde{\mbox{\boldmath $p$}}_{cg}^T, \end{eqnarray*} where $\mbox{\boldmath $R$}$ specifies the rotation between the principle axes and the body's coordinate system. Note that for underwater simulation, an entirely new library is made with the {\tt DM_HYDRODYNAMICS} environment variable defined. In this case, this class requires additional hydrodynamic parameters to compute the additional hydrodynamic effects. These are set with the {\tt setHydrodynamicParameters} function. The {\tt volume} parameter is the volume of fluid that this rigid body displaces. The {\tt I\_added\_mass} parameter is a $6\times 6$ positive semi-definite matrix corresponding to the added mass. The third parameter, {\tt cb\_pos} is the position of the center of bouyancy with the respect to the body's coordinate system. The remaining parameters are used to compute a rough approximation of a drag force. In this algorithm, the body must be approximated with an axis aligned cylinder. The {\tt drag\_axis} indicates which axis (0 for x axis, 1 for y, or 2 for z), {\tt cyl\_min} and {\tt cyl\_max} gives the coordinates along this axis which defines the extent of the approximating cylinder, and {\tt cyl\_radius} defines its radius. Finally, {\tt C\_d} defines the coefficient of drag. This discussion requires the obvious note about units. DynaMechs makes no assumptions about length and mass units (only their consistency). It is required that once a convention is chosen (MKS, cgs, etc..), it is adhered to in the specification of ALL the parameters in all of the classes. Motion of rigid bodies can be under the influence of a variety of external forces. Complaint forces (a function of the rigid body's state) can be implemented by subclassing from {\tt dmForce} and "adding" instantiations of them to this class. The {\tt dmContactModel} is an example of a derived force class. Any number of previously instantiated {\tt dmForce} objects can be added to the {\tt dmRigidBody} class using the {\tt addForce} function. The number of force objects associated with this class is returned when a call to {\tt getNumForces} is made. Force objects are added to an internal list in order such that the first one is index 0, the second is index 1, and so forth. The current index of a force object in the list of associated objects is returned when a call to {\tt getForceIndex} is made and the pointer to a {\tt dmForce} object, in question, is provided. Alternatively a pointer to a force object is returned when a call to {\tt getForce} is made with a given index. This function returns NULL if the index is out of range (0,..,num\_forces-1). Force objects can be removed with a call to either {\tt removeForce} function, which will return true if the operation is successful. The force to be removed can be referenced either by its index or a pointer. If the index is out of range or the pointer doesn't match any of the current force objects in the list, or there was an internal failure, the function will return false. Note that when a force object is removed all indices for forces added later than the one in question will be renumbered (one lower). In addition to the force objects, this class also provides the functions, {\tt setExternalForce} and {\tt getExternalForce}, which can be used to directly specify an external force exerted on the rigid body. The parameter, {\tt force}, is a spatial vector consisting of the moment and linear force expressed with respect to the body's coordinate system. The {\tt computeBeta}, and, in the case of hydrodynamic simulation, {\tt computeDrag} and {\tt computeHydrodynamicBias} are all functions called by the {\tt ABForwardKinematics} functions of the various derived objects to compute state (position and velocity) dependent bias forces experience by the bodies. See also {\tt dmLink}, {\tt dmForce}, {\tt dmContactModel}, {\tt dmLoadFile\_dm}. */ class DM_DLL_API dmRigidBody : public dmLink { public: /// dmRigidBody(); /// virtual ~dmRigidBody(); /// bool setInertiaParameters(Float mass, CartesianTensor inertia, CartesianVector cg_pos); /// void getInertiaParameters(Float &mass, CartesianTensor inertia, CartesianVector cg_pos) const; // manage a list of force objects. /// unsigned int getNumForces() const { return m_force.size(); } /// bool addForce(dmForce *force); /// int getForceIndex(dmForce *force) const; /// dmForce *getForce(unsigned int index) const; /// bool removeForce(dmForce *force); /// bool removeForce(unsigned int index); /// virtual void pushForceStates(); /// virtual void popForceStates(); /// virtual Float getPotentialEnergy(const dmABForKinStruct &link_val, CartesianVector a_gravity) const; /// virtual Float getKineticEnergy(const dmABForKinStruct &link_val) const; /// void getExternalForce(SpatialVector force) { for (int i=0; i<6; i++) force[i] = m_external_force[i]; } /// void setExternalForce(SpatialVector force) { for (int i=0; i<6; i++) m_external_force[i] = force[i]; } /// void computeBeta(const dmABForKinStruct &link_curr_val, SpatialVector beta); #ifdef DM_HYDRODYNAMICS /// void setHydrodynamicParameters(Float volume, SpatialTensor I_added_mass, CartesianVector cb_pos, int drag_axis, Float cyl_min, Float cyl_max, Float cyl_radius, Float C_d); /// void computeDrag(SpatialVector v_rel, SpatialVector f_D); /// void computeHydrodynamicBias(const dmABForKinStruct &val, SpatialVector beta_H); #endif protected: // not implemented dmRigidBody(const dmRigidBody &); dmRigidBody &operator=(const dmRigidBody &); // the following is used to initialize AB vars virtual void initABVars() = 0; protected: SpatialTensor m_SpInertia; // 6x6 spatial inertia matrix // this also contains the addedMass when // hydrodynamic simulation is being // performed. // Note: the spatial inertia matrix is computed as follows: // | I_bar \tilde{mass*cg_pos} | // I = | | // | \tilde{mass*cg_pos}' mass*E_3 | // // where E_3 is the 3x3 indentity matrix, // h = mass*cg_pos, and // tilde = crossproduct operator // AB algorithm variables common to all rigid bodies SpatialVector m_beta; // body bias force SpatialVector m_beta_star; // AB bias force SpatialTensor m_I_star; // AB Inertia SpatialVector m_external_force; // direct external force wrt to BCS // list of force objects that act on rigid body like compliant contacts vector m_force; private: // This are variables that only the rigid body object seems to use: Float m_mass; CartesianVector m_cg_pos; // position of center of gravity in BCS CartesianVector m_h; // first mass moment = mass*cg_pos. CartesianTensor m_I_bar; // 3x3 inertia tensor about body axes. #ifdef DM_HYDRODYNAMICS Float m_displaced_fluid_vol; // volume of fluid displaced by body. Float m_displaced_fluid_mass; // mass of fluid displaced by body CartesianVector m_cb_pos; // position of center of buoyancy in BCS SpatialTensor m_I_added_mass; // 6x6 added mass/inertia matrix int m_axis; // drag parameters (for cylinder) SpatialVector m_Cd_A_p; // spatial coefficients for cube's drag Float m_x0, m_length, m_radius; Float m_Ca, m_C2rl; #endif }; #endif