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

📄 kalman_c.txt

📁 kalman C程序
💻 TXT
📖 第 1 页 / 共 2 页
字号:
		raw_gyro_25v[2]);
	printf("Time ref: %4.8lf Sample freq: %4.8lf\n", dt, 1/dt);
	printf("Accelerometer state est: Roll: %4.8f Pitch: %4.8f Yaw: %4.8f\n",
		angle_reference_from_accels[0],
		angle_reference_from_accels[1],
		angle_reference_from_accels[2]);
	printf("Kalman filtered output: Roll: %4.8f Pitch: %4.8f Yaw: %4.8f\n",
		angle_estimate[0],
		angle_estimate[1],
		angle_estimate[2]);
	printf("Kalman filtered output degs: Roll: %4.8f Pitch: %4.8f Yaw: %4.8f\n",
		angle_estimate[0]*r2d,
		angle_estimate[1]*r2d,
		angle_estimate[2]*r2d);
	printf("Gps size: %d time: %f satellites: %d lat: %f lon: %f, alt: %f\n",
		sizeof(gpsPacket),
		gpsPacket.time,
		gpsPacket.satelites,
		gpsPacket.latitude,
		gpsPacket.longitude,
		gpsPacket.altitude);
	printf("Ultrasound altimeter: %f\n", ultrasound);
	printf("Compass heading: %d %d %f\n", compass_low,compass_high,compass_heading);
	printf("Battery: %f\n\n", battery);
}

/*******************************************************************
	SAMPLE SERIAL LINE FOR IMU DATA
	32 byte packet (16 short values)
********************************************************************/
int readimu(void){
	char		c,d;
	int			i;
	short		temp;
	
	fread(&c,1,1,fp);
	if(c=='A'){
		printf("Got start\n");
		fread(&ultrasound_raw,1,1,fp);
		ultrasound = (((ultrasound_raw * 5.0) / 255.0) / 0.01) * 2.24;
		
		fread(&compass_low,1,1,fp);
		fread(&compass_high,1,1,fp);
		
		compass_heading = (compass_high * 256.0) + compass_low;
		
		fread(&gpsPacket.altitude,4,1,fp);
		fread(&gpsPacket.longitude,4,1,fp);
		fread(&gpsPacket.latitude,4,1,fp);
		fread(&gpsPacket.satelites,4,1,fp);
		fread(&gpsPacket.time,4,1,fp);
				
		//got packet start. read next 33 bytes, count samples and check for packet end byte.
		fread(&temp,2,1,fp); raw_gyro_rates[1] = temp;			//gyro rateout
		fread(&temp,2,1,fp); raw_gyro_25v[1] = temp;			//2.5v ref
		fread(&temp,2,1,fp); raw_gyro_temperatures[1]=temp;		//gyro temp
		fread(&temp,2,1,fp); //raw_accels[1] = temp;			//accel y raw (patch y)
		fread(&temp,2,1,fp); raw_accels[2] = temp;				//accel x raw (patch z)

		fread(&temp,2,1,fp); raw_gyro_rates[0] = temp;			//gyro rateout
		fread(&temp,2,1,fp); raw_gyro_25v[0] = temp;			//2.5v ref
		fread(&temp,2,1,fp); raw_gyro_temperatures[0]=temp;		//gyro temp
		fread(&temp,2,1,fp); //raw_accels[0] = temp;			//accel y raw (patch z)
		fread(&temp,2,1,fp); //raw_accels[2] = temp;			//accel x raw

		fread(&temp,2,1,fp); raw_gyro_rates[2] = temp;			//gyro rateout
		fread(&temp,2,1,fp); raw_gyro_25v[2] = temp;			//2.5v ref
		fread(&temp,2,1,fp); raw_gyro_temperatures[2]=temp;		//gyro temp
		fread(&temp,2,1,fp); raw_accels[1] = temp;				//accel y raw (patch y)
		fread(&temp,2,1,fp); raw_accels[0] = temp;				//accel x raw (patch z)
		
		fread(&temp,2,1,fp); battery = temp;					//battery voltage
		
		fread(&c,1,1,fp);
	}
	//appply correction factors (from 2.5v ref) to roll gyro outputs
	for(i=0;i<3;i++){
		gyro_25v_correction[i] = (2.5/raw_gyro_25v[i])*1024;
		gyro_25v_correction[i] = (gyro_25v_correction[i]/5);
		raw_gyro_rates[i] = gyro_25v_correction[i]*raw_gyro_rates[i];
		raw_gyro_temperatures[i] = gyro_25v_correction[i]*raw_gyro_temperatures[i];
	}
		
	if(c=='Z' && checkvars())
		return 1;
	else{
		printf("Errored\n");
		return 0;
	}
}

