Skip to content

About

This repository contains the source code and data for Inverse Geometric Locomotion, published at SIGGRAPH 2025.

Resources

Stars

20 stars

Watchers

1 watching

Forks

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Inverse Geometric Locomotion

Teaser

Quentin Becker* · Oliver Gross* · Mark Pauly
(* denotes equal contribution)

Paper PDF Project Page

About

This repository contains the source code and data for Inverse Geometric Locomotion (IGL), published at SIGGRAPH 2025.

Tools from this repository solve the control problem of geometric locomotion i.e., motion solely determined by a body's changing shape.

Motion From Shape Change introduces a dissipation metric unifying purely inertial (platform divers, astronauts) and dissipative setups (snake, worm, or sperm cell motion), but requires users to manually design the gaits. By introducing reduced shape spaces, space-time interpolation, and regularizations, IGL efficiently recovers a shape sequence that achieves a user-defined goal through first-order continuous optimization. See for instance the snake making its way through the obstacles to reach the flags above.

Code Structure

The repository is structured as follows,

inverse_geometric_locomotion
├── data
├── ext
│   ├── geolab
│   └── torchcubicspline
├── images
├── notebooks
├── output
└── python
    ├── experiments
    │   ├── *_settings.py
    │   └── *.py
    ├── *.py
    └── *utils.py

In alphabetical order,

  • data/ stores some meshes that are used in some experiments.
  • ext/ contains external libraries that are needed for the project. In our case geolab, which contains some useful input-output functions for geometric data, and torchcubicspline, a PyTorch-based library that contains utilities to parameterize and optimize snake gaits using a few control points.
  • images/ contains some illustrations for this README file.
  • notebooks/ is where you can create notebooks to interactively experiment with the code. We typically use them to peak at optimization results generated by scripts in python/experiments/: See snake_straight_traj_parse.ipynb that parses and visualizes results.
  • output/ will be populated when you run experiments and is intended to store code output (forward simulation and optimization) as well as graphs, metrics, renders, etc.
  • python/ contains scripts for running experiments in parallel (in python/experiments/), the functions related to forward simulation and sensitivity analysis, and utilitary functions. In python/experiments/, we name experiment scripts and settings scripts by pairs: For instance snake_straight_traj.py and snake_straight_traj_settings.py. You can create your own experiment by following the same template.

Installation

First, clone the repository recursively as follows

git clone --recurse-submodules -j8 git@github.com:EPFL-LGG/inverse_geometric_locomotion.git

Or if you already cloned the repository, run

git submodule update --init --recursive

Make sure you have pandoc installed on your machine. This part is only relevant for the astronaut example and can be skipped.

Simply create a conda environment and install the dependencies

conda create --name igl_env
conda activate igl_env
conda install -y scipy=1.10 matplotlib numpy=1 jupyterlab tqdm opencv absl-py
conda install -y pytorch::pytorch -c pytorch
conda install -y -c conda-forge meshplot nbstripout pypandoc
pip install ffmpeg-python
pip install libigl
pip install pygmsh
nbstripout --install

Note that ffmpeg-python might not be compatible with your os (in particular for Windows users). In that case, please install conda install -y ffmpeg instead.

Run code

Simply activate your environment and run

jupyter lab

You can also run experiments scripts in python/experiments/ by executing the following command in a terminal inside the experiments/ subfolder with the igl_env conda environment activated,

python snake_straight_traj.py --trial_number=0

Parsing results

After running an optimization script i.e., a script matching python/experiments/*.py, a .json file is produced as a way to keep a record of the optimization progress and the resulting gait. It is typically located in the output/ folder and is generated by one of the functions in python/geometry_io.py.

Notwithstanding some slight differences, export_snakes_to_json, export_meshes_to_json, and export_graphs_to_json all export pos_, g, pos which can be used to construct the shape sequence:

  • pos_ is an array of shape (n_ts, n_points, 3) and represents the gait in the shape space. Each "row" pos_[i] is a point cloud at time i.
  • g is an array of shape (n_ts, 7) serves registering the shape in the world space. Each row g[i] is a rigid transformation at time i where g[i, :4] is the unit quaternion representing the rotation and g[i, 4:] is the translational part.
  • pos is an array of shape (n_ts, n_points, 3) and pos[i] results from the application of the rigid transformation g[i] to the corresponding point cloud pos_[i]. It is therefore the displaced shape.

Each data type has its own connectivity type (edges or faces) and is stored in the output .json file. We leave it to the user to convert the data to their prefered type. As an example, we provide conversion methods to wavefront .obj format next.

def write_obj_polylines(vertices, edges, output_obj_path):
    # Don't forget to increment edge indices by 1 since python indexing starts as 0.
    with open(output_obj_path, 'w') as obj_file:
        for vertex in vertices:
              obj_file.write(f'v {vertex[0]} {vertex[1]} {vertex[2]}\n')
          for edge in edges:
              obj_file.write(f'l {edge[0]} {edge[1]}\n')

def write_obj_surfaces(vertices, faces, output_obj_path):
    # Don't forget to increment face indices by 1 since python indexing starts as 0.
    with open(output_obj_path, 'w') as obj_file:
        for vertex in vertices:
              obj_file.write(f'v {vertex[0]} {vertex[1]} {vertex[2]}\n')
          for face in faces:
              obj_file.write(f'f {face[0]} {face[1]} {face[2]}\n')

Citation

If you use this codebase in your project, please consider citing our work:

@article{becker2025igl,
  author = {Becker, Quentin and Gross, Oliver and Pauly, Mark},
  title = {Inverse Geometric Locomotion},
  year = {2025},
  issue_date = {August 2025},
  publisher = {Association for Computing Machinery},
  address = {New York, NY, USA},
  volume = {44},
  number = {4},
  issn = {0730-0301},
  url = {https://doi.org/10.1145/3731187},
  doi = {10.1145/3731187},
  journal = {ACM Trans. Graph.},
  month = jul,
  articleno = {141},
  numpages = {17},
}

About

This repository contains the source code and data for Inverse Geometric Locomotion, published at SIGGRAPH 2025.

Resources

Stars

20 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages