ami-iit / rod

The ultimate Python tool for RObot Descriptions processing.
https://pypi.org/project/rod/
BSD 3-Clause "New" or "Revised" License
13 stars 3 forks source link

Update `MeshBuilder` class #38

Open diegoferigo opened 4 weeks ago

diegoferigo commented 4 weeks ago

This PR enhances the mesh support introduced in #33. In particular:

cc @lorycontixd can you please try if the changes break your pipeline? For sure you have to update mesh_path with mesh_uri. Sorry for this change, I overlooked this use-case in your original contribution.

diegoferigo commented 4 weeks ago

cc @flferretti

lorycontixd commented 4 weeks ago

@diegoferigo With these changes, nothing is broken from my side!

diegoferigo commented 4 weeks ago

With these changes, nothing is broken from my side!

Excellent! I assume nothing broken except the change of name of mesh_uri.

diegoferigo commented 3 weeks ago

Waiting a quick check from @traversaro before merging.

lorycontixd commented 3 weeks ago

With these changes, nothing is broken from my side!

Excellent! I assume nothing broken except the change of name of mesh_uri.

Yes, exactly!

traversaro commented 3 weeks ago

I am a bit confused by the mass property in MeshBuilder . In all other <Something>Builder, the mass is taken from the PrimitiveBuilder, and then the inertia is computed as proportional to the mass (so the density is taken implicitly from the mass). Instead, in the MeshBuilder there is an additional mass attribute of MeshBuilder, and if the mass is set and the inertia is not set, the mass is ignored while computing the inertia, getting instead the density from trimesh (that is anyhow not set, so I guess it will default to 1.0, see https://github.com/mikedh/trimesh/blob/4.4.1/trimesh/triangles.py#L233-L234), is that intentional?

traversaro commented 3 weeks ago

It is also not clear to me where we are accounting for the center of mass when computing the inertia properties. For all other primitive shapes, the center of mass is at the origin of the frame in which the primitive shape is expressed, but this is not true for meshes.

diegoferigo commented 3 weeks ago

I am a bit confused by the mass property in MeshBuilder . In all other <Something>Builder, the mass is taken from the PrimitiveBuilder, and then the inertia is computed as proportional to the mass (so the density is taken implicitly from the mass). Instead, in the MeshBuilder there is an additional mass attribute of MeshBuilder, and if the mass is set and the inertia is not set, the mass is ignored while computing the inertia, getting instead the density from trimesh (that is anyhow not set, so I guess it will default to 1.0, see https://github.com/mikedh/trimesh/blob/4.4.1/trimesh/triangles.py#L233-L234), is that intentional?

All *Builder class, as you commented, need the user to specify the desired mass, and the defaul inertia (always expressed in the CoM since the user can define a custom one manually) is computed automatically from the shape.

Meshes are different, because it's not possible to compute the inertia automatically unless, as you linked, the density is set and the mesh is watertight. The MeshBuilder allows the following cases:

It is also not clear to me where we are accounting for the center of mass when computing the inertia properties. For all other primitive shapes, the center of mass is at the origin of the frame in which the primitive shape is expressed, but this is not true for meshes.

I think this is related to what I asked in a previous review https://github.com/ami-iit/rod/pull/33#discussion_r1599564591. Right now, all the builders expect the inertia expressed in a frame located at the CoM. If this is not the case, the user can specify a different pose of such frame when they call: link = builder.build_link().add_inertial(pose=Pose(...)).add_visual().add_collision().build().

traversaro commented 3 weeks ago

Thanks, the explanation of the different use case is more clear. To be even more clear, I will name the following use cases you mentioned.

However, I am bit confused as in the tests only the mass is specified, following the use case common in the rest of the primitive builder, i.e.

Just to complete the analysis, there is a UC4 in which the user overrides the inertia specified at the shape level, i.e.

In the following I provide comments for all this use cases:

UC1

I think this is related to what I asked in a previous review https://github.com/ami-iit/rod/pull/33#discussion_r1599564591.

Actually this was referred to the pose of the mesh, that is a transform between the link frame and the frame in which the mesh (i.e. the point composing the mesh) is expressed. For a generic mesh, there is no constraint for the center of mass of the mesh to lay at the origin of the frame in which the point of the mesh is expressed.

In general, a mesh can have a CoM in a point different from the origin of the frame in which the mesh is expressed (diffently from the primitive shapes currently supported), so I think it make sense to permit the user to also specify the CoM in this API.

UC2

The user creates the MeshBuilder from a mesh they developed and control (or at least, access and update programmatically), therefore they can store the proper information to let trimesh compute automatically the inertial properties.

I see two main problems in this use case:

UC3

Apparently this workflow is the one used in the tests.

Meshes are different, because it's not possible to compute the inertia automatically unless, as you linked, the density is set and the mesh is watertight. The MeshBuilder allows the following cases:

Just fyi the only condition if for the mesh to be watertight. As long as as the mesh is watertight, you can compute the density corresponding to a given mass as mass/volume, and you can compute the inertia at the CoM as InertiaWithRodMass = ((mass/volume)/trimeshdensity)*InertiaWithTrimeshdensity . So a possible strategy is to permit to compute the inertia from the mass, and just raise an error if the mesh is not watertight. However, in this case you also need to properly propagate the CoM from the mesh, that is not currently accounted for (see previous comments).

UC4

  • UC4: The full inertia parametes (mass, center of mass, inertia) are specified explicitly via link = builder.build_link().add_inertial(pose=Pose(...)).add_visual().add_collision().build()

From what I understand, this UC seems clear.

traversaro commented 3 weeks ago

Ah, probably I would at least explicitly disallow the possibility of not setting the mass but setting explicitly the inertia.

diegoferigo commented 3 days ago

Getting back on this PR. Thanks for the feedback @traversaro!

For the moment, I'm focusing on other things with higher priority. Let's see when I find some time to process your suggestions. Leaving this PR as stale for a more while.