⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ahrs.cpp

📁 UAV 自动驾驶的
💻 CPP
字号:
/* -*- indent-tabs-mode:T; c-basic-offset:8; tab-width:8; -*- vi: set ts=8: *  $Id: AHRS.cpp,v 2.16 2003/03/15 05:53:38 tramm Exp $ * * (c) Trammell Hudson * (c) Aaron Kahn * * AHRS simulator based on Kalman filtering of the gyro and * accelerometer data.  Converted from Aaron's matlab code * to use the C++ math library. * ************** * *  This file is part of the autopilot simulation package. * *  Autopilot is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  Autopilot is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with Autopilot; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * */#include <AHRS.h>#include <mat/Vector.h>#include <mat/Matrix.h>#include <mat/Matrix_Invert.h>#include <mat/Quat.h>#include <mat/Nav.h>#include <mat/Conversions.h>#include <mat/Kalman.h>#include <iostream>#include <fstream>#include <cmath>#include <cstdio>#include <vector>#include <string>#include "macros.h"namespace imufilter{using namespace util;using namespace libmat;using namespace std;voidAHRS::make_a_matrix(	Matrix<N,N> &		A,	const Vector<3> &	pqr) const{	const state_t &		x = this->state;	const double		p = pqr[0] / 2.0;	const double		q = pqr[1] / 2.0;	const double		r = pqr[2] / 2.0;	const double		q0 = x.q[0] / 2.0;	const double		q1 = x.q[1] / 2.0;	const double		q2 = x.q[2] / 2.0;	const double		q3 = x.q[3] / 2.0;	A[0][0] =  0;	A[0][1] = -p;	A[0][2] = -q;	A[0][3] = -r;	A[0][4] =  q1;	A[0][5] =  q2;	A[0][6] =  q3;	A[1][0] =  p;	A[1][1] =  0;	A[1][2] =  r;	A[1][3] = -q;	A[1][4] = -q0;	A[1][5] =  q3;	A[1][6] = -q2;	A[2][0] =  q;	A[2][1] = -r;	A[2][2] =  0;	A[2][3] =  p;	A[2][4] = -q3;	A[2][5] = -q0;	A[2][6] =  q1;	A[3][0] =  r;	A[3][1] =  q;	A[3][2] = -p;	A[3][3] =  0;	A[3][4] =  q2;	A[3][5] = -q1;	A[3][6] = -q0;	for( int i=4 ; i<N ; i++ )		for( int j=0 ; j<N ; j++ )			A[i][j] = 0;}voidAHRS::propagate_state(	const Vector<3> &	pqr){	state_t &		x = this->state;	const double		p = pqr[0] / 2.0;	const double		q = pqr[1] / 2.0;	const double		r = pqr[2] / 2.0;	const double		q0 = x.q[0];	const double		q1 = x.q[1];	const double		q2 = x.q[2];	const double		q3 = x.q[3];	Vector<4>		Xdot(		-p * q1 - q * q2 - r * q3,		 p * q0 - q * q3 + r * q2,		 p * q3 + q * q0 - r * q1,		-p * q2 + q * q1 + r * q0	);	Xdot *= this->dt;	x.q += Xdot;	x.q.norm_self();}voidAHRS::propagate_covariance(	const Matrix<N,N> &	A){	Matrix<N,N>		Pdot( this->Q );	Pdot += A * this->P;	Pdot += this->P * A.transpose();	Pdot *= this->dt;	this->P += Pdot;	this->trace = 0;	for( int i=0 ; i<N ; i++ )		this->trace += this->P[i][i];	}template<	int			m>voidAHRS::do_kalman(	const Matrix<m,N> &	C,	const Matrix<m,m> &	R,	const Vector<m> &	eTHETA){	state_t &		x( this->state );	// We throw away the K result	Matrix<N,m>		K;	// Kalman() wants a vector, not an object.  Serialize the	// state data into this vector, then extract it out again	// once we're done with the loop.	Vector<N>		X_vect;	X_vect[0]	= x.q[0];	X_vect[1]	= x.q[1];	X_vect[2]	= x.q[2];	X_vect[3]	= x.q[3];	X_vect[4]	= x.bias[0];	X_vect[5]	= x.bias[1];	X_vect[6]	= x.bias[2];	Kalman(		this->P,		X_vect,		C,		R,		eTHETA,		K	);	x.q[0]		= X_vect[0];	x.q[1]		= X_vect[1];	x.q[2]		= X_vect[2];	x.q[3]		= X_vect[3];	x.bias[0]	= X_vect[4];	x.bias[1]	= X_vect[5];	x.bias[2]	= X_vect[6];	x.q.norm_self();}voidAHRS::kalman_attitude_update(	const Vector<3> &	accel,	const Matrix<3,3> &	DCM,	const Vector<3> &	THETAe){	double			err;	state_t &		x( this->state );	// compute the euler angles from the accelerometers	const Vector<3>		THETAm( accel2euler( accel, THETAe[2] ) );	// make the C matrix	Matrix<2,N>		C;	// PHI section	err = 2.0 / ( sqr(DCM[2][2]) + sqr(DCM[1][2]) );	C[0][0] = ( x.q[1] * DCM[2][2]                            ) * err;	C[0][1] = ( x.q[0] * DCM[2][2] + 2.0 * x.q[1] * DCM[1][2] ) * err;	C[0][2] = ( x.q[3] * DCM[2][2] + 2.0 * x.q[2] * DCM[1][2] ) * err;	C[0][3] = ( x.q[2] * DCM[2][2]                            ) * err;	C[0][4] = 0.0;	C[0][5] = 0.0;	C[0][6] = 0.0;	// THETA section	err = -1.0 / sqrt(1.0 - sqr(DCM[0][2]) );	C[1][0] = -2.0 * x.q[2] * err;	C[1][1] =  2.0 * x.q[3] * err;	C[1][2] = -2.0 * x.q[0] * err;	C[1][3] =  2.0 * x.q[1] * err;	C[1][4] = 0.0;	C[1][5] = 0.0;	C[1][6] = 0.0;	// compute the error; this should be ( THETAm - THETAe ),	// but we can only use the pitch and roll angles here	Vector<2>		eTHETA;	eTHETA[0] = THETAm[0] - THETAe[0];	eTHETA[1] = THETAm[1] - THETAe[1];	this->do_kalman(		C,		this->R_attitude,		eTHETA	);}voidAHRS::kalman_compass_update(	double			heading,		// degrees	const Matrix<3,3> &	DCM,	const Vector<3> &	THETAe){	state_t &		x( this->state );	const double		q0 = x.q[0];	const double		q1 = x.q[1];	const double		q2 = x.q[2];	const double		q3 = x.q[3];	Matrix<1,N>		C( 0 );	// PSI section	const double		err = 2 / (sqr(DCM[0][0]) + sqr(DCM[0][1]));	C[0][0] = err * ( q3 * DCM[0][0] );	C[0][1] = err * ( q2 * DCM[0][0] );	C[0][2] = err * ( q1 * DCM[0][0] + 2.0 * q2 * DCM[0][1] );	C[0][3] = err * ( q0 * DCM[0][0] + 2.0 * q3 * DCM[0][1] );	// Compute the error	Vector<1>		eTHETA;	eTHETA[0] = heading - THETAe[2];	if( eTHETA[0] > C_PI )		eTHETA[0] -= 2.0 * C_PI;	else	if( eTHETA[0] < -C_PI )		eTHETA[0] += 2.0 * C_PI;	this->do_kalman(		C,		this->R_heading,		eTHETA	);}AHRS::AHRS(	double			dt) :	dt( dt ){	this->reset();}voidAHRS::reset(){	//this->P			= eye<N,double>();	this->P.fill();	P[4][4] = 1;	P[5][5] = 1;	P[6][6] = 1;	this->Q.fill();	this->R_attitude.fill();	this->R_heading.fill();	// Quaterion attitude estimate noise	this->Q[0][0] = 0.0001;	this->Q[1][1] = 0.0001;	this->Q[2][2] = 0.0001;	this->Q[3][3] = 0.0001;	// Gyro bias	this->Q[4][4] = 0.03;	this->Q[5][5] = 0.03;	this->Q[6][6] = 0.03;	this->R_attitude[0][0] = 0.3;	this->R_attitude[1][1] = 0.3;	this->R_heading[0][0] = 0.5;}/* * We assume that the vehicle is still during the first sample * and use the values to help us determine the zero point for the * gyro bias and accelerometers. * * You must call this once you have the samples from the IMU * and compass.  Perhaps throw away the first few to let things * stabilize. */voidAHRS::initialize(	const Vector<3> &	accel,	const Vector<3> &	pqr,	double			heading){	this->state.bias	= pqr;	this->state.q		= euler2quat( accel2euler( accel, heading ) );	this->theta		= quat2euler( this->state.q );}voidAHRS::imu_update(	const Vector<3> &	accel,	const Vector<3> &	pqr_raw){	const state_t &		x( this->state );	const Vector<3>		pqr( pqr_raw - x.bias );	Matrix<N,N>		A;	this->make_a_matrix( A, pqr );	this->propagate_state( pqr );	this->propagate_covariance( A );	/* Compute the DCM and angle estimate here */	const Matrix<3,3> 	DCM( quatDC( x.q ) );	const Vector<3>		THETAe( quat2euler( x.q ) );	this->kalman_attitude_update(		accel,		DCM,		THETAe	);	/* compute angles from quaternions */	this->theta	= quat2euler( x.q );	/* Store our bias and converted angular rates */	this->accel	= accel;	this->bias	= x.bias;	this->pqr	= pqr_raw - x.bias;}voidAHRS::compass_update(	double			heading){	const state_t &		x( this->state );	/* Compute the DCM and angle estimate here */	const Matrix<3,3> 	DCM( quatDC( x.q ) );	const Vector<3>		THETAe( quat2euler( x.q ) );	this->kalman_compass_update(		heading,		DCM,		THETAe	);}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -