예제 #1
0
const CPoint3DWORLD CLandmark::_getOptimizedLandmarkSTEREOUV( const UIDFrame& p_uFrame, const CPoint3DWORLD& p_vecInitialGuess )
{
    //ds initial values
    Eigen::Matrix4d matH( Eigen::Matrix4d::Zero( ) );
    Eigen::Vector4d vecB( Eigen::Vector4d::Zero( ) );
    CPoint3DHomogenized vecX( CMiniVisionToolbox::getHomogeneous( p_vecInitialGuess ) );
    //Eigen::Matrix2d matOmega( Eigen::Matrix2d::Identity( ) );
    double dErrorSquaredTotalPixelsPREVIOUS = 0.0;

    //ds iterations (break-out if convergence reached early)
    for( uint32_t uIteration = 0; uIteration < CLandmark::uCapIterations; ++uIteration )
    {
        //ds counts
        double dErrorSquaredTotalPixels = 0.0;
        uint32_t uInliers               = 0;

        //ds initialize setup
        matH.setZero( );
        vecB.setZero( );

        //ds do calibration over all recorded values
        for( const CMeasurementLandmark* pMeasurement: m_vecMeasurements )
        {
            //ds apply the projection to the transformed point
            const Eigen::Vector3d vecABCLEFT  = pMeasurement->matProjectionWORLDtoLEFT*vecX;
            const Eigen::Vector3d vecABCRIGHT = pMeasurement->matProjectionWORLDtoRIGHT*vecX;

            //ds buffer c value
            const double dCLEFT  = vecABCLEFT.z( );
            const double dCRIGHT = vecABCRIGHT.z( );

            //ds compute error
            const Eigen::Vector2d vecUVLEFT( vecABCLEFT.x( )/dCLEFT, vecABCLEFT.y( )/dCLEFT );
            const Eigen::Vector2d vecUVRIGHT( vecABCRIGHT.x( )/dCRIGHT, vecABCRIGHT.y( )/dCRIGHT );
            const Eigen::Vector4d vecError( vecUVLEFT.x( )-pMeasurement->ptUVLEFT.x,
                                            vecUVLEFT.y( )-pMeasurement->ptUVLEFT.y,
                                            vecUVRIGHT.x( )-pMeasurement->ptUVRIGHT.x,
                                            vecUVRIGHT.y( )-pMeasurement->ptUVRIGHT.y );

            //ds current error
            const double dErrorSquaredPixels = vecError.transpose( )*vecError;

            //std::printf( "[%06lu][%04u] error: %4.2f %4.2f %4.2f %4.2f (squared: %4.2f)\n", uID, uIteration, vecError(0), vecError(1), vecError(2), vecError(3) , dErrorSquaredPixels );

            //ds check if outlier
            double dWeight = 1.0;
            if( dKernelMaximumErrorSquaredPixels < dErrorSquaredPixels )
            {
                dWeight = dKernelMaximumErrorSquaredPixels/dErrorSquaredPixels;
            }
            else
            {
                ++uInliers;
            }
            dErrorSquaredTotalPixels += dWeight*dErrorSquaredPixels;

            //ds jacobian of the homogeneous division
            Eigen::Matrix< double, 2, 3 > matJacobianLEFT;
            matJacobianLEFT << 1/dCLEFT,          0, -vecABCLEFT.x( )/( dCLEFT*dCLEFT ),
                                      0,   1/dCLEFT, -vecABCLEFT.y( )/( dCLEFT*dCLEFT );

            Eigen::Matrix< double, 2, 3 > matJacobianRIGHT;
            matJacobianRIGHT << 1/dCRIGHT,           0, -vecABCRIGHT.x( )/( dCRIGHT*dCRIGHT ),
                                        0,   1/dCRIGHT, -vecABCRIGHT.y( )/( dCRIGHT*dCRIGHT );

            //ds final jacobian
            Eigen::Matrix< double, 4, 4 > matJacobian;
            matJacobian.setZero( );
            matJacobian.block< 2,4 >(0,0) = matJacobianLEFT*pMeasurement->matProjectionWORLDtoLEFT;
            matJacobian.block< 2,4 >(2,0) = matJacobianRIGHT*pMeasurement->matProjectionWORLDtoRIGHT;

            //ds precompute transposed
            const Eigen::Matrix< double, 4, 4 > matJacobianTransposed( matJacobian.transpose( ) );

            //ds accumulate
            matH += dWeight*matJacobianTransposed*matJacobian;
            vecB += dWeight*matJacobianTransposed*vecError;
        }

        //ds solve constrained system (since dx(3) = 0.0) and update x solution
        vecX.block< 3,1 >(0,0) += matH.block< 4, 3 >(0,0).householderQr( ).solve( -vecB );

        //std::printf( "[%06lu][%04u]: %6.2f %6.2f %6.2f %6.2f (delta 2norm: %f inliers: %u)\n", uID, uIteration, vecX.x( ), vecX.y( ), vecX.z( ), vecX(3), vecDeltaX.squaredNorm( ), uInliers );

        //std::fprintf( m_pFilePosition, "%04lu %06lu %03u %03lu %03u %6.2f\n", p_uFrame, uID, uIteration, m_vecMeasurements.size( ), uInliers, dRSSCurrent );

        //ds check if we have converged
        if( CLandmark::dConvergenceDelta > std::fabs( dErrorSquaredTotalPixelsPREVIOUS-dErrorSquaredTotalPixels ) )
        {
            //ds compute average error
            const double dErrorSquaredAveragePixels = dErrorSquaredTotalPixels/m_vecMeasurements.size( );

            //ds if acceptable inlier/outlier ratio
            if( CLandmark::dMinimumRatioInliersToOutliers < static_cast< double >( uInliers )/m_vecMeasurements.size( ) )
            {
                //ds success
                ++uOptimizationsSuccessful;

                //ds update average
                dCurrentAverageSquaredError = dErrorSquaredAveragePixels;

                //ds check if optimal
                if( dMaximumErrorSquaredAveragePixels > dErrorSquaredAveragePixels )
                {
                    bIsOptimal = true;
                }

                //std::printf( "<CLandmark>(_getOptimizedLandmarkSTEREOUV) [%06lu] converged (%2u) in %3u iterations to (%6.2f %6.2f %6.2f) from (%6.2f %6.2f %6.2f) ARSS: %6.2f (inliers: %u/%lu)\n",
                //             uID, uOptimizationsSuccessful, uIteration, vecX(0), vecX(1), vecX(2), p_vecInitialGuess(0), p_vecInitialGuess(1), p_vecInitialGuess(2), dCurrentAverageSquaredError, uInliers, m_vecMeasurements.size( ) );

                //ds update the estimate
                return vecX.block< 3,1 >(0,0);
            }
            else
            {
                ++uOptimizationsFailed;
                //std::printf( "<CLandmark>(_getOptimizedLandmarkSTEREOUV) landmark [%06lu] optimization failed - solution unacceptable (average error: %f, inliers: %u, iteration: %u)\n", uID, dErrorSquaredAveragePixels, uInliers, uIteration );

                //ds if still here the calibration did not converge - keep the initial estimate
                return p_vecInitialGuess;
            }
        }
        else
        {
            //ds update error
            dErrorSquaredTotalPixelsPREVIOUS = dErrorSquaredTotalPixels;
        }
    }

    ++uOptimizationsFailed;
    //std::printf( "<CLandmark>(_getOptimizedLandmarkSTEREOUV) landmark [%06lu] optimization failed - system did not converge\n", uID );

    //ds if still here the calibration did not converge - keep the initial estimate
    return p_vecInitialGuess;
}
예제 #2
0
  void Arnoldi<SCAL>::Calc (int numval, Array<Complex> & lam, int numev, 
                            Array<shared_ptr<BaseVector>> & hevecs, 
                            const BaseMatrix * pre) const
  { 
    static Timer t("arnoldi");    
    static Timer t2("arnoldi - orthogonalize");    
    static Timer t3("arnoldi - compute large vectors");

    RegionTimer reg(t);

    auto hv  = a.CreateVector();
    auto hv2 = a.CreateVector();
    auto hva = a.CreateVector();
    auto hvm = a.CreateVector();
   
    int n = hv.FV<SCAL>().Size();    
    int m = min2 (numval, n);


    Matrix<SCAL> matH(m);
    Array<shared_ptr<BaseVector>> abv(m);
    for (int i = 0; i < m; i++)
      abv[i] = a.CreateVector();

    auto mat_shift = a.CreateMatrix();
    mat_shift->AsVector() = a.AsVector() - shift*b.AsVector();  
    shared_ptr<BaseMatrix> inv;
    if (!pre)
      inv = mat_shift->InverseMatrix (freedofs);
    else
      {
        auto itso = make_shared<GMRESSolver<double>> (*mat_shift, *pre);
        itso->SetPrintRates(1);
        itso->SetMaxSteps(2000);
        inv = itso;
      }

    hv.SetRandom();
    hv.SetParallelStatus (CUMULATED);
    FlatVector<SCAL> fv = hv.FV<SCAL>();
    if (freedofs)
      for (int i = 0; i < hv.Size(); i++)
	if (! (*freedofs)[i] ) fv(i) = 0;

    t2.Start();
    // matV = SCAL(0.0);   why ?
    matH = SCAL(0.0);

    *hv2 = *hv;
    SCAL len = sqrt (S_InnerProduct<SCAL> (*hv, *hv2)); // parallel
    *hv /= len;
    
    for (int i = 0; i < m; i++)
      {
	cout << IM(1) << "\ri = " << i << "/" << m << flush;
	/*
	for (int j = 0; j < n; j++)
	  matV(i,j) = hv.FV<SCAL>()(j);
	*/
	*abv[i] = *hv;

	*hva = b * *hv;
	*hvm = *inv * *hva;

	for (int j = 0; j <= i; j++)
	  {
            /*
            SCAL sum = 0.0;
	    for (int k = 0; k < n; k++)
	      sum += hvm.FV<SCAL>()(k) * matV(j,k);
	    matH(j,i) = sum;
	    for (int k = 0; k < n; k++)
	      hvm.FV<SCAL>()(k) -= sum * matV(j,k);
            */
            /*
            SCAL sum = 0.0;
            FlatVector<SCAL> abvj = abv[j] -> FV<SCAL>();
            FlatVector<SCAL> fv_hvm = hvm.FV<SCAL>();
	    for (int k = 0; k < n; k++)
	      sum += fv_hvm(k) * abvj(k);
	    matH(j,i) = sum;
	    for (int k = 0; k < n; k++)
	      fv_hvm(k) -= sum * abvj(k);
            */

	    matH(j,i) = S_InnerProduct<SCAL> (*hvm, *abv[j]);
	    *hvm -= matH(j,i) * *abv[j];
	  }
		
	*hv = *hvm;
	*hv2 = *hv;
	SCAL len = sqrt (S_InnerProduct<SCAL> (*hv, *hv2));
	if (i<m-1) matH(i+1,i) = len; 
	
	*hv /= len;
      }
      
    t2.Stop();
    t2.AddFlops (double(n)*m*m);
    cout << "n = " << n << ", m = " << m << " n*m*m = " << n*m*m << endl;
    cout << IM(1) << "\ri = " << m << "/" << m << endl;	    

	    
    Vector<Complex> lami(m);
    Matrix<Complex> evecs(m);    
    Matrix<Complex> matHt(m);

    matHt = Trans (matH);
    
    evecs = Complex (0.0);
    lami = Complex (0.0);

    cout << "Solve Hessenberg evp with Lapack ... " << flush;
    LapackHessenbergEP (matH.Height(), &matHt(0,0), &lami(0), &evecs(0,0));
    cout << "done" << endl;
	    
    for (int i = 0; i < m; i++)
      lami(i) =  1.0 / lami(i) + shift;

    lam.SetSize (m);
    for (int i = 0; i < m; i++)
      lam[i] = lami(i);

    t3.Start();
    if (numev>0)
      {
	int nout = min2 (numev, m); 
	hevecs.SetSize(nout);
	for (int i = 0; i< nout; i++)
	  {
	    hevecs[i] = a.CreateVector();
	    *hevecs[i] = 0;
	    for (int j = 0; j < m; j++)
	      *hevecs[i] += evecs(i,j) * *abv[j];
	    // hevecs[i]->FVComplex() = Trans(matV)*evecs.Row(i);
	  }
      }
    t3.Stop();
  } 
