ModelSpace
All Classes Namespaces Functions Variables Enumerations Pages
Body.hpp
1/******************************************************************************
2* Copyright (c) ATTX LLC 2024. All Rights Reserved.
3*
4* This software and associated documentation (the "Software") are the
5* proprietary and confidential information of ATTX, LLC. The Software is
6* furnished under a license agreement between ATTX and the user organization
7* and may be used or copied only in accordance with the terms of the agreement.
8* Refer to 'license/attx_license.adoc' for standard license terms.
9*
10* EXPORT CONTROL NOTICE: THIS SOFTWARE MAY INCLUDE CONTENT CONTROLLED UNDER THE
11* INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) OR THE EXPORT ADMINISTRATION
12* REGULATIONS (EAR99). No part of the Software may be used, reproduced, or
13* transmitted in any form or by any means, for any purpose, without the express
14* written permission of ATTX, LLC.
15******************************************************************************/
16/*
17Body header file
18
19Author: Alex Reynolds
20*/
21#ifndef BODY_HPP
22#define BODY_HPP
23
24#include "data_management/DataIO.hpp"
25#include "Frame.hpp"
26#include "Node.hpp"
27
28namespace clockwerk {
29
30 /// @brief Class to define a body as a frame with mass and inertia
31 ///
32 /// This file defines the base body class which forms the basis for 6-DOF
33 /// dynaics. Bodies are special invocations of the Frame object with mass
34 /// and inertia, which allows them to interact with frames freely.
35 ///
36 /// For the individual body, inertia is assumed to be about the frame center.
37 ///
38 /// TODO
39 /// For now, the body class enforces the following constraints in order to
40 /// make things simpler and verify dynamics.
41 /// - Bodies may only be children of frames
42 /// - Nodes may only be children of bodies
43 /// - Joints are restricted to fully free or fully locked
44 ///
45 /// Unless otherwise noted units should be assumed metric
46 template <typename T>
47 class Body : public Frame<T> {
48 public:
49 /// @brief Parent constructor for the body object
50 /// @param name The name of the body
51 /// @param par The frame parent. Default is nullptr
52 Body(const std::string &name, Frame<T>* par=nullptr);
53
54 /// @brief Signal/parameter for the body's mass
55 clockwerk::DataIO<T> mass = clockwerk::DataIO<T>(nullptr, "mass", 1.0);
56 /// @brief Signal/parameter for the body's inertia
57 clockwerk::DataIO<Matrix<T, 3, 3>> inertia = clockwerk::DataIO<Matrix<T, 3, 3>>(nullptr, "inertia",
58 clockwerk::Matrix<T, 3, 3>({{1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}}));
59 /// @brief Signal/parameter for the body's composite mass.
60 /// @note Is calculated -- should not be modified
61 clockwerk::DataIO<T> composite_mass = clockwerk::DataIO<T>(nullptr, "composite_mass", 1.0);
62 /// @brief Signal/parameter for the body's composite inertia.
63 /// @note Is calculated -- should not be modified
64 clockwerk::DataIO<Matrix<T, 3, 3>> composite_inertia = clockwerk::DataIO<Matrix<T, 3, 3>>(nullptr, "composite_inertia",
65 clockwerk::Matrix<T, 3, 3>({{1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}}));
66
67 /* Nice handle to the body itself for mapping*/
68 clockwerk::DataIO<Body<T>*> self_id = clockwerk::DataIO<Body<T>*>(nullptr, "self_id", this);
69
70 /// @brief Function to recurse through the body and its children to apply external
71 /// forces and moments to the "correct" body by resolving them to locations
72 /// where there are degrees of freedom.
73 /// @note Specific implementation of this function for body class. Overwrites
74 /// frame class implementation
76
77 /// @brief Function to recurse through the body and its children to resolve applied
78 /// external forces and moments into acceleration and angular acceleration
79 /// @note Implicitly applies acceleration/ang accel to the body frame
80 /// @note Assumes calcBodyTreeForcesMoments has been called to calculate forces/moments
81 /// @note Specific implementation of this function for body class. Overwrites
82 /// frame class implementation
84
85 /// @brief Function to resolve passthrough forces/moments into a force/moment pair in parent body frame origin
86 /// @param force_parentcg__p Implicit return of passthrough force applied to this body in the parent body frame
87 /// @param moment_parentcg__p Implicit return of passthrough moment applied to this body in the parent body frame,
88 /// RESOLVED TO A FORCE/MOMENT COUPLE AT THE PARENT FRAME LOCATION
89 void getFMPairAtParentOrigin(CartesianVector<T, 3> &force_parentcg__p, CartesianVector<T, 3> &moment_parentcg__p);
90
91 /// Getters for force and moment stuff
93 CartesianVector<T, 3> externalMoment() {return _ext_moment__b;}
94 CartesianVector<T, 3> passthroughForce() {return _passthrough_force__b;}
95 CartesianVector<T, 3> passthroughMoment() {return _passthrough_moment__b;}
96
97 protected:
98 /// @brief Function to recurse through children and calculate body composite inertia
100
101 /// @brief Function to resolve forces and moments to body frame as applied and passed through
102 void _calcAppliedForceMoment(const CartesianVector<T, 3> &force, const CartesianVector<T, 3> &moment);
103
104 /// Applied external force and moment on the body
106 CartesianVector<T, 3> _ext_moment__b;
107
108 /// Passthrough force on the body -- force not applied here but passed on to parent body
110 CartesianVector<T, 3> _passthrough_moment__b;
111 };
112
113 template <typename T>
114 Body<T>::Body(const std::string &name, Frame<T>* par)
115 : Frame<T>(name, par, true) {
116
117 /// Set frame type to body
119 }
120
121 template <typename T>
122 int Body<T>::calcFrameTreeExtForcesMoments() {
123 /// Set our internal forces/moments to zero for fresh calculation
124 _ext_force__b.setToZeros();
125 _ext_moment__b.setToZeros();
126 _passthrough_force__b.setToZeros();
127 _passthrough_moment__b.setToZeros();
128
129 /// This calculation is executed from the tree "leaves" in, so we recurse first and execute
130 /// calculations on our way back out
131 /// If we have children, get their stuff
132 if(this->nChildren()) {
133 /// Temporary variables to hold force and moment calculations from parents
134 CartesianVector<T, 3> force_tmp;
135 CartesianVector<T, 3> moment_tmp;
136
137 for(unsigned int i = 0; i < this->nChildren(); i++) {
138 /// Our pointer is technically stored as graph tree object -- cast to frame
139 Frame<T>* ptr = (Frame<T>*)GraphTreeObject::_children[i];
140 /// We ignore anything that is not a node or a body -- handle both appropriately
141 if(ptr->type() == BODY) {
142 /// Recurse further through body
143 Body<T>* body_ptr = (Body<T>*)ptr;
144 body_ptr->calcFrameTreeExtForcesMoments();
145
146 /// Now that we've calculated (implicitly) our child body's forces and moments,
147 /// resolve the passthrough forces into our body
148 body_ptr->getFMPairAtParentOrigin(force_tmp, moment_tmp);
149
150 /// Calculate the applied and passed through elements of our force and moment
151 _calcAppliedForceMoment(force_tmp, moment_tmp);
152 } else if(ptr->type() == NODE) {
153 /// Nodes are not allowed to have children, so we can safely pull our forces
154 /// and moments from them without issue. Do that here
155 Node<T>* node_ptr = (Node<T>*)ptr;
156 node_ptr->getFMPairAtParentOrigin(force_tmp, moment_tmp);
157
158 /// Calculate the applied and passed through elements of our force and moment
159 _calcAppliedForceMoment(force_tmp, moment_tmp);
160 } else {
161 /// We're looking at a frame. Don't do anything, but recurse
162 /// further to see if its children do anything interesting
163 ptr->calcFrameTreeExtForcesMoments();
164 }
165 }
166 }
167
168 return NO_ERROR;
169 }
170
171 template <typename T>
172 int Body<T>::calcFrameTreeExtAcceleration() {
173 /// First calculate our composite CM recursively by calling our calculation function
175
176 /// TODO: Implement recursive and offset composite CM/inertia here
177
178 /// Now calculate our acceleration based on mass
179 Frame<T>::_acc_f_p__p = Frame<T>::quat_f_p().toDCM().inverse()*_ext_force__b;
180 multiply((T)1.0/composite_mass(), Frame<T>::_acc_f_p__p, Frame<T>::_acc_f_p__p);
181
182 /// Now calculate our angular acceleration on the basis of our applied moment and omega
183 CartesianVector<T, 3> w_f_root_f = Frame<T>::rootRelAngularVelocity();
184 CartesianVector<T, 3> tmp = _ext_moment__b - tilde(w_f_root_f)*composite_inertia()*w_f_root_f;
185 Matrix<T, 3, 3> ci_inverse;
186 int err = composite_inertia().inverse(ci_inverse); if(err) {return err;}
187 Frame<T>::_alpha_f_p__f = ci_inverse*tmp;
188
189 return NO_ERROR;
190 }
191
192 template <typename T>
193 void Body<T>::_calcCompositeMassInertiaCM() {
194 /// TODO: Update for multiple body case
197 }
198
199 template <typename T>
200 void Body<T>::_calcAppliedForceMoment(const CartesianVector<T, 3> &force, const CartesianVector<T, 3> &moment) {
201 /// Calculate which elements of the force and moment are applied (affect body motion)
202 /// and which are passed through (affect parent body motion, make this body into a node)
203 eAdd(Frame<T>::_t_joint.freedom()*force, _ext_force__b, _ext_force__b);
204 eAdd(Frame<T>::_t_joint.dependency()*force, _passthrough_force__b, _passthrough_force__b);
205 eAdd(Frame<T>::_r_joint.freedom()*moment, _ext_moment__b, _ext_moment__b);
206 eAdd(Frame<T>::_r_joint.dependency()*moment, _passthrough_moment__b, _passthrough_moment__b);
207 }
208
209 template <typename T>
210 void Body<T>::getFMPairAtParentOrigin(CartesianVector<T, 3> &force_parentcg__p,
211 CartesianVector<T, 3> &moment_parentcg__p) {
212 // First calculate our passthrough force in parent frame
213 DCM<T> dcm_p_f = Frame<T>::quat_f_p().toDCM().inverse();
214 force_parentcg__p = dcm_p_f*_passthrough_force__b;
215
216 /// Now add our moment couple to our already applied moment
217 moment_parentcg__p = dcm_p_f*_passthrough_moment__b + cross(Frame<T>::pos_f_p__p(), force_parentcg__p);
218 }
219
220}
221
222#endif
CartesianVector< T, 3 > _ext_force__b
Applied external force and moment on the body.
Definition Body.hpp:105
void getFMPairAtParentOrigin(CartesianVector< T, 3 > &force_parentcg__p, CartesianVector< T, 3 > &moment_parentcg__p)
Function to resolve passthrough forces/moments into a force/moment pair in parent body frame origin.
Definition Body.hpp:210
void _calcCompositeMassInertiaCM()
Function to recurse through children and calculate body composite inertia.
Definition Body.hpp:193
CartesianVector< T, 3 > _passthrough_force__b
Passthrough force on the body – force not applied here but passed on to parent body.
Definition Body.hpp:109
int calcFrameTreeExtForcesMoments()
Function to recurse through the body and its children to apply external forces and moments to the "co...
Definition Body.hpp:122
int calcFrameTreeExtAcceleration()
Function to recurse through the body and its children to resolve applied external forces and moments ...
Definition Body.hpp:172
clockwerk::DataIO< Matrix< T, 3, 3 > > inertia
Signal/parameter for the body's inertia.
Definition Body.hpp:57
clockwerk::DataIO< T > mass
Signal/parameter for the body's mass.
Definition Body.hpp:55
clockwerk::DataIO< Matrix< T, 3, 3 > > composite_inertia
Signal/parameter for the body's composite inertia.
Definition Body.hpp:64
Body(const std::string &name, Frame< T > *par=nullptr)
Parent constructor for the body object.
Definition Body.hpp:114
CartesianVector< T, 3 > externalForce()
Getters for force and moment stuff.
Definition Body.hpp:92
void _calcAppliedForceMoment(const CartesianVector< T, 3 > &force, const CartesianVector< T, 3 > &moment)
Function to resolve forces and moments to body frame as applied and passed through.
Definition Body.hpp:200
clockwerk::DataIO< T > composite_mass
Signal/parameter for the body's composite mass.
Definition Body.hpp:61
Standard vector class derived from Matrix.
Definition CartesianVector.hpp:39
Class defining a direction cosine matrix inherited from Matrix.
Definition DCM.hpp:71
Class for inter-object communication.
Definition DataIO.hpp:46
Frame class definition.
Definition Frame.hpp:92
Base class for object organization.
Definition GraphTreeObject.h:87
std::vector< GraphTreeObject * > _children
Pointers to the object's children – automatically set to an empty vector, and can be increased to any...
Definition GraphTreeObject.h:234
uint8_t _graph_tree_type
Variable to store graph tree object type.
Definition GraphTreeObject.h:251
Matrix math implementation.
Definition Matrix.hpp:54
#define NO_ERROR
Definition clockwerkerrors.h:31