The Lab

Subscribearticles
This blog documents the patterns that appear when I build systems, the limits I push to see where they break, and the concepts that change how I design. Analysis, field notes, open questions.

Grab the float by its antenna and pull. Choose a fish bite, trigger a rise, turn on the rain or the wind. The Reset button brings the pond back to its starting state.

Real-time water simulation with WebGL and three.js: physical buoyancy, GPU waves and Snell refraction

3 hours ago
Interactive A fishing float on a pond, in real time in the browser, with no video and no pre-rendered frames. It is the first scene of the water work in Genesis 3D, my web 3D editor: a shot I would have rendered offline a few years ago, held here at display rate, and interactive.

GPU wave simulation: the wave equation on a heightfield



The surface around the float is a 512 × 512 heightfield over 2 × 2 m, about 4 mm per cell. The wave equation runs in a fragment shader, ping-ponging between two render targets in 4 ms substeps. The grid follows the float, shifting by a whole number of cells. It has three sources: the change in the float’s submerged volume, the meniscus rising and falling along the antenna (hence the constant rings), and the impacts of rain and fish rises.

Physical buoyancy: a rigid body in 64 slices



The float is a rigid body cut into 64 slices. Each one computes its submerged volume, its buoyancy and its drag. It carries 2.7 g of shot, in real units (metres, seconds, newtons). Fish bites are not animated: they are force functions applied to the line. The line is a Verlet rope that only transmits tension when taut, and that handles the wet or dry state of the nylon at the surface.

Water rendering: reflection, Snell refraction, absorption



Reflection comes from a mirror camera rendered into a render target. For refraction, whatever lies underwater is displaced in the vertex shader according to Snell’s law, with a bisection search for the point where the ray enters the surface. Screen-space refraction displaced thin objects: the line drew a V. Pond water absorbs light according to the real length of its path. Wind ripples are analytic wave trains modulated by a noise that sends gusts across the water.

Physical depth of field



The three.js BokehPass is corrected to compute a true lens circle of confusion, 1 − focus / depth, instead of a blur that grows linearly with distance. Everything that must be blurred therefore needs a real depth. Raindrops are instanced ribbons with the real thickness of a drop: one-pixel lines vanished in the blur.

Procedural rain



Rain rings are computed in the water shader. Four families of drops, from fine to heavy, are spread over hashed grids, with one draw per cell and per cycle, random sizes and showers that move in patches. Near the float, the drops also enter the wave simulation, and the float feels them.

Architecture: OffscreenCanvas in a Web Worker



The scene runs in a Web Worker with an OffscreenCanvas, so the page stays smooth while scrolling; Safari falls back to the main thread. Nothing is downloaded except the sounds: lily pads, leaves and environment are generated at load time. Sound goes through WebAudio, spatialised by the on-screen position of each event.

What we are working on



The same water at every scale, in real units: a glass you can tip over, a tank, a river made of PBF particles. And a sailing simulator: my gaff cutter on an FFT ocean, with wake, foam and apparent wind, in WebGPU.

DIP Rig: from 3D model to robot

1 month ago
I have been using Cinema 4D since I was about seventeen. I am forty-two today. For a long time, I never really asked myself why I spent so much time in that software. It was not especially to produce final images. Even less to become a modeler or animator in the classical sense. What interested me was always a little before the render. Understanding how a human body is built, why a joint works one way and not another, how a wing folds, how an object holds together, how a facade breaks down, how to get a credible volume with few enough polygons that every quad has a reason to exist. There was something like a puzzle in it. I could spend hours rebuilding an object just to understand how its forms were organized, then turn around it, move the parts, change a joint, and watch how everything else reacted. Photography probably taught me as much about 3D as 3D itself, because it forced me to understand what light actually does to volume. I think, deep down, I have always used creative tools as instruments for mentally taking reality apart.

The problem is that a traditional 3D scene always ends up dying the moment you decide to show it. You choose a camera, launch a render, and all the space you built is reduced to an image or a sequence where you decided in advance where someone would look. That has always frustrated me. I like to interact with things. I am not much of a gamer, but I like entering a system, moving around it, causing a reaction, seeing what changes. When I discovered Unreal, something clicked, because for the first time I could actually make things live inside the worlds I was building. Characters could exist there. Objects could respond. An environment could keep producing something after I stopped manipulating it directly. Virtual reality pushed that idea even further, but with an obvious limit: it is still hard to access. You need a headset, a machine, a setup, and sometimes you have to explain how to enter the experience before you can even show what it contains.

