code: public static void errorsHomographySymm(List<AssociatedPair> observations ,
  											DMatrixRMaj H ,
  											@Nullable DMatrixRMaj H_inv ,
  											GrowQueue_F64 storage )
  	{
  		storage.reset();
  		if( H_inv == null )
  			H_inv = new DMatrixRMaj(3,3);
  		CommonOps_DDRM.invert(H,H_inv);
  
  		Point3D_F64 tmp = new Point3D_F64();
  
  		for (int i = 0; i < observations.size(); i++) {
  			AssociatedPair p = observations.get(i);
  
  			double dx,dy;
  			double error = 0;
  
  			GeometryMath_F64.mult(H,p.p1,tmp);
  			if( Math.abs(tmp.z) <= UtilEjml.EPS )
  				continue;
  			dx = p.p2.x - tmp.x/tmp.z;
  			dy = p.p2.y - tmp.y/tmp.z;
  			error += dx*dx + dy*dy;
  
  			GeometryMath_F64.mult(H_inv,p.p2,tmp);
  			if( Math.abs(tmp.z) <= UtilEjml.EPS )
  				continue;
  			dx = p.p1.x - tmp.x/tmp.z;
  			dy = p.p1.y - tmp.y/tmp.z;
  			error += dx*dx + dy*dy;
  
  			storage.add(error);
  		}
  	}
docs: <p>Computes symmetric Euclidean error for each observation and puts it into the storage. If the homography
  projects the point into the plane at infinity (z=0) then it is skipped</p>
  
  error[i] = (H*x1 - x2')**2 + (inv(H)*x2 - x1')**2<br>
  
  @param observations (Input) observations
  @param H (Input) Homography
  @param H_inv (Input) Inverse of homography. if null it will be computed internally
  @param storage (Output) storage for found errors