Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the possibility to display the arrows in MeshcatVizualizer #1087

Merged
merged 3 commits into from
Aug 9, 2023

Conversation

GiulioRomualdi
Copy link
Member

This PR allows you to easily draw arrows in MeshcatVizualizer

The original idea was taken from @rob-mau and generalized to avoid using non-standard datatype.

For instance the following code

from idyntree.visualize import MeshcatVisualizer
viz = MeshcatVisualizer()
viz.load_arrow(radius=0.01, shape_name="arrow", color=[255/255, 157/255, 68/255])
viz.set_arrow_transform(origin=[0, 0.5, 0], vector=[0.5, 0.33, 1], shape_name="arrow")

draws the following arrow
image

@rob-mau
Copy link

rob-mau commented Jul 24, 2023

Hi Giulio, I was reading your implementation of the rotation matrix R. You can avoid to compute the variable s, since:

$$ \frac{1 - \cos \theta}{\sin^2 \theta} = \frac{1 - \cos \theta}{1 - \cos^2 \theta} = \frac{1}{1 + \cos \theta} = \frac{1}{1 + \hat{\boldsymbol{x}}^\top \hat{\boldsymbol{y}}} $$

In this case the rotation matrix can be computed as:

$$ R(\hat{\boldsymbol{x}}, \, \hat{\boldsymbol{y}}) \triangleq I + S(\hat{\boldsymbol{x}} \wedge \hat{\boldsymbol{y}}) + \frac{1}{1 + \hat{\boldsymbol{x}}^\top \hat{\boldsymbol{y}}} \, S(\hat{\boldsymbol{x}} \wedge \hat{\boldsymbol{y}})^2 $$

With this formulation, there is no singularity in $\theta = 0$, so you can avoid the conditional statement:
if s < 1e-6: R = np.eye(3) else: ...

You can also avoid to compute the cross product $\hat{\boldsymbol{x}} \wedge \hat{\boldsymbol{y}}$, since:

$$ S(\hat{\boldsymbol{x}} \wedge \hat{\boldsymbol{y}}) = \hat{\boldsymbol{y}} \, \hat{\boldsymbol{x}}^\top - \hat{\boldsymbol{x}} \, \hat{\boldsymbol{y}}^\top $$

but I don't know which computation is better.

@GiulioRomualdi
Copy link
Member Author

Hi @rob-mau thank you for the hint. However, I think we still need an if indeed in case $\hat{\boldsymbol{x}}^\top \hat{\boldsymbol{y}} = -1$
the following is not defined (at least in the computer)

$$ R(\hat{\boldsymbol{x}}, \, \hat{\boldsymbol{y}}) \triangleq I + S(\hat{\boldsymbol{x}} \wedge \hat{\boldsymbol{y}}) + \frac{1}{1 + \hat{\boldsymbol{x}}^\top \hat{\boldsymbol{y}}} \, S(\hat{\boldsymbol{x}} \wedge \hat{\boldsymbol{y}})^2 $$

bindings/python/visualize/meshcat_visualizer.py Outdated Show resolved Hide resolved
transform[3, 3] = 1

if np.linalg.norm(vector) < 1e-6:
warnings.warn("The vector is too small to be visualized.", category=UserWarning, stacklevel=2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there something less than warning? It often happens that you don't care too much about the length of the arrow before displaying it. Having a warning continuously printed might be annoying

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, if you display data from a sensor (i.e. force sensor) it makes total sense to have a near 0 value, there is any other reason to have this print/check?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done 4bdfa9c

@S-Dafarra
Copy link
Contributor

Btw, you can also compute the relative rotation by simply computing the corresponding axis and angle that align the two vectors. The first can be computed via the cross product, the second via the dot product. Since we are already loading iDynTree bindings, it may make sense to use directly the builtin function in iDynTree:

static Rotation RotAxis(const Direction & direction, const double angle);

I did the same for the visualization of vectors in the iDynTree visualizer:

iDynTree::toEigen(rotationAxis) = iDynTree::toEigen(yDirection).cross(iDynTree::toEigen(vectorDirection));
rotationAxis.Normalize();
double rotationAngle = std::acos(iDynTree::toEigen(vectorDirection).dot(iDynTree::toEigen(yDirection)));
iDynTree::Rotation arrowRotationMatrix = iDynTree::Rotation::RotAxis(rotationAxis, rotationAngle);

@rob-mau
Copy link

rob-mau commented Jul 26, 2023

I think we still need an if indeed in case $\hat{\boldsymbol{x}}^\top \hat{\boldsymbol{y}} = -1$ the following is not defined

Yes, the singularity in $\theta = \pi$ is not remuvable. Also evaluating $R$ as Stefano suggested we have this problem. When the two vectors are aligned, the normal axis is not uniquely defined and the cross product between them is equal to the zero vector. Indeterminate forms (0/0) appear in the Rodrigues' formula.

GiulioRomualdi and others added 2 commits August 3, 2023 15:05
Co-authored-by: Stefano Dafarra <stefano.dafarra@gmail.com>
@traversaro
Copy link
Member

@GiulioRomualdi is this ready to be merged, right?

@GiulioRomualdi
Copy link
Member Author

yes

@traversaro traversaro closed this Aug 9, 2023
@traversaro traversaro reopened this Aug 9, 2023
@traversaro traversaro merged commit 309501b into master Aug 9, 2023
50 of 53 checks passed
@traversaro traversaro deleted the meshcat_viz_arrows branch August 9, 2023 11:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants