Simulate and optimize planar leg mechanisms using PSO and GA
LeggedSnake is a project intended to make the simulation of walking linkages fast and easy. We believe that building walking linkages is fun and could be useful. Our philosophy is to provide a quick way of building, optimizing and testing walking linkages.
We handle planar leg mechanisms in three main parts:
- Linkage conception in simple Python relying on pylinkage.
- Kinematic optimization with
Walkerclass, inheriting from pylinkage's
- Dynamic simulation and its optimization using genetic algorithms.
- For the documentation, check the docs at hugofara.github.io/leggedsnake!
- Source code is hosted on GitHub as HugoFara/leggedsnake
- We also provide a Python package on PyPi, test leggedsnake.
- If you just want to chill out looking at walking linkages striving to survive, join the discussions.
Contributors are welcome!
The package is hosted on PyPi as leggedsnake, use:
pip install leggedsnake
Setting up Virtual Environment
We provide an environment.yml file for conda. Use
conda env update --file environment.yml --name leggedsnake-env to install the requirements in a separate environment.
If you are looking for a development version, check the GitHub repo under HugoFara/leggedsnake.
Python 3, numpy for calculation, matplotlib for drawing, and standard libraries.
For kinematic optimization you can either use the built-in algorithm, or PySwarms, under MIT license. PySwarms is a much more complexe package which provides quick calculations, however with modern laptops the built-in swarm optimization should be quick enough to fit your needs.
Dynamic optimization relies on multiple packages. First of all it uses Pymunk, made by Victor Blomqvist, as a physics engine. Then you can either use the built-in algorithm, or the GA module from PyGAD. PyGAD is a complete library providing much more than genetic algorithms, so it might be heavy. PyGAD is more complete than the built-in however, so I haven't decided to continue on PyGAD or switch for another solution in the future.
First, you need to define joints for your
Walker as described in pylinkage documentation. Once your joints (let's say they are in a joint object), you should have something like that:
import leggedsnake as ls # Center of the Walker A = ls.Static(x=0, y=0, name="A") B = ls.Crank(1, 0, distance=1, angle=0.31, name="Crank") # etc... let's say with have joints up to E my_walker = ls.Walker( joints=(A, B, C, D, E), name="My Walker" )
Walker is just a herited class of
Linkage, with some useful methods, and behaves quite the same way.
Kinematic optimization using Particle Swarm Optimization (PSO)
No change compared to a classic linkage optimization. You should use the
stride method from the utility module as fitness functions.
This set of rules should work well for a stride maximisation problem:
- Rebuild the Walker with the provided set of dimensions, and do a complete turn.
- If the Walker raise an UnbuildableError, its score is 0 (or
- float('inf')if you use other evaluation functions.
- Verify if it can pass a certain obstacke using
stepfunction. If not, its score is 0.
- Eventually mesure the length of its stide with the
stridefunction. Return this length as its score.
Dynamic Optimization using Genetic Algorithm (GA)
Kinematic optimization is fast, however it can return weird results, and it has no sense of gravity while walking heavily relies on gravity. This is why you may need to use dynamic optimization thanks to Pymunk. However the calculation is much more slower, and you can no longer tests millions of linkages as in PSO (or you will need time). This is why we use genetic algorithm, because it can provide good results with less parents.
We handle everything almost evything world definition to linkage conversion. Appart from the GA parameters, you just have to define a fitness function. Here are the main steps for a maximisation problem:
- Create a function of two arguments, the first one should be the paramaters of the linkage, the second the initial positions for the joints.
- Try to do a revolution in kinematic simulation. If the Walker raises an
UnbuildableErrorset its score to
- Otherwise use this procedure
def dynamic_linkage_fitness(walker): """ Make the dynamic evalutaion of a Walker. Return yield and initial position of joints. """ world = pe.World() # We handle all the conversions world.add_linkage(walker) # Simulation duration (in seconds) duration = 40 # Somme of yields tot = 0 # Motor turned on duration dur = 0 n = duration * pe.params["camera"]["fps"] n /= pe.params["simul"]["time_coef"] for j in range(int(n)): efficiency, energy = world.update(j) tot += efficiency dur += energy if dur == 0: return - float('inf'), list() print("Score:", tot / dur) # Return 100 times average yield, and initial positions as the final score return tot / dur, pos
And now, relax while your computer recreates a civilisation of walking machines!
For this part we will focus on the Strider linkage, an exemple file is provided at
docs/examples/strider.py. The linkage looks like this:
Looks cool? Let's simulate it dynamically!
Oops! Here is what you get when you forget to add more legs! There is real danger here, because your walker crawls well, you will be able to optimize efficiently the "crawler", which may be not your goal.
Let's add three more leg pairs. Why three? Many legs means more mass and constraints, so less yield and more intensive computations. On the other hand, we always want the center of mass over the support line, which means that if the walker begins to lift a foot (let's say a front foot), and another doesn't come on the ground ahead of it, the linkage will to fall nose to the ground. With more foots we make the "snooping" time shorter, and a total of four leg pairs is a minimum for this unoptimized version.
A simple way to do it is:
my_linkage.add_legs(3) # Replace "my_linkage" with your Walker object
Let's have a look at the artist:
Use the vizualisation tools provided! The optimization tools should always give you a score with a better fitness, but it might not be what you expected. Tailor your optimization and then go for a long run will make you save a lot of time.
Do not use optimized linkages from the start! The risk is to fall to quickly into a suboptimal solution. They are several mechanisms to prevent that (starting from random position), however it can always have an impact on the rest of the optimization.
Try to minimize the number of elements in the optimizations! You can often use some linkage's properties to reduce the number of simulation parameters. For instance, the Strider linkage has an axial symmetry. While it is irrelevant to use this property in dynamic simulation, you can use "half" your Strider in a kinematic optimization, which is much faster:
Release history Release notifications | RSS feed
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Hashes for leggedsnake-0.3.0-py3-none-any.whl