In February 2026, I discovered Three.js, and that is probably where part of what I do today began to come together. I created Genesis 3D because I wanted to put real interactive 3D content in a browser, without asking visitors to install anything and without turning my site into a technical demo with a thirty-second load time. I knew Spline and Vectary, but they were far too heavy for what I wanted. My site still had to score one hundred out of one hundred on Lighthouse while containing genuinely interactive experiences. That constraint had a healthy consequence: whenever a mechanism was not essential, it had to disappear. Genesis 3D was built that way, out of necessity, and it made me discover something I had not really formulated before: making an object feel alive often requires much less than we imagine, provided we act at the right level.

At first, I only wanted to display objects and manipulate them. Then I wanted them to move, then to respond, then to perceive. I started adding internal states to them. From that point on, I no longer really had an animated fish in front of me. I had a fish that could be hungry, tired, want to move closer to other individuals, flee something, or accept a risk it would have refused a few seconds earlier. I built simulations, small games, an aquarium, then a pond where the fish had a form of social life. One of the things that struck me most came from a very classic problem: the school. We know very well how to build a school of fish mathematically. Rules of cohesion, alignment, and separation have existed for a long time, and they can maintain a credible group. It works, but I realized I was working on the consequence without treating the cause. The math explains how a fish can stay correctly positioned among the others. It does not explain why it would want to stay there. If I give it fear of isolation, a need for protection, and a desire to survive, the problem changes completely. The mechanics of the school remain useful, but they become the final expression of a deeper motivation.

That is exactly the kind of shift that has fascinated me since I started working seriously on artificial intelligence. I spent about three years learning language models, agentic systems, memory, routing, attention mechanisms, and everything that allows several forms of intelligence to work inside the same architecture. Yet the further I go, the less the model itself interests me as the central object. What interests me is the point where several very simple mechanisms stop being isolated functions. Perception, memory, internal state, constraints, decision, action, learning: past a certain level of interaction, something happens between them. The system receives a change from the outside world. That change passes through its internal state. A response is produced. That response in turn changes the world. Then the system has to live with the consequence of what it just did. I think this is where what I call, for lack of a better word, life begins. Not magical consciousness. Not a chatbot with two mood variables added to it. A loop coherent enough that a digital organism stops merely executing orders and starts having to deal with what happens to it.

And quite naturally, all of this brought me back to Cinema 4D.

Returning to the starting tool



I needed a robotic arm for a new demonstration on my site. I could of course model and rig it in Cinema 4D as I always had, but I immediately ran into a problem I have known for a long time: traditional rigging there quickly becomes extremely heavy. To articulate an arm, a character, or a machine correctly, you usually assemble joints, IK chains, solvers that calculate the intermediate rotations needed to bring the end of a chain to a target, then a whole set of constraints meant to stop the system from using its freedom to do anything it wants. You impose a preferred direction, angular limits, controllers, targets, dependencies, sometimes fixes meant to stop another fix from creating unwanted behavior. It works, of course. Cinema 4D has been used professionally for decades, and I do not claim to know its internal implementation well enough to explain precisely why some rigs become so costly. But I see a typical problem of old, general-purpose software: layers have been added for years to answer very different uses, and they cannot simply disappear because thousands of scenes and workflows still depend on them.

What struck me while working in Three.js was that I could move a complete human body, with its constraints, directly in a browser at sixty frames per second, while some structures became painful to manipulate in Cinema 4D on the same machine. I had not invented a better universal solver. I had done almost the opposite: I had refused to build one. For a robotic joint, I only need an axis, a range, a position, possibly friction, and the geometric relationship with the next segment. The classical system starts from a structure free enough to answer a huge number of situations, then adds rules to forbid useless movements. I start from a structure that only knows how to do what it is physically supposed to do, and I add freedom only when it becomes necessary. That is the difference between an additive architecture and what I would almost call a subtractive one: instead of stacking mechanisms until the system behaves correctly, I start by removing everything that has no reason to exist.

But my main problem was not even performance. It was repetition. I had no desire to create a rig in Cinema 4D, then recreate another one in a web simulation, a third in the Python environment used for learning, and yet another logic on Raspberry Pi or Arduino when the arm became physical. A joint limit remains a joint limit wherever it is executed. A motor always has a rotation range, torque, speed, and inertia. Why rewrite the same reality four times just because the tool executing it changes? So the motivation behind DIP Rig is much less noble than a grand architectural revelation: I was being lazy. But that is often an excellent design constraint. I wanted to describe a mechanism once and be able to make it live everywhere.

