00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009 #include "mvl_psi.h"
00010
00011 #include <vcl_cmath.h>
00012 #include <vcl_cassert.h>
00013 #include <vcl_cstdlib.h>
00014
00015 #if 0
00016 # define mvl_psi_temp_name(l, r) U l = r
00017 #else
00018 # define mvl_psi_temp_name(l, r) U const &l = r
00019 #endif
00020
00021
00022
00023
00024 template <mvl_typename U>
00025 U mvl_psi_constraint(U const abcde[5])
00026 {
00027
00028
00029
00030 mvl_psi_temp_name(a, abcde[0]);
00031 mvl_psi_temp_name(b, abcde[1]);
00032 mvl_psi_temp_name(c, abcde[2]);
00033 mvl_psi_temp_name(d, abcde[3]);
00034 mvl_psi_temp_name(e, abcde[4]);
00035
00036 return a*b*d - a*b*e + a*c*e - a*d*e - b*c*d + b*d*e;
00037 }
00038
00039
00040 template <mvl_typename U>
00041 void mvl_psi_constraint_restrict(U const p[5],
00042 U const q[5],
00043 U coeffs[4])
00044 {
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 U values[4]; {
00056 values[0] = mvl_psi_constraint(p);
00057 values[1] = mvl_psi_constraint(q);
00058 U tmp[5];
00059 for (int i=0; i<5; ++i) tmp[i] = p[i] + q[i];
00060 values[2] = mvl_psi_constraint(tmp);
00061 for (int i=0; i<5; ++i) tmp[i] = p[i] - q[i];
00062 values[3] = mvl_psi_constraint(tmp);
00063 }
00064
00065
00066 coeffs[0] = 2 * values[0];
00067 coeffs[1] = - 2 * values[1] + values[2] - values[3];
00068 coeffs[2] = -2 * values[0] + values[2] + values[3];
00069 coeffs[3] = 2 * values[1];
00070 }
00071
00072 template <mvl_typename U>
00073 void mvl_psi_apply(U const XYZT[4], U abcde[5])
00074 {
00075 mvl_psi_temp_name(X, XYZT[0]);
00076 mvl_psi_temp_name(Y, XYZT[1]);
00077 mvl_psi_temp_name(Z, XYZT[2]);
00078 mvl_psi_temp_name(W, XYZT[3]);
00079
00080 abcde[0] = X*Y - X*W;
00081 abcde[1] = X*Z - X*W;
00082 abcde[2] = Y*Z - X*W;
00083 abcde[3] = Y*W - X*W;
00084 abcde[4] = Z*W - X*W;
00085 }
00086
00087 template <mvl_typename U>
00088 void mvl_psi_invert_direct(U const abcde[5], U XYZT[4], int which)
00089 {
00090 mvl_psi_temp_name(a, abcde[0]);
00091 mvl_psi_temp_name(b, abcde[1]);
00092 mvl_psi_temp_name(c, abcde[2]);
00093 mvl_psi_temp_name(d, abcde[3]);
00094 mvl_psi_temp_name(e, abcde[4]);
00095
00096 switch (which) {
00097 case 0:
00098
00099
00100
00101
00102
00103
00104
00105 XYZT[0] = 1;
00106 XYZT[1] = (c-d)/(b );
00107 XYZT[2] = (c-e)/(a );
00108 XYZT[3] = (d-e)/(a-b);
00109 break;
00110
00111 case 1:
00112
00113
00114
00115
00116
00117
00118
00119 XYZT[0] = (b )/(c-d);
00120 XYZT[1] = 1;
00121 XYZT[2] = (b-e)/(a-d);
00122 XYZT[3] = ( -e)/(a-c);
00123 break;
00124
00125 case 2:
00126
00127
00128
00129
00130
00131
00132
00133 XYZT[0] = (a )/(c-e);
00134 XYZT[1] = (a-d)/(b-e);
00135 XYZT[2] = 1;
00136 XYZT[3] = ( -d)/(b-c);
00137 break;
00138
00139 case 3:
00140
00141
00142
00143
00144
00145
00146
00147 XYZT[0] = (a-b)/(d-e);
00148 XYZT[1] = (a-c)/( -e);
00149 XYZT[2] = (b-c)/( -d);
00150 XYZT[3] = 1;
00151 break;
00152
00153 default:
00154 vcl_abort();
00155 };
00156 }
00157
00158 template <mvl_typename U>
00159 void mvl_psi_invert_direct(U const abcde[5], U XYZT[4])
00160 {
00161 mvl_psi_temp_name(a, abcde[0]);
00162 mvl_psi_temp_name(b, abcde[1]);
00163 mvl_psi_temp_name(c, abcde[2]);
00164 mvl_psi_temp_name(d, abcde[3]);
00165 mvl_psi_temp_name(e, abcde[4]);
00166
00167
00168
00169
00170
00171
00172
00173 bool cd_b = vcl_abs(c - d) <= vcl_abs(b);
00174 bool ce_a = vcl_abs(c - e) <= vcl_abs(a);
00175 bool de_ab = vcl_abs(d - e) <= vcl_abs(a - b);
00176 bool be_ad = vcl_abs(b - e) <= vcl_abs(a - d);
00177 bool ac_e = vcl_abs(a - c) <= vcl_abs(e);
00178 bool bc_d = vcl_abs(b - c) <= vcl_abs(d);
00179
00180 if (false)
00181 { }
00182
00183 else if (cd_b && ce_a && de_ab)
00184 mvl_psi_invert_direct(abcde, XYZT, 0);
00185
00186 else if (!cd_b && be_ad && !ac_e)
00187 mvl_psi_invert_direct(abcde, XYZT, 1);
00188
00189 else if (!ce_a && !be_ad && !bc_d)
00190 mvl_psi_invert_direct(abcde, XYZT, 2);
00191
00192 else if (!de_ab && ac_e && bc_d)
00193 mvl_psi_invert_direct(abcde, XYZT, 3);
00194
00195 else
00196 assert(false);
00197 }
00198
00199 #include <vnl/vnl_matrix_ref.h>
00200 #include <vnl/algo/vnl_svd_economy.h>
00201
00202 template <mvl_typename U>
00203 void mvl_psi_invert_design(U const abcde[5], U XYZT[4])
00204 {
00205 mvl_psi_temp_name(a, abcde[0]);
00206 mvl_psi_temp_name(b, abcde[1]);
00207 mvl_psi_temp_name(c, abcde[2]);
00208 mvl_psi_temp_name(d, abcde[3]);
00209 mvl_psi_temp_name(e, abcde[4]);
00210
00211 U design[6*4] = {
00212 e-d, 0 , 0 , a-b,
00213 e-c, 0 , a , 0 ,
00214 d-c, b , 0 , 0 ,
00215 0 , e , 0 , a-c,
00216 0 , e-b, a-d, 0 ,
00217 0 , 0 , d , b-c
00218 };
00219
00220 vnl_svd_economy<U> svd(vnl_matrix_ref<U>(6, 4, design));
00221 svd.nullvector().copy_out(XYZT);
00222 }
00223
00224 template <mvl_typename U>
00225 void mvl_psi_invert(U const abcde[5], U XYZT[4])
00226 {
00227 #if 1 // capes_at_robots - mvl_psi_invert_direct fails occasionally : I think it is missing a case.
00228 mvl_psi_invert_design(abcde, XYZT);
00229 #else
00230 mvl_psi_invert_direct(abcde, XYZT);
00231 #endif
00232 }
00233
00234
00235
00236 #define instantiate(U) \
00237 template U mvl_psi_constraint(U const [5]); \
00238 template void mvl_psi_constraint_restrict(U const [5], U const [5], U [4]); \
00239 template void mvl_psi_apply(U const [4], U [5]); \
00240 template void mvl_psi_invert_direct(U const [5], U [4], int); \
00241 template void mvl_psi_invert_direct(U const [5], U [4]); \
00242 template void mvl_psi_invert_design(U const [5], U [4]); \
00243 template void mvl_psi_invert(U const [5], U [4])
00244
00245 instantiate(double);
00246
00247 #undef instantiate