RavEngine
Loading...
Searching...
No Matches
PxVehicleLinearMath.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
26// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
27// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
28
29#ifndef PX_VEHICLE_LINEAR_MATH_H
30#define PX_VEHICLE_LINEAR_MATH_H
35#include "vehicle/PxVehicleSDK.h"
36
37#if !PX_DOXYGEN
38namespace physx
39{
40#endif
41
42#define MAX_VECTORN_SIZE (PX_MAX_NB_WHEELS+3)
43
45{
46public:
47
48 VectorN(const PxU32 size)
49 : mSize(size)
50 {
51 PX_ASSERT(mSize <= MAX_VECTORN_SIZE);
52 }
53 ~VectorN()
54 {
55 }
56
57 VectorN(const VectorN& src)
58 {
59 for(PxU32 i = 0; i < src.mSize; i++)
60 {
61 mValues[i] = src.mValues[i];
62 }
63 mSize = src.mSize;
64 }
65
66 PX_FORCE_INLINE VectorN& operator=(const VectorN& src)
67 {
68 for(PxU32 i = 0; i < src.mSize; i++)
69 {
70 mValues[i] = src.mValues[i];
71 }
72 mSize = src.mSize;
73 return *this;
74 }
75
76 PX_FORCE_INLINE PxF32& operator[] (const PxU32 i)
77 {
78 PX_ASSERT(i < mSize);
79 return (mValues[i]);
80 }
81
82 PX_FORCE_INLINE const PxF32& operator[] (const PxU32 i) const
83 {
84 PX_ASSERT(i < mSize);
85 return (mValues[i]);
86 }
87
88 PX_FORCE_INLINE PxU32 getSize() const {return mSize;}
89
90private:
91
92 PxF32 mValues[MAX_VECTORN_SIZE];
93 PxU32 mSize;
94};
95
97{
98public:
99
100 MatrixNN()
101 : mSize(0)
102 {
103 }
104 MatrixNN(const PxU32 size)
105 : mSize(size)
106 {
107 PX_ASSERT(mSize <= MAX_VECTORN_SIZE);
108 }
109 MatrixNN(const MatrixNN& src)
110 {
111 for(PxU32 i = 0; i < src.mSize; i++)
112 {
113 for(PxU32 j = 0; j < src.mSize; j++)
114 {
115 mValues[i][j] = src.mValues[i][j];
116 }
117 }
118 mSize=src.mSize;
119 }
120 ~MatrixNN()
121 {
122 }
123
124 PX_FORCE_INLINE MatrixNN& operator=(const MatrixNN& src)
125 {
126 for(PxU32 i = 0;i < src.mSize; i++)
127 {
128 for(PxU32 j = 0;j < src.mSize; j++)
129 {
130 mValues[i][j] = src.mValues[i][j];
131 }
132 }
133 mSize = src.mSize;
134 return *this;
135 }
136
137 PX_FORCE_INLINE PxF32 get(const PxU32 i, const PxU32 j) const
138 {
139 PX_ASSERT(i < mSize);
140 PX_ASSERT(j < mSize);
141 return mValues[i][j];
142 }
143 PX_FORCE_INLINE void set(const PxU32 i, const PxU32 j, const PxF32 val)
144 {
145 PX_ASSERT(i < mSize);
146 PX_ASSERT(j < mSize);
147 mValues[i][j] = val;
148 }
149
150 PX_FORCE_INLINE PxU32 getSize() const {return mSize;}
151
152 PX_FORCE_INLINE void setSize(const PxU32 size)
153 {
154 PX_ASSERT(size <= MAX_VECTORN_SIZE);
155 mSize = size;
156 }
157
158public:
159
160 PxF32 mValues[MAX_VECTORN_SIZE][MAX_VECTORN_SIZE];
161 PxU32 mSize;
162};
163
164
165/*
166 LUPQ decomposition
167
168 Based upon "Outer Product LU with Complete Pivoting," from Matrix Computations (4th Edition), Golub and Van Loan
169
170 Solve A*x = b using:
171
172 MatrixNNLUSolver solver;
173 solver.decomposeLU(A);
174 solver.solve(b, x);
175*/
177{
178private:
179
180 MatrixNN mLU;
181 PxU32 mP[MAX_VECTORN_SIZE-1]; // Row permutation
182 PxU32 mQ[MAX_VECTORN_SIZE-1]; // Column permutation
183 PxF32 mdetM;
184
185public:
186
189
190 PxF32 getDet() const {return mdetM;}
191
192 void decomposeLU(const MatrixNN& A)
193 {
194 const PxU32 D = A.mSize;
195
196 mLU = A;
197
198 mdetM = 1.0f;
199
200 for (PxU32 k = 0; k < D-1; ++k)
201 {
202 PxU32 pivot_row = k;
203 PxU32 pivot_col = k;
204 float abs_pivot_elem = 0.0f;
205 for (PxU32 c = k; c < D; ++c)
206 {
207 for (PxU32 r = k; r < D; ++r)
208 {
209 const PxF32 abs_elem = PxAbs(mLU.get(r,c));
210 if (abs_elem > abs_pivot_elem)
211 {
212 abs_pivot_elem = abs_elem;
213 pivot_row = r;
214 pivot_col = c;
215 }
216 }
217 }
218
219 mP[k] = pivot_row;
220 if (pivot_row != k)
221 {
222 mdetM = -mdetM;
223 for (PxU32 c = 0; c < D; ++c)
224 {
225 //swap(m_LU(k,c), m_LU(pivot_row,c));
226 const PxF32 pivotrowc = mLU.get(pivot_row, c);
227 mLU.set(pivot_row, c, mLU.get(k, c));
228 mLU.set(k, c, pivotrowc);
229 }
230 }
231
232 mQ[k] = pivot_col;
233 if (pivot_col != k)
234 {
235 mdetM = -mdetM;
236 for (PxU32 r = 0; r < D; ++r)
237 {
238 //swap(m_LU(r,k), m_LU(r,pivot_col));
239 const PxF32 rpivotcol = mLU.get(r, pivot_col);
240 mLU.set(r,pivot_col, mLU.get(r,k));
241 mLU.set(r, k, rpivotcol);
242 }
243 }
244
245 mdetM *= mLU.get(k,k);
246
247 if (mLU.get(k,k) != 0.0f)
248 {
249 for (PxU32 r = k+1; r < D; ++r)
250 {
251 mLU.set(r, k, mLU.get(r,k) / mLU.get(k,k));
252 for (PxU32 c = k+1; c < D; ++c)
253 {
254 //m_LU(r,c) -= m_LU(r,k)*m_LU(k,c);
255 const PxF32 rc = mLU.get(r, c);
256 const PxF32 rk = mLU.get(r, k);
257 const PxF32 kc = mLU.get(k, c);
258 mLU.set(r, c, rc - rk*kc);
259 }
260 }
261 }
262 }
263
264 mdetM *= mLU.get(D-1,D-1);
265 }
266
267 //Given a matrix A and a vector b find x that satisfies Ax = b, where the matrix A is the matrix that was passed to decomposeLU.
268 //Returns true if the lu decomposition indicates that the matrix has an inverse and x was successfully computed.
269 //Returns false if the lu decomposition resulted in zero determinant ie the matrix has no inverse and no solution exists for x.
270 //Returns false if the size of either b or x doesn't match the size of the matrix passed to decomposeLU.
271 //If false is returned then each relevant element of x is set to zero.
272 bool solve(const VectorN& b, VectorN& x) const
273 {
274 const PxU32 D = x.getSize();
275
276 if((b.getSize() != x.getSize()) || (b.getSize() != mLU.getSize()) || (0.0f == mdetM))
277 {
278 for(PxU32 i = 0; i < D; i++)
279 {
280 x[i] = 0.0f;
281 }
282 return false;
283 }
284
285 x = b;
286
287 // Perform row permutation to get Pb
288 for(PxU32 i = 0; i < D-1; ++i)
289 {
290 //swap(x(i), x(m_P[i]));
291 const PxF32 xp = x[mP[i]];
292 x[mP[i]] = x[i];
293 x[i] = xp;
294 }
295
296 // Forward substitute to get (L^-1)Pb
297 for (PxU32 r = 1; r < D; ++r)
298 {
299 for (PxU32 i = 0; i < r; ++i)
300 {
301 x[r] -= mLU.get(r,i)*x[i];
302 }
303 }
304
305 // Back substitute to get (U^-1)(L^-1)Pb
306 for (PxU32 r = D; r-- > 0;)
307 {
308 for (PxU32 i = r+1; i < D; ++i)
309 {
310 x[r] -= mLU.get(r,i)*x[i];
311 }
312 x[r] /= mLU.get(r,r);
313 }
314
315 // Perform column permutation to get the solution (Q^T)(U^-1)(L^-1)Pb
316 for (PxU32 i = D-1; i-- > 0;)
317 {
318 //swap(x(i), x(m_Q[i]));
319 const PxF32 xq = x[mQ[i]];
320 x[mQ[i]] = x[i];
321 x[i] = xq;
322 }
323
324 return true;
325 }
326
327};
328
329
331{
332public:
333
334 void solve(const PxU32 maxIterations, const PxF32 tolerance, const MatrixNN& A, const VectorN& b, VectorN& result) const
335 {
336 const PxU32 N = A.getSize();
337
338 VectorN DInv(N);
339 PxF32 bLength2 = 0.0f;
340 for(PxU32 i = 0; i < N; i++)
341 {
342 DInv[i] = 1.0f/A.get(i,i);
343 bLength2 += (b[i] * b[i]);
344 }
345
346 PxU32 iteration = 0;
347 PxF32 error = PX_MAX_F32;
348 while(iteration < maxIterations && tolerance < error)
349 {
350 for(PxU32 i = 0; i < N; i++)
351 {
352 PxF32 l = 0.0f;
353 for(PxU32 j = 0; j < i; j++)
354 {
355 l += A.get(i,j) * result[j];
356 }
357
358 PxF32 u = 0.0f;
359 for(PxU32 j = i + 1; j < N; j++)
360 {
361 u += A.get(i,j) * result[j];
362 }
363
364 result[i] = DInv[i] * (b[i] - l - u);
365 }
366
367 //Compute the error.
368 PxF32 rLength2 = 0;
369 for(PxU32 i = 0; i < N; i++)
370 {
371 PxF32 e = -b[i];
372 for(PxU32 j = 0; j < N; j++)
373 {
374 e += A.get(i,j) * result[j];
375 }
376 rLength2 += e * e;
377 }
378 error = (rLength2 / (bLength2 + 1e-10f));
379
380 iteration++;
381 }
382 }
383};
384
386{
387public:
388
389 bool solve(const MatrixNN& A_, const VectorN& b_, VectorN& result) const
390 {
391 const PxF32 a = A_.get(0,0);
392 const PxF32 b = A_.get(0,1);
393 const PxF32 c = A_.get(0,2);
394
395 const PxF32 d = A_.get(1,0);
396 const PxF32 e = A_.get(1,1);
397 const PxF32 f = A_.get(1,2);
398
399 const PxF32 g = A_.get(2,0);
400 const PxF32 h = A_.get(2,1);
401 const PxF32 k = A_.get(2,2);
402
403 const PxF32 detA = a*(e*k - f*h) - b*(k*d - f*g) + c*(d*h - e*g);
404 if(0.0f == detA)
405 {
406 return false;
407 }
408 const PxF32 detAInv = 1.0f/detA;
409
410 const PxF32 A = (e*k - f*h);
411 const PxF32 D = -(b*k - c*h);
412 const PxF32 G = (b*f - c*e);
413 const PxF32 B = -(d*k - f*g);
414 const PxF32 E = (a*k - c*g);
415 const PxF32 H = -(a*f - c*d);
416 const PxF32 C = (d*h - e*g);
417 const PxF32 F = -(a*h - b*g);
418 const PxF32 K = (a*e - b*d);
419
420 result[0] = detAInv*(A*b_[0] + D*b_[1] + G*b_[2]);
421 result[1] = detAInv*(B*b_[0] + E*b_[1] + H*b_[2]);
422 result[2] = detAInv*(C*b_[0] + F*b_[1] + K*b_[2]);
423
424 return true;
425 }
426};
427
428#if !PX_DOXYGEN
429} // namespace physx
430#endif
431
432#endif
Definition PxVehicleLinearMath.h:386
Definition PxVehicleLinearMath.h:331
Definition PxVehicleLinearMath.h:177
Definition PxVehicleLinearMath.h:97
Definition PxVehicleLinearMath.h:45
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
PX_CUDA_CALLABLE PX_FORCE_INLINE float PxAbs(float a)
abs returns the absolute value of its argument.
Definition PxMath.h:109