The idea of plugins had started a few months earlier in a much more modest way. While working on Echo Bot, I needed to calculate the real length of cables passing through different parts of the robot. We had written a few Python scripts to solve that in Cinema 4D. They worked well, and I thought it was stupid to leave that mechanism as temporary scripts that would end up lost in a folder when it could become a real tool. The first plugin was born like that. I think it is simply called Cables. I liked the idea, but I put it aside. Between printing, wiring, and soldering Echo, rebuilding the site, and the rest of my projects, properly learning everything about interfaces and the C4D plugin ecosystem was simply not a priority.

Coming back to the articulated arm reopened the subject. I first wanted to check that I could communicate cleanly with the outside world from Cinema 4D. I had already installed conversational assistants in most of my applications, so bringing the principle here felt natural. In a few hours, I had a chatbot able to talk to an external API and act inside the software. It became DIP Chat, or Cath depending on the place. For now, I see it mostly as proof that the bridge works. It can obviously be used to automate a huge number of tasks: correctly renaming fifty joints, reorganizing several hundred objects, finding a part in a hierarchy, or preparing a scene are not things I want to spend my attention on. Those are exactly the tasks an assistant should absorb so I can work on what actually matters. For it to become a general-purpose tool, though, it will need something much cleaner than one large prompt filled with documentation. Cinema 4D has a considerable number of commands, parameters, and workflows. Sending all of that with every request would be as costly as it is inefficient. So I started an attention mechanism able to identify the need, provide the agent only with useful context, and give it access to a knowledge base when it has to look further. It is a huge project, probably a full-time job if I want to do it properly, and paradoxically it is not what interests me most in Cath. What interests me is turning it into the language interface for speaking directly to the systems living inside the scene.

That is where DIP Rig comes in.

Building a body once



The plugin begins deliberately simply. You open an empty scene, launch DIP Rig, and choose the type of body to generate. I started with a six-axis robotic arm because it is probably the best object for testing everything I want to build without mixing too many problems at the same time. No navigation, no dynamic balance as on a biped or a hexapod, no dozen limbs that need to coordinate: a few motors, a limited work volume, and a set of actions that are easy to define. Find an object, approach it, grasp it, move it, put it down. Understand an order. Say yes or no when an action is possible or impossible. Execute.

The plugin then asks for the type of end effector. We started with a fairly classic parallel gripper, but the same logic can support a hand, a printing tool, a milling head, or any system that needs different kinematics. You define the main dimensions of the arm, then DIP Rig generates a first chain of markers that you can move to adjust proportions. I like starting in that direction: build the mechanics first, then draw around them, rather than modeling a beautiful object and discovering afterward that its real articulation makes no sense. The current arm is deliberately plausible. Lengths, axis positions, and lever arms were drawn so they would not require absurd effort from the motors when the system is transposed physically.

Once the markers are in place, one click on Build generates the joint chain, axes, main limits, and a low-definition mesh that can be used immediately. This mesh is not meant to become the final model. It simply gives a clean enough base to understand the volume and start working. From there, I can manipulate the arm directly, animate it with keyframes and Bézier curves like any other rig, or take each element in the hierarchy, work on it in a separate document, model a real part around the existing center distances, then place it back into the project. As long as the axes and distances are respected, the system does not change. So you can gradually move from an arm made of primitives to a machine detailed down to the servo housings without rebuilding the mechanics.

But the truly important part is not the rig generation. It is the DIP Rig tag added to the chain. I see it as a program inside the program. Cinema 4D becomes the environment that hosts the scene and the creation tools. The tag embeds the mechanics that give behavior to the body. Motion engine, constraints, motor description, useful physical model, perception, internal state, then gradually decision, language, and learning. The principle is to keep this intelligence independent enough from Cinema 4D that it can be carried elsewhere. Today it runs in Python inside the software. An equivalent version can run in JavaScript inside Genesis 3D. Another can end up on the controller of a real machine. What I want to export is therefore not only a model or an animation. I want to export the physical logic of the body.

This distinction matters because it completely changes the role of Cinema 4D in my work. It is no longer simply the software where I model what I will later build. It becomes a laboratory where I can build, simulate, observe, and prepare the real machine with the same constraints that will continue to exist once it leaves the screen.

We already ran into a case that sums up this philosophy quite well with the gripper. To get a functional grasp quickly, we had started by welding the object to the palm: as soon as the jaws closed on it, a frozen matrix made it part of the hand. Technically, it worked very well. I had it removed almost immediately because it was magic. If I am building a system meant to learn how to grasp objects, I cannot artificially remove the entire interesting part of the problem at the moment when surfaces come into contact. With a weld, all grasps are equal: straight, crooked, by a corner. There is nothing left to learn. A real gripper holds because it applies force, because materials produce friction, because the object resists, and because the motors return information about the effort they are providing. A grasp can be bad, slip, require too much torque, or start becoming unstable. If the simulator turns all of that into a simple “attached” boolean, the robot does not learn to grasp. It learns to trigger a function.

