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

Modify the URDF model for meshes paths #23

Open
LudovicaDanovaro opened this issue Dec 11, 2024 · 9 comments
Open

Modify the URDF model for meshes paths #23

LudovicaDanovaro opened this issue Dec 11, 2024 · 9 comments
Assignees

Comments

@LudovicaDanovaro
Copy link

Objective

The goal is to make the human model URDF agnostic to local directory paths for meshes. Currently, the mesh files in the URDF model are referenced using a fixed local directory path. This requires modifying the URDF file on every computer or for every user. Instead, we aim to update the URDF to use a package variable, which will:

  1. Allow mesh paths to follow a standard format, such as:
    <mesh filename="package://human-model-generator/meshes/Pelvis.stl" scale="0.58333333 1.03030303 1.03030303"/>
  2. Require the package variable to be set as an environment variable by the user. This variable should point to the meshes folder inside the human-model-generator repository.
  3. Enable interchanging URDF models without requiring any modifications to the file.
@LudovicaDanovaro
Copy link
Author

Steps

  1. Edit the URDF Model

    • Replace all hardcoded mesh paths in the URDF file with the format:
      <mesh filename="package://human-model-generator/meshes/[mesh_name].stl" scale="[scale_x] [scale_y] [scale_z]"/>
      where [mesh_name] is the name of the mesh file, and [scale_x] [scale_y] [scale_z] are the scaling factors.
  2. Set the Environment Variable

    • Inform users that they must set the package environment variable to point to their local path for the meshes folder. For example in Windows in cmd, run as administrator:
       setx package "C:\path\to\human-model-generator\meshes" /M
    • Add documentation on how to set environment variables for different operating systems (Linux, macOS, Windows).
  3. Update Documentation

    • Add a detailed section in the repository README file explaining:
      • The purpose of the package variable.
      • How to set the variable.
      • How the URDF references the mesh files using this variable.

@LudovicaDanovaro
Copy link
Author

Implementation

I have implemented the changes in the testAgnostic branch, with the corresponding commit 95b1e72. The main objective of these changes was to modify the .urdf model generated by the human model generator to make it agnostic to local directory paths for meshes. This was achieved by replacing the absolute paths with a standard package:// format, which will allow the model to be shared across different machines without the need for modification.

Code Changes

In the first part, the .urdf file is modified to remove any absolute paths to the mesh files. Instead of hardcoding paths, the mesh filenames are referenced with the package:// format, as shown below:

<visual name="Pelvis">
  <geometry>
    <mesh filename="package://meshes/Pelvis.stl" scale="0.6 1.06060606 1.06060606"/>
  </geometry>
  <material name="Link">
    <color rgba="0.9922 0.8667 0.7922 1.0"/>
  </material>
  <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
</visual>
<visual name="Pelvis_RightRecAbd">
  <geometry>
    <mesh filename="package://meshes/Pelvis_RightRecAbd.stl" scale="0.6 1.06060606 1.06060606"/>
  </geometry>
  <material name="muscle">
    <color rgba="0.9922 0.8667 0.7922 1.0"/>
  </material>
  <origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0"/>
</visual>

This change allows the .urdf model to reference mesh files using a relative path structure, which can be dynamically adjusted depending on the environment variable for the mesh directory. This is crucial for sharing the model across different machines, as it removes the dependency on specific local directory paths.

Here’s the code that accomplishes this:

with open(URDF_FILE_PATH, "r") as file:
    urdf_content = file.read()

def modify_mesh_line(match):
    filename = match.group(1)
    scale_values = match.group(2)
    new_filename = "package://meshes/" + filename.split("\\")[-1]
    return f'<mesh filename="{new_filename}" scale="{scale_values}"/>'

modified_urdf_content = re.sub(r'<mesh filename=".*?\\meshes\\(.*?)" scale="(.*?)"/>', modify_mesh_line, urdf_content)

with open(URDF_FILE_PATH, "w") as file:
    file.write(modified_urdf_content)