예제 #3
0
const CPoint3DWORLD CLandmark::_getOptimizedLandmarkLEFT3D( const UIDFrame& p_uFrame, const CPoint3DWORLD& p_vecInitialGuess )
{
    //ds initial values
    Eigen::Matrix3d matH( Eigen::Matrix3d::Zero( ) );
    Eigen::Vector3d vecB( Eigen::Vector3d::Zero( ) );
    const Eigen::Matrix3d matOmega( Eigen::Matrix3d::Identity( ) );
    double dErrorSquaredTotalMetersPREVIOUS = 0.0;

    //ds 3d point to optimize
    CPoint3DWORLD vecX( p_vecInitialGuess );

    //ds iterations (break-out if convergence reached early)
    for( uint32_t uIteration = 0; uIteration < CLandmark::uCapIterations; ++uIteration )
    {
        //ds counts
        double dErrorSquaredTotalMeters = 0.0;
        uint32_t uInliers               = 0;

        //ds initialize setup
        matH.setZero( );
        vecB.setZero( );

        //ds do calibration over all recorded values
        for( const CMeasurementLandmark* pMeasurement: m_vecMeasurements )
        {
            //ds get error
            const Eigen::Vector3d vecError( vecX-pMeasurement->vecPointXYZWORLD );

            //ds current error
            const double dErrorSquaredMeters = vecError.transpose( )*vecError;

            //ds check if outlier
            double dWeight = 1.0;
            if( 0.1 < dErrorSquaredMeters )
            {
                dWeight = 0.1/dErrorSquaredMeters;
            }
            else
            {
                ++uInliers;
            }
            dErrorSquaredTotalMeters += dWeight*dErrorSquaredMeters;

            //ds accumulate (special case as jacobian is the identity)
            matH += dWeight*matOmega;
            vecB += dWeight*vecError;
        }

        //ds update x solution
        vecX += matH.ldlt( ).solve( -vecB );

        //ds check if we have converged
        if( CLandmark::dConvergenceDelta > std::fabs( dErrorSquaredTotalMetersPREVIOUS-dErrorSquaredTotalMeters ) )
        {
            //ds compute average error
            const double dErrorSquaredAverageMeters = dErrorSquaredTotalMeters/m_vecMeasurements.size( );

            //ds if acceptable (don't mind about the actual number of inliers - we could be at this point with only 2 measurements -> 2 inliers -> 100%)
            if( 0 < uInliers )
            {
                //ds success
                ++uOptimizationsSuccessful;

                //ds update average
                dCurrentAverageSquaredError = dErrorSquaredAverageMeters;

                //ds check if optimal
                if( 0.075 > dErrorSquaredAverageMeters )
                {
                    bIsOptimal = true;
                }

                //std::printf( "<CLandmark>(_getOptimizedLandmarkWORLD) [%06lu] converged (%2u) in %3u iterations to (%6.2f %6.2f %6.2f) from (%6.2f %6.2f %6.2f) ARSS: %6.2f (inliers: %u/%lu)\n",
                //             uID, uOptimizationsSuccessful, uIteration, vecX(0), vecX(1), vecX(2), p_vecInitialGuess(0), p_vecInitialGuess(1), p_vecInitialGuess(2), dCurrentAverageSquaredErrorPixels, uInliers, m_vecMeasurements.size( ) );

                return vecX;
            }
            else
            {
                ++uOptimizationsFailed;
                //std::printf( "<CLandmark>(_getOptimizedLandmarkWORLD) landmark [%06lu] optimization failed - solution unacceptable (average error: %f, inliers: %u, iteration: %u)\n", uID, dErrorSquaredAverageMeters, uInliers, uIteration );

                //ds if still here the calibration did not converge - keep the initial estimate
                return p_vecInitialGuess;
            }
        }
        else
        {
            //ds update error
            dErrorSquaredTotalMetersPREVIOUS = dErrorSquaredTotalMeters;
        }
    }

    ++uOptimizationsFailed;
    //std::printf( "<CLandmark>(_getOptimizedLandmarkWORLD) landmark [%06lu] optimization failed - system did not converge\n", uID );

    //ds if still here the calibration did not converge - keep the initial estimate
    return p_vecInitialGuess;
}