openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

257 lines
7.5 KiB

/*
* Copyright 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TMAT_IMPLEMENTATION
#error "Don't include TMatHelpers.h directly. use ui/mat*.h instead"
#else
#undef TMAT_IMPLEMENTATION
#endif
#ifndef UI_TMAT_HELPERS_H
#define UI_TMAT_HELPERS_H
#include <stdint.h>
#include <sys/types.h>
#include <math.h>
#include <utils/Debug.h>
#include <utils/String8.h>
#define PURE __attribute__((pure))
namespace android {
// -------------------------------------------------------------------------------------
/*
* No user serviceable parts here.
*
* Don't use this file directly, instead include ui/mat*.h
*/
/*
* Matrix utilities
*/
namespace matrix {
inline int PURE transpose(int v) { return v; }
inline float PURE transpose(float v) { return v; }
inline double PURE transpose(double v) { return v; }
inline int PURE trace(int v) { return v; }
inline float PURE trace(float v) { return v; }
inline double PURE trace(double v) { return v; }
template<typename MATRIX>
MATRIX PURE inverse(const MATRIX& src) {
COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::COL_SIZE == MATRIX::ROW_SIZE );
typename MATRIX::value_type t;
const size_t N = MATRIX::col_size();
size_t swap;
MATRIX tmp(src);
MATRIX inverse(1);
for (size_t i=0 ; i<N ; i++) {
// look for largest element in column
swap = i;
for (size_t j=i+1 ; j<N ; j++) {
if (fabs(tmp[j][i]) > fabs(tmp[i][i])) {
swap = j;
}
}
if (swap != i) {
/* swap rows. */
for (size_t k=0 ; k<N ; k++) {
t = tmp[i][k];
tmp[i][k] = tmp[swap][k];
tmp[swap][k] = t;
t = inverse[i][k];
inverse[i][k] = inverse[swap][k];
inverse[swap][k] = t;
}
}
t = 1 / tmp[i][i];
for (size_t k=0 ; k<N ; k++) {
tmp[i][k] *= t;
inverse[i][k] *= t;
}
for (size_t j=0 ; j<N ; j++) {
if (j != i) {
t = tmp[j][i];
for (size_t k=0 ; k<N ; k++) {
tmp[j][k] -= tmp[i][k] * t;
inverse[j][k] -= inverse[i][k] * t;
}
}
}
}
return inverse;
}
template<typename MATRIX_R, typename MATRIX_A, typename MATRIX_B>
MATRIX_R PURE multiply(const MATRIX_A& lhs, const MATRIX_B& rhs) {
// pre-requisite:
// lhs : D columns, R rows
// rhs : C columns, D rows
// res : C columns, R rows
COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_A::ROW_SIZE == MATRIX_B::COL_SIZE );
COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_R::ROW_SIZE == MATRIX_B::ROW_SIZE );
COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_R::COL_SIZE == MATRIX_A::COL_SIZE );
MATRIX_R res(MATRIX_R::NO_INIT);
for (size_t r=0 ; r<MATRIX_R::row_size() ; r++) {
res[r] = lhs * rhs[r];
}
return res;
}
// transpose. this handles matrices of matrices
template <typename MATRIX>
MATRIX PURE transpose(const MATRIX& m) {
// for now we only handle square matrix transpose
COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE );
MATRIX result(MATRIX::NO_INIT);
for (size_t r=0 ; r<MATRIX::row_size() ; r++)
for (size_t c=0 ; c<MATRIX::col_size() ; c++)
result[c][r] = transpose(m[r][c]);
return result;
}
// trace. this handles matrices of matrices
template <typename MATRIX>
typename MATRIX::value_type PURE trace(const MATRIX& m) {
COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE );
typename MATRIX::value_type result(0);
for (size_t r=0 ; r<MATRIX::row_size() ; r++)
result += trace(m[r][r]);
return result;
}
// trace. this handles matrices of matrices
template <typename MATRIX>
typename MATRIX::col_type PURE diag(const MATRIX& m) {
COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE );
typename MATRIX::col_type result(MATRIX::col_type::NO_INIT);
for (size_t r=0 ; r<MATRIX::row_size() ; r++)
result[r] = m[r][r];
return result;
}
template <typename MATRIX>
String8 asString(const MATRIX& m) {
String8 s;
for (size_t c=0 ; c<MATRIX::col_size() ; c++) {
s.append("| ");
for (size_t r=0 ; r<MATRIX::row_size() ; r++) {
s.appendFormat("%7.2f ", m[r][c]);
}
s.append("|\n");
}
return s;
}
}; // namespace matrix
// -------------------------------------------------------------------------------------
/*
* TMatProductOperators implements basic arithmetic and basic compound assignments
* operators on a vector of type BASE<T>.
*
* BASE only needs to implement operator[] and size().
* By simply inheriting from TMatProductOperators<BASE, T> BASE will automatically
* get all the functionality here.
*/
template <template<typename T> class BASE, typename T>
class TMatProductOperators {
public:
// multiply by a scalar
BASE<T>& operator *= (T v) {
BASE<T>& lhs(static_cast< BASE<T>& >(*this));
for (size_t r=0 ; r<lhs.row_size() ; r++) {
lhs[r] *= v;
}
return lhs;
}
// divide by a scalar
BASE<T>& operator /= (T v) {
BASE<T>& lhs(static_cast< BASE<T>& >(*this));
for (size_t r=0 ; r<lhs.row_size() ; r++) {
lhs[r] /= v;
}
return lhs;
}
// matrix * matrix, result is a matrix of the same type than the lhs matrix
template<typename U>
friend BASE<T> PURE operator *(const BASE<T>& lhs, const BASE<U>& rhs) {
return matrix::multiply<BASE<T> >(lhs, rhs);
}
};
/*
* TMatSquareFunctions implements functions on a matrix of type BASE<T>.
*
* BASE only needs to implement:
* - operator[]
* - col_type
* - row_type
* - COL_SIZE
* - ROW_SIZE
*
* By simply inheriting from TMatSquareFunctions<BASE, T> BASE will automatically
* get all the functionality here.
*/
template<template<typename U> class BASE, typename T>
class TMatSquareFunctions {
public:
/*
* NOTE: the functions below ARE NOT member methods. They are friend functions
* with they definition inlined with their declaration. This makes these
* template functions available to the compiler when (and only when) this class
* is instantiated, at which point they're only templated on the 2nd parameter
* (the first one, BASE<T> being known).
*/
friend BASE<T> PURE inverse(const BASE<T>& m) { return matrix::inverse(m); }
friend BASE<T> PURE transpose(const BASE<T>& m) { return matrix::transpose(m); }
friend T PURE trace(const BASE<T>& m) { return matrix::trace(m); }
};
template <template<typename T> class BASE, typename T>
class TMatDebug {
public:
String8 asString() const {
return matrix::asString( static_cast< const BASE<T>& >(*this) );
}
};
// -------------------------------------------------------------------------------------
}; // namespace android
#undef PURE
#endif /* UI_TMAT_HELPERS_H */