So we made the jaws kinematic. A kinematic jaw has infinite mass, because a motor holds it and nothing should be able to push it back, but it has real speed and participates in contacts like any other body. The object is then attached to nothing: it is held by friction between the two jaws, and by nothing else. Clamped hard and well centered, it holds. Clamped softly or crookedly, it slips and falls. Nobody wrote “release”: it became a consequence.

And that was not enough. A jaw driven by position produces no normal force, so friction has nothing to multiply. The measurement is clear: the hand rises thirty centimeters and the cube stays on the table. We had to go down one more level and drive the jaw not by position but by force, on a rail with a single degree of freedom, solved with the contacts. Only then did the grasp begin to exist.

It is a small technical story, but it contains two things that keep returning in my systems. The first is that an interesting simulation must be able to fail: if it protects the system from error, it also removes the possibility of learning why that error exists. The second is less pleasant, and I find it even more useful: replacing a shortcut with a real mechanism is not enough if that mechanism is not fed by anything. Friction was the right answer. It remained ineffective as long as no force came to feed it.

When a command becomes a behavior



Saying “take the red cube and put it on the left” seems like a simple command. In reality, it is interesting precisely because it forces several levels of the system to collaborate without any of them being able to solve the problem alone. First it has to understand what I am asking, then identify the red cube. If it is not visible, the robot has to explore its environment, move its camera or its body depending on its morphology, until it finds something that matches the target well enough. Then comes a first decision: is this object actually manipulable? Is the gripper large enough? Is the required effort compatible with the motors? Does the cube’s orientation allow a correct grasp, or would it be better to push it slightly so it presents itself differently?

That last question matters more than it seems, because it immediately reveals the problem of compromise. An excessively cautious system can spend ten hours adjusting an object to get a theoretically perfect grasp. Conversely, an overly aggressive system will accumulate failures and wear. Part of intelligence, then, is determining what is good enough. At some point, it has to accept risk and try. When the gripper closes, the force feedback from the motors becomes a sensor in itself. Pressure increases until contact. If it then varies while the object is supposed to be still, something may be slipping. The robot can slightly adjust its grip, change orientation, tighten, or decide that the situation is not reliable and start again.

Once the object is grasped, the path to the target creates another set of problems. The shortest movement through space is not necessarily the best. A direct trajectory can intersect another object, put too much load on a joint, or place the arm in a configuration it will later struggle to leave. It may be more efficient to rise, move around an obstacle, then come back down. If the requested area already exists in spatial memory, the system can go there directly. Otherwise it has to locate it. When it descends to place the cube, a slight change in resistance can indicate contact with the support and trigger the opening of the jaws.

What I find interesting is that none of these operations is especially spectacular in isolation. Search, approach, grasp, check, carry, avoid, place, retract. I want them to stay small. My goal is to build a library of reusable phases that can be recombined depending on the body and the task. The same mechanism that lets a gripper understand that it is forcing can be used elsewhere so a joint stops a dangerous movement. The same spatial search system can find a cube, a charging station, or a person. I think of my architectures a lot like Legos: complexity should not live inside one huge function able to do everything, but in the relationships between simple pieces that can be reused in other systems.

This is where I deliberately use the word “life.” For me, life is not tied to the presence of an LLM. A language model can perfectly well be a useful layer in a completely dead organism. What interests me is an algorithmic loop between outside and inside. A stimulus exists, the system perceives it, its state changes, it analyzes possible consequences, then acts to recover or maintain a situation that suits it. Abnormal pressure on a joint can become the functional equivalent of pain. The robot is forcing, so something is threatening its integrity. The right answer is not necessarily a system error and a hard stop. It can look for what is preventing it from moving, test a withdrawal movement, observe whether the pressure drops, and continue until it returns to a safe state. For a biped pushed sideways, the same principle could use a gyroscope, accelerometer, and available motor margin to search for a new stable configuration.

I can code part of these responses, but I do not want to code all of them. What interests me is defining the conditions the system must try to answer. Pain, energy consumption, time, precision, wear, stability, and success or failure of a task can become positive or negative signals. A fitness function can provide a first structure, but even its weights do not necessarily have to remain completely fixed. I have a global understanding of the system, and I can propose coherent initial values. But I am not inside the body I am building. I cannot feel the exact sum of all the constraints produced by the length of a segment, the torque of a motor, an acceleration, the weight of an object, and the way a gripper entered into contact with it. At some point, if I want the system to truly improve, I have to give it enough freedom to find a way of doing things that fits its own body rather than my intuition of it.

