跳到正文
DEV Community· sishiya (しし屋)·· 2 小時前AI 評分48

以手寫 2D 物理和遺傳算法教彈簧關節生物行走

Teaching spring-and-joint creatures to walk with a genetic algorithm (hand-written 2D physics)

AI 導讀

Manabi Lab 製作的網頁以手寫 2D 物理和遺傳算法,讓由關節球和彈簧肌肉組成的生物演化,以走得更遠為目標。生物在平地、斜坡、冰面、月球及水下環境中移動,每次模擬 15 秒,並設有碰撞和有效身體檢查,避免演化利用物理漏洞。編寫網頁和文章時使用了 Claude。

正文

I made a page where creatures made only of joints (balls) and muscles (springs) evolve with a genetic algorithm (GA) to travel as far as possible. Besides flat ground, you can pick a slope, ice, the Moon or underwater. The physics and the GA are both hand-written, no libraries.

https://sishiya.github.io/manabi-lab/ga-creatures/?lang=en

Creatures start with random shapes and rhythms, and over the generations they find bodies and ways of moving that go forward in their environment. This post covers how the bodies and physics are built, and how I kept the GA from exploiting gaps in the physics.

Genes = the body's blueprint

One creature's genes hold:

  • positions of 3–8 joints (inside a 1 m square) and the foot friction coefficient (0.2–1.2)
  • for each muscle: the two joints it connects, contracted and extended lengths (0.15–1.6 m), spring constant (150–600 N/m), when in the cycle it starts contracting and for how long
  • the body's rhythm period (0.4–2.0 seconds)

A muscle is a damped spring (damping 0.5 of critical) that heads toward the short length during its contraction window and the long length otherwise.

Physics: 15 seconds at 1/120-second steps

  • joints are 2 kg balls, moved for 15 seconds at 1/120-second steps (1800 steps)
  • the ground pushes back penetrating joints and removes downward speed, with no bounce
  • sideways speed is reduced by friction and a "grip on the ground" force

The score is the center of mass's x after 15 seconds minus its starting x.

Environments just change gravity or friction:

Environment What changes
Slope gravity tilted 10° (the picture is rotated)
Ice friction × 0.1
Moon gravity 1.62 m/s²
Underwater gravity 0 (neutral buoyancy), quadratic drag on speed perpendicular to each muscle rod

The slope started at 15°, but even after 100 generations creatures only got 4 m, so it became 10°.

Preventing bodies from passing through themselves

The first version had no collision between body parts. That allowed motions impossible in a plane, like a joint passing through its own muscle rod. Where the physics has a gap, a GA will find solutions that use it.

So from v3, there is collision, collideBody():

  • joints are 5.5 cm-radius balls, muscles 6 cm-thick rods
  • penetration is pushed back in proportion to mass, and approaching speed is removed (no bounce)
  • each joint remembers which side of a muscle it is on, and is put back if it ends up on the other side (no tunneling even when fast)

After adding collision, I checked that momentum is conserved and that mechanical energy does not increase for a body with its muscles stopped.

Speed is about 100 ms per generation of 100 creatures (15–35 ms before collision).

A body whose physics broke scores 0

A body with strong springs might make the integration diverge and fly off. Since the score is distance traveled, that would count as "went far".

So if speed exceeds 60 m/s, the calculation is treated as broken and the score is 0.

Only bodies buildable in a plane are born

A body whose joints are too close or whose muscles cross cannot exist in a plane. So bodies are born only if they satisfy validBody():

  • joints at least 13 cm apart
  • joints at least 10.5 cm from muscles not attached to them
  • no muscles crossing

If a mutation breaks the shape, it retries up to 10 times; otherwise the parent is kept. If crossover's mixing of joint positions breaks it, positions come from one parent.

Inside the GA

Two selection methods:

  • Top half: the top half survives as is, and each makes one child
  • Tournament: only the top two survive; for the rest, the stronger of two random creatures becomes a parent

Mutations nudge values on a log-normal scale, and also change the body: adding or removing joints, adding or removing muscles.

Crossover starts from one parent's shape and takes same-numbered joints, muscles linking the same two points, and the period from the other parent with 50% chance. Between parents of different shapes, only the overlapping parts mix (a simplification).

A small gotcha

All scripts share names at the top level, so naming the body thickness BODY collided with the font setting BODY in the drawing code and stopped loading. Now I grep for any new uppercase name before using it.

Main sources

  • J. H. Holland (1975) Adaptation in Natural and Artificial Systems
  • K. Sims (1994) "Evolving Virtual Creatures", SIGGRAPH 94

This page is part of Manabi Lab, a series of small learning apps that run in the browser (English and Japanese). The code and this post were written together with AI (Claude).

https://sishiya.github.io/manabi-lab/?lang=en

來源:DEV Community · dev.to