Random walk on animation channel

I want to add a random walk noise to the motion of an object. By random walk, I'm talking about the mathematical term. What it would mean is that for each frame the value of the channel is offset from it's value at the previous frame buy a random amount.

This is a diagram of a random walk on a grid. It demonstrates the idea, but the actual motion I am looking for is not constrained to even steps on a grid.

So I want to implement this on animation channels, like position and rotation. I'm trying to fake stop motion, and adding a bit of noise to the motion makes it look more convincing. But just adding noise to the channel doesn't look as good. This is because when you stop-motion animate something, you go frame by frame, adding on from the last position, whereas the noise channel modifier doesn't remember the value from the last frame, so the randomness isn't cumulative. It's a subtle difference.

So is there an already existing way to add random walk noise to animation channels, or am I going to have to script it myself?

• What about using a GeometryNodes modifier with a Simulation Zone and some *Empty*(s) to store the noise from last frame ? Commented May 6 at 13:37

(Using Blender 3.6.8)

Objective

To superimpose some cumulative randomness to a deterministic displacement.

The animation above shows a triangle animated with a uniform translation, and a decorrelated moving square put at the front of a random walk on a grid. Suzanne motion is a linear combination of both, with weighted contribution of randomness. It is to notice that Suzanne is not wandering away from the triangle, even if the random front is far from its starting position.
The animation below illustrates what could be achieved with a simulated Brownian motion instead of a random walk on a grid.

Approach

To detail the explanation, the process is split in many objects, some with dedicated GeometryNodes modifiers.

1. Deterministic Walker (Prism):
1.1. Its position is animated by inserting keyframes after moving it, at frames 1 and 250 for the demonstration.
1.2. Using the Graph Editor, a Linear Interpolation Mode is set for all three coordinates.
2. Random Path & Path (Lattice):
2.1. The random walk on a grid is built with a GeometryNodes modifier based on a Simulation Zone, and it is manipulated as an independent Mesh.
2.2. For the demonstration, the "Path" object is just giving some volume to the "Random Path" object to render it.
3. Random Walker (Cube):
3.1. To track the front of the random walk and to access its displacement, a GeometryNodes modifier is attached to an object "exposing" its position for other objects to read.
3.2. For the demonstration a Cube is used, but a Single Vertex should be favoured if only one single position has to be "exposed".
4. Walker (Suzanne):
4.1. A GeometryNodes modifier is attached to the object to animate. Its inputs are:
4.1.1. The weight scaling the random contribution.
4.1.2. Both walkers, random and deterministic.
4.2. The Location of the deterministic walker is recovered through an Object Info node.
4.3. The Position of the first vertex (i.e. with Index 0) of the random walker is recovered by a Sample Index node set in Point domain.
4.4. A weighted linear combination is computed by a Multiply Add math node.
4.5. The origin of the object is not modified, only its vertices position with a Transform Geometry node.

NB: Obviously for final rendering, all these objects should be hidden except the Walker (i.e. Suzanne for the demonstration).

Random path and walker

1. The path is made of adjacent edges added using a Join Geometry node, one at a time inside a Simulation Zone.
2. Such an edge is built with a Mesh line node with just two points:
2.1. The first end point position is recovered from the previous frame through the Prev input socket, initialized as (0,0,0) at frame 1. A Sample Index node is required to get a single position, independent of how many points are in the recycled Geometry. To do so, its Index socket is hardcoded to 0.
2.2. The second end point position is defined by an Offset. Consequently, its value is captured after the Mesh line node by a Sample Index node with Index set to 1, to be transferred to the next frame.
3. (dark red frame) To simulate a random walk on a grid, the offset is drawn from a "lookup table" using a Sample Index node:
3.1. Four vertices at cardinal directions are generated by a Mesh Circle node set with a unitary Radius.
3.2. A random integer between 0 and 3 is drawn with a Random Value node whom Seed is changing with the Frame count recovered through a Scene Time node. It is to notice that the ID input socket is hardcoded to 0 to get a single random value.
4. (dark green frame) To simulate a Brownian motion (i.e. the limit of a random walk when the step size goes to zero), the offset is drawn with a Random Value node with Data Type set to Vector.
5. Because a random walk might drift significantly before a very large number of steps is made to get a statistically centred distribution, the current path is centred at every frame, outside of the Simulation Zone:
5.1. The centre of its Bounding Box is computed as the average between Min and Max corners position.
5.2. This vector is subtracted from every vertex position using the Translation of a Transform Geometry node. So the origin of the object is not affected, but its points are moved "around" its origin.

1. To "expose" the location of the random path front at each frame, the above GeometryNodes modifier is attached to an object with at least one vertex, if only one vector must be exposed. NB: If more information must be exposed, other vertices of the same object can be used to encode more data by adapting this graph.
2. The Geometry of the random path is recovered through an Object Info node.
3. By construction, the front is the last point. Its index is computed by subtracting 1 to the number of points recovered through a Domain Size node.
4. From this Index, a Sample Index node is used to get the front Position, that can be scaled with the Randomness user-defined parameter.
5. This vector is used to shift the "exposing" object using a Transform Geometry node. NB: Consequently, the exact front position might not be transferred. If this is a requirement, a Set Position node should be used instead.

How to use it

The "Random Walker" GeometryNodes modifier can be attached directly to an object with keyframed "deterministic" transformations, without using an intermediate "observer" and a weighted linear combination. Other randomized Paths can be added to make noise on rotation and scaling.

Resources

Path Renderer

1. To visualize the random path, edges are converted to curves, to transform these to cylinders using a classical Mesh to Curve & Curve to Mesh nodes sequence.
2. It is to notice that to reduce the resulting mesh size, a Merge by Distance node is inserted after the path Geometry is recovered through an Object Info node. This node is not incorporated in the path builder GN graph as it is reordering vertices. Consequently, the last point might not be the path front when backtracking occurs.

Blender file:

• This is a very rigorous exploration of the topic! I noted in the question that I wasn't after motion constrained to unit steps on a grid, but rather something like Brownian motion, but this might be useful to someone.
– stib
Commented May 9 at 5:53

Thanks to @StefLancien for suggesting geometry nodes, of course geonodes is the answer!

If anyone is playing along at home this geonode setup uses a random vector offset which accumulates inside a simulation zone. It is applied equally to all the points in the geometry (by overriding the ID field, otherwise each point is offset individually which distorts the mesh. The value you give for the ID is not important, it can be anything).

Here's the updated node tree, using Scene time to drive the seed (thank you @StefLAncien). Also all the unnecessary nodes have been moved out of the simulation zone, as it's only the vectors that need to be incremented, this is simpler and probably faster to calculate. The cumulative randomness is calculated with a random offset per frame of -1 to 1, then this is scaled outside the simulation zone using the controls. This makes it simpler, and means that you can bake the simulation, but then change the size of the effect without having to re-bake.

This also applies random, cumulative rotation (not shown in the gif, I couldn't be bothered going through the process of making a new gif). Scale would be trivially easy to add, I leave that as an exercise to the reader.

The position noise is only on x and y, you could add the output of the variance nodes to the combine xyz nodes to add Z motion, ditto for rotation, it's only on the Z axis.

• (1) Instead of incrementing a "seed", the Frame count can be used from a Scene Time node. (2) Delta Time is not changing because from the documentation, it is "The time in seconds between frames", not the time since the first frame. Commented May 9 at 16:55
• Ah, thanks. That explains delta time as well.
– stib
Commented May 10 at 0:02