This is probably the most philosophical question behind everything I have been building for several years: at what point does a succession of deterministic mechanisms, later enriched by probabilistic analysis and learning, end up producing behavior that nobody explicitly wrote? I often encounter it through side effects. Two mechanisms come into conflict. One pushes in a direction, and the other forbids exactly that direction. Most of the time, it is simply a problem to solve. Finding these conflicts is a huge part of my work. But sometimes an intermediate state appears, a solution that was not described anywhere and simply results from the interaction between several rules. Sometimes it is bad and has to disappear. Sometimes it is more interesting than what I had planned.

That is also what I like about evolutionary algorithms. Introducing noise or mutations means deliberately accepting the loss of some local control to see whether the system finds a stability we would not have imagined. What matters is not chance itself, but what selection does with it afterward. A strange solution that appears once does not interest me much. A strange solution that is reproducible, more efficient, and able to survive the same constraints as the others becomes interesting immediately.

Of course, the boundary between laboratory and real world must remain extremely clear. I can let a simulation explore absurd behaviors, virtually break an arm, or test a strategy that would never be acceptable around people. A self-driving car could theoretically discover a way of driving that is much more efficient than humans’. If it drives among humans, it cannot simply impose its own protocol on reality on the grounds that it is mathematically better. The social environment itself becomes a constraint of the system. Conversely, when nobody else is involved, I want to be able to let things diverge much more freely. A population can develop a completely different way of performing a task and continue evolving in that direction while another explores elsewhere. I can then measure, compare, keep several lineages, and possibly deliberately eliminate a behavior that is performant because it becomes bad under another criterion. If a fish swims extremely well but its strategy makes it unable to maintain enough social relationships to survive, its local performance is no longer enough. Conversely, if an entire population ends up swimming upside down and that creates no viability problem, I do not see why I would arbitrarily decide that the solution is wrong.

I think nature produced part of its diversity exactly that way. Evolution has no aesthetic obligation. It keeps what holds together well enough in a given context.

I am not God. I set up a world, observe what happens in it, and filter when a behavior starts to have consequences beyond the laboratory.

A laboratory that learns from reality



How all of this will be implemented in DIP Rig will depend a lot on what the project becomes. If it remains mainly my tool, I can allow myself a very experimental approach. Generate several variants of the same arm, change their proportions, change the motors, test different decision architectures and training systems, launch a considerable number of instances in parallel, and let them live through hundreds of thousands of virtual trajectories. Some may favor precision, others speed, others mechanical economy. The selected solutions will depend on the use. A six-axis 3D printer has almost nothing to do with an arm intended to move objects. The first probably has to favor continuity of motion, repeatability, low vibration, and precision. The second can accept other compromises. A robot working near humans adds another world of constraints again.

If DIP Rig is ever meant to be used by other people, some parts will necessarily have to be fixed. We will distinguish what is validated from what is experimental, collect as much feedback as possible, and several profiles can evolve in parallel for different motors, sizes, and uses. But the logic remains the same: I am not looking for universally optimal behavior. I am looking for an architecture capable of producing or learning behavior that is coherent with a body, a task, and an environment.

And this is where DIP Rig starts to change my way of working in Cinema 4D much more deeply. When I built Echo Bot, a huge amount of time was spent recreating physical components in the virtual world. Measuring a servo, rebuilding its volume, checking the holes, positioning the axes, then drawing a printable part around all of that. When a component changed, part of that knowledge had to be recreated elsewhere. I now want to build a servo library containing not only their geometry, but their physical behavior: range, torque, speed, dimensions, and possibly consumption, temperature, or data retrieved from the real motor. The same thing can exist for sensors, joints, grippers, batteries, and gradually for entire subsystems.

The essential change is that an element created once can truly become reusable knowledge. I will be able to generate a new robot from already known components instead of redrawing the same foundations. But above all, I want to close the loop with the physical machine. The real robot must be able to send its data back to the model. If a servo produces less torque than the simulation predicted, if a joint heats faster, if a theoretically optimal movement generates vibrations the model did not know about, I want to be able to reinject that information into the simulation. The virtual twin then stops being a representation prepared before fabrication. It becomes a model gradually corrected by the real body.