print("[OUTPUT] Model with 'package' successfully created. ✔")

In the second part of the code, the process of visualizing the model requires the mesh files to be accessible using absolute paths. This is where the environment variable comes in: it points to the local directory containing the mesh files, allowing the model to load correctly in different environments.

Here’s how the environment variable is used to modify the .urdf file for visualization:

package_value = os.getenv('package')

if not package_value:
    raise EnvironmentError("The environment variable 'package' is not set")

with open(URDF_FILE_PATH, "r") as file:
    urdf_content = file.read()

def modify_mesh_line2(match):
    filename = match.group(1)
    scale_values = match.group(2)
    new_filename = f"{package_value}/" + filename.split("\\")[-1]
    return f'<mesh filename="{new_filename}" scale="{scale_values}"/>'

modified_urdf_content = re.sub(r'<mesh filename=".*?//meshes/(.*?)" scale="(.*?)"/>', modify_mesh_line2, urdf_content)

with open(URDF_FILE_PATH, "w") as file:
    file.write(modified_urdf_content)

print("[OUTPUT] Model with path successfully created. ✔")

This approach ensures that the model can be visualized with the correct mesh paths when the environment variable is set.

To make this work, users must set the environment variable package to point to their local meshes directory. This can be done as follows:

  • On Windows, run the following command in cmd (as Administrator):
    setx package "C:\path\to\human-model-generator\meshes" /M
    
  • On Linux or macOS, use the following command in the terminal:
    export package=/path/to/human-model-generator/meshes
    

@traversaro
Copy link
Contributor

traversaro commented Dec 11, 2024

Hello @LudovicaDanovaro , I am afraid using package env variable and interpreting the package:// uri in this way is not compatible with how most tools interpret URDF files. For a simple example of a library that transforms package:// uri to absolute file paths, check https://github.com/ami-iit/resolve-robotics-uri-py and https://github.com/ami-iit/resolve-robotics-uri-py/blob/main/src%2Fresolve_robotics_uri_py%2Fresolve_robotics_uri_py.py

@LudovicaDanovaro
Copy link
Author

@traversaro I modified the main.py in this commit by using the pachage:// URI instead of the environment variable. Did you mean to do it this way?

@traversaro
Copy link
Contributor

@traversaro I modified the main.py in this commit by using the pachage:// URI instead of the environment variable. Did you mean to do it this way?

Just FYI, the link to the commit I guess is 1048b96 . Anyhow, while I see that we are not setting anymore the package environment variable, I am not sure I get what is the goal of your modifications. In particular, it is not clear to me how the files generated by this repo are typically consumed downstream by other sofware. If you want we can quickly align on Teams or in persons.

@traversaro
Copy link
Contributor

More in general, instead of parsing the generated URDF two times to modify some values, could it make sense to directly set the mesh URI we want to set in

filename=os.path.join(mesh_folder, f"{link_name}.stl"),
scale=[scale["X"], scale["Y"], scale["Z"]],
combine=False,
)
),
origin=original_origin,
material=Material(name="Link", color=OPT_COLOR_LINK_MESH),
)
link.visuals = []
link.visuals.append(visual)
if link_name in map_link_to_muscles:
muscles = map_link_to_muscles[link_name]
for muscle in muscles:
muscle_scale = scalingParamMesh[link_name]
muscle_visual = Visual(
name=muscle,
geometry=Geometry(
mesh=Mesh(
filename=os.path.join(mesh_folder, f"{muscle}.stl"),
scale=[
?

@LudovicaDanovaro
Copy link
Author

@Supermonkey-design

@LudovicaDanovaro
Copy link
Author

At the moment of this commit, there are already some issues. To solve this problem I opened an issue in https://github.com/fishbotics/urchin: fishbotics/urchin#28

@traversaro
Copy link
Contributor

Thanks @LudovicaDanovaro ! In the meanwhile using the absolute path when dealing with urchin and then changing the path in the xml is a perfectly fine workaround!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants