Closed jwnimmer-tri closed 1 year ago
FYI we already have code that calculates the centroid of the volume enclosed by a triangulated surface mesh. As a by product, it also calculates the volume (6 times of volume to be precise):
I think there are basically two ways to offer this API:
(1) Add a new dedicated function.
class Parser {
ModelInstanceIndex AddMeshModelFromFile(
const std::string& file_name,
double scale = 1.0, // in meters per obj coordinate
double density = 1.0, // in kg/L
const std::string& model_name = {});
ModelInstanceIndex AddMeshModelFromString(
const std::string& file_contents,
const std::string& file_type,
double scale = 1.0, // in meters per obj coordinate
double density = 1.0, // in kg/L
const std::string& model_name = {});
};
(2) Use the existing function but separately configure the properties:
class Parser {
// Existing API
ModelInstanceIndex AddModelFromFile(const std::string& file_name, const std::string& model_name = {});
ModelInstanceIndex AddModelFromString(const std::string& file_contents, const std::string& file_type, const std::string& model_name = {});
// New API
void set_standalone_mesh_scale(double scale);
void set_standalone_mesh_density(double density);
};
The user would first set the scale and density (the scale is probably homogeneous for all of their art assets, and the density will not matter if they are only doing geometrical queries), and then can add the mesh using only its filename. Option (2) might be slightly more compatible with lists of model files (e.g., model directives) that pre-suppose a filename is all that's necessary.
The other different-direction answer would be to publish a sdformat-generating script, given an obj.
Another possible tactic here: it seems like the MJCF syntax for loading a mesh as a manipuland is somewhat terse. An example of using that format to easily load an *.obj
might be sufficient on its own, without changing the Parser.
@SeanCurtis-TRI any chance you would be interested in taking this one?
Yep. I'll take this one.
@jwnimmer-tri Do you have a link to the MJCF syntax to which you refer? I've skimmed the website but nothing jumped out in this particular context.
See TestMesh
in detail_mujoco_parser_test.cc
.
<mujoco model="box">
<asset>
<mesh name="box" file="box.obj"/>
</asset>
<worldbody>
<geom name="box_geom" type="mesh" mesh="box"/>
</worldbody>
</mujoco>
From f2f: when loading an *.obj
, if it has an embedded name, use that as the model name (and body name). Otherwise, use the file basename as the model name. Otherwise, use a hardcoded placeholder name like "wavefront_string_mesh" or whatever (only relevant when parsing from strings).
Slight elaboration on the name discussion.
model_name
. So, that puts some shades of grey here. There are two axes: naming protocol and model-body name agreement.
model_name
is specified, that wins.model_name
is explicitly passed, should the model be one thing (the user-specified model name) and the body another (the OBJ object name)?model_name
and model_name_body
? Or should the definitely always match?I'd suggest the following (ever so slightly modified) protocol for (at least) the model instance.
SGTM
For example, if the OBJ has an object name but a model_name is explicitly passed, should the model be one thing (the user-specified model name) and the body another (the OBJ object name)?
I think this one is probably a coin toss. Mu gut feeling goes towards model_name == body_name
for this feature, to be the most uniform. I could see the embedded obj name being the geometry instance name, if anything.
Presumably loading the same mesh multiple times should have the same semantics ...
Yes.
Re-opening with one other thought. (We might decide to skip but...)
Should we add a little demo of this feature to one of the tutorials? I think possibly users might not know about it otherwise.
Maybe "authoring_multibody_simulation"?
Back to @SeanCurtis-TRI to add sample code to a tutorial.
I'll take over updating the tutorials.
When adding manipulands to a scene, the current workflow is to develop a mesh for the object, and then write an SDFormat file that refers to the mesh, then feed that SDFormat file to the parser. Both the mesh and the SDFormat file go into source control.
The content of the SDFormat file is fairly boilerplate, and we often create it using semi-scripted methods. Even with that, it's extra work to write and maintain that boilerplate.
We should update the
multibody::Parser
to accept*.obj
files directly as an input format.It should add a new model instance, floating body, visual and proximity geometry, and should compute the mass and inertia from the mesh itself, using approximations as necessary (e.g., assume uniform density, possibly even assume the density of water).
One problem will be the units of the mesh. Mesh tools tend to operate on obj files in centimeters (millimeters?) by convention, but we also have meshes that use meters. We might need a way for the user to specify their units, but I'm not sure how to do that.