Home | History | Annotate | Download | only in AKFS_APIs_8975
      1 /******************************************************************************
      2  * $Id: AKFS_AOC.c 580 2012-03-29 09:56:21Z yamada.rj $
      3  ******************************************************************************
      4  *
      5  * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  */
     19 #include "AKFS_AOC.h"
     20 #include "AKFS_Math.h"
     21 
     22 /*
     23  * CalcR
     24  */
     25 static AKFLOAT CalcR(
     26 	const	AKFVEC*	x,
     27 	const	AKFVEC*	y
     28 ){
     29 	int16	i;
     30 	AKFLOAT	r;
     31 
     32 	r = 0.0;
     33 	for(i = 0; i < 3; i++){
     34 		r += (x->v[i]-y->v[i]) * (x->v[i]-y->v[i]);
     35 	}
     36 	r = sqrt(r);
     37 
     38 	return r;
     39 }
     40 
     41 /*
     42  * From4Points2Sphere()
     43  */
     44 static int16 From4Points2Sphere(
     45 	const	AKFVEC		points[],	/*! (i/o)	: input vectors  */
     46 			AKFVEC*		center,		/*! (o)	: center of sphere   */
     47 			AKFLOAT*	r			/*! (i)	: add/subtract value */
     48 ){
     49 	AKFLOAT	dif[3][3];
     50 	AKFLOAT	r2[3];
     51 
     52 	AKFLOAT	A;
     53 	AKFLOAT	B;
     54 	AKFLOAT	C;
     55 	AKFLOAT	D;
     56 	AKFLOAT	E;
     57 	AKFLOAT	F;
     58 	AKFLOAT	G;
     59 
     60 	AKFLOAT	OU;
     61 	AKFLOAT	OD;
     62 
     63 	int16	i, j;
     64 
     65 	for(i = 0; i < 3; i++){
     66 		r2[i] = 0.0;
     67 		for(j = 0; j < 3; j++){
     68 			dif[i][j] = points[i].v[j] - points[3].v[j];
     69 			r2[i] += (points[i].v[j]*points[i].v[j]
     70 					- points[3].v[j]*points[3].v[j]);
     71 		}
     72 		r2[i] *= 0.5;
     73 	}
     74 
     75 	A = dif[0][0]*dif[2][2] - dif[0][2]*dif[2][0];
     76 	B = dif[0][1]*dif[2][0] - dif[0][0]*dif[2][1];
     77 	C = dif[0][0]*dif[2][1] - dif[0][1]*dif[2][0];
     78 	D = dif[0][0]*r2[2]		- dif[2][0]*r2[0];
     79 	E = dif[0][0]*dif[1][1] - dif[0][1]*dif[1][0];
     80 	F = dif[1][0]*dif[0][2] - dif[0][0]*dif[1][2];
     81 	G = dif[0][0]*r2[1]		- dif[1][0]*r2[0];
     82 
     83 	OU = D*E + B*G;
     84 	OD = C*F + A*E;
     85 
     86 	if(fabs(OD) < AKFS_EPSILON){
     87 		return -1;
     88 	}
     89 
     90 	center->v[2] = OU / OD;
     91 
     92 	OU = F*center->v[2] + G;
     93 	OD = E;
     94 
     95 	if(fabs(OD) < AKFS_EPSILON){
     96 		return -1;
     97 	}
     98 
     99 	center->v[1] = OU / OD;
    100 
    101 	OU = r2[0] - dif[0][1]*center->v[1] - dif[0][2]*center->v[2];
    102 	OD = dif[0][0];
    103 
    104 	if(fabs(OD) < AKFS_EPSILON){
    105 		return -1;
    106 	}
    107 
    108 	center->v[0] = OU / OD;
    109 
    110 	*r = CalcR(&points[0], center);
    111 
    112 	return 0;
    113 
    114 }
    115 
    116 /*
    117  * MeanVar
    118  */
    119 static void MeanVar(
    120 	const	AKFVEC	v[],			/*!< (i)   : input vectors */
    121 	const	int16	n,				/*!< (i)   : number of vectors */
    122 			AKFVEC*	mean,			/*!< (o)   : (max+min)/2 */
    123 			AKFVEC*	var				/*!< (o)   : variation in vectors */
    124 ){
    125 	int16	i;
    126 	int16	j;
    127 	AKFVEC	max;
    128 	AKFVEC	min;
    129 
    130 	for(j = 0; j < 3; j++){
    131 		min.v[j] = v[0].v[j];
    132 		max.v[j] = v[0].v[j];
    133 		for(i = 1; i < n; i++){
    134 			if(v[i].v[j] < min.v[j]){
    135 				min.v[j] = v[i].v[j];
    136 			}
    137 			if(v[i].v[j] > max.v[j]){
    138 				max.v[j] = v[i].v[j];
    139 			}
    140 		}
    141 		mean->v[j] = (max.v[j] + min.v[j]) / 2.0;	/*mean */
    142 		var->v[j] = max.v[j] - min.v[j];			/*var  */
    143 	}
    144 }
    145 
    146 /*
    147  * Get4points
    148  */
    149 static void Get4points(
    150 	const	AKFVEC	v[],			/*!< (i)   : input vectors */
    151 	const	int16	n,				/*!< (i)   : number of vectors */
    152 			AKFVEC	out[]			/*!< (o)   : */
    153 ){
    154 	int16	i, j;
    155 	AKFLOAT temp;
    156 	AKFLOAT d;
    157 
    158 	AKFVEC	dv[AKFS_HBUF_SIZE];
    159 	AKFVEC	cross;
    160 	AKFVEC	tempv;
    161 
    162 	/* out 0 */
    163 	out[0] = v[0];
    164 
    165 	/* out 1 */
    166 	d = 0.0;
    167 	for(i = 1; i < n; i++){
    168 		temp = CalcR(&v[i], &out[0]);
    169 		if(d < temp){
    170 			d = temp;
    171 			out[1] = v[i];
    172 		}
    173 	}
    174 
    175 	/* out 2 */
    176 	d = 0.0;
    177 	for(j = 0; j < 3; j++){
    178 		dv[0].v[j] = out[1].v[j] - out[0].v[j];
    179 	}
    180 	for(i = 1; i < n; i++){
    181 		for(j = 0; j < 3; j++){
    182 			dv[i].v[j] = v[i].v[j] - out[0].v[j];
    183 		}
    184 		tempv.v[0] = dv[0].v[1]*dv[i].v[2] - dv[0].v[2]*dv[i].v[1];
    185 		tempv.v[1] = dv[0].v[2]*dv[i].v[0] - dv[0].v[0]*dv[i].v[2];
    186 		tempv.v[2] = dv[0].v[0]*dv[i].v[1] - dv[0].v[1]*dv[i].v[0];
    187 		temp =	tempv.u.x * tempv.u.x
    188 			  +	tempv.u.y * tempv.u.y
    189 			  +	tempv.u.z * tempv.u.z;
    190 		if(d < temp){
    191 			d = temp;
    192 			out[2] = v[i];
    193 			cross = tempv;
    194 		}
    195 	}
    196 
    197 	/* out 3 */
    198 	d = 0.0;
    199 	for(i = 1; i < n; i++){
    200 		temp =	  dv[i].u.x * cross.u.x
    201 				+ dv[i].u.y * cross.u.y
    202 				+ dv[i].u.z * cross.u.z;
    203 		temp = fabs(temp);
    204 		if(d < temp){
    205 			d = temp;
    206 			out[3] = v[i];
    207 		}
    208 	}
    209 }
    210 
    211 /*
    212  * CheckInitFvec
    213  */
    214 static int16 CheckInitFvec(
    215 	const	AKFVEC	*v		/*!< [in]	vector */
    216 ){
    217 	int16 i;
    218 
    219 	for(i = 0; i < 3; i++){
    220 		if(AKFS_FMAX <= v->v[i]){
    221 			return 1;       /* initvalue */
    222 		}
    223 	}
    224 
    225 	return 0;       /* not initvalue */
    226 }
    227 
    228 /*
    229  * AKFS_AOC
    230  */
    231 int16 AKFS_AOC(				/*!< (o)   : calibration success(1), failure(0) */
    232 			AKFS_AOC_VAR*	haocv,	/*!< (i/o)	: a set of variables */
    233 	const	AKFVEC*			hdata,	/*!< (i)	: vectors of data    */
    234 			AKFVEC*			ho		/*!< (i/o)	: offset             */
    235 ){
    236 	int16	i, j;
    237 	int16	num;
    238 	AKFLOAT	tempf;
    239 	AKFVEC	tempho;
    240 
    241 	AKFVEC	fourpoints[4];
    242 
    243 	AKFVEC	var;
    244 	AKFVEC	mean;
    245 
    246 	/* buffer new data */
    247 	for(i = 1; i < AKFS_HBUF_SIZE; i++){
    248 		haocv->hbuf[AKFS_HBUF_SIZE-i] = haocv->hbuf[AKFS_HBUF_SIZE-i-1];
    249 	}
    250 	haocv->hbuf[0] = *hdata;
    251 
    252 	/* Check Init */
    253 	num = 0;
    254 	for(i = AKFS_HBUF_SIZE; 3 < i; i--){
    255 		if(CheckInitFvec(&haocv->hbuf[i-1]) == 0){
    256 			num = i;
    257 			break;
    258 		}
    259 	}
    260 	if(num < 4){
    261 		return AKFS_ERROR;
    262 	}
    263 
    264 	/* get 4 points */
    265 	Get4points(haocv->hbuf, num, fourpoints);
    266 
    267 	/* estimate offset */
    268 	if(0 != From4Points2Sphere(fourpoints, &tempho, &haocv->hraoc)){
    269 		return AKFS_ERROR;
    270 	}
    271 
    272 	/* check distance */
    273 	for(i = 0; i < 4; i++){
    274 		for(j = (i+1); j < 4; j++){
    275 			tempf = CalcR(&fourpoints[i], &fourpoints[j]);
    276 			if((tempf < haocv->hraoc)||(tempf < AKFS_HR_TH)){
    277 				return AKFS_ERROR;
    278 			}
    279 		}
    280 	}
    281 
    282 	/* update offset buffer */
    283 	for(i = 1; i < AKFS_HOBUF_SIZE; i++){
    284 		haocv->hobuf[AKFS_HOBUF_SIZE-i] = haocv->hobuf[AKFS_HOBUF_SIZE-i-1];
    285 	}
    286 	haocv->hobuf[0] = tempho;
    287 
    288 	/* clear hbuf */
    289 	for(i = (AKFS_HBUF_SIZE>>1); i < AKFS_HBUF_SIZE; i++) {
    290 		for(j = 0; j < 3; j++) {
    291 			haocv->hbuf[i].v[j]= AKFS_FMAX;
    292 		}
    293 	}
    294 
    295 	/* Check Init */
    296 	if(CheckInitFvec(&haocv->hobuf[AKFS_HOBUF_SIZE-1]) == 1){
    297 		return AKFS_ERROR;
    298 	}
    299 
    300 	/* Check ovar */
    301 	tempf = haocv->hraoc * AKFS_HO_TH;
    302 	MeanVar(haocv->hobuf, AKFS_HOBUF_SIZE, &mean, &var);
    303 	if ((var.u.x >= tempf) || (var.u.y >= tempf) || (var.u.z >= tempf)){
    304 		return AKFS_ERROR;
    305 	}
    306 
    307 	*ho = mean;
    308 
    309 	return AKFS_SUCCESS;
    310 }
    311 
    312 /*
    313  * AKFS_InitAOC
    314  */
    315 void AKFS_InitAOC(
    316 			AKFS_AOC_VAR*	haocv
    317 ){
    318 	int16 i, j;
    319 
    320 	/* Initialize buffer */
    321 	for(i = 0; i < AKFS_HBUF_SIZE; i++) {
    322 		for(j = 0; j < 3; j++) {
    323 			haocv->hbuf[i].v[j]= AKFS_FMAX;
    324 		}
    325 	}
    326 	for(i = 0; i < AKFS_HOBUF_SIZE; i++) {
    327 		for(j = 0; j < 3; j++) {
    328 			haocv->hobuf[i].v[j]= AKFS_FMAX;
    329 		}
    330 	}
    331 
    332 	haocv->hraoc = 0.0;
    333 }
    334 
    335