question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Numerical instability in `trimesh.geometry.align_vectors`

See original GitHub issue

Hi!

I came across this edge case where align_vectors returned a non rigid transform, it might be that this tolerance should be relaxed a bit?

>>> import trimesh
>>> import numpy as np
>>> vector_1 = np.array([ 7.12106798e-07, -7.43194705e-08,  1.00000000e+00])
>>> vector_2 = np.array([0, 0, -1])
>>> transform = trimesh.geometry.align_vectors(vector_1, vector_2)
>>> transform
array([[-9.78992868e-01,  2.06538826e-01,  7.12106798e-07,
         0.00000000e+00],
       [ 2.06538826e-01,  9.78444446e-01, -7.43194705e-08,
         0.00000000e+00],
       [-7.12106798e-07,  7.43194705e-08, -1.00054842e+00,
         0.00000000e+00],
       [ 0.00000000e+00,  0.00000000e+00,  0.00000000e+00,
         1.00000000e+00]])
>>> np.linalg.det(transform)
1.0010971441512102

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:10 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
wannesvanloockcommented, May 6, 2020

To give some context regarding the method proposed by @lejafar. The SVD is used here to construct a basis for the null space of the vector (the last two columns of the svd). The first column is the normalized vector itself. The result will always be rigid, i.e. abs(determinant) == 1. It is however is not guaranteed to be right handed, and this is where @lejafar proposal fails (cfr #608). This is simple to fix by reversing one of the axes:

def right_handed_basis(a):
    '''Constructs a right handed basis from a and the null space of a.'''
    u, *_ = np.linalg.svd(a[:, np.newaxis])
    if np.linalg.det(u) < 0:
        u[:, -1] *= -1
    return u

def align_vectors(a, b):
    a_R_o = right_handed_basis(a)
    b_R_o = right_handed_basis(b)
    return a_R_o.dot(b_R_o.T)

Note that this should work in all cases.

1reaction
mikedhcommented, Aug 27, 2019

Good catch! I’m able to reproduce, and yeah I definitely think align_vectors should always return a rigid transform. I’ll add an assert is_rigid(T) to unit tests, and try to generate more examples of failing values before working on a fix.

Thanks for the report!

Read more comments on GitHub >

github_iconTop Results From Across the Web

trimesh.geometry — trimesh 3.17.1 documentation
A data vector can be passed which is then used instead of booleans. Parameters. columns (int) – Number of columns, usually number of...
Read more >
libigl Tutorial
We mostly use matrices and vectors. This greatly favors code reusability and forces the function authors to expose all the parameters used by...
Read more >
Segmentation — CristalX 1.1.0 documentation
If numpy vectors are passed as inputs, the resulting area is incorrect! WHY? Notes. The code is not optimized for speed and for...
Read more >
A finite-element based mesh morphing approach for surface ...
the geometric information captured via a point cloud to the format required by a numerical simulation is a challenging and crucial process.
Read more >
Novel alignment method for optical 3D gear metrology of spur ...
Alignment is proven to be a key step in optical gear geometry. ... the alignment of full-field optical measurements and numerical simulation ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found