2017-08-01 14:30:58 +02:00
/*
Bullet Continuous Collision Detection and Physics Library
Copyright ( c ) 2003 - 2013 Erwin Coumans http : //bulletphysics.org
This software is provided ' as - is ' , without any express or implied warranty .
In no event will the authors be held liable for any damages arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it freely ,
subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not claim that you wrote the original software . If you use this software in a product , an acknowledgment in the product documentation would be appreciated but is not required .
2. Altered source versions must be plainly marked as such , and must not be misrepresented as being the original software .
3. This notice may not be removed or altered from any source distribution .
*/
///original version written by Erwin Coumans, October 2013
# ifndef BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
# define BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
# include "btMLCPSolverInterface.h"
///This solver is mainly for debug/learning purposes: it is functionally equivalent to the btSequentialImpulseConstraintSolver solver, but much slower (it builds the full LCP matrix)
class btSolveProjectedGaussSeidel : public btMLCPSolverInterface
{
public :
btScalar m_leastSquaresResidualThreshold ;
btScalar m_leastSquaresResidual ;
btSolveProjectedGaussSeidel ( )
2019-01-03 14:26:51 +01:00
: m_leastSquaresResidualThreshold ( 0 ) ,
m_leastSquaresResidual ( 0 )
2017-08-01 14:30:58 +02:00
{
}
2019-01-03 14:26:51 +01:00
virtual bool solveMLCP ( const btMatrixXu & A , const btVectorXu & b , btVectorXu & x , const btVectorXu & lo , const btVectorXu & hi , const btAlignedObjectArray < int > & limitDependency , int numIterations , bool useSparsity = true )
2017-08-01 14:30:58 +02:00
{
if ( ! A . rows ( ) )
return true ;
//the A matrix is sparse, so compute the non-zero elements
A . rowComputeNonZeroElements ( ) ;
//A is a m-n matrix, m rows, n columns
btAssert ( A . rows ( ) = = b . rows ( ) ) ;
int i , j , numRows = A . rows ( ) ;
2019-01-03 14:26:51 +01:00
2017-08-01 14:30:58 +02:00
btScalar delta ;
2019-01-03 14:26:51 +01:00
for ( int k = 0 ; k < numIterations ; k + + )
2017-08-01 14:30:58 +02:00
{
m_leastSquaresResidual = 0.f ;
2019-01-03 14:26:51 +01:00
for ( i = 0 ; i < numRows ; i + + )
2017-08-01 14:30:58 +02:00
{
delta = 0.0f ;
if ( useSparsity )
{
2019-01-03 14:26:51 +01:00
for ( int h = 0 ; h < A . m_rowNonZeroElements1 [ i ] . size ( ) ; h + + )
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
j = A . m_rowNonZeroElements1 [ i ] [ h ] ;
if ( j ! = i ) //skip main diagonal
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
delta + = A ( i , j ) * x [ j ] ;
2017-08-01 14:30:58 +02:00
}
}
2019-01-03 14:26:51 +01:00
}
else
2017-08-01 14:30:58 +02:00
{
2019-01-03 14:26:51 +01:00
for ( j = 0 ; j < i ; j + + )
delta + = A ( i , j ) * x [ j ] ;
for ( j = i + 1 ; j < numRows ; j + + )
delta + = A ( i , j ) * x [ j ] ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
btScalar aDiag = A ( i , i ) ;
2017-08-01 14:30:58 +02:00
btScalar xOld = x [ i ] ;
2019-01-03 14:26:51 +01:00
x [ i ] = ( b [ i ] - delta ) / aDiag ;
2017-08-01 14:30:58 +02:00
btScalar s = 1.f ;
2019-01-03 14:26:51 +01:00
if ( limitDependency [ i ] > = 0 )
2017-08-01 14:30:58 +02:00
{
s = x [ limitDependency [ i ] ] ;
2019-01-03 14:26:51 +01:00
if ( s < 0 )
s = 1 ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
if ( x [ i ] < lo [ i ] * s )
x [ i ] = lo [ i ] * s ;
if ( x [ i ] > hi [ i ] * s )
x [ i ] = hi [ i ] * s ;
2017-08-01 14:30:58 +02:00
btScalar diff = x [ i ] - xOld ;
2019-01-03 14:26:51 +01:00
m_leastSquaresResidual + = diff * diff ;
2017-08-01 14:30:58 +02:00
}
2019-01-03 14:26:51 +01:00
btScalar eps = m_leastSquaresResidualThreshold ;
if ( ( m_leastSquaresResidual < eps ) | | ( k > = ( numIterations - 1 ) ) )
2017-08-01 14:30:58 +02:00
{
# ifdef VERBOSE_PRINTF_RESIDUAL
2019-01-03 14:26:51 +01:00
printf ( " totalLenSqr = %f at iteration #%d \n " , m_leastSquaresResidual , k ) ;
2017-08-01 14:30:58 +02:00
# endif
break ;
}
}
return true ;
}
} ;
2019-01-03 14:26:51 +01:00
# endif //BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H