AnimatLab  2
Test
BlJoint.cpp
1 // BlJoint.cpp: implementation of the BlJoint class.
2 //
4 
5 #include "StdAfx.h"
6 #include "BlJoint.h"
7 #include "BlMotorizedJoint.h"
8 #include "BlRigidBody.h"
9 #include "BlSimulator.h"
10 
11 namespace BulletAnimatSim
12 {
13  namespace Environment
14  {
15 
17 // Construction/Destruction
19 
20 BlJoint::BlJoint()
21 {
22  m_btJoint = NULL;
23  m_bt6DofJoint = NULL;
24 
25  m_lpVsParent = NULL;
26  m_lpVsChild = NULL;
27  m_lpVsSim = NULL;
28  m_lpBlParent = NULL;
29  m_lpBlChild = NULL;
30  m_btParent = NULL;
31  m_btChild = NULL;
32 
33  m_fltPrevBtJointPos = 0;
34  m_fltPrevJointPos = 0;
35 
36  for(int iIdx=0; iIdx<6; iIdx++)
37  m_aryBlRelaxations[iIdx] = NULL;
38 }
39 
40 BlJoint::~BlJoint()
41 {
42 }
43 
44 BlSimulator *BlJoint::GetBlSimulator()
45 {
46  if(!m_lpVsSim)
47  {
48  m_lpVsSim = dynamic_cast<BlSimulator *>(m_lpThisAB->GetSimulator());
49  if(!m_lpThisVsMI)
50  THROW_TEXT_ERROR(Osg_Err_lThisPointerNotDefined, Osg_Err_strThisPointerNotDefined, "m_lpVsSim, " + m_lpThisAB->Name());
51  }
52  return m_lpVsSim;
53 }
54 
55 bool BlJoint::Physics_IsDefined()
56 {
57  if(m_btJoint)
58  return true;
59  else
60  return false;
61 }
62 
63 void BlJoint::InitBaseJointPointers(RigidBody *lpParent, RigidBody *lpChild, ConstraintRelaxation **aryRelaxations, int iDisallowSpringIndex)
64 {
65  if(!lpParent)
66  THROW_ERROR(Al_Err_lParentNotDefined, Al_Err_strParentNotDefined);
67 
68  if(!lpChild)
69  THROW_ERROR(Al_Err_lChildNotDefined, Al_Err_strChildNotDefined);
70 
71  m_lpBlParent = dynamic_cast<BlRigidBody *>(lpParent);
72  if(!m_lpBlParent)
73  THROW_ERROR(Bl_Err_lUnableToConvertToBlRigidBody, Bl_Err_strUnableToConvertToBlRigidBody);
74 
75  m_lpBlChild = dynamic_cast<BlRigidBody *>(lpChild);
76  if(!m_lpBlChild)
77  THROW_ERROR(Bl_Err_lUnableToConvertToBlRigidBody, Bl_Err_strUnableToConvertToBlRigidBody);
78 
79  m_btParent = m_lpBlParent->Part();
80  m_btChild = m_lpBlChild->Part();
81 
82  for(int iIdx=0; iIdx<6; iIdx++)
83  {
84  if(aryRelaxations[iIdx])
85  {
86  BlConstraintRelaxation *lpRelax = dynamic_cast<BlConstraintRelaxation *>(aryRelaxations[iIdx]);
87  m_aryBlRelaxations[iIdx] = lpRelax;
88  }
89  else
90  m_aryBlRelaxations[iIdx] = NULL;
91  }
92 
93  if(iDisallowSpringIndex >= 0 && iDisallowSpringIndex <6 && m_aryBlRelaxations[iDisallowSpringIndex])
94  m_aryBlRelaxations[iDisallowSpringIndex]->DisallowSpringEnable(true);
95 }
96 
97 
98 void BlJoint::SetLimitValues()
99 {
100  if(m_bt6DofJoint)
101  {
102  GetLimitsFromRelaxations(m_vLowerLinear, m_vUpperLinear, m_vLowerAngular, m_vUpperAngular);
103 
104  m_bt6DofJoint->setLinearLowerLimit(m_vLowerLinear);
105  m_bt6DofJoint->setLinearUpperLimit(m_vUpperLinear);
106  m_bt6DofJoint->setAngularLowerLimit(m_vLowerAngular);
107  m_bt6DofJoint->setAngularUpperLimit(m_vUpperAngular);
108  }
109 }
110 
111 void BlJoint::DeletePhysics(bool bIncludeChildren)
112 {
113  if(!m_btJoint)
114  return;
115 
116  if(GetBlSimulator() && GetBlSimulator()->DynamicsWorld())
117  {
118  GetBlSimulator()->DynamicsWorld()->removeConstraint(m_btJoint);
119  delete m_btJoint;
120  }
121 
122  m_btJoint = NULL;
123 }
124 
125 float BlJoint::GetCurrentBtPositionScaled()
126 {
127  float fltDistanceUnits = m_lpThisAB->GetSimulator()->DistanceUnits();
128  float fltMassUnits = m_lpThisAB->GetSimulator()->MassUnits();
129 
130  float fltCurrentJointPos = GetCurrentBtPosition();
131 
132  //if(GetSimulator()->Time() > 5.64)
133  // fltCurrentJointPos = fltCurrentJointPos;
134 
135  //If this joint uses radians then at the +/- PI boundaries the sign can flip.
136  //So we need to keep an internal representation of its position and update this with a delta of the change in position
137  // that the physics engine is telling us. This allows the joint position to roll-over past 2PI so we have a steady velocity
138  // and position without discontinuties. It also allows us to see how many times the joint has finished a complete revolution.
139  if(m_lpThisJoint->UsesRadians())
140  {
141  int iPrevPosSign = Std_Sign(m_fltPrevBtJointPos);
142  float fltDelta = 0;
143  if(Std_Sign(fltCurrentJointPos) != iPrevPosSign && fabs(fltCurrentJointPos - m_fltPrevBtJointPos) > 0.1)
144  fltDelta = fltCurrentJointPos - (-m_fltPrevBtJointPos);
145  else
146  fltDelta = fltCurrentJointPos - m_fltPrevBtJointPos;
147 
148  fltCurrentJointPos = m_lpThisJoint->JointPosition() + fltDelta;
149  }
150 
151  if(!m_lpThisJoint->UsesRadians())
152  fltCurrentJointPos *= fltDistanceUnits;
153 
154  return fltCurrentJointPos;
155 }
156 
157 void BlJoint::Physics_CollectData()
158 {
159  OsgJoint::Physics_CollectData();
160 
161  if(m_lpThisJoint && m_btJoint && m_lpThisJoint->GetSimulator())
162  {
163  float fltCurrentJointPos = GetCurrentBtPositionScaled();
164  float fltJointVel = (fltCurrentJointPos - m_fltPrevJointPos)/(m_lpThisJoint->GetSimulator()->PhysicsTimeStep());
165 
166  //Only update the joints data when we need to do robot synch, but still update our internal data.
167  //if(m_lpThisJoint->NeedsRobotSynch())
168  //{
169  m_lpThisJoint->JointPosition(fltCurrentJointPos);
170  m_lpThisJoint->JointVelocity(fltJointVel);
171  //}
172 
173  m_fltPrevBtJointPos = GetCurrentBtPosition();
174  m_fltPrevJointPos = fltCurrentJointPos;
175  }
176 }
177 
178 void BlJoint::Physics_ResetSimulation()
179 {
180  if(m_btJoint)
181  {
182  m_lpThisJoint->WakeDynamics();
183  m_fltPrevBtJointPos = 0;
184  m_fltPrevJointPos = 0;
185  OsgJoint::Physics_ResetSimulation();
186  }
187 }
188 
189 void BlJoint::CalculateRelativeJointMatrices(btTransform &mtJointRelToParent, btTransform &mtJointRelToChild)
190 {
191  CStdFPoint vRot(0, 0, 0);
192  CalculateRelativeJointMatrices(vRot, mtJointRelToParent,mtJointRelToChild);
193 }
194 
195 void BlJoint::CalculateRelativeJointMatrices(CStdFPoint vAdditionalRot, btTransform &mtJointRelToParent, btTransform &mtJointRelToChild)
196 {
197  osg::Matrix mtParent = GetParentPhysicsWorldMatrix();
198  osg::Matrix mtChild = GetChildWorldMatrix();
199  CStdFPoint vPos1 = m_lpThisMI->Position();
200  CStdFPoint vRot1 = m_lpThisMI->Rotation() + vAdditionalRot;
201  osg::Matrix osgJointRelChild = SetupMatrix(vPos1, vRot1);
202 
203  osg::Matrix mtJointMTFromChild = osgJointRelChild * mtChild;
204  osg::Matrix mtLocalRelToParent = mtJointMTFromChild * osg::Matrix::inverse(mtParent);
205 
206  osg::Matrix mtChildCom = GetChildComMatrix(true);
207  osg::Matrix mtJointRelChild = osgJointRelChild * mtChildCom;
208 
209  mtJointRelToParent = osgbCollision::asBtTransform(mtLocalRelToParent);
210  mtJointRelToChild = osgbCollision::asBtTransform(mtJointRelChild);
211 }
212 
213 void BlJoint::GetLimitsFromRelaxations(btVector3 &vLowerLinear, btVector3 &UpperLinear, btVector3 &vLowerAngular, btVector3 &vUpperAngular)
214 {
215  btVector3 vLimits;
216 
217  for(int iIdx=0, iBlIdx=0; iIdx<3; iIdx++, iBlIdx++)
218  {
219  if(m_aryBlRelaxations[iBlIdx] && m_aryBlRelaxations[iBlIdx]->Enabled())
220  {
221  vLowerLinear[iIdx] = m_aryBlRelaxations[iBlIdx]->MaxLimit();
222  UpperLinear[iIdx] = m_aryBlRelaxations[iBlIdx]->MinLimit();
223  }
224  else
225  {
226  vLowerLinear[iIdx] = 0;
227  UpperLinear[iIdx] = 0;
228  }
229  }
230 
231  for(int iIdx=0, iBlIdx=3; iIdx<3; iIdx++, iBlIdx++)
232  {
233  if(m_aryBlRelaxations[iBlIdx] && m_aryBlRelaxations[iBlIdx]->Enabled())
234  {
235  vLowerAngular[iIdx] = m_aryBlRelaxations[iBlIdx]->MaxLimit();
236  vUpperAngular[iIdx] = m_aryBlRelaxations[iBlIdx]->MinLimit();
237  }
238  else
239  {
240  vLowerAngular[iIdx] = 0;
241  vUpperAngular[iIdx] = 0;
242  }
243  }
244 }
245 
246 
247  } // Environment
248 } //BulletAnimatSim
A common class for all rigid body data specific to vortex.
Definition: BlRigidBody.h:87
int Std_Sign(float fltVal)
Determines the sign of a number.
Classes for implementing the cm-labs vortex physics engine for AnimatLab.
virtual float MinLimit()
Gets the minimum value that this relaxation can move.
BlConstraintRelaxation * m_aryBlRelaxations[6]
The bullet relaxation for the primary displacement relaxation.
Definition: BlJoint.h:45
virtual bool DisallowSpringEnable()
Gets the disallow spring enable.
virtual float MaxLimit()
Gets the maximum value that this relaxation can move.