Quentin Becker*
·
Oliver Gross*
·
Mark Pauly
(* denotes equal contribution)
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.
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 casegeolab, which contains some useful input-output functions for geometric data, andtorchcubicspline, 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 inpython/experiments/: Seesnake_straight_traj_parse.ipynbthat 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 (inpython/experiments/), the functions related to forward simulation and sensitivity analysis, and utilitary functions. Inpython/experiments/, we name experiment scripts and settings scripts by pairs: For instancesnake_straight_traj.pyandsnake_straight_traj_settings.py. You can create your own experiment by following the same template.
First, clone the repository recursively as follows
git clone --recurse-submodules -j8 git@github.com:EPFL-LGG/inverse_geometric_locomotion.gitOr if you already cloned the repository, run
git submodule update --init --recursiveMake 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 --installNote 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.
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=0After 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 timei.gis an array of shape(n_ts, 7)serves registering the shape in the world space. Each rowg[i]is a rigid transformation at timeiwhereg[i, :4]is the unit quaternion representing the rotation andg[i, 4:]is the translational part.posis an array of shape(n_ts, n_points, 3)andpos[i]results from the application of the rigid transformationg[i]to the corresponding point cloudpos_[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')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},
}