From there, the data accumulated by one project can also become useful to the next ones. A grasping strategy learned on one arm can serve as the starting point for another manipulator. A physical model refined from a real servo improves all simulations using that component. A joint that has discovered certain zones of useless effort can provide constraints for other morphologies. Each new machine gradually enriches the shared library.

That is exactly how I think about my other systems: a brick should not lose its value when the project that created it is finished. If it solved something general, it should be able to move back up into the architecture and be reused elsewhere.

Looking at DIP Rig today, when the project has existed for only two days and I am developing it alongside the rest of my site, I think what I like most is precisely that it does not feel like starting something new. It feels like many things are finally returning to the same place.

I spent nearly twenty-five years using 3D to understand form, light, motion, and matter. Then I spent three years focused almost exclusively on artificial intelligence, language models, agents, and how to build architectures able to perceive, remember, decide, and learn. For a while, those two paths seemed almost independent. In reality, learning AI systems is what now lets me return to 3D and look at an articulated object differently. And it is probably because I come from 3D that I keep trying to give an environment, constraints, and finally a body to the intelligent architectures I build.

Genesis 3D allowed me to make systems live directly in a browser. The fish forced me to distinguish the mechanics of a behavior from the reason that causes it. Homeostasis taught me to distribute responsibilities between autonomous components. Echo pushed me toward memory, internal state, reflexes, and learning. Echo Bot added matter, inertia, energy, mechanical pain, and that extraordinary property of the physical world: when an idea is bad, gravity usually ends up giving its opinion. DIP Rig now sits at the crossing of all of that, but this time inside professional software I did not build.

That also matters to me. Until now, a large part of my systems have lived inside my own ecosystem. Genesis, Genesis 3D, Homeostasis, Echo: I control the structure in which they exist. DIP Rig lets me check that this way of thinking is not only suited to tools I created myself. I enter Cinema 4D, market software I have used since adolescence, and I apply exactly the same principles there: reduce mechanics to what is essential, create autonomous bricks, give intelligence only the space where it adds something, connect the system to the outside world, and preserve as much as possible an architecture that remains portable.

Claude Code obviously plays a huge role in the speed at which all of this becomes possible. I am not a developer, and I am not trying to become one. I understand systems, their dependencies, flows, what should exist and what should not, then I work with AI to materialize that architecture. The more the tools progress, the less I have to spend my energy on implementation itself, and the more I can think at the level that interests me: why the system acts, what information it lacks, which constraints are actually necessary, how much freedom can be left to it, and when an interaction between several mechanisms starts producing something nobody had planned.

That is probably what finally connects everything I do.

I think I am trying to mentally build a kind of large function of the living. Not a universal equation, and not a literal biological imitation, but a set of mechanisms general enough to work with different bodies, different perceptions, and different abilities. Each project gives me one more variable. A fish brings a question about the group and fear. A vector memory brings a question about the continuity of context. A robot brings pain and wear. An arm brings manipulation, friction, and the relationship between intention and movement. A plugin brings the idea that the same architecture can survive a change of software, language, or even matter.

The more these pieces begin to come together, the less I feel I am building different projects.

I feel more like I am observing the same system from several places.

Echo appears in 3D with a ball and butterflies. Rotate him, throw the ball to him, and watch his reactions.

How Echo adapts its behavior

2 months ago
August 11, 2026.

We were trying to fix a fairly simple problem: when Echo finds a reaction that works, she ends up replaying it in exactly the same way. The obvious reflex would be to artificially lower the value of a response when it is repeated too often, just to force a little variety. But that feels wrong to me. If a behavior works a thousand times, why should it become worse simply because it has been used a thousand times? What should be able to question a behavior is not its frequency. It is what happens after.

If Echo makes a small sound when the cat rubs against her, and the cat stays, comes back, or seems to react well, there is no reason to break that reflex. But if the same behavior eventually makes the cat run away, if her own gauges do not move in the expected direction, or if what she was trying to obtain no longer happens, then there is information. The consequence has changed. So the behavior can be reassessed. I prefer that to a kind of fatigue counter programmed arbitrarily into the system.

At the same time, I do not want her to always look for a perfect answer. If five different reactions work well in a situation, it makes sense to keep all five. It is probably better that way. The more valid paths there are, the more the behavior can vary without becoming random. Echo would not choose at random from everything she could do. She would choose from several things that have already shown they can work. That avoids the vending-machine effect, where one input always produces exactly the same output.

This connects directly to what I was already thinking about language learning: learning is not enough. The system must be able to unlearn. An association that has been reinforced must be able to weaken, or be set aside, if new experiences contradict it. Otherwise the system accumulates certainties and ends up trapped by what it learned first. The mechanism has to be reversible. A rule can appear, become strong, then become a candidate again if it stops working.

