void apply_planar_homography(float *input, int width, int height, float **H, float bg, int order, float *out, float x0, float y0, int nwidth, int nheight) { if (DEBUG) printf("width: %d height: %d ------> nwidth: %d nheight: %d \n", width, height, nwidth, nheight); /// We compute inverse transformation if (DEBUG) { printf("Matrix: \n"); print_float_matrix(H,3,3); } float **V = allocate_float_matrix(3,3); luinv(H, V, 3); if (DEBUG) { printf("Inverse Matrix: \n"); print_float_matrix(V,3,3); } float *coeffs; float *ref; float cx[12],cy[12],ak[13]; if (order!=0 && order!=1 && order!=-3 && order!=3 && order!=5 && order!=7 && order!=9 && order!=11) { printf("unrecognized interpolation order.\n"); exit(-1); } if (order>=3) { coeffs = new float[width*height]; finvspline(input,order,coeffs,width,height); ref = coeffs; if (order>3) init_splinen(ak,order); } else { coeffs = NULL; ref = input; } int xi,yi; float xp,yp; float res; int n1,n2; float p=-0.5; /// For each point in new image we compute its anti image and interpolate the new value for(int i=0; i < nwidth; i++) for(int j=0; j < nheight; j++) { float vec[3]; vec[0] = (float) i + x0; vec[1] = (float) j + y0; vec[2] = 1.0f; float vres[3]; float_vector_matrix_product(V, vec ,vres , 3); if (vres[2] != 0.0f) { vres[0] /= vres[2]; vres[1] /= vres[2]; xp = (float) vres[0]; yp = (float) vres[1]; if (order == 0) { xi = (int)floor((double)xp); yi = (int)floor((double)yp); if (xi<0 || xi>=width || yi<0 || yi>=height) res = bg; else res = input[yi*width+xi]; } else { if (xp<0. || xp>=(float)width || yp<0. || yp>=(float)height) res=bg; else { //xp -= 0.5; yp -= 0.5; int xi = (int)floor((double)xp); int yi = (int)floor((double)yp); float ux = xp-(float)xi; float uy = yp-(float)yi; switch (order) { case 1: /* first order interpolation (bilinear) */ n2 = 1; cx[0]=ux; cx[1]=1.f-ux; cy[0]=uy; cy[1]=1.f-uy; break; case -3: /* third order interpolation (bicubic Keys' function) */ n2 = 2; keys(cx,ux,p); keys(cy,uy,p); break; case 3: /* spline of order 3 */ n2 = 2; spline3(cx,ux); spline3(cy,uy); break; default: /* spline of order >3 */ n2 = (1+order)/2; splinen(cx,ux,ak,order); splinen(cy,uy,ak,order); break; } res = 0.; n1 = 1-n2; if (xi+n1>=0 && xi+n2<width && yi+n1>=0 && yi+n2<height) { int adr = yi*width+xi; for (int dy=n1;dy<=n2;dy++) for (int dx=n1;dx<=n2;dx++) res += cy[n2-dy]*cx[n2-dx]*ref[adr+width*dy+dx]; } else for (int dy=n1;dy<=n2;dy++) for (int dx=n1;dx<=n2;dx++) res += cy[n2-dy]*cx[n2-dx]*v(ref,xi+dx,yi+dy,bg,width,height); } } out[j*nwidth+i] = res; } } }
void Odometry::compute() { mutex.wait(); //read the encoders (deg) ienc->getEncoder(0,&encA); ienc->getEncoder(1,&encB); ienc->getEncoder(2,&encC); //read the speeds (deg/s) ienc->getEncoderSpeed(0,&velA); ienc->getEncoderSpeed(1,&velB); ienc->getEncoderSpeed(2,&velC); //remove the offset and convert in radians enc[0]= -(encA - encA_offset) * 0.0174532925; enc[1]= -(encB - encB_offset) * 0.0174532925; enc[2]= -(encC - encC_offset) * 0.0174532925; //estimate the speeds iCub::ctrl::AWPolyElement el; el.data=enc; el.time=Time::now(); encv= encvel_estimator->estimate(el); // ------------------------------------------------------------------------------------- // The following formulas are adapted from: // "A New Odometry System to reduce asymmetric Errors for Omnidirectional Mobile Robots" // ------------------------------------------------------------------------------------- //compute the orientation. odom_theta is expressed in radians odom_theta = geom_r*(enc[0]+enc[1]+enc[2])/(3*geom_L); //build the kinematics matrix yarp::sig::Matrix kin; kin.resize(3,3); kin.zero(); kin(0,0) = -sqrt(3.0)/2.0; kin(0,1) = 0.5; kin(0,2) = geom_L; kin(1,0) = sqrt(3.0)/2.0; kin(1,1) = 0.5; kin(1,2) = geom_L; kin(2,0) = 0; kin(2,1) = -1.0; kin(2,2) = geom_L; kin = kin/geom_r; yarp::sig::Matrix ikin = luinv(kin); //build the rotation matrix yarp::sig::Matrix m1; m1.resize(3,3); m1.zero(); m1(0,0) = cos (odom_theta); m1(0,1) = -sin (odom_theta); m1(1,0) = sin (odom_theta); m1(1,1) = cos (odom_theta); m1(2,2) = 1; yarp::sig::Matrix m2; m2.resize(3,3); m2.zero(); m2(0,0) = cos (0.0); m2(0,1) = -sin (0.0); m2(1,0) = sin (0.0); m2(1,1) = cos (0.0); m2(2,2) = 1; yarp::sig::Vector odom_cart_vels; //velocities expressed in the world reference frame yarp::sig::Vector ikart_cart_vels; //velocities expressed in the ikart reference frame odom_cart_vels = m1*ikin*encv; ikart_cart_vels = m2*ikin*encv; ikart_vel_x = ikart_cart_vels[1]; ikart_vel_y = ikart_cart_vels[0]; ikart_vel_theta = ikart_cart_vels[2]; ikart_vel_lin = sqrt(odom_vel_x*odom_vel_x + odom_vel_y*odom_vel_y); odom_vel_x = odom_cart_vels[1]; odom_vel_y = odom_cart_vels[0]; odom_vel_theta = odom_cart_vels[2]; //these are not currently used if (ikart_vel_lin<0.001) { odom_vel_heading = 0; ikart_vel_heading = 0; } else { odom_vel_heading = atan2(odom_vel_x,odom_vel_y)*57.2957795; ikart_vel_heading = atan2(ikart_vel_x,ikart_vel_y)*57.2957795; } //the integration step odom_x=odom_x + (odom_vel_x * period/1000.0); odom_y=odom_y + (odom_vel_y * period/1000.0); //compute traveled distance (odometer) traveled_distance = traveled_distance + fabs(ikart_vel_lin * period/1000.0); traveled_angle = traveled_angle + fabs(ikart_vel_theta * period/1000.0); /* [ -(3^(1/2)*r)/3, (3^(1/2)*r)/3, 0] [ r/3, r/3, -(2*r)/3] [ r/(3*L), r/(3*L), r/(3*L)]*/ /*odom_x = -1.73205080*geom_r/3 * encA + 1.73205080*geom_r/3 * encB; odom_y = geom_r/3 * encA + geom_r/3 * encB - (2*geom_r)/3 * encC;*/ /* odom_x = geom_r/(3* 0.86602)* ( (co3p-co3m)*encA + (-cos(odom_theta)-co3p)*encB + (cos(odom_theta)+co3m)*encC ); odom_y = geom_r/(3* 0.86602)* ( (si3m+si3p)*encA + (-sin(odom_theta)-si3p)*encB + (sin(odom_theta)-si3m)*encC ); */ //convert from radians back to degrees odom_theta *= 57.2957795; ikart_vel_theta *= 57.2957795; odom_vel_theta *= 57.2957795; traveled_angle *= 57.2957795; mutex.post(); timeStamp.update(); if (port_odometry.getOutputCount()>0) { port_odometry.setEnvelope(timeStamp); Bottle &b=port_odometry.prepare(); b.clear(); b.addDouble(odom_x); b.addDouble(odom_y); b.addDouble(odom_theta); b.addDouble(odom_vel_x); b.addDouble(odom_vel_y); b.addDouble(odom_vel_theta); port_odometry.write(); } if (port_odometer.getOutputCount()>0) { port_odometer.setEnvelope(timeStamp); Bottle &t=port_odometer.prepare(); t.clear(); t.addDouble(traveled_distance); t.addDouble(traveled_angle); port_odometer.write(); } if (port_ikart_vels.getOutputCount()>0) { port_ikart_vels.setEnvelope(timeStamp); Bottle &v=port_ikart_vels.prepare(); v.clear(); v.addDouble(ikart_vel_x); v.addDouble(ikart_vel_y); v.addDouble(ikart_vel_theta); port_ikart_vels.write(); } }