ICAM Toulouse · A126 · Robot Soccer Kit · team of 8

Digital TwinWrite a game strategy for two robots, test it in the simulator, then face the real field. The gap between the two is the lesson.

Platform
Robot Soccer Kit: robots, overhead camera, simulator, referee, supervisor
Goal
A two-robot strategy, validated in simulation, played in a match against another group
Method
Agile · OpenProject Kanban and Gantt · work split by RUN
Language
Python · multithreading
The robot soccer field with robots and ball
The real field · two robots per side, one camera above
01 · Simulation vs realityMeasure the gap, then correct for it

The twin was 35 to 45 % slower than the robot it modelled.

90 cm move · simulator3.616s
90 cm move · real robot1.956s
Kickenergy lossnot modelled
Ball and robot positionsmall offsetsim → field

The simulator ignores floor flatness, friction and the energy actually transferred to the ball. Each deviation became a correction coefficient in the code, so the strategy tuned in simulation still worked on the field.

Bar chart: simulation time vs real time
Travel time · sim vs real
Kick measurements
Kick distance · averages
02 · The strategyThree phases, four runs
Phase 1 · RUN 1–2

Positioning

Every object on the field gets a repulsion coefficient. If something sits on the path, the next x/y waypoint is recomputed on the fly, so the robot rounds opponents on the shortest safe line.

Phase 2 · RUN 3

Ball interaction

Opponent near the ball: switch to defence and hold five seconds to see if it stays. Ball behind us: circle around it to line up with the opposing goal before the shot.

Phase 3 · RUN 4

Defence & attack

Two modes running in parallel threads sharing memory, so the team reacts to the ball and to the opponent at the same time without blocking either loop.

03 · CodePython · threads · shared state

One process per team, one thread per role. Attack and defence read the same camera frame from a shared data object and write their own motor commands, so neither loop waits on the other.

  • Common data. A single class holds ball, robot and opponent positions from the overhead camera; every thread reads it, only the vision callback writes it.
  • Repulsion field. Each obstacle contributes a coefficient; the next waypoint is the argmin of the field along the path to the target, recomputed every frame.
  • Calibrated, not trusted. Measured sim-to-field ratios on speed and kick distance live as constants in the strategy, so the same code runs in both worlds.
# simplified strategy runner
class CommonData:
    ball, robots, opponents = None, {}, {}
    SPEED_K = 1.956 / 3.616     # field / simulator

def attack(cd):
    while playing:
        if behind(cd.ball, me):      # circle to face the goal
            goto(orbit(cd.ball, goal), avoid=cd.opponents)
        else:
            kick_towards(goal)

def defense(cd):
    while playing:
        if near(cd.opponents, cd.ball):
            hold(5.0)               # wait, see if it stays
            block_line(cd.ball, own_goal)

Thread(target=attack,  args=(cd,)).start()
Thread(target=defense, args=(cd,)).start()
Python · threading · Robot Soccer Kit API
Thread code
Thread orchestration · actual code
Defence code
Defence mode · actual code
04 · What it taughtConclusion
Twin
Test without risk

A digital twin lets you break a strategy a hundred times before a robot ever moves.

Calibration
Deviations are data

Measured gaps became coefficients; the model got closer to the field every run.

Team
Split by run

Parallel tasks per RUN kept eight people moving; Kanban kept them aligned.

PythonMultithreadingRobot Soccer KitComputer visionOpenProjectAgile