MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
module-wheel2.cc
Go to the documentation of this file.
1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/modules/module-wheel2/module-wheel2.cc,v 1.75 2017/01/12 14:58:41 masarati Exp $ */
2 /*
3  * MBDyn (C) is a multibody analysis code.
4  * http://www.mbdyn.org
5  *
6  * Copyright (C) 1996-2017
7  *
8  * Pierangelo Masarati <masarati@aero.polimi.it>
9  * Paolo Mantegazza <mantegazza@aero.polimi.it>
10  *
11  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12  * via La Masa, 34 - 20156 Milano, Italy
13  * http://www.aero.polimi.it
14  *
15  * Changing this copyright notice is forbidden.
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation (version 2 of the License).
20  *
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */
31 
32 #include "mbconfig.h" /* This goes first in every *.c,*.cc file */
33 
34 #include "dataman.h"
35 #include "userelem.h"
36 
37 #include <iostream>
38 #include <limits>
39 #include <cfloat>
40 #include <limits>
41 
42 #include "module-wheel2.h"
43 
44 class Wheel2
45 : virtual public Elem, public UserDefinedElem
46 {
47 private:
48 
49  // wheel node
51 
52  // wheel axle direction (wrt/ wheel node)
54 
55  // (flat) ground node
57 
58  // ground position/orientation (wrt/ ground node)
61 
62  // wheel geometry
66 
68  doublereal dRNP; /* R+nG'*pG */
70 
71  // tyre properties
75 
76  // friction data
77  bool bSlip;
82 
83  // output data
96 
97 public:
98  Wheel2(unsigned uLabel, const DofOwner *pDO,
99  DataManager* pDM, MBDynParser& HP);
100  virtual ~Wheel2(void);
101 
102  virtual void Output(OutputHandler& OH) const;
103  virtual void WorkSpaceDim(integer* piNumRows, integer* piNumCols) const;
106  doublereal dCoef,
107  const VectorHandler& XCurr,
108  const VectorHandler& XPrimeCurr);
110  AssRes(SubVectorHandler& WorkVec,
111  doublereal dCoef,
112  const VectorHandler& XCurr,
113  const VectorHandler& XPrimeCurr);
114  unsigned int iGetNumPrivData(void) const;
115  int iGetNumConnectedNodes(void) const;
116  void GetConnectedNodes(std::vector<const Node *>& connectedNodes) const;
117  void SetValue(DataManager *pDM, VectorHandler& X, VectorHandler& XP,
119  std::ostream& Restart(std::ostream& out) const;
120  virtual unsigned int iGetInitialNumDof(void) const;
121  virtual void
122  InitialWorkSpaceDim(integer* piNumRows, integer* piNumCols) const;
125  const VectorHandler& XCurr);
127  InitialAssRes(SubVectorHandler& WorkVec, const VectorHandler& XCurr);
128 };
129 
130 Wheel2::Wheel2(unsigned uLabel, const DofOwner *pDO,
131  DataManager* pDM, MBDynParser& HP)
132 : Elem(uLabel, flag(0)),
133 UserDefinedElem(uLabel, pDO)
134 {
135  // help
136  if (HP.IsKeyWord("help")) {
137  silent_cout(
138 " \n"
139 "Module: wheel2 \n"
140 "Author: Stefania Gualdi <gualdi@aero.polimi.it> \n"
141 " Pierangelo Masarati <masarati@aero.polimi.it> \n"
142 "Organization: Dipartimento di Ingegneria Aerospaziale \n"
143 " Politecnico di Milano \n"
144 " http://www.aero.polimi.it \n"
145 " \n"
146 " All rights reserved \n"
147 " \n"
148 "Connects 2 structural nodes: \n"
149 " - Wheel \n"
150 " - Ground \n"
151 " \n"
152 "Note: \n"
153 " - The Axle and the Wheel structural nodes must be connected \n"
154 " by a joint that allows relative rotations only about \n"
155 " one axis (the axle) \n"
156 " - The center of the wheel is assumed coincident with \n"
157 " the position of the wheel structural node \n"
158 " - The Ground structural node supports a plane defined \n"
159 " a point and a direction orthogonal to the plane (future \n"
160 " versions might use an arbitrary, deformable surface) \n"
161 " - The forces are applied at the \"contact point\", that \n"
162 " is defined according to geometrical properties \n"
163 " of the system and according to the relative position \n"
164 " and orientation of the Wheel and Ground structural nodes \n"
165 " \n"
166 " - Input: \n"
167 " <wheel structural node label> , \n"
168 " <wheel axle direction> , \n"
169 " <ground structural node label> , \n"
170 " <reference point position of the ground plane> , \n"
171 " <direction orthogonal to the ground plane> , \n"
172 " <wheel radius> , \n"
173 " <torus radius> , \n"
174 " <volume coefficient (black magic?)> , \n"
175 " <tire pressure> , \n"
176 " <tire polytropic exponent> , \n"
177 " <reference velocity for tire hysteresis> \n"
178 " [ slip , \n"
179 " <longitudinal friction coefficient drive> \n"
180 " <lateral friction coefficient drive for s.r.=0> \n"
181 " <lateral friction coefficient drive for s.r.=1> \n"
182 " [ , threshold , <slip ratio velocity threshold> , \n"
183 " <slip angle velocity threshold> ] ] \n"
184 " \n"
185 " - Output: \n"
186 " 1) element label \n"
187 " 2-4) tire force in global reference frame \n"
188 " 5-7) tire couple in global reference frame \n"
189 " 8) effective radius \n"
190 " 9) tire radial deformation \n"
191 " 10) tire radial deformation velocity \n"
192 " 11) slip ratio \n"
193 " 12) slip angle \n"
194 " 13) longitudinal friction coefficient \n"
195 " 14) lateral friction coefficient \n"
196 " 15) axis relative tangential velocity \n"
197 " 16) point of contact relative tangential velocity \n"
198  << std::endl);
199 
200  if (!HP.IsArg()) {
201  /*
202  * Exit quietly if nothing else is provided
203  */
204  throw NoErr(MBDYN_EXCEPT_ARGS);
205  }
206  }
207 
208  // read wheel node
209  pWheel = dynamic_cast<const StructNode *>(pDM->ReadNode(HP, Node::STRUCTURAL));
210 
211  // read wheel axle
213  WheelAxle = HP.GetVecRel(RF);
214 
215  // read ground node
216  pGround = dynamic_cast<const StructNode *>(pDM->ReadNode(HP, Node::STRUCTURAL));
217 
218  // read ground position/orientation
219  RF = ReferenceFrame(pGround);
220  GroundPosition = HP.GetPosRel(RF);
221  GroundDirection = HP.GetVecRel(RF);
222 
223  // normalize ground orientation
225  if (d <= std::numeric_limits<doublereal>::epsilon()) {
226  silent_cerr("Wheel2(" << uLabel << "): "
227  "null direction at line " << HP.GetLineData()
228  << std::endl);
230  }
231  GroundDirection /= sqrt(d);
232 
233  // wheel geometry
234  dRadius = HP.GetReal();
235  dInternalRadius = HP.GetReal();
236  dVolCoef = HP.GetReal();
237 
238  // reference area
240 
241  // parameter required to compute Delta L
243 
244  // reference volume
247 
248  // tyre properties
249  dP0 = HP.GetReal();
250  dGamma = HP.GetReal();
251  dHystVRef = HP.GetReal();
252 
253  // friction
254  bSlip = false;
255  if (HP.IsKeyWord("slip")) {
256  bSlip = true;
257 
258  /*
259  * Parametri di attrito
260  */
261  pMuX0 = HP.GetDriveCaller();
262  pMuY0 = HP.GetDriveCaller();
263  pMuY1 = HP.GetDriveCaller();
264 
265  dvThreshold = 0.;
266  dAlphaThreshold = 0.;
267  if (HP.IsKeyWord("threshold")) {
268  dvThreshold = HP.GetReal();
269  if (dvThreshold < 0.) {
270  silent_cerr("Wheel2(" << uLabel << "): "
271  "illegal velocity threshold " << dvThreshold
272  << " at line " << HP.GetLineData() << std::endl);
273  dvThreshold = std::abs(dvThreshold);
274  }
275 
276  dAlphaThreshold = HP.GetReal();
277  if (dvThreshold < 0.) {
278  silent_cerr("Wheel2(" << uLabel << "): "
279  "illegal slip angle threshold " << dAlphaThreshold
280  << " at line " << HP.GetLineData() << std::endl);
281  dAlphaThreshold = std::abs(dAlphaThreshold);
282  }
283  }
284  }
285 
287 
288  std::ostream& out = pDM->GetLogFile();
289  out << "wheel2: " << uLabel
290  << " " << pWheel->GetLabel() //node label
291  << " " << WheelAxle //wheel axle
292  << " " << pGround->GetLabel() //ground label
293  << " " << GroundDirection //ground direction
294  << " " << dRadius //wheel radius
295  << " " << dInternalRadius //wheel internal radius
296  << std::endl;
297 }
298 
300 {
301  NO_OP;
302 }
303 
304 void
306 {
307  if (bToBeOutput()) {
308  std::ostream& out = OH.Loadable();
309 
310  out << std::setw(8) << GetLabel() // 1: label
311  << " " << F // 2-4: force
312  << " " << M // 5-7: moment
313  << " " << dInstRadius // 8: inst. radius
314  << " " << dDeltaL // 9: radial deformation
315  << " " << dVn // 10: radial deformation velocity
316  << " " << dSr // 11: slip ratio
317  << " " << 180./M_PI*dAlpha // 12: slip angle
318  << " " << dMuX // 13: longitudinal friction coefficient
319  << " " << dMuY // 14: lateral friction coefficient
320  << " " << dVa // 15: axis relative velocity
321  << " " << dVc // 16: POC relative velocity
322  << std::endl;
323  }
324 }
325 
326 void
327 Wheel2::WorkSpaceDim(integer* piNumRows, integer* piNumCols) const
328 {
329  *piNumRows = 12;
330  *piNumCols = 12;
331 }
332 
335  doublereal dCoef,
336  const VectorHandler& XCurr,
337  const VectorHandler& XPrimeCurr)
338 {
339  WorkMat.SetNullMatrix();
340 
341  return WorkMat;
342 }
343 
346  doublereal dCoef,
347  const VectorHandler& XCurr,
348  const VectorHandler& XPrimeCurr)
349 {
350  // ground orientation in the absolute frame
352 
353  // wheel-ground distance in the absolute frame
354  Vec3 x = pWheel->GetXCurr() - pGround->GetXCurr();
355 
356  // contact when dDeltaL > 0
357  dDeltaL = dRNP - x*n;
358 
359  // reset output data
361 
362  dSr = 0.;
363  dAlpha = 0.;
364 
365  dMuX = 0.;
366  dMuY = 0.;
367 
368  dVa = 0.;
369  dVc = 0.;
370 
371  if (dDeltaL < 0.) {
372 
373  F = Zero3;
374  M = Zero3;
375 
377  dDeltaL = 0.;
378 
379  // no need to assemble residual contribution
380  WorkVec.Resize(0);
381 
382  return WorkVec;
383  }
384 
385  // resize residual
386  integer iNumRows = 0;
387  integer iNumCols = 0;
388  WorkSpaceDim(&iNumRows, &iNumCols);
389 
390  WorkVec.ResizeReset(iNumRows);
391 
392  integer iGroundFirstMomIndex = pGround->iGetFirstMomentumIndex();
393  integer iWheelFirstMomIndex = pWheel->iGetFirstMomentumIndex();
394 
395  // equations indexes
396  for (int iCnt = 1; iCnt <= 6; iCnt++) {
397  WorkVec.PutRowIndex(iCnt, iGroundFirstMomIndex + iCnt);
398  WorkVec.PutRowIndex(6 + iCnt, iWheelFirstMomIndex + iCnt);
399  }
400 
401  // relative speed between wheel axle and ground
402  Vec3 va = pWheel->GetVCurr() - pGround->GetVCurr()
404 
405  dVa = (va - n*(n*va)).Norm();
406 
407  // relative speed between wheel and ground at contact point
408  Vec3 v = va - (pWheel->GetWCurr()).Cross(n*dInstRadius);
409 
410  // normal component of relative speed
411  // (positive when wheel departs from ground)
412  dVn = n*v;
413 
414  dVc = (v - n*dVn).Norm();
415 
416  // estimated contact area
417  doublereal dA = dRefArea*(dDeltaL/dInternalRadius);
418 
419  // estimated intersection volume
420  doublereal dDeltaV = .5*dA*dDeltaL;
421 
422  // estimated tyre pressure (polytropic)
423  doublereal dP = dP0*pow(dV0/(dV0 - dDeltaV), dGamma);
424 
425  // we assume the contact point lies at the root of the normal
426  // to the ground that passes through the center of the wheel
427  // this means that the axle needs to remain parallel to the ground
428  Vec3 pc = pWheel->GetXCurr() - (n*dInstRadius);
429 
430  // force
431  doublereal dFn = (dA*dP*(1. - tanh(dVn/dHystVRef)));
432  F = n*dFn;
433 
434  if (bSlip) {
435  // "forward" direction: axle cross normal to ground
436  Vec3 fwd = (pWheel->GetRCurr()*WheelAxle).Cross(n);
437  doublereal d = fwd.Dot();
438  if (d < std::numeric_limits<doublereal>::epsilon()) {
439  silent_cerr("Wheel2(" << GetLabel() << "): "
440  "wheel axle is (neraly) orthogonal "
441  "to the ground" << std::endl);
443  }
444  fwd /= sqrt(d);
445 
446  // slip ratio
447  doublereal dvx = fwd.Dot(v);
448  doublereal sgn = copysign(1., dvx);
449  doublereal dfvx = std::abs(dvx);
450  doublereal dvax = fwd.Dot(va);
451  doublereal dfvax = std::abs(dvax);
452 
453  // FIXME: if vax ~ 0 (e.g. because the vehicle stopped)
454  // the "sleep" ratio needs to be small, right?
455  dSr = dfvx/(dfvax + dvThreshold);
456  if (dSr > 1.) {
457  dSr = 1.;
458  }
459 
460  // "lateral" direction: normal to ground cross forward
461  Vec3 lat = n.Cross(fwd);
462 
463  // lateral speed of wheel center
464  doublereal dvay = lat.Dot(va);
465 
466  // wheel center drift angle
467  // NOTE: the angle is restricted to the first quadran
468  // the angle goes to zero when the velocity is below threshold
469  dAlpha = atan2(dvay, std::abs(dvax));
470  if (dAlphaThreshold > 0.) {
471  doublereal dtmp = tanh(sqrt(dvax*dvax + dvay*dvay)/dAlphaThreshold);
472  dAlpha *= dtmp*dtmp;
473  }
474 
475  // longitudinal friction coefficient
476  doublereal dMuX0 = pMuX0->dGet(dSr);
477 
478  // NOTE: -1 < alpha/(pi/2) < 1
479  dMuX = dMuX0*sgn*(1. - std::abs(dAlpha)/M_PI_2);
480 
481  // force correction: the longitudinal friction coefficient
482  // is used with the sign of the contact point relative speed
483  F -= fwd*dFn*dMuX;
484 
485  if (dvay != 0.) {
486  doublereal dMuY0 = pMuY0->dGet(dAlpha);
487  doublereal dMuY1 = pMuY1->dGet(dAlpha);
488 
489  dMuY = dMuY0 + (dMuY1 - dMuY0)*dSr;
490 
491  // force correction
492  F -= lat*dFn*dMuY;
493  }
494  }
495 
496  // moment
497  M = (pc - pWheel->GetXCurr()).Cross(F);
498 
499  WorkVec.Sub(1, F);
500  WorkVec.Sub(4, (pc - pGround->GetXCurr()).Cross(F));
501  WorkVec.Add(7, F);
502  WorkVec.Add(10, M);
503 
504  return WorkVec;
505 }
506 
507 unsigned int
509 {
510  return 0;
511 }
512 
513 int
515 {
516  // wheel + ground
517  return 2;
518 }
519 
520 void
521 Wheel2::GetConnectedNodes(std::vector<const Node *>& connectedNodes) const
522 {
523  // wheel + ground
524  connectedNodes.resize(2);
525 
526  connectedNodes[0] = pWheel;
527  connectedNodes[1] = pGround;
528 }
529 
530 void
534 {
535  NO_OP;
536 }
537 
538 std::ostream&
539 Wheel2::Restart(std::ostream& out) const
540 {
541  return out << "# not implemented yet" << std::endl;
542 }
543 
544 unsigned
546 {
547  return 0;
548 }
549 
550 void
551 Wheel2::InitialWorkSpaceDim(integer* piNumRows, integer* piNumCols) const
552 {
553  *piNumRows = 0;
554  *piNumCols = 0;
555 }
556 
559  const VectorHandler& XCurr)
560 {
561  WorkMat.SetNullMatrix();
562  return WorkMat;
563 }
564 
567 {
568  WorkVec.Resize(0);
569  return WorkVec;
570 }
571 
572 bool
574 {
576 
577  if (!SetUDE("wheel2", rf)) {
578  delete rf;
579  return false;
580  }
581 
582  return true;
583 }
584 
585 #ifndef STATIC_MODULES
586 extern "C" int
587 module_init(const char *module_name, void *pdm, void *php)
588 {
589  if (!wheel2_set()) {
590  silent_cerr("Wheel2: "
591  "module_init(" << module_name << ") "
592  "failed" << std::endl);
593  return -1;
594  }
595  return 0;
596 }
597 #endif // ! STATIC_MODULES
flag fReadOutput(MBDynParser &HP, const T &t) const
Definition: dataman.h:1064
GradientExpression< UnaryExpr< FuncTanh, Expr > > tanh(const GradientExpression< Expr > &u)
Definition: gradient.h:2982
Vec3 GroundPosition
doublereal dInstRadius
#define M_PI
Definition: gradienttest.cc:67
const Vec3 Zero3(0., 0., 0.)
doublereal dVn
Vec3 Cross(const Vec3 &v) const
Definition: matvec3.h:218
void GetConnectedNodes(std::vector< const Node * > &connectedNodes) const
long int flag
Definition: mbdyn.h:43
virtual bool bToBeOutput(void) const
Definition: output.cc:890
const DriveCaller * pMuX0
GradientExpression< BinaryExpr< FuncPow, LhsExpr, RhsExpr > > pow(const GradientExpression< LhsExpr > &u, const GradientExpression< RhsExpr > &v)
Definition: gradient.h:2961
const DriveCaller * pMuY1
unsigned int iGetNumPrivData(void) const
#define MBDYN_EXCEPT_ARGS
Definition: except.h:63
Definition: matvec3.h:98
virtual void ResizeReset(integer)
Definition: vh.cc:55
virtual const Mat3x3 & GetRCurr(void) const
Definition: strnode.h:1012
doublereal Dot(const Vec3 &v) const
Definition: matvec3.h:243
doublereal dDeltaL
const StructNode * pGround
bool bSlip
VariableSubMatrixHandler & InitialAssJac(VariableSubMatrixHandler &WorkMat, const VectorHandler &XCurr)
doublereal dP0
virtual void Sub(integer iRow, const Vec3 &v)
Definition: vh.cc:78
doublereal dVc
#define NO_OP
Definition: myassert.h:74
doublereal dMuX
doublereal dVa
std::vector< Hint * > Hints
Definition: simentity.h:89
doublereal dvThreshold
const StructNode * pWheel
VariableSubMatrixHandler & AssJac(VariableSubMatrixHandler &WorkMat, doublereal dCoef, const VectorHandler &XCurr, const VectorHandler &XPrimeCurr)
const DriveCaller * pMuY0
virtual unsigned int iGetInitialNumDof(void) const
virtual void PutRowIndex(integer iSubRow, integer iRow)=0
virtual void WorkSpaceDim(integer *piNumRows, integer *piNumCols) const
void SetValue(DataManager *pDM, VectorHandler &X, VectorHandler &XP, SimulationEntity::Hints *ph)
virtual ~Wheel2(void)
Vec3 GetPosRel(const ReferenceFrame &rf)
Definition: mbpar.cc:1331
void SetNullMatrix(void)
Definition: submat.h:1159
virtual bool IsKeyWord(const char *sKeyWord)
Definition: parser.cc:910
std::ostream & Loadable(void) const
Definition: output.h:506
doublereal copysign(doublereal x, doublereal y)
Definition: gradient.h:97
doublereal dVolCoef
doublereal dAlphaThreshold
bool wheel2_set(void)
doublereal dRadius
doublereal dGamma
std::ostream & Restart(std::ostream &out) const
doublereal dRNP
virtual integer iGetFirstMomentumIndex(void) const =0
virtual const Vec3 & GetWCurr(void) const
Definition: strnode.h:1030
unsigned int uLabel
Definition: withlab.h:44
doublereal dV0
Wheel2(unsigned uLabel, const DofOwner *pDO, DataManager *pDM, MBDynParser &HP)
GradientExpression< UnaryExpr< FuncSqrt, Expr > > sqrt(const GradientExpression< Expr > &u)
Definition: gradient.h:2974
VectorExpression< VectorCrossExpr< VectorLhsExpr, VectorRhsExpr >, 3 > Cross(const VectorExpression< VectorLhsExpr, 3 > &u, const VectorExpression< VectorRhsExpr, 3 > &v)
Definition: matvec.h:3248
doublereal dMuY
virtual const Vec3 & GetXCurr(void) const
Definition: strnode.h:310
virtual void Add(integer iRow, const Vec3 &v)
Definition: vh.cc:63
Definition: except.h:79
doublereal dHystVRef
int iGetNumConnectedNodes(void) const
virtual doublereal dGet(const doublereal &dVar) const =0
Vec3 WheelAxle
Vec3 GetVecRel(const ReferenceFrame &rf)
Definition: mbpar.cc:1584
VectorExpression< VectorExpr, N_rows >::ScalarType Norm(const VectorExpression< VectorExpr, N_rows > &u)
Definition: matvec.h:3163
Vec3 GroundDirection
doublereal dAlpha
virtual bool IsArg(void)
Definition: parser.cc:807
Definition: elem.h:75
virtual void InitialWorkSpaceDim(integer *piNumRows, integer *piNumCols) const
std::ostream & GetLogFile(void) const
Definition: dataman.h:326
bool SetUDE(const std::string &s, UserDefinedElemRead *rude)
Definition: userelem.cc:97
doublereal dRefArea
int module_init(const char *module_name, void *pdm, void *php)
This function registers our user defined element for the math parser.
virtual void Output(OutputHandler &OH) const
doublereal dSr
virtual const Vec3 & GetVCurr(void) const
Definition: strnode.h:322
DriveCaller * GetDriveCaller(bool bDeferred=false)
Definition: mbpar.cc:2033
SubVectorHandler & AssRes(SubVectorHandler &WorkVec, doublereal dCoef, const VectorHandler &XCurr, const VectorHandler &XPrimeCurr)
doublereal dInternalRadius
virtual void SetOutputFlag(flag f=flag(1))
Definition: output.cc:896
GradientExpression< BinaryExpr< FuncAtan2, LhsExpr, RhsExpr > > atan2(const GradientExpression< LhsExpr > &u, const GradientExpression< RhsExpr > &v)
Definition: gradient.h:2962
double doublereal
Definition: colamd.c:52
long int integer
Definition: colamd.c:51
virtual HighParser::ErrOut GetLineData(void) const
Definition: parsinc.cc:697
unsigned int GetLabel(void) const
Definition: withlab.cc:62
Node * ReadNode(MBDynParser &HP, Node::Type type) const
Definition: dataman3.cc:2309
virtual void Resize(integer iNewSize)=0
SubVectorHandler & InitialAssRes(SubVectorHandler &WorkVec, const VectorHandler &XCurr)
virtual doublereal GetReal(const doublereal &dDefval=0.0)
Definition: parser.cc:1056