braddodson / pointmatcher.net

Implementation of ICP in C#
Apache License 2.0
27 stars 57 forks source link

System.ArgumentException: 'Matrix must be positive definite.' #1

Open Qusai-Azzam opened 6 years ago

Qusai-Azzam commented 6 years ago

Hello Developers, i got this Exception when i Use this Code, "System.ArgumentOutOfRangeException: 'Specified argument was out of the range of valid values. Parameter name: The number of columns of a matrix must be positive.'" Here is My Code, and thanks in Advance for your help :

       var readingPoints = new List<DataPoint>();
        var referencePoints = new List<DataPoint>();

        Vector3 dVec1 = new Vector3(-0.2967872f, 0.07480811f, 0.3788449f);
        Vector3 dVec2 = new Vector3(-0.2375435f, 0.07482694f, 0.3390627f);
        Vector3 dVec3 = new Vector3(-0.1699704f, 0.09031584f, 0.2926779f);
        Vector3 dVec4 = new Vector3(-0.08458908f, 0.09454262f, 0.3008334f);
        Vector3 dVec5 = new Vector3(-0.008116714f, 0.1069966f, 0.3251371f);
        Vector3 dVec6 = new Vector3(0.06125673f, 0.1056816f, 0.3781575f);
        Vector3 dVec7 = new Vector3(-0.122625f, 0.09119529f, 0.3357856f);

        DataPoint dpoint1 = new DataPoint { point = dVec1, normal = Vector3.Normalize(dVec1) };
        DataPoint dpoint2 = new DataPoint { point = dVec2, normal = Vector3.Normalize(dVec2) };
        DataPoint dpoint3 = new DataPoint { point = dVec3, normal = Vector3.Normalize(dVec3) };
        DataPoint dpoint4 = new DataPoint { point = dVec4, normal = Vector3.Normalize(dVec4) };
        DataPoint dpoint5 = new DataPoint { point = dVec5, normal = Vector3.Normalize(dVec5) };
        DataPoint dpoint6 = new DataPoint { point = dVec6, normal = Vector3.Normalize(dVec6) };
        DataPoint dpoint7 = new DataPoint { point = dVec7, normal = Vector3.Normalize(dVec7) };

        readingPoints.Add(dpoint1);
        readingPoints.Add(dpoint2);
        readingPoints.Add(dpoint3);
        readingPoints.Add(dpoint4);
        readingPoints.Add(dpoint5);
        readingPoints.Add(dpoint6);
        readingPoints.Add(dpoint7);

        var reading = new DataPoints
        {
            points = readingPoints.ToArray(),
            contiansNormals = true,
        };

        Vector3 rVec1 = new Vector3(-0.3207868f, 0.07550032f, 0.3456057f);
        Vector3 rVec2 = new Vector3(-0.2668087f, 0.08369328f, 0.2892195f);
        Vector3 rVec3 = new Vector3(-0.07828052f, 0.07665844f, 0.2688065f);
        Vector3 rVec4 = new Vector3(-0.07828052f, 0.07665844f, 0.2688065f);
        Vector3 rVec5 = new Vector3(-0.004118666f, 0.1029833f, 0.2820587f);
        Vector3 rVec6 = new Vector3(0.0516735f, 0.1072405f, 0.3227094f);
        Vector3 rVec7 = new Vector3(-0.1334717f, 0.08830917f, 0.2922978f);

        DataPoint rpoint1 = new DataPoint { point = rVec1, normal = Vector3.Normalize(rVec1) };
        DataPoint rpoint2 = new DataPoint { point = rVec2, normal = Vector3.Normalize(rVec2) };
        DataPoint rpoint3 = new DataPoint { point = rVec3, normal = Vector3.Normalize(rVec3) };
        DataPoint rpoint4 = new DataPoint { point = rVec4, normal = Vector3.Normalize(rVec4) };
        DataPoint rpoint5 = new DataPoint { point = rVec5, normal = Vector3.Normalize(rVec5) };
        DataPoint rpoint6 = new DataPoint { point = rVec6, normal = Vector3.Normalize(rVec6) };
        DataPoint rpoint7 = new DataPoint { point = rVec7, normal = Vector3.Normalize(rVec7) };

        referencePoints.Add(rpoint1);
        referencePoints.Add(rpoint2);
        referencePoints.Add(rpoint3);
        referencePoints.Add(rpoint4);
        referencePoints.Add(rpoint5);
        referencePoints.Add(rpoint6);
        referencePoints.Add(rpoint7);

        var reference = new DataPoints
        {
            points = referencePoints.ToArray(),
            contiansNormals = true,
        };

        EuclideanTransform initialTransform = new EuclideanTransform();
        initialTransform.translation = new Vector3(-0.02399f, 0f, 0.0332392f);

        var axis = Vector3.Normalize(RandomVector());
        initialTransform.rotation = Quaternion.CreateFromAxisAngle(axis, (float)(0.02 * Math.PI * 2));
        initialTransform.rotation = Quaternion.Normalize(initialTransform.rotation);

        ICP icp = new ICP();
        icp.ReadingDataPointsFilters = new RandomSamplingDataPointsFilter(prob: 0.1f);
        icp.ReferenceDataPointsFilters = new 
        SamplingSurfaceNormalDataPointsFilter(SamplingMethod.Bin, ratio: 0.2f);
        icp.OutlierFilter = new TrimmedDistOutlierFilter(ratio: 0.5f);
        var transform = icp.Compute(reading, reference, initialTransform);
