📄 spatial_matrix.cpp
字号:
#include <hk_math/vecmath.h>
#include <hk_math/spatial_matrix.h>
#include <hk_math/spatial_vector.h>
// construct spatial isolated inertia matrix from I and m
// [ 0 M ]
// [ I 0 ]
void hk_Spatial_Matrix::set_spatial_inertia_tensor( const hk_Matrix3& inertia_tensor, const hk_real mass )
{
m_Block[0][0].set_zero();
m_Block[0][1].set_diagonal( mass, mass, mass );
m_Block[1][0] = inertia_tensor;
m_Block[1][1].set_zero();
}
// spatial transform from frame F to G =
// [ R 0 ] where R is rotation taking vector from F to G
// [ -r~R R ] and r is vector from origin of F to origin of G in G's frame of reference
//
void hk_Spatial_Matrix::set_spatial_transform( const hk_Matrix3& R, const hk_Vector3& r )
{
hk_Matrix3 rR;
hk_Vector3 r_neg( -r.x, -r.y, -r.z );
rR.set_cross_skew( r_neg, R );
m_Block[0][0] = R;
m_Block[0][1].set_zero();
m_Block[1][1] = R;
m_Block[1][0] = rR;
}
// spatial transform from frame F to G =
// [ R 0 ] where R is transform taking vector from F to G
// [ -r~R R ] and r is vector from origin of F to origin of G in G's frame of reference
//
void hk_Spatial_Matrix::set_spatial_transform( const hk_Transform& cartesian_frame )
{
HK_ASSERT(0);
/* hk_Matrix3 rR;
hk_real raw[16];
cartesian_frame.get_4x4_column_major( raw );
hk_Matrix3 R;
//!me
R.set_cols( hk_Vector3(raw[0], raw[1], raw[2] ),
hk_Vector3(raw[4], raw[5], raw[6] ),
hk_Vector3(raw[8], raw[9], raw[10] ));
//!me ack figure out which it should be!!!
R.set_cols( hk_Vector3(raw[0], raw[4], raw[8] ),
hk_Vector3(raw[1], raw[5], raw[9] ),
hk_Vector3(raw[2], raw[6], raw[10] ));
hk_Vector3 r;
r.set_rotated_dir( cartesian_frame, cartesian_frame.get_translation() );
hk_Vector3 r_neg( -r.x, -r.y, -r.z );
rR.set_cross_skew( r_neg, R );
m_Block[0][0] = R;
m_Block[0][1].set_zero();
m_Block[1][1] = R;
m_Block[1][0] = rR;*/
}
void hk_Spatial_Matrix::set_mul( hk_Spatial_Matrix& a, hk_Spatial_Matrix& b )
{
hk_Matrix3 work;
work.set_mul3( a.m_Block[0][0], b.m_Block[0][0] );
m_Block[0][0].set_mul3( a.m_Block[0][1], b.m_Block[1][0] );
m_Block[0][0] += work;
work.set_mul3( a.m_Block[0][0], b.m_Block[0][1] );
m_Block[0][1].set_mul3( a.m_Block[0][1], b.m_Block[1][1] );
m_Block[0][1] += work;
work.set_mul3( a.m_Block[1][0], b.m_Block[0][0] );
m_Block[1][0].set_mul3( a.m_Block[1][1], b.m_Block[1][0] );
m_Block[1][0] += work;
work.set_mul3( a.m_Block[1][0], b.m_Block[0][1] );
m_Block[1][1].set_mul3( a.m_Block[1][1], b.m_Block[1][1] );
m_Block[1][1] += work;
}
void hk_Spatial_Matrix::set_add( hk_Spatial_Matrix& a, hk_Spatial_Matrix& b )
{
m_Block[0][0] = a.m_Block[0][0];
m_Block[0][0] += b.m_Block[0][0];
m_Block[1][0] = a.m_Block[1][0];
m_Block[1][0] += b.m_Block[1][0];
m_Block[0][1] = a.m_Block[0][1];
m_Block[0][1] += b.m_Block[0][1];
m_Block[1][1] = a.m_Block[1][1];
m_Block[1][1] += b.m_Block[1][1];
}
void hk_Spatial_Matrix::set_sub( hk_Spatial_Matrix& a, hk_Spatial_Matrix& b )
{
m_Block[0][0] = a.m_Block[0][0];
m_Block[0][0] -= b.m_Block[0][0];
m_Block[1][0] = a.m_Block[1][0];
m_Block[1][0] -= b.m_Block[1][0];
m_Block[0][1] = a.m_Block[0][1];
m_Block[0][1] -= b.m_Block[0][1];
m_Block[1][1] = a.m_Block[1][1];
m_Block[1][1] -= b.m_Block[1][1];
}
void hk_Spatial_Matrix::operator += ( const hk_Spatial_Matrix& Ma )
{
m_Block[0][0] += Ma.m_Block[0][0];
m_Block[1][0] += Ma.m_Block[1][0];
m_Block[0][1] += Ma.m_Block[0][1];
m_Block[1][1] += Ma.m_Block[1][1];
}
void hk_Spatial_Matrix::operator -= ( const hk_Spatial_Matrix& Ma )
{
m_Block[0][0] -= Ma.m_Block[0][0];
m_Block[1][0] -= Ma.m_Block[1][0];
m_Block[0][1] -= Ma.m_Block[0][1];
m_Block[1][1] -= Ma.m_Block[1][1];
}
void hk_Spatial_Matrix::operator *= ( hk_real a )
{
int idr,idc;
for( idr = 0; idr < 3; idr++ ){
for( idc = 0; idc < 3; idc++ ){
m_Block[0][0].set_elem(idr, idc, m_Block[0][0](idr, idc)*a);
m_Block[1][0].set_elem(idr, idc, m_Block[1][0](idr, idc)*a);
m_Block[0][1].set_elem(idr, idc, m_Block[0][1](idr, idc)*a);
m_Block[1][1].set_elem(idr, idc, m_Block[1][1](idr, idc)*a);
}
}
}
void hk_Spatial_Matrix::set_vector_mul_vector( const hk_Spatial_Vector &a, const hk_Spatial_Vector &b )
{
int idr, idc;
for( idr = 0; idr < 3; idr++ ){
for( idc = 0; idc < 3; idc++ ){
m_Block[0][0].set_elem(idr, idc, a.top(idr)*b.bottom(idc));
}
}
for( idr = 0; idr < 3; idr++ ){
for( idc = 0; idc < 3; idc++ ){
m_Block[0][1].set_elem(idr, idc, a.top(idr)*b.top(idc));
}
}
for( idr = 0; idr < 3; idr++ ){
for( idc = 0; idc < 3; idc++ ){
m_Block[1][0].set_elem(idr, idc, a.bottom(idr)*b.bottom(idc));
}
}
for( idr = 0; idr < 3; idr++ ){
for( idc = 0; idc < 3; idc++ ){
m_Block[1][1].set_elem(idr, idc, a.bottom(idr)*b.top(idc));
}
}
}
void hk_Spatial_Matrix::set_identity()
{
m_Block[0][0].set_identity_rotation();
m_Block[1][1].set_identity_rotation();
m_Block[0][1].set_zero();
m_Block[1][0].set_zero();
}
#define MIN_REAL 0.0000001f
#define MAX_REAL 10000000.0f
//!me temporary..... Steve, you probably have a better solver
void hk_Spatial_Matrix::gausse_siedel_solve( hk_real A[][6], int dim, hk_real *x, hk_real *b )
{
static int *order;
static int order_size = 0;
hk_real max_pivot, factor;
int elimcol, elimrow, check_pivot, backcol, backrow, target_row, target_col;
int max_order_row_index;
if( dim > order_size ){
delete order;
order = new int[ dim ]; //(int *)malloc( dim * sizeof(real) );
order_size = dim;
}
for( target_row = 0; target_row < dim; target_row++ ){
order[target_row] = target_row;
}
// eliminate all columns
for( elimcol = 0; elimcol < dim; elimcol++ ){
max_order_row_index = elimcol;
// get row with largest value at pivot from set of rows not eliminated already
for( max_pivot = 0, check_pivot = elimcol; check_pivot < dim; check_pivot++ ){
if( max_pivot < hk_Math::fabs(A[order[check_pivot]][elimcol]) ){
max_pivot = hk_Math::fabs(A[order[check_pivot]][elimcol]);
max_order_row_index = check_pivot;
}
}
// swap rows in order
elimrow = order[max_order_row_index];
order[max_order_row_index] = order[elimcol];
order[elimcol] = elimrow;
// elimination: only eliminate all rows that haven't been reduced already
for( target_row = elimcol+1; target_row < dim; target_row++ ){
if( A[elimrow][elimcol] == 0.0f ){ //!me should report errors
//!me instead of failing I should try to fix it the best I can.
//!me much better to have wierd results than to fail completely.
//!me Here's what to do: look up cholesky factorization
//!me or do this: try to figure out what vector is missing in
//!me order to get b. take dot product with b and subract from
//!me b for every row ( column? ) then whatever is left is
//!me what this 0 row should be ( might have to take it from
//!me column space to row space first ). Cool!?!?!
factor = 0.0f; // the whole row was 0.0, so fail nicely
// printf( "shit singular matrix\n");
// exit(1);
}else{
if( hk_Math::fabs(A[elimrow][elimcol]) < MIN_REAL ){
// exit(1);
factor = MAX_REAL;
}else{
factor = A[order[target_row]][elimcol]/A[elimrow][elimcol];
}
}
// do each column for this elimanation step that hasn't been eliminated already
for( target_col = elimcol; target_col < dim; target_col++ ){
A[order[target_row]][target_col] -= factor*A[elimrow][target_col];
}
// modify b as well for the elimination
b[order[target_row]] -= factor*b[elimrow];
}
}
// find solutions with back substitution
for( backcol = dim-1; backcol >= 0; backcol-- ){
x[backcol] = b[order[backcol]];
for( backrow = dim-1; backrow > backcol; backrow-- ){
x[backcol] -= A[order[backcol]][backrow]*x[backrow];
}
if( A[order[backcol]][backcol] == 0 ){
// exit(1);
x[backcol] = 0; //!me fail nicely
}else{
x[backcol] = x[backcol]/A[order[backcol]][backcol];
}
}
}
void hk_Spatial_Matrix::linear_solve( hk_Spatial_Vector &sx, const hk_Spatial_Vector &sb )
{
hk_real x[6];
hk_real b[6];
hk_real A[6][6];
int idx, jdx;
for( idx = 0; idx < 3; idx++ ){
x[idx] = sx.top(idx);
b[idx] = sb.top(idx);
x[idx+3] = sx.bottom(idx);
b[idx+3] = sb.bottom(idx);
for( jdx = 0; jdx < 3; jdx++ ){
A[idx][jdx] = m_Block[0][0](idx,jdx);
A[idx+3][jdx] = m_Block[1][0](idx,jdx);
A[idx+3][jdx+3] = m_Block[1][1](idx,jdx);
A[idx][jdx+3] = m_Block[0][1](idx,jdx);
}
}
// solve this sucker
gausse_siedel_solve( A, 6, x, b );
for( idx = 0; idx < 6; idx++ ){
sx(idx) = x[idx];
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -