pointmatcher.net icon indicating copy to clipboard operation
pointmatcher.net copied to clipboard

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

Open Qusai-Azzam opened this issue 6 years ago • 11 comments

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);

Qusai-Azzam avatar Aug 02 '18 13:08 Qusai-Azzam

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

djambo avatar Nov 19 '18 03:11 djambo

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.

Bob-Yeah avatar Mar 05 '19 13:03 Bob-Yeah

I'm having the same problem!

mvelayati avatar Apr 19 '19 20:04 mvelayati

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

Titibo26 avatar Aug 26 '19 12:08 Titibo26

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 avatar Dec 13 '19 14:12 Titibo26

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.

Titibo26 avatar Dec 19 '19 15:12 Titibo26

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.

iquizei avatar Feb 19 '21 04:02 iquizei

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; }

Titibo26 avatar Feb 19 '21 11:02 Titibo26

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

iquizei avatar Feb 24 '21 07:02 iquizei

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)

Titibo26 avatar Feb 24 '21 10:02 Titibo26

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.

iquizei avatar Feb 24 '21 10:02 iquizei