Humans can also take part in this loop, but I do not want to turn them into a remote control. A thumbs-up or thumbs-down is not meant to tell Echo what to do next time. It simply adds information about the consequence of what she just did. The same goes for speech, or for the absence of a reaction. If someone spontaneously tells her that it was good, that is data. If someone does not react at all, that is data too. And if I give her a thumbs-down when she does not understand what the problem was, she can simply ask why. In that case, we are not injecting a magic rule. We are giving her information she did not have.

Then I realized something was still missing: it depends on who is in front of her. A reaction can work perfectly with me and be unbearable for someone else. One person may like Echo coming very close. Another may find it intrusive. If I reduce everything to “in this situation, this gesture works,” I lose an essential dimension. She should be able to learn instead: “in this situation, with this person, this behavior produced this.”

That means keeping both levels at the same time. A general base, built from all experiences, so Echo does not start from zero every time she meets someone. And above it, a separate history for each person. Not just a profile with three saved preferences, but an accumulation of different experiences. The same behavior can therefore be strongly reinforced in one relationship and much less in another.

In the end, I think the important shift is there: I am no longer necessarily trying to make Echo converge toward the best answer. I am trying to let her keep several answers that work, question them when their consequences change, and understand that those consequences also depend on context and on the person.

A behavior is not good in the absolute.

It is good somewhere, at a given moment, with someone.

A sketch-style robot shows the load on its motors. Push or press it to see its joints change colour with the load.

Getting Echo to walk without straining

2 months ago
July 28–29, 2026.

That night, I was mostly trying to answer a basic question: will my motors actually be able to make Echo walk? The first calculations were not very reassuring. On some movements, we were reaching peaks around 114% of stall torque. The obvious reaction would have been to conclude that the motors were too weak. But instead of changing the hardware, I started changing the gait: four legs on the ground instead of three, shorter strides, a faster cadence, more sweep from the coxa, and fewer large movements that create huge lever arms. With the exact same motors and the same robot, we came back down to around 76%.

It made me realize I might have been looking at the problem backward. You can build a body powerful enough to withstand any movement you impose on it. Or you can build a movement that uses the body you have correctly. In the second case, the question is no longer only “how much force can my motors produce?”, but “why am I asking them for that much force?” Bad geometry, a leg too far out, a sudden acceleration, or a posture change at the wrong moment can turn an ordinary gesture into a major effort.

I started paying more attention to the way I move. When we walk, get up, or move something, we are not constantly fighting gravity and inertia. We use them. We build momentum, change geometry, shift the center of mass, sometimes let a limb move almost by itself, and only guide the motion. Even when I get out of bed, if a position hurts, I do not push harder. I roll, let my legs drop, and use their mass to help me rise. The right answer to excessive effort is often to change the movement, not to add force.

And Echo has exactly what makes this interesting: its motors talk. They do not only receive angles. They also return load, current, temperature, position, and speed. Until now, I mostly saw them as actuators. In reality, they can also become part of its proprioception. The robot can know at all times where force is building up, where heat is rising, whether a movement is becoming abrupt, or whether a joint is starting to leave its comfortable range.

From there, I no longer really want to code “the right gait.” I can provide a clean enough base so it does not start by doing anything random, but the final gait should be refined according to what the body itself sends back. It has to reach a goal, move forward, follow someone, turn, rest, while also trying to limit effort, noise, consumption, balance loss, and sudden movements. The way it walks then becomes a compromise between several constraints, rather than an animation replayed the same way every time.

This is exactly where movement meets what I have been building from the start around homeostasis. If a servo starts to strain, it is not only diagnostic information meant for me. It can become an internal signal for Echo. The same goes for temperature or consumption. The body says: “this way of doing things costs me too much.” Behavior can then change before something breaks. I much prefer that idea to a system that executes an order perfectly until it reaches a physical limit. Pain, if I use that word for the robot, should start as this: information that pushes it to modify the action.

It also means Echo does not truly know its body on the day I finish assembling it. A spec sheet can give me a maximum torque or a temperature limit, but two legs printed from the same files will never be perfectly identical. One bearing will be a little tighter, one cable will rub more, mechanical play will differ, and then wear will appear over time. So I want it to be able to map its own limits gradually: move slowly, observe what happens, learn that one joint is freer in one direction than another, and update that map as it goes.

