Fig1. ライブラリの目的
Fig2. 使用するシステム
Fig3. アライメントの例(パネルの張り合わせ)
/* マルチカメラ応用位置決めライブラリサンプルコード(シミュレータ付属) */ /* エラー処理を省略している箇所がありますので注意して下さい。*/ #include <math.h> #include <stdio.h> #include "fie.h" #define DATA_FILE "XYQPARAM.DAT" /* データセーブ用 */ #define CHAN_N 2 /* カメラ数 */ /* 計算用の諸定義 */ #define PI_DEG 180.0 /* π(度) */ #define PI_RAD 3.14159265358979 /* π(rad) */ /********************************** カメラパラメータ **********************************/ #define CAM1_X ( - 24.0 ) /* 固定カメラ1取り付け位置X */ #define CAM1_Y ( - 24.0 ) /* 固定カメラ1取り付け位置Y */ #define CAM1_Q ( 30.0 * PI_RAD / PI_DEG ) /* 固定カメラ1取り付け位置θ(rad) */ #define CAM1_RES ( 1.0 ) /* 固定カメラ1スケール値 1(画素) = dRes(mm) */ #define CAM2_X ( - 6.0 ) /* 固定カメラ2取り付け位置X */ #define CAM2_Y ( - 18.0 ) /* 固定カメラ2取り付け位置Y */ #define CAM2_Q ( 0.0 * PI_RAD / PI_DEG ) /* 固定カメラ2取り付け位置θ(rad) */ #define CAM2_RES ( 1.0 ) /* 固定カメラ2スケール値 1(画素) = dRes(mm) */ /********************************** キャリブレーションパラメータ **********************************/ #define CLB_MARK1_X ( - 6.0 ) /* ステージ上のキャリブレーションマーク1X座標 */ #define CLB_MARK1_Y ( - 6.0 ) /* ステージ上のキャリブレーションマーク1Y座標 */ #define CLB_MARK2_X ( 6.0 ) /* ステージ上のキャリブレーションマーク2X座標 */ #define CLB_MARK2_Y ( - 6.0 ) /* ステージ上のキャリブレーションマーク2Y座標 */ #define SFT_X ( 6.0 ) /* キャリブレーションX方向シフト量(mm) */ #define SFT_Y ( - 6.0 ) /* キャリブレーションY方向シフト量(mm) */ #define ROT_Q ( 60.0 * PI_RAD / PI_DEG ) /* キャリブレーション総回転量(rad) ±x度ならばこの値は2・x度になる */ #define CORREC_COUNT 3 /* 補正計算回数 */ /********************************** アライメントパラメータ **********************************/ #define ATGT_MARK1_X ( - 6.0 ) /* ステージ上のターゲットマーク1X座標 */ #define ATGT_MARK1_Y ( - 6.0 ) /* ステージ上のターゲットマーク1Y座標 */ #define ATGT_MARK2_X ( 6.0 ) /* ステージ上のターゲットマーク2X座標 */ #define ATGT_MARK2_Y ( - 6.0 ) /* ステージ上のターゲットマーク2Y座標 */ #define AOBJ_MARK1_X ( - 6.0 ) /* ステージ上のオブジェクトマーク1X座標 */ #define AOBJ_MARK1_Y ( - 12.0 ) /* ステージ上のオブジェクトマーク1Y座標 */ #define AOBJ_MARK2_X ( 6.0 ) /* ステージ上のオブジェクトマーク2X座標 */ #define AOBJ_MARK2_Y ( - 12.0 ) /* ステージ上のオブジェクトマーク2Y座標 */ #define LIMIT 0.01 /* アライメント精度(mm) */ #define RETRY_N 3 /* 精度が未達の場合の最大繰り返し回数 */ /* 内部で定義した関数 */ static VOID calc_correct_calib_pos( DOUBLE, DOUBLE, DOUBLE, DOUBLE *, DOUBLE *, DOUBLE * ); static INT calibration( DOUBLE, DOUBLE, DOUBLE, char[] ); static INT alignment( char[] ); /* シミュレーションデータ作成用関数 */ static INT simu_vTt( DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE *, DOUBLE * ); /************ メイン関数 ************/ VOID main( VOID ) { // FIEライブラリの使用前に必ずコールする必要があります。 fnFIE_setup(); /* キャリブレーション実行 */ if( F_ERR_NONE == calibration( SFT_X, SFT_Y, ROT_Q, DATA_FILE ) ){ /* アライメント実行 */ alignment( DATA_FILE ); } // 終了処理 fnFIE_teardown(); } /* ファイル書き込み用関数 */ static INT write_data( VOID *data, INT sz, VOID* strm ){ return (INT)fwrite( data, 1, sz, (FILE*)strm ); } /* ファイル読込用関数 */ static INT read_data( VOID *data, INT sz, VOID* strm ){ return (INT)fread( data, 1, sz, (FILE*)strm ); } /* カメラとXYθステージのキャリブレーション */ static INT calibration( DOUBLE shift_x, /* 入力:キャリブレーションステージ平行X移動量 */ DOUBLE shift_y, /* 入力:キャリブレーションステージ平行Y移動量 */ DOUBLE rot_q, /* 入力:キャリブレーションステージ回転θ移動量(rad) */ char *file_name /* 入力:パラメータを保存するファイルの名称 */ ){ INT ch; INT status = -1; INT loop; DPNT_T posit[CHAN_N][4]; DPNT_T correc[CHAN_N][2], center[CHAN_N]; DOUBLE x_cor, y_cor, q_cor; DOUBLE d_tXm[CHAN_N],d_tYm[CHAN_N]; DOUBLE now_x, now_y,now_q; FHANDLE hxyqn; const DOUBLE cam_x[CHAN_N] = { CAM1_X, CAM2_X }; const DOUBLE cam_y[CHAN_N] = { CAM1_Y, CAM2_Y }; const DOUBLE cam_q[CHAN_N] = { CAM1_Q, CAM2_Q }; const DOUBLE cam_res[CHAN_N] = { CAM1_RES, CAM2_RES }; fvstream strm; // データストリーム /* キャリブレーションシステムのオープン */ if( NULL == ( hxyqn = fnFIE_xyqn_open() ) ) goto exit; /* キャリブレーションマーク */ d_tXm[0] = CLB_MARK1_X; d_tYm[0] = CLB_MARK1_Y; d_tXm[1] = CLB_MARK2_X; d_tYm[1] = CLB_MARK2_Y; for( ch=0; ch<CHAN_N; ch++ ){ /* 「カメラ座標系上の基準点」の座標取得 */ now_x = 0.0; now_y = 0.0; now_q = 0.0; simu_vTt( cam_x[ch], cam_y[ch], cam_q[ch], cam_res[ch], now_x, now_y, now_q, d_tXm[ch], d_tYm[ch], &posit[ch][0].x, &posit[ch][0].y ); /* 「カメラ座標系上のシフト参照点」の座標取得 */ now_x = shift_x; now_y = shift_y; now_q = 0.0; simu_vTt( cam_x[ch], cam_y[ch], cam_q[ch], cam_res[ch], now_x, now_y, now_q, d_tXm[ch], d_tYm[ch], &posit[ch][1].x, &posit[ch][1].y ); /* 「カメラ座標系上の+側回転参照点」の座標取得 */ now_x = 0.0; now_y = 0.0; now_q = rot_q / 2.0; simu_vTt( cam_x[ch], cam_y[ch], cam_q[ch], cam_res[ch], now_x, now_y, now_q, d_tXm[ch], d_tYm[ch], &posit[ch][2].x, &posit[ch][2].y ); /* 「カメラ座標系上の−側回転参照点」の座標取得 */ now_x = 0.0; now_y = 0.0; now_q = - rot_q / 2.0; simu_vTt( cam_x[ch], cam_y[ch], cam_q[ch], cam_res[ch], now_x, now_y, now_q, d_tXm[ch], d_tYm[ch], &posit[ch][3].x, &posit[ch][3].y ); } printf( "-- CALIBRATION START --\n\r" ); printf( "OPEN DATA\n\r" ); printf( "MRK1 BASE (%8.3f, %8.3f)(画素,画素)\n\r", posit[0][0].x, posit[0][0].y ); printf( "MRK1 SFT (%8.3f, %8.3f)(画素,画素)\n\r", posit[0][1].x, posit[0][1].y ); printf( "MRK1 ROT+ (%8.3f, %8.3f)(画素,画素)\n\r", posit[0][2].x, posit[0][2].y ); printf( "MRK1 ROT- (%8.3f, %8.3f)(画素,画素)\n\r", posit[0][3].x, posit[0][3].y ); printf( "MRK2 BASE (%8.3f, %8.3f)(画素,画素)\n\r", posit[1][0].x, posit[1][0].y ); printf( "MRK2 SFT (%8.3f, %8.3f)(画素,画素)\n\r", posit[1][1].x, posit[1][1].y ); printf( "MRK2 ROT+ (%8.3f, %8.3f)(画素,画素)\n\r", posit[1][2].x, posit[1][2].y ); printf( "MRK2 ROT- (%8.3f, %8.3f)(画素,画素)\n\r", posit[1][3].x, posit[1][3].y ); /***************************** キャリブレーションのオープン *****************************/ if( F_ERR_NONE != fnFIE_xyqn_calc_table( hxyqn, shift_x, shift_y, rot_q, CHAN_N, (const DPNT_T *)posit ) ) goto exit; /* 補正を繰り返すことでキャリブレーションの精度を高めることが可能です。 */ for( loop = 0; loop < CORREC_COUNT; loop++ ){ /******************************************* 「XYθステージ座標系上の基準点」座標の取得 *******************************************/ fnFIE_xyqn_get_center( hxyqn, center ); /* 誤差が全く無い場合には、ここで求まる center の値 CLB_MARKn_X(Y)と同じ値になります */ printf( "CENTER DATA:%d\n\r", loop + 1 ); printf( "MRK1 CENT (%8.3f, %8.3f)(mm,mm)\n\r", center[0].x, center[0].y ); printf( "MRK2 CENT (%8.3f, %8.3f)(mm,mm)\n\r", center[1].x, center[1].y ); for( ch=0; ch<CHAN_N; ch++ ){ /* 「XYθステージ座標系上の基準点」を中心として+Δθ移動した時の座標取得 */ calc_correct_calib_pos( center[ch].x, center[ch].y, rot_q / 2.0, &x_cor, &y_cor, &q_cor ); now_x = x_cor; now_y = y_cor; now_q = q_cor; simu_vTt( cam_x[ch], cam_y[ch], cam_q[ch], cam_res[ch], now_x, now_y, now_q, d_tXm[ch], d_tYm[ch], &correc[ch][0].x, &correc[ch][0].y ); /* 「XYθステージ座標系上の基準点」を中心として−Δθ移動した時の座標取得 */ calc_correct_calib_pos( center[ch].x, center[ch].y, - rot_q / 2.0, &x_cor, &y_cor, &q_cor ); now_x = x_cor; now_y = y_cor; now_q = q_cor; simu_vTt( cam_x[ch], cam_y[ch], cam_q[ch], cam_res[ch], now_x, now_y, now_q, d_tXm[ch], d_tYm[ch], &correc[ch][1].x, &correc[ch][1].y ); } /******************************************* 「XYθステージ座標系上の基準点」の座標補正 *******************************************/ fnFIE_xyqn_correction( hxyqn, (const DPNT_T *)correc ); } /* 誤差が全く無い場合には、ここで求まる correc はBASEと同じ値である (ステージは動いているが、画面上に写る(計測される)マーク位置は移動しない)*/ printf( "CORREC DATA:%d\n\r", loop + 1 ); printf( "MRK1 CROT+(%8.3f, %8.3f)(画素,画素)\n\r", correc[0][0].x, correc[0][0].y ); printf( "MRK1 CROT-(%8.3f, %8.3f)(画素,画素)\n\r", correc[0][1].x, correc[0][1].y ); printf( "MRK2 CROT+(%8.3f, %8.3f)(画素,画素)\n\r", correc[1][0].x, correc[1][0].y ); printf( "MRK2 CROT-(%8.3f, %8.3f)(画素,画素)\n\r", correc[1][1].x, correc[1][1].y ); // ストリームの準備 strm.read = read_data; strm.write = write_data; strm.stream = NULL; /************************************ パラメータステージをファイルに保管 ************************************/ strm.stream = fopen( file_name, "wb" ); fnFIE_xyqn_save( hxyqn, &strm ); fclose( (FILE*)strm.stream ); strm.stream = NULL; status = 0; exit: fnFIE_free_object( hxyqn ); return( status ); } /* 位置合わせ */ static INT alignment( char * file_name /* 入力:使用するパラメータファイルの名称 */ ){ INT ch; INT status = -1; INT retry, err_cnt; DOUBLE x, y, q; DOUBLE now_x, now_y, now_q; DPNT_T base_on_cam[CHAN_N], mark_on_cam[CHAN_N]; DPNT_T base_on_xyq[CHAN_N], mark_on_xyq[CHAN_N]; DPNT_T residual[CHAN_N]; FHANDLE hxyqn; const DOUBLE cam_x[CHAN_N] = { CAM1_X, CAM2_X }; const DOUBLE cam_y[CHAN_N] = { CAM1_Y, CAM2_Y }; const DOUBLE cam_q[CHAN_N] = { CAM1_Q, CAM2_Q }; const DOUBLE cam_res[CHAN_N] = { CAM1_RES, CAM2_RES }; DOUBLE d_tXtm[CHAN_N], d_tYtm[CHAN_N]; DOUBLE d_tXom[CHAN_N], d_tYom[CHAN_N]; fvstream strm; // データストリーム /* キャリブレーションシステムのオープン */ if( NULL == ( hxyqn = fnFIE_xyqn_open() ) ) goto exit; /* アライメントターゲットマークステージ上の位置 */ d_tXtm[0] = ATGT_MARK1_X; d_tYtm[0] = ATGT_MARK1_Y; d_tXtm[1] = ATGT_MARK2_X; d_tYtm[1] = ATGT_MARK2_Y; /* アライメントオブジェクトマークステージ上の位置 */ d_tXom[0] = AOBJ_MARK1_X; d_tYom[0] = AOBJ_MARK1_Y; d_tXom[1] = AOBJ_MARK2_X; d_tYom[1] = AOBJ_MARK2_Y; // ストリームの準備 strm.read = read_data; strm.write = write_data; strm.stream = NULL; /*************************************************** アライメントデータのオープン ***************************************************/ strm.stream = fopen( file_name, "rb" ); if( F_ERR_NONE != fnFIE_xyqn_load( hxyqn, &strm ) ) goto exit; fclose( (FILE*)strm.stream ); /* ステージ初期位置は原点 */ now_x = 0.0; now_y = 0.0; now_q = 0.0; /* 「カメラ座標系上の到達点(ターゲット位置)」の座標取得 */ for( ch=0; ch<CHAN_N; ch++ ){ simu_vTt( cam_x[ch], cam_y[ch], cam_q[ch], cam_res[ch], now_x, now_y, now_q, d_tXtm[ch], d_tYtm[ch], &base_on_cam[ch].x, &base_on_cam[ch].y ); } /************************************************ 「xyθステージ座標系上の到達点」の座標算出 ************************************************/ fnFIE_xyqn_trans_coord( hxyqn, base_on_cam, base_on_xyq ); for( retry = 0; retry < RETRY_N; retry++ ){ /* 「カメラ座標系上の対象点(オブジェクト位置)」の座標取得 */ for( ch=0; ch<CHAN_N; ch++ ){ simu_vTt( cam_x[ch], cam_y[ch], cam_q[ch], cam_res[ch], now_x, now_y, now_q, d_tXom[ch], d_tYom[ch], &mark_on_cam[ch].x, &mark_on_cam[ch].y ); } /************************************************ 「xyθステージ座標系上の対象点」の座標算出 ************************************************/ fnFIE_xyqn_trans_coord( hxyqn, mark_on_cam, mark_on_xyq ); /* 到達点と対象点の距離を計算 */ /* 現在のステージ上のマーク位置のずれをチェック */ for( ch = 0; ch < CHAN_N; ch++ ){ residual[ch].x = base_on_xyq[ch].x - mark_on_xyq[ch].x; residual[ch].y = base_on_xyq[ch].y - mark_on_xyq[ch].y; /* 状況報告 */ printf( "MRK%2d DIFF(%8.3f, %8.3f)(mm,mm)\n\r", ch, residual[ch].x, residual[ch].y ); } err_cnt = 0; /* マーク間距離の検証 */ for( ch = 0; ch < CHAN_N; ch++ ){ /* アライメントの規格として、マーク間距離を判断 */ if( ( LIMIT<fabs( residual[ch].x ) ) || ( LIMIT<fabs( residual[ch].y )) ){ err_cnt++; break; } } if( err_cnt ){ /**************************** アライメント実行 ****************************/ if( F_ERR_NONE != fnFIE_xyqn_trans_execute( hxyqn, base_on_cam, mark_on_cam, now_x, now_y, now_q, &x, &y, &q ) ) goto exit; printf( "ALIGN:%d\n\r", retry + 1 ); printf( "PRE TPOS (%8.3f, %8.3f, %8.3f)(mm,mm,度)\n\r", now_x, now_y, now_q * PI_DEG / PI_RAD ); printf( "NXT TPOS (%8.3f, %8.3f, %8.3f)(mm,mm,度)\n\r", x, y, q * PI_DEG / PI_RAD ); /* 現在のXYθステージ位置・姿勢を更新する */ now_x = x; now_y = y; now_q = q; }else{ /* アライメントが規格内に収まった */ break; } } //アライメント結果表示(正常終了時にはステージを移動させた回数も) if( err_cnt ) printf( "ALIGNMENT FAILED !!\n\r" ); else printf( "ALIGNMENT SUCCESS !!(%d)\n\r", retry ); status = 0; exit: fnFIE_free_object( hxyqn ); return( status ); } /**************************************************************** fnFIE_xyqn_correction();に使用するステージ位置の計算 下記パラメータ(xc,xc)を中心にステージをqc回転させる時のステージの移動量を求めている。 ****************************************************************/ static VOID calc_correct_calib_pos( DOUBLE xc, /* 入力:XYθステージ座標系上の基準点X座標 */ DOUBLE yc, /* 入力:XYθステージ座標系上の基準点Y座標 */ DOUBLE qc, /* 入力:XYθステージ座標系上の基準点を中心としてqc分回転させる */ DOUBLE *x_cor, /* 出力:XYθステージのX移動量 */ DOUBLE *y_cor, /* 出力:XYθステージのY移動量 */ DOUBLE *q_cor /* 出力:XYθステージのθ移動量 */ ){ DOUBLE ksin, kcos; DPNT_T p_new, p_old; p_old.x = xc; p_old.y = yc; ksin = sin( qc ); kcos = cos( qc ); p_new.x = p_old.x * kcos - p_old.y * ksin; p_new.y = p_old.x * ksin + p_old.y * kcos; *x_cor = p_old.x - p_new.x; *y_cor = p_old.y - p_new.y; *q_cor = qc; } /****************************************** カメラ シミュレーションデータの生成 ステージ上のマーク位置をビデオ座標上の計測位置にする。 ******************************************/ static INT simu_vTt( DOUBLE dX, /* 入力:カメラ取り付け位置X */ DOUBLE dY, /* 入力:カメラ取り付け位置Y */ DOUBLE dQ, /* 入力:カメラ取り付け位置θ(rad) */ DOUBLE dRes, /* 入力:スケール値 1(画素) = dRes(mm) */ DOUBLE dTblX, /* 入力:ステージ位置X */ DOUBLE dTblY, /* 入力:ステージ位置Y */ DOUBLE dTblQ, /* 入力:ステージ位置θ(rad) */ DOUBLE d_tXm, /* 入力:ステージ上のマーク位置X */ DOUBLE d_tYm, /* 入力:ステージ上のマーク位置Y */ DOUBLE *dp_vXm, /* 出力:画面に映った上のマークの計測位置X */ DOUBLE *dp_vYm /* 出力:画面に映った上のマークの計測位置Y */ ){ INT status = -1; DOUBLE rad_q; FMATRIX *mat_res = NULL, *imat_cam = NULL, *mat_tbl = NULL, *mat_wrk = NULL; FMATRIX *mat_vTt = NULL; FVECTOR *vect_v = NULL, *vect_t = NULL; if ( NULL == ( mat_res = fnFIE_mat_aalloc( 3, 3 ) ) ) goto exit; if ( NULL == ( imat_cam = fnFIE_mat_aalloc( 3, 3 ) ) ) goto exit; if ( NULL == ( mat_tbl = fnFIE_mat_aalloc( 3, 3 ) ) ) goto exit; if ( NULL == ( mat_vTt = fnFIE_mat_aalloc( 3, 3 ) ) ) goto exit; if ( NULL == ( mat_wrk = fnFIE_mat_aalloc( 3, 3 ) ) ) goto exit; if ( NULL == ( vect_v = fnFIE_mat_valloc( 3 ) ) ) goto exit; if ( NULL == ( vect_t = fnFIE_mat_valloc( 3 ) ) ) goto exit; //スケール mat_res->m[0][0] = cos(0.0)/dRes; mat_res->m[0][1] = -sin(0.0)/dRes; mat_res->m[0][2] = 0.0; mat_res->m[1][0] = sin(0.0)/dRes; mat_res->m[1][1] = cos(0.0)/dRes; mat_res->m[1][2] = 0.0; mat_res->m[2][0] = 0.0; mat_res->m[2][1] = 0.0; mat_res->m[2][2] = 1.0; //カメラ位置 rad_q = dQ; imat_cam->m[0][0] = cos(rad_q); imat_cam->m[0][1] = -sin(rad_q); imat_cam->m[0][2] = dX; imat_cam->m[1][0] = sin(rad_q); imat_cam->m[1][1] = cos(rad_q); imat_cam->m[1][2] = dY; imat_cam->m[2][0] = 0.0; imat_cam->m[2][1] = 0.0; imat_cam->m[2][2] = 1.0; fnFIE_mat_inverse( imat_cam ); //ステージ rad_q = dTblQ; mat_tbl->m[0][0] = cos(rad_q); mat_tbl->m[0][1] = -sin(rad_q); mat_tbl->m[0][2] = dTblX; mat_tbl->m[1][0] = sin(rad_q); mat_tbl->m[1][1] = cos(rad_q); mat_tbl->m[1][2] = dTblY; mat_tbl->m[2][0] = 0.0; mat_tbl->m[2][1] = 0.0; mat_tbl->m[2][2] = 1.0; //ステージ上の座標->(ワールド座標->)カメラ座標変換行列を生成 fnFIE_mat_mul_aa( mat_res, imat_cam, mat_wrk ); fnFIE_mat_mul_aa( mat_wrk, mat_tbl, mat_vTt ); //座標変換 vect_t->v[0] = d_tXm; vect_t->v[1] = d_tYm; vect_t->v[2] = 1.0; fnFIE_mat_mul_av( mat_vTt, vect_t, vect_v ); *dp_vXm = vect_v->v[0]; *dp_vYm = vect_v->v[1]; status = 0; exit: fnFIE_mat_afree( imat_cam ); fnFIE_mat_afree( mat_res ); fnFIE_mat_afree( mat_tbl ); fnFIE_mat_afree( mat_vTt ); fnFIE_mat_afree( mat_wrk ); fnFIE_mat_vfree( vect_t ); fnFIE_mat_vfree( vect_v ); return( status ); }
関数 | |
FHANDLE FVALGAPI | fnFIE_xyqn_open (VOID) |
キャリブレーションシステムのオープン | |
INT FVALGAPI | fnFIE_xyqn_calc_table (FHANDLE hcalib, DOUBLE delt_x, DOUBLE delt_y, DOUBLE delt_q, INT channels, const DPNT_T *pos_tbl) |
キャリブレーションテーブルの計算 | |
INT FVALGAPI | fnFIE_xyqn_get_channels (FHANDLE hcalib, INT *channels) |
カメラチャネル数の取得 | |
INT FVALGAPI | fnFIE_xyqn_get_center (FHANDLE hcalib, DPNT_T *ch_center) |
補正計算用回転中心の取得 | |
INT FVALGAPI | fnFIE_xyqn_correction (FHANDLE hcalib, const DPNT_T *pos_tbl) |
基準点座標の補正計算 | |
INT FVALGAPI | fnFIE_xyqn_trans_coord (FHANDLE hcalib, const DPNT_T *inp, DPNT_T *out) |
カメラ座標からXYθテーブル座標へ変換 | |
INT FVALGAPI | fnFIE_xyqn_trans_execute (FHANDLE hcalib, const DPNT_T *base_on_cam, const DPNT_T *mark_on_cam, DOUBLE xo, DOUBLE yo, DOUBLE qo, DOUBLE *x, DOUBLE *y, DOUBLE *q) |
位置あわせをする際の位置・姿勢算出 | |
INT FVALGAPI | fnFIE_xyqn_load (FHANDLE hcalib, fvstream *strm) |
キャリブレーションデータのストリーム読み込み | |
INT FVALGAPI | fnFIE_xyqn_save (FHANDLE hcalib, fvstream *strm) |
キャリブレーションデータのストリーム書き込み | |
INT FVALGAPI | fnFIE_xyqn_get_status (FHANDLE hcalib, INT *status) |
キャリブレーション状態の確認 |
FHANDLE FVALGAPI fnFIE_xyqn_open | ( | VOID | ) |
キャリブレーションシステムのオープン
キャリブレーションシステムをオープンします。 本関数でオープンしたオブジェクトは不要になったら fnFIE_free_object() にて解放してください。
INT FVALGAPI fnFIE_xyqn_calc_table | ( | FHANDLE | hcalib, | |
DOUBLE | delt_x, | |||
DOUBLE | delt_y, | |||
DOUBLE | delt_q, | |||
INT | channels, | |||
const DPNT_T * | pos_tbl | |||
) |
キャリブレーションテーブルの計算
与えられたシフト量・回転量及び座標値群から xyθテーブルによる位置合わせに必要なパラメータテーブルを生成します。
最終目標であるアライメントを行うために、ステージとカメラの位置関係を求める必要があります。 その際に、ステージを指定通りに移動させ、『ステージの移動量』と『それに追従して移動するマークの計測位置』 の関係を用いることでステージとカメラの位置関係を計算します。 そのために本ライブラリでは、ステージに対して「XYの平行移動」、「+回転」、「−回転」への指定量の移動が必要になります。
pos_tbl は、テーブルを平行移動(移動量:delt_x , delt_y )、+回転(移動量:delt_q / 2.0 )、−回転(移動量:- delt_q / 2.0 )を行ったときのマーク位置配列で、 次のような配置で、 チャネル( channels )数分だけ配置します。
pos_tbl[0] ch0 の基準マーク位置座標 pos_tbl[1] ch0 の平行移動時マーク位置座標 pos_tbl[2] ch0 の+回転時マーク位置座標 pos_tbl[3] ch0 の−回転時マーク位置座標 pos_tbl[4] ch1 の基準マーク位置座標 pos_tbl[5] ch1 の平行移動時マーク位置座標 pos_tbl[6] ch1 の+回転時マーク位置座標 pos_tbl[7] ch1 の−回転時マーク位置座標 pos_tbl[8] ch2 の基準マーク位置座標 ・・・ ・・・ ・・・ pos_tbl[ ( channels - 2 ) * 4 + 3 ] ch( channels -2) の−回転時マーク位置座標 pos_tbl[ ( channels - 1 ) * 4 ] ch( channels -1) の基準マーク位置座標 pos_tbl[ ( channels - 1 ) * 4 + 1 ] ch( channels -1) の平行移動時マーク位置座標 pos_tbl[ ( channels - 1 ) * 4 + 2 ] ch( channels -1) の+回転時マーク位置座標 pos_tbl[ ( channels - 1 ) * 4 + 3 ] ch( channels -1) の−回転時マーク位置座標
fig.キャリブレーションに使用するデータ(チャネル( channels )数は 2)
[in,out] | hcalib | キャリブレーションシステムのハンドル |
[in] | delt_x | 平行移動キャリブレーション時のX方向シフト量Δx(mm):符号付きの数値で指定 |
[in] | delt_y | 平行移動キャリブレーション次のY方向シフト量Δy(mm):符号付きの数値で指定 |
[in] | delt_q | 回転量Δθ(rad):符号無しの数値で指定 |
[in] | channels | カメラチャネル数(2以上) |
[in] | pos_tbl | キャリブレーションデータテーブル |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_OBJECT | 不正なオブジェクトが渡された | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された | |
F_ERR_NOMEMORY | メモリ不足 | |
F_ERR_CALC_IMPOSSIBLE | 与えられた座標で計算不能 | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
INT FVALGAPI fnFIE_xyqn_get_channels | ( | FHANDLE | hcalib, | |
INT * | channels | |||
) |
カメラチャネル数の取得
fnFIE_xyqn_calc_table() 実行時に指定されたカメラチャネル数を取得します。
[in] | hcalib | キャリブレーションシステムのハンドル |
[out] | channels | カメラチャネル数 |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_OBJECT | 不正なオブジェクトが渡された | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された
| |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
INT FVALGAPI fnFIE_xyqn_get_center | ( | FHANDLE | hcalib, | |
DPNT_T * | ch_center | |||
) |
補正計算用回転中心の取得
xyθテーブル座標系上の各々の基準点座標を返します。
[in] | hcalib | キャリブレーションシステムのハンドル |
[out] | ch_center | 各チャネルの基準点座標配列 fnFIE_xyqn_calc_table() 実行時に指定したチャネル数分の領域が必要です。 |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_OBJECT | 不正なオブジェクトが渡された | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された
| |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
INT FVALGAPI fnFIE_xyqn_correction | ( | FHANDLE | hcalib, | |
const DPNT_T * | pos_tbl | |||
) |
基準点座標の補正計算
fnFIE_xyqn_calc_table() で計算された基準点座標を補正します。
弊社では、本関数の使用により、一般的に考えられるキャリブレーション手法に一工夫加えることで補正を行い、より精度の良いキャリブレーションを実現しております。
なお、補正計算処理には適切なデータを入力する必要がありますので、次の手順で使用してください。
fig.基準点座標補正の手順
で表され、実際に回転補正を行うための rev_q には fnFIE_xyqn_calc_table()で使用した回転量である delt_q/2.0, -delt_q/2.0 を指定してください。 補正移動のイメージとしては、キャリブレーション時に使用したマークに対してθ回転を行い、その回転によって移動した量をXY移動で元に戻すような移動です。 キャリブレーション時の精度が良い場合には、±θ補正移動をした後のマークの位置が基準時のマーク位置の近くへと戻ります。
fig.キャリブレーション補正時のステージ及び、画像上のマーク移動
pos_tbl[0] ch0 の+回転補正時マーク位置座標 pos_tbl[1] ch0 の−回転補正時マーク位置座標 pos_tbl[2] ch1 の+回転補正時マーク位置座標 pos_tbl[3] ch1 の−回転補正時マーク位置座標 pos_tbl[4] ch2 の+回転補正時マーク位置座標 ・・・ ・・・ ・・・ pos_tbl[ ( channels - 2 ) * 2 + 1 ] ch( channels -2) の−回転補正時マーク位置座標 pos_tbl[ ( channels - 1 ) * 2 + 0 ] ch( channels -1) の+回転補正時マーク位置座標 pos_tbl[ ( channels - 1 ) * 2 + 1 ] ch( channels -1) の−回転補正時マーク位置座標
[in,out] | hcalib | キャリブレーションシステムのハンドル |
[in] | pos_tbl | 補正計算用座標値群を格納したテーブル |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_OBJECT | 不正なオブジェクトが渡された | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された
| |
F_ERR_NOMEMORY | メモリ不足 | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
カメラ座標からXYθテーブル座標へ変換
カメラ座標系上の座標値をxyθテーブル座標系上の座標値に変換します。
inp と out はカメラ座標の配列です。 要素数は共に fnFIE_xyqn_calc_table() 実行時に指定したチャネル数となります。
[in] | hcalib | キャリブレーションシステムのハンドル |
[in] | inp | 各カメラ座標配列(カメラ座標系) |
[out] | out | 各カメラ座標配列(XYθ座標系) |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_OBJECT | 不正なオブジェクトが渡された | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された
| |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
INT FVALGAPI fnFIE_xyqn_trans_execute | ( | FHANDLE | hcalib, | |
const DPNT_T * | base_on_cam, | |||
const DPNT_T * | mark_on_cam, | |||
DOUBLE | xo, | |||
DOUBLE | yo, | |||
DOUBLE | qo, | |||
DOUBLE * | x, | |||
DOUBLE * | y, | |||
DOUBLE * | q | |||
) |
位置あわせをする際の位置・姿勢算出
与えられた座標値( base_on_cam[] , mark_on_cam[] )を利用してxyθテーブルの移動量を決定します。 base_on_cam と mark_on_cam は座標の配列です。 要素数は共に fnFIE_xyqn_calc_table() 実行時に指定したチャネル数となります。
[in] | hcalib | キャリブレーションシステムのハンドル |
[in] | base_on_cam | カメラ座標系上のnチャネル分の基準座標配列 |
[in] | mark_on_cam | カメラ座標系上のnチャネル分のマーク座標配列 |
[in] | xo | テーブル現在位置X座標(mm) |
[in] | yo | テーブル現在位置Y座標(mm) |
[in] | qo | テーブル現在位置θ座標(rad) |
[out] | x | テーブル移動後X座標(mm) |
[out] | y | テーブル移動後Y座標(mm) |
[out] | q | テーブル移動後θ座標(rad) |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_OBJECT | 不正なオブジェクトが渡された | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された
| |
F_ERR_NOMEMORY | メモリ不足 | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
INT FVALGAPI fnFIE_xyqn_load | ( | FHANDLE | hcalib, | |
fvstream * | strm | |||
) |
キャリブレーションデータのストリーム読み込み
キャリブレーションデータを、指定のデータストリームから読み込みます。
[in] | hcalib | キャリブレーションシステムのハンドル |
[out] | strm | データストリーム |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_OBJECT | 不正なオブジェクトが渡された | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
INT FVALGAPI fnFIE_xyqn_save | ( | FHANDLE | hcalib, | |
fvstream * | strm | |||
) |
キャリブレーションデータのストリーム書き込み
キャリブレーションデータを、指定のデータストリームに書き込みます。
[in] | hcalib | キャリブレーションシステムのハンドル |
[in] | strm | データストリーム |
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_OBJECT | 不正なオブジェクトが渡された | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された
| |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |
INT FVALGAPI fnFIE_xyqn_get_status | ( | FHANDLE | hcalib, | |
INT * | status | |||
) |
キャリブレーション状態の確認
オープン後、キャリブレーションデータが作成されているかどうか、 つまり、 fnFIE_xyqn_calc_table() もしくは fnFIE_xyqn_load() が実行されたかを取得します。
[in] | hcalib | キャリブレーションシステムのハンドル |
[out] | status | キャリブレーションデータの状態
|
F_ERR_NONE | 正常終了 | |
F_ERR_INVALID_OBJECT | 不正なオブジェクトが渡された | |
F_ERR_INVALID_PARAM | 不正なパラメータが渡された | |
F_ERR_NO_LICENCE | ライセンスエラー、または未初期化エラー |