/***************************************************************************
	3 POINT GYRO TEMPERATURE CALIBRATION BASED ON ANALOG'S APPNOTE.
	NEEDS ADDITIONAL WORK AND WE REALLY SHOULD IGNORE TABLE VALUES AND
	MEASURE EACH OF OUR GYROS AND THEN CREATE A TEMPvsOUTPUT TABLE FOR THEM
***************************************************************************/
void compensate_gyro_temp_drifts(){
	//local variables
	float gyro_null[3],gyro_scale_factor[3];
	float gyro_temp_differential[3];
	float gyro_temp_differential_squared[3];
	float gyro_rates_temp_compensated[3];
	int i;
	
	//if we convert to rads BEFORE the correction, can the extra precision of
	//the float's mantissa increase the scale precision? probably not, but we'll
	//try it later just to be sure.
	
	for(i=0;i<3;i++){
		//calculate null temp point (temp out at current vout)
		//current temp - reference temp (25 degrees celsius)
		gyro_temp_differential[i] = (raw_gyro_temperatures[i]-raw_gyro_temperatures_null[i])*a2v;
		//previous var square
		gyro_temp_differential_squared[i] = gyro_temp_differential[i]*gyro_temp_differential[i];
		//current null value (center) from reference null value
		gyro_null[i] = (raw_gyro_rates_null[i]*a2v) + 0.0086*(gyro_temp_differential[i])+0.03597*(gyro_temp_differential_squared[i]);
		//compensate current output with temp correction
		gyro_rates_temp_compensated[i] = (raw_gyro_rates[i]*a2v) - gyro_null[i];
		//convert to degrees by applying the scale factor according to temp
		gyro_scale_factor[i] = 12.744 + 1.26056*(gyro_temp_differential[i])+0.6728*(gyro_temp_differential_squared[i]);
		//transform P into corrected degrees per second
		corrected_rates[i] = gyro_rates_temp_compensated[i] / (gyro_scale_factor[i]/1000);
		// WE'RE FINISHED EXECUTING OUR CORRECTIONS.
		// WE NOW HAVE EXPORTED CORRECTED VALUES FOR P,Q,R (ROLL,PITCH,YAW) as float corrected_rates in EULER.
		//WE WANT RADS
		corrected_rates[i] = corrected_rates[i]*d2r - gyro_bias[i];
	}
}

/*******************************************************************
	TRANSFORM ACCELEROMETER DATA INTO ANGLES (RADIANS)
********************************************************************/
void accel2angle(void){
	int i;
	// Create reference attitute estimation for matrix.
	
	// when perpendicular to level, output accuracy decreases 17.5mg per angle of tilt, so
	// use last angle to calculate scale factor change
	// real_accel[i] = accels[i] - 0.0175*angle_estimate[i]
	
	accels[0] = ((raw_accels[0] - raw_accels_null[0])*a2v)/0.312;
	accels[1] = ((raw_accels[1] - raw_accels_null[1])*a2v)/0.312;
	accels[2] = ((raw_accels[2] - raw_accels_null[2])*a2v)/0.312; //was 1
	
	// Calculate g ( ||g_vec|| )
	float g = sqrt(accels[0]*accels[0] + accels[1]*accels[1] + accels[2]*accels[2]);
	
	printf("Gs: %4.8f %4.8f %4.8f (g=%f)\n", accels[0], accels[1], accels[2],g);
		
	if(g==0)
		exit(1);
	
	//values in radians
	angle_reference_from_accels[0] = -asin(accels[0] / g);
	angle_reference_from_accels[1] = asin(accels[1] / g);
	angle_reference_from_accels[2] = 0.0;//compass_heading*d2r; //gps_heading or compass;
}

/***********************************************************************
	SANITIZE OUR INPUT PACKETS
************************************************************************/
int checkvars(void){
	int i;
	
	//just a sanity check. if not good, return false so the main iterator can
	//ignore this packet.
	printf("Raw accels: %f %f %f\n", raw_accels[0],raw_accels[1],raw_accels[2]);
	for(i=0;i<3;i++){
		if(raw_gyro_rates[i] <= 0 || raw_gyro_rates[i] >= 1024 || raw_accels[i] <= 0 && raw_accels[i] >= 1024)
		return 0;
	}
	
	return 1;
}

/***********************************************************************
	Microsecond precision difftime for "accurate" integration
************************************************************************/
double timeval_subtract(struct timeval *x, struct timeval *y){
	double a,b,result;
	
	a = x->tv_sec + (x->tv_usec/1000000.0);
	b = y->tv_sec + (y->tv_usec/1000000.0);
	
	result = a-b;
	
	return(result);
}

void state_update() //called on new gyro output available
{
	int i;
	
	//state update really is just a progression of the internal covariance estimate.
	//it does not use any imu output, only the time ref.
	//the integration, unlike what happens with rotomotion's code, is done in gyro2angle.
	//this allows us to track cross-axis interference :)
	
	for(i=0;i<3;i++){
		float Pdot[2 * 2] = {
			Q_angle - P[i][0][1] - P[i][1][0],	/* 0,0 */
					- P[i][1][1],				/* 0,1 */
					- P[i][1][1],				/* 1,0 */
			Q_gyro								/* 1,1 */
		};

		/* Update the covariance matrix */
		P[i][0][0] += Pdot[0] * dt;
		P[i][0][1] += Pdot[1] * dt;
		P[i][1][0] += Pdot[2] * dt;
		P[i][1][1] += Pdot[3] * dt;
	}
}

void kalman_update(int axis_index) // i is axis index
{
	float angle_err;
	
	const float C_0 = 1.0;
	
	angle_err = angle_reference_from_accels[i] - angle_estimate[i];

	const float PCt_0 = C_0 * P[i][0][0];
	const float PCt_1 = C_0 * P[i][1][0];
			
	//error estimate
	const float E = R_angle + C_0 * PCt_0;

	const float	K_0 = PCt_0 / E;
	const float	K_1 = PCt_1 / E;
			
	const float	t_0 = PCt_0;
	const float	t_1 = C_0 * P[i][0][1];

	P[i][0][0] -= K_0 * t_0;
	P[i][0][1] -= K_0 * t_1;
	P[i][1][0] -= K_1 * t_0;
	P[i][1][1] -= K_1 * t_1;
		
	angle_estimate[i] += K_0 * angle_err;
	gyro_bias[i] += K_1 * angle_err;
}

⌨️ 快捷键说明

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