Hello coder magicians, i am looking for a pattern based on (or inspired by) the caterpillar walk as demonstrated in this video [Gut Check: Caterpillars Walk Gut First  YouTube]
Someone can help me out?
Hey @jdhollan 
Two questions for you.

Can you confirm you’re looking for this, but along a straight strip of LEDs? If so, how long is your strip (how many LEDs)? And what’s the spacial density (for example, 60 per meter)? Or, do you have a 2D matrix of pixels and want to show the gutfirst dynamic in 2D?

Can you give a sense for where you’re at in your coding journey? Are you looking for this one particular readymade pattern but aren’t likely to pick up coding on Pixelblaze over the long run? Or do you already know your way around some languages but are stuck on the math for this particular problem?
Thanks Jeff. Yes, i mainly work with 144 l/m strips and a diffuser at 2 cm distance so the individual pixels mix with the adjacent colors. The length is not important, the caterpillar goes from A to B, B to A all 2D
I am into lighting hardware, so my personal coding skills and maths are limited, but once the course is set, friends of mine will be glad to finetune.
The end goal is to make a pixelblaze animated clock dial where the caterpillar is the seconds hand movement.
Here’s something quick to get you started.
Some limitations vs your description, as I understood it:
 Points shift left and right, vs advancing
 The total number of pixels and base frequency spacing need to be multiples to repeat a circular cycle correctly
 The variable walking pulse width means there’s not a perfectly continuous motion (it pauses between pulses)
// Caterpillar
// Jeff Vyduna 2022, MIT License
// For: https://forum.electromage.com/t/caterpillarwalkinpixels/2701/2
// Inspiration: https://www.youtube.com/watch?v=ftaZpeG67vw&feature=youtu.be
var spacing = 30
var squeezeFactor = 4
var sharpness = 16
var t1
export function beforeRender(delta) {
t1 = 2 * (time(.1)  .5) // 1..1 ramp
}
var lastSign = 1 // 1 = positive or 0 = negative value
export function render(index) {
var frac = index / pixelCount
var freq = spacing + squeezeFactor * parabola((frac  t1), sharpness)
var cycle = sin(freq * frac)
// Detect zero crossings. Assumes stateful, indexordered rendering.
// Pixel is on if it follows a zerocrossing in a sinusoid
v = (cycle >= 0) != lastSign
lastSign = cycle >= 0
hsv(0, 0, v)
}
// Parabolic pulse. In 0..1, out 0..1, peak centered at x = 0.5
// Higher k gives a narrower pulse
// https://www.desmos.com/calculator/okkks9osla
function parabola(x, k) {
if (x <= 0  x >= 1) return 0
return pow(4 * x * (1  x), k)
}
@jeff, I think we had just about the same idea  model the stretch/squash movement with a sineish waveform. I’m traveling, so it’s a little awkward, but here’s my first take:
// Caterpillar movement test
//
// Drives a multisegment critter around the screen, using
// a sinusoid to play with the distance between segments.
//
// MIT License
// 12/2022 ZRanger1
//
var wormSize = 0.075;
var segSpacing = .34;
var segments = 5;
var speed = .61;
var timebase = 0;
var t1,t2,t3;
var xoffs = array(segments);
var yoffs = array(segments)
// center origin and scale coords so they range from 1 to 1
translate(0.5,0.5);
scale(2,2)
export function beforeRender(delta) {
timebase = (timebase + delta / 1000) % 3600;
t1 = timebase * speed; // movement speed
t2 = time(0.1); // color change speed
// calculate segment distance stretch/squish
t3 = 0.5+0.5*(1wave(time(0.03)));
// move the entire critter along a circular path
for (i = 0;i < segments; i++ ) {
var t = t1 + (segSpacing*t3 * (i+1));
xoffs[i] = 0.9 * sin(t)
yoffs[i] = 0.9 * cos(t)
}
}
export function render2D(index,x,y) {
var b = 0;
// Add the light contribution of each segment to the current pixel value
for (i = 0; i < segments; i++) {
var px = xoffs[i];
var py = yoffs[i];
b += wormSize / hypot(xpx,ypy) ;
}
b = smoothstep(0.5,5.4,b)
hsv(t2,1b/6,b);
}
Looks like longitudinal waves to me…
numSegments = 5
forwardSpeed = 0.2
mean = 0.5
stddev = 0.2
backwardSpeed = 0.3
A = 0.1
lambda = 0.2
phi = 0
export function beforeRender(delta) {
t1 = time(forwardSpeed)
t2 = time(backwardSpeed)
phi = time(0.3)
}
export function render(index) {
// start with a travelling wave
x = frac(t1 + displacement + index/pixelCount*numSegments)
// set up an opposing wave.
displacement = A * sin(PI2 * t2 / lambda  PI2 * t2 + phi)
// turn it into a normal curve
fx = exp(1 * pow(x  displacement + 0*mean, 2) / (2*pow(stddev, 2))) / (stddev * sqrt(PI2))
hsv(0.3, 1, fx)
}
This is so nice to look at! I post some videos here. The setup is a ring with inner and outer rgbstrip. [Jacob on Instagram: "With the help of some smart coders at Electromages forum this CATERPILLAR movie got live!"]