The same problem applies to learning. I obviously cannot make the real robot try thousands of gaits until it finds the right one. The hardware is expensive, the motors heat up, and a broken part can take hours to print. Simulation therefore becomes the place where we search, and the real body the place where we verify. An interesting solution appears in the digital twin, we test it on Echo, measure the gap, then feed that gap back into the simulation. Reality is not just there to confirm that it works. It is there to correct the model that will be used for the next search.

That is probably what interests me most in all this. At first, I thought I was teaching a robot to walk. In reality, I am beginning to build the conditions for a body to learn how to use itself. Its way of moving could change with its battery, its temperature, its wear, the floor, a leg that starts to strain, or simply the goal of the moment. A gait that works perfectly today may no longer be the best one in six months.

So it will probably never learn to walk once and for all.

It will learn to walk with the body it has today.

Echo’s wiring diagram connects the battery, boards, sensors, and eighteen servomotors. Trace a power route or a specific signal.

Designing Echo’s electronics

3 months ago
Electronics was probably the most stressful part of the project. In mechanics, even when I did not know exactly what I was doing, I could look at a part, measure it, print it, maybe break it, and understand what was wrong. In electronics, my starting level was much easier to summarize: I knew absolutely nothing. Not “not much.” Nothing. And unlike a printed part that is too weak, a wiring mistake can take out several components at once.

At first, I relied a lot on the models I was working with. Claude, Claude Code, ChatGPT, then stronger models as they became available. The problem was that the diagram quickly became too dense. Each answer could be locally correct while forgetting a constraint set three days earlier: a voltage, a current spike, a connector, a component already ordered, the available space in the body, or simply the fact that a cable had to physically pass somewhere. The diagram changed several times because elements were missing, then because some solutions would not have held once everything was connected together. At one point, I understood that I could not just ask a chatbot “is this wiring correct?” and hope someone would keep the whole architecture in mind for me.

So I built software for it. Every component of the robot is represented there, linked to the others, and tied to its real electrical characteristics. The goal was not to make a nice diagram. It was to have a representation I could query: how much passes here, what peaks are possible, which power supply supports what, where the current flows, and above all what I will actually have to plug in on assembly day. I needed to understand the system before I had the wires in my hands. The diagram gradually became a source of truth: if a component changes, if a power supply disappears, or if a branch becomes useless, the architecture has to show it immediately.

That work also made me remove many things I had planned at the start. As with the mechanical design, I began with too much, then removed. A bit like sculpture: I add material, then refine until only what really serves remains. Some sensors were redundant. Some elements added wiring, weight, and power draw for little benefit. Others would have been perfectly possible on a diagram, but much less so in a body where every centimeter is already used. The latest version lost pieces almost every week, and today I think I have reached something I cannot really reduce further without removing an important function.

The power system itself changed a lot. I bought things that eventually disappeared from the architecture, changed cable gauges, revised paths, simplified branches. It cost me money, sometimes simply because I learned a constraint after already ordering what had seemed logical the day before. After a while, I stopped trying to optimize every euro. The budget remained a constraint, but it could not become a reason to build something I knew was wrong. When I look at the power drawer and the available volume in the brain today, I know anyway that I could not have kept much more.

I was lucky on one point: I designed the inside of the drawer and the final layout of the brain very late. By then, I finally knew the real size of the components, the cables required, and almost all the connections. Their position is now measured to the millimeter. Some elements pass underneath, others above, the large cables take one side, the signals another, and some connections have to remain accessible once the robot is assembled. What looks on the diagram like a simple line between two boxes becomes, inside the robot, a real cable with a diameter, a bend radius, two connectors, and a physical path that has to fit somewhere.

A large part is already wired today, and for the first time I feel that I really understand the role and place of each element in the electrical system. But I keep one simple reservation: until everything is connected and I have pressed the switch, I will not know if I succeeded. This is probably the part of the project where I am least able to predict the result with certainty. The diagram is coherent, the calculations hold, the components are in place, but there remains that very concrete moment when several weeks of reasoning become current in real wires.

What amuses me is that at first I thought AI would let me avoid having to understand all this. With the best models I had access to, I thought I could describe my problem and gradually obtain a reliable architecture. In reality, they were extremely useful for searching, explaining, calculating, or checking parts of it, but none of them could carry the full set of constraints alone. In the end, I had to understand the system well enough to know which questions to ask, which answers to reject, and what still needed to be simplified.

I am still not an electronics engineer. But now, when I look at this diagram, I know what each line represents and why it is there.

The next step will be less theoretical: power it up.

Let's work together

Innovation grows out of collaboration. Together, let's build solutions that matter.
Owan
Hello, my name is Owan, I am David's assistant. How can I help you?
0/2000