djambo commented 5 years ago

Could you find a solution to this? I am having the same issue and I can't get it to work.

Bob-Yeah commented 5 years ago

maybe you are using too few points or too simple model and there may be something wrong in the filters. You can read in two actual obj files and try again.

mvelayati commented 5 years ago

I'm having the same problem!

Titibo26 commented 5 years ago

Hi there, Still not resolved ? I'm facing the same problem. Thx

Titibo26 commented 4 years ago

I am working on it right now,I'm testing the code with a random cloud generator, and it seems to work except when the cloud is 2D. It means if all points of a cloud have a constant cord (ex: Z = 0 for all points, OR Y = 10 for all points or whatever (it is reproductible)), it'll throw this exception. It seems to be related to the Cholesky computation (in the mathnet lib) which can be effectivly a problem if one term of the matrix is = 0. So, we maybe need to modify the code to distinguish 2D clouds from 3D clouds so the matrix computation is done with a 2x2 positive matrix instead of 3x3 ? i'll search if it is possible to make it.

Titibo26 commented 4 years ago

Hello there,

I finally found a way to bypass this error. It seems to happend because of rounding or smthg. in ICP.CS, more precisely in computeWithTransformedReference(...).

Sometimes, T_iter turn to be NaN and it is returned so what is done after that just go wrong (matrix are note positive as they contains NaN !)

What i've done for now : I'm checking if T_iter is NaN after ErrorMinimizerHelper.Compute(...) and if it is, i do : T_iter = last_T_iter and then i break the while loop.

This bypass surely degrades result but at least i can go one with this.

iquizei commented 3 years ago

Hello there,

I finally found a way to bypass this error. It seems to happend because of rounding or smthg. in ICP.CS, more precisely in computeWithTransformedReference(...).

Sometimes, T_iter turn to be NaN and it is returned so what is done after that just go wrong (matrix are note positive as they contains NaN !)

What i've done for now : I'm checking if T_iter is NaN after ErrorMinimizerHelper.Compute(...) and if it is, i do : T_iter = last_T_iter and then i break the while loop.

This bypass surely degrades result but at least i can go one with this.

It seems like T_iter is not a double type value, how did you check if it is NaN of not in C# ? Thank you.

Titibo26 commented 3 years ago

You have to test the problematic value (which in my case is related to rotation as i'm matching 2D horizontal scans) I've done this :

if (Double.IsNaN(T_iter.rotation.W)) { Debug.WriteLine("Iteration stopped because T_iter was NaN."); T_iter = lastT_iter; break; }

iquizei commented 3 years ago

You have to test the problematic value (which in my case is related to rotation as i'm matching 2D horizontal scans) I've done this :

if (Double.IsNaN(T_iter.rotation.W)) { Debug.WriteLine("Iteration stopped because T_iter was NaN."); T_iter = lastT_iter; break; }

I am working on 2D scan at the moment as well. My problem is on Chloesky.Solve that said "Matrix must be positive definite" Is it possible if I have a look in your code ?

Thank you very much

Titibo26 commented 3 years ago

TO bypass this error ("Matrix must be positive definite") i added the checking code after line 128 in ICP.Cs :

    T_iter = ErrorMinimizerHelper.Compute(stepReading, reference, outlierWeights, matches, this.ErrorMinimizer) * T_iter; 

            if (Double.IsNaN(T_iter.rotation.W))
            {
                Debug.WriteLine("Iteration stopped because T_iter was NaN.");
                T_iter = lastT_iter;
                break;
            }

You need to find which component of "T_iter" is nan. for me it is "rotation.W" (im working on 2d scan with Z as rotation axes)

iquizei commented 3 years ago

TO bypass this error ("Matrix must be positive definite") i added the checking code after line 128 in ICP.Cs :

    T_iter = ErrorMinimizerHelper.Compute(stepReading, reference, outlierWeights, matches, this.ErrorMinimizer) * T_iter; 

            if (Double.IsNaN(T_iter.rotation.W))
            {
                Debug.WriteLine("Iteration stopped because T_iter was NaN.");
                T_iter = lastT_iter;
                break;
            }

You need to find which component of "T_iter" is nan. for me it is "rotation.W" (im working on 2d scan with Z as rotation axes)

Thank you very much for being so active. You are truly helpful.

I am going to try implement this one in my own code and will give you the result after this.

Thank you very much.