Question

The scenario is as follows. There is a PC running a complex piece of AI software wirelessly controlling a number of soccer robots. This software is written and maintained by a team of students that changes every year.

This means that every year a new team of a dozen relatively inexperienced developers has to learn to work with this system, maintain it, and improve it. This means it needs to be easy to learn, but also hard to get wrong. As an example, C++ is easy to learn, but easy to get wrong, while Haskell would be hard to learn, but hard to get wrong.

In my mind, contenders for suitable languages would be things such as Java, Python and Go. Where Java and Python are hard to shoot yourself in the foot, but provide little guidance in terms of design. Although I've never used Go myself, it seems to be designed with large teams of inexperienced programmers in mind, strongly encouraging a particular model of abstraction en concurrency.

For the software itself it is important that sub-teams can work on parts relatively independently, that it is fast enough to control a dozen robots in real time in a fast-paced game, and that the system is easy to debug and maintain.

There is a hierarchy of high-level strategy, per-robot actions, and low-level control. It seems natural to decouple these in separate threads, but this gives challenges in having a reproducible, observable, debuggable system.

Ideally you'd want to be able to instantiate the system at a given point in history and replay it from there, single-stepping through all decisions made by the AI. It is not entirely clear to me how to do this.

If all nodes were completely stateless and deterministic it may be sufficient to replay the sensor data. CSP may be a reasonable way to have deterministic processes. In case of stateful nodes, some sort of transactional state model seems to be needed. I think Datomic is really interesting in this area, but ultimately I'm not sure how to approach this.

So maybe the hardest and most objective question is: How to architecture a hierarchical AI and control system in a deterministic, replayable and debuggable way that is hard to get wrong?

Was it helpful?

Solution

Ideally you'd want to be able to instantiate the system at a given point in history and replay it from there,

That means you need to make your entire system's state portable, and parameterized.

Parameterized makes me think of dependency injection. So you can tell things what state to be in. Look up tell, don't ask1,2

Portable just means you can save it and load it later in something else without having to reverse engineer the layout because the layout is obvious when you look at it. json is my current favorite for this. No hex editor required. No going blind staring at XML tags.

The hard part is capturing all state. State likes to leak into dark corners when you're not looking. Working functionally helps with this. It's hard to hide state when most of your system is stateless.

Please don't take that to mean I'm insisting on Haskell or some other functional language. With a little discipline you can be functional in Java or C#. That is, you can design most of your code to be immutable so your state is easier to find.

Try teaching the students those principles and see if it doesn't make it easier for them to develop designs that make debugging easier.

Licensed under: CC-BY-SA with attribution
scroll top