Ejemplo n.º 1
0
void CRenWin3D::DrawAxis()
{
    glDisable(GL_LIGHTING);
    glClear(GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrtho(-2.0f, 2.0f, -1.5f, 1.5f, 0.1f, 100.0f);

    glm::mat4 rotMx = glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), m_front, m_up);

    glm::vec4 vecX(0.1f, 0.0f, 0.0f, 1.0f);
    glm::vec4 vecY(0.0f, 0.1f, 0.0f, 1.0f);
    glm::vec4 vecZ(0.0f, 0.0f, 0.1f, 1.0f);
    vecX = rotMx * vecX;
    vecY = rotMx * vecY;
    vecZ = rotMx * vecZ;

    glTranslatef(-1.9f, -1.4f, -20.0f);

    glColor3f(1.0f, 0.0f, 0.0f);
    glBegin(GL_LINES);
        glVertex3f(0.0f, 0.0f, 0.0f);
        glVertex3f(vecX.x, vecX.y, vecX.z);
    glEnd();
    glColor3f(0.0f, 1.0f, 0.0f);
    glBegin(GL_LINES);
        glVertex3f(0.0f, 0.0f, 0.0f);
        glVertex3f(vecY.x, vecY.y, vecY.z);
    glEnd();
    glColor3f(0.0f, 0.0f, 1.0f);
    glBegin(GL_LINES);
        glVertex3f(0.0f, 0.0f, 0.0f);
        glVertex3f(vecZ.x, vecZ.y, vecZ.z);
    glEnd();

    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);

    if(m_lighting)
    {
        glEnable(GL_LIGHTING);
    }
    glColor3f(1.0f, 1.0f, 1.0f);
}
Ejemplo n.º 2
0
void popblas::testBlas::test_gemv() {
    float alpha = 2;
    pop::F32 dataA[] = {0, 3, 2,
                   1, -2, 3,
                   5, 6, 2,
                   0, 1, 2,
                   3, 6, 1};
    pop::F32 dataX[] = {1, 2, 3};
    float beta = 1;
    pop::F32 dataY[] = {1,1,1,1,1};
    pop::MatN<2, pop::F32> vecX(pop::VecN<2, int>(3, 1), dataX);
    pop::MatN<2, pop::F32> vecY(pop::VecN<2, int>(5, 1), dataY);
    pop::MatN<2, pop::F32> matA(pop::VecN<2, int>(5, 3), dataA);
    pop::MatN<2, pop::F32> opMatA = matA.transpose();
    blas::gemv(alpha, opMatA, 'T', vecX, beta, vecY);
    std::cout << vecY << std::endl;
}
Ejemplo n.º 3
0
void customAttrManip::updateManipLocations()
//
// Description
// 	  This method places the manip in the scene according to the information
//    obtained from the attached transform node.  The position and orientation
//    of the distance manip is determined.
//
{
	MVector  trans = nodeTranslation();
	MQuaternion  q = nodeRotation();

	MFnDistanceManip freePointManipFn(fManip);

	MVector vecX(1.0, 0.0, 0.0);

	freePointManipFn.setDirection(vecX);
	freePointManipFn.rotateBy(q);
	freePointManipFn.setTranslation(trans, MSpace::kWorld);
}
Ejemplo n.º 4
0
void popblas::testBlas::test_ger() {
    pop::F32 dataX[] = {2,3,4};
    pop::F32 datamatX[] = {2, 3, 4,
                      1, 5, 3,
                      2, 1, 0};
    pop::F32 dataY[] = {1,3,5,7,2};
    pop::F32 alpha = 2;
    pop::MatN<2, pop::F32> vecX(pop::VecN<2, int>(1, 3), dataX);
    pop::MatN<2, pop::F32> matX(pop::VecN<2, int>(3, 3), datamatX);
    pop::MatN<2, pop::F32> vecY(pop::VecN<2, int>(1, 5), dataY);
    pop::MatN<2, pop::F32> matA(3, 5);
    pop::MatN<2, pop::F32> matB(3, 5);
    matA = 0; matB = 0;
    blas::ger(alpha, vecX, vecY, matA);
    pop::MatN<2, pop::F32> vecmatX = matX.selectRow(0);
    blas::ger(alpha, vecmatX, vecY, matB);
    std::cout << matA << std::endl;
    std::cout << matB << std::endl;
}
Ejemplo n.º 5
0
bool DecalManager::clipDecal( DecalInstance *decal, Vector<Point3F> *edgeVerts, const Point2F *clipDepth )
{
   PROFILE_SCOPE( DecalManager_clipDecal );

   // Free old verts and indices.
   _freeBuffers( decal );

   ClippedPolyList clipper;

   clipper.mNormal.set( Point3F( 0, 0, 0 ) );
   clipper.mPlaneList.setSize(6);

   F32 halfSize = decal->mSize * 0.5f;
   
   // Ugly hack for ProjectedShadow!
   F32 halfSizeZ = clipDepth ? clipDepth->x : halfSize;
   F32 negHalfSize = clipDepth ? clipDepth->y : halfSize;
   Point3F decalHalfSize( halfSize, halfSize, halfSize );
   Point3F decalHalfSizeZ( halfSizeZ, halfSizeZ, halfSizeZ );

   MatrixF projMat( true );
   decal->getWorldMatrix( &projMat );

   const VectorF &crossVec = decal->mNormal;
   const Point3F &decalPos = decal->mPosition;

   VectorF newFwd, newRight;
   projMat.getColumn( 0, &newRight );
   projMat.getColumn( 1, &newFwd );   

   VectorF objRight( 1.0f, 0, 0 );
   VectorF objFwd( 0, 1.0f, 0 );
   VectorF objUp( 0, 0, 1.0f );

   // See above re: decalHalfSizeZ hack.
   clipper.mPlaneList[0].set( ( decalPos + ( -newRight * halfSize ) ), -newRight );
   clipper.mPlaneList[1].set( ( decalPos + ( -newFwd * halfSize ) ), -newFwd );
   clipper.mPlaneList[2].set( ( decalPos + ( -crossVec * decalHalfSizeZ ) ), -crossVec );
   clipper.mPlaneList[3].set( ( decalPos + ( newRight * halfSize ) ), newRight );
   clipper.mPlaneList[4].set( ( decalPos + ( newFwd * halfSize ) ), newFwd );
   clipper.mPlaneList[5].set( ( decalPos + ( crossVec * negHalfSize ) ), crossVec );

   clipper.mNormal = -decal->mNormal;

   Box3F box( -decalHalfSizeZ, decalHalfSizeZ );

   projMat.mul( box );

   DecalData *decalData = decal->mDataBlock;

   PROFILE_START( DecalManager_clipDecal_buildPolyList );
   getContainer()->buildPolyList( box, decalData->clippingMasks, &clipper );   
   PROFILE_END();

   clipper.cullUnusedVerts();
   clipper.triangulate();
   clipper.generateNormals();
   
   if ( clipper.mVertexList.empty() )
      return false;

#ifdef DECALMANAGER_DEBUG
   mDebugPlanes.clear();
   mDebugPlanes.merge( clipper.mPlaneList );
#endif

   decal->mVertCount = clipper.mVertexList.size();
   decal->mIndxCount = clipper.mIndexList.size();
   
   Vector<Point3F> tmpPoints;

   tmpPoints.push_back(( objFwd * decalHalfSize ) + ( objRight * decalHalfSize ));
   tmpPoints.push_back(( objFwd * decalHalfSize ) + ( -objRight * decalHalfSize ));
   tmpPoints.push_back(( -objFwd * decalHalfSize ) + ( -objRight * decalHalfSize ));
   
   Point3F lowerLeft(( -objFwd * decalHalfSize ) + ( objRight * decalHalfSize ));

   projMat.inverse();

   _generateWindingOrder( lowerLeft, &tmpPoints );

   BiQuadToSqr quadToSquare( Point2F( lowerLeft.x, lowerLeft.y ),
                             Point2F( tmpPoints[0].x, tmpPoints[0].y ), 
                             Point2F( tmpPoints[1].x, tmpPoints[1].y ), 
                             Point2F( tmpPoints[2].x, tmpPoints[2].y ) );  

   Point2F uv( 0, 0 );
   Point3F vecX(0.0f, 0.0f, 0.0f);

   // Allocate memory for vert and index arrays
   _allocBuffers( decal );  
   
   Point3F vertPoint( 0, 0, 0 );

   for ( U32 i = 0; i < clipper.mVertexList.size(); i++ )
   {
      const ClippedPolyList::Vertex &vert = clipper.mVertexList[i];
      vertPoint = vert.point;

      // Transform this point to
      // object space to look up the
      // UV coordinate for this vertex.
      projMat.mulP( vertPoint );

      // Clamp the point to be within the quad.
      vertPoint.x = mClampF( vertPoint.x, -decalHalfSize.x, decalHalfSize.x );
      vertPoint.y = mClampF( vertPoint.y, -decalHalfSize.y, decalHalfSize.y );

      // Get our UV.
      uv = quadToSquare.transform( Point2F( vertPoint.x, vertPoint.y ) );

      const RectF &rect = decal->mDataBlock->texRect[decal->mTextureRectIdx];

      uv *= rect.extent;
      uv += rect.point;      

      // Set the world space vertex position.
      decal->mVerts[i].point = vert.point;
      
      decal->mVerts[i].texCoord.set( uv.x, uv.y );
      
      decal->mVerts[i].normal = clipper.mNormalList[i];
      
      decal->mVerts[i].normal.normalize();

      if( mFabs( decal->mVerts[i].normal.z ) > 0.8f ) 
         mCross( decal->mVerts[i].normal, Point3F( 1.0f, 0.0f, 0.0f ), &vecX );
      else if ( mFabs( decal->mVerts[i].normal.x ) > 0.8f )
         mCross( decal->mVerts[i].normal, Point3F( 0.0f, 1.0f, 0.0f ), &vecX );
      else if ( mFabs( decal->mVerts[i].normal.y ) > 0.8f )
         mCross( decal->mVerts[i].normal, Point3F( 0.0f, 0.0f, 1.0f ), &vecX );
   
      decal->mVerts[i].tangent = mCross( decal->mVerts[i].normal, vecX );
   }

   U32 curIdx = 0;
   for ( U32 j = 0; j < clipper.mPolyList.size(); j++ )
   {
      // Write indices for each Poly
      ClippedPolyList::Poly *poly = &clipper.mPolyList[j];                  

      AssertFatal( poly->vertexCount == 3, "Got non-triangle poly!" );

      decal->mIndices[curIdx] = clipper.mIndexList[poly->vertexStart];         
      curIdx++;
      decal->mIndices[curIdx] = clipper.mIndexList[poly->vertexStart + 1];            
      curIdx++;
      decal->mIndices[curIdx] = clipper.mIndexList[poly->vertexStart + 2];                
      curIdx++;
   } 

   if ( !edgeVerts )
      return true;

   Point3F tmpHullPt( 0, 0, 0 );
   Vector<Point3F> tmpHullPts;

   for ( U32 i = 0; i < clipper.mVertexList.size(); i++ )
   {
      const ClippedPolyList::Vertex &vert = clipper.mVertexList[i];
      tmpHullPt = vert.point;
      projMat.mulP( tmpHullPt );
      tmpHullPts.push_back( tmpHullPt );
   }

   edgeVerts->clear();
   U32 verts = _generateConvexHull( tmpHullPts, edgeVerts );
   edgeVerts->setSize( verts );

   projMat.inverse();
   for ( U32 i = 0; i < edgeVerts->size(); i++ )
      projMat.mulP( (*edgeVerts)[i] );

   return true;
}
Ejemplo n.º 6
0
  int
  process(const ecto::tendrils& inputs, const ecto::tendrils& outputs)
  {
    // Get the origin of the plane
    cv::Point origin;

    cv::Matx33f K, R;
    cv::Vec3f T;
    if (*do_center_)
      origin = cv::Point(masks_->cols/2, masks_->rows/2);
    else {
      if (!K_ || K_->empty() || !R_in_ || R_in_->empty() || !T_in_ || T_in_->empty()) {
        *found_ = false;
        return ecto::OK;
      }
      K = *K_;
      R = *R_in_;
      T = *T_in_;
      cv::Vec3f T = K*T;
      origin = cv::Point(T(0)/T(2), T(1)/T(2));
    }

    // Go over the plane masks and simply count the occurrence of each mask
    std::vector<int> occurrences(256, 0);
    for(int y = std::max(0, origin.y - *window_size_); y < std::min(masks_->rows, origin.y + *window_size_); ++y) {
      uchar *mask = masks_->ptr<uchar>(y) + std::max(0, origin.x - *window_size_);
      uchar *mask_end = masks_->ptr<uchar>(y) + std::min(masks_->cols, origin.x + *window_size_);
      for(; mask != mask_end; ++mask)
        if (*mask != 255)
          ++occurrences[*mask];
    }

    // Find the most common plane
    int best_index = -1;
    int best_count = 0;
    for(size_t i = 0; i < 255; ++i) {
      if (occurrences[i] > best_count) {
        best_index = i;
        best_count = occurrences[i];
      }
    }

    // Convert the plane coefficients to R,t
    cv::Matx33f rotation;
    cv::Vec3f translation;
    if (best_index >= 0) {
      *coeffs_ = (*planes_)[best_index];
      float a = (*coeffs_)[0], b = (*coeffs_)[1], c = (*coeffs_)[2], d = (*coeffs_)[3];

      // Deal with translation
      if (*do_center_) {
        getPlaneTransform(*coeffs_, rotation, translation);
        // Make sure T_ points to the center of the image
        translation = cv::Vec3f(0,0,-d/c);
      } else {
        // Have T_ point to the origin. Find alpha such that alpha*Kinv*origin is on the plane
        cv::Matx33f K_inv = K.inv();
        cv::Vec3f origin_inv = cv::Mat(K_inv * cv::Vec3f(origin.x, origin.y, 1));
        float alpha = -d/(a*origin_inv(0) + b*origin_inv(1) + c*origin_inv(2));
        translation = alpha*origin_inv;
        if (translation(2) < 0)
          translation = -translation;

        // Make the rotation fit to the plane (but as close as possible to the current estimate
        // Get the Z axis
        cv::Vec3f N(a, b, c);
        N = N/cv::norm(N);
        // Get the X, Y axes
        cv::Vec3f vecX(R(0,0), R(1,0), R(2,0));
        cv::Vec3f vecY(R(0,1), R(1,1), R(2,1));
        // Project them onto the plane
        vecX = vecX - vecX.dot(N)*N;
        vecY = vecY - vecY.dot(N)*N;
        vecX = vecX/cv::norm(vecX);
        vecY = vecY/cv::norm(vecY);
        // Get the median
        cv::Vec3f median = vecX + vecY;
        median = median/cv::norm(median);
        // Get a new basis
        cv::Vec3f vecYtmp = vecY - median.dot(vecY)*median;
        cv::Vec3f vecXtmp = vecX - median.dot(vecX)*median;
        vecYtmp = vecYtmp/cv::norm(vecYtmp);
        vecXtmp = vecXtmp/cv::norm(vecXtmp);
        // Get the rectified X/Y axes
        cv::Vec3f vecXnew = median + vecXtmp;
        cv::Vec3f vecYnew = median + vecYtmp;
        vecXnew = vecXnew/cv::norm(vecXnew);
        vecYnew = vecYnew/cv::norm(vecYnew);
        // Fill in the matrix
        rotation = cv::Matx33f(vecXnew(0), vecYnew(0), N(0), vecXnew(1), vecYnew(1), N(1), vecXnew(2), vecYnew(2), N(2));
      }

      *R_out_ = cv::Mat(rotation);
      *T_out_ = cv::Mat(translation);
      *found_ = true;
    } else
      *found_ = false;

    return ecto::OK;
  }
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
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;
}