Issue with state-machine non-deterministic turns using time tracking in Gazebo simulation

My name is Harold, and I am an Automation and Control Engineering student at Politécnico Colombiano Jaime Isaza Cadavid.

I am currently developing a state-machine based navigation script to perform a complete zigzag (lawnmower) coverage path inside a house environment. The expected behavior is for the robot to move horizontally back and forth in parallel lines, switching directions after completing each U-turn sequence.

However, I am currently facing a significant issue where the robot fails to achieve a reliable horizontal path on its return. After analyzing the behavior, we identified that the fixed-time thresholds used to control the rotation states do not consistently result in precise 90-degree turns. Every time the simulation runs or reconnects, the actual execution speed of the time loop changes, causing the robot to slightly under-rotate or over-rotate. This small angular deviation accumulates rapidly, causing the robot to drift into a diagonal path and eventually crash against the interior walls.

I am sharing my current code block below in case anyone can spot the issue or provide a better recommendation to stabilize these turns without depending exclusively on execution time:

import HAL
import WebGUI
import Frequency
import time

V_LINEAL = 0.5
W_GIRO = 1.5
DIST_CARRIL = 2.2
CERCA_MURO = 0.55

estado = “AVANCE”
reloj = time.time()

def sensor_frente(laser):
if laser is None or len(laser.values) < 180:
return 99.0
return min(laser.values[87:93])

while True:
Frequency.tick()

data_laser = HAL.getLaserData()
choque = HAL.getBumperData()
frente = sensor_frente(data_laser)

tocado = (choque is not None and choque.state == 1)

if estado == "AVANCE":
    HAL.setV(V_LINEAL)
    HAL.setW(0.0)
    
    if time.time() - reloj > 1.5:
        if frente < CERCA_MURO or tocado:
            HAL.setV(0.0)
            HAL.setW(0.0)
            time.sleep(0.3)
            
            if tocado:
                HAL.setV(-0.4)
                time.sleep(0.5)
                HAL.setV(0.0)
                time.sleep(0.2)
                
            estado = "GIRO_1"
            reloj = time.time()

elif estado == "GIRO_1":
    HAL.setV(0.0)
    HAL.setW(W_GIRO)
    
    if time.time() - reloj >= 3.5:
        HAL.setV(0.0)
        HAL.setW(0.0)
        time.sleep(0.3)
        estado = "LADO"
        reloj = time.time()

elif estado == "LADO":
    HAL.setV(V_LINEAL)
    HAL.setW(0.0)
    
    if time.time() - reloj >= DIST_CARRIL:
        HAL.setV(0.0)
        HAL.setW(0.0)
        time.sleep(0.3)
        estado = "GIRO_2"
        reloj = time.time()

elif estado == "GIRO_2":
    HAL.setV(0.0)
    HAL.setW(W_GIRO)
    
    if time.time() - reloj >= 3.4:
        HAL.setV(0.0)
        HAL.setW(0.0)
        time.sleep(0.3)
        estado = "REGRESO"
        reloj = time.time()

elif estado == "REGRESO":
    HAL.setV(V_LINEAL)
    HAL.setW(0.0)
    
    if time.time() - reloj >= 6.0:
        HAL.setV(0.0)
        HAL.setW(0.0)
        estado = "FIN"

elif estado == "FIN":
    HAL.setV(0.0)
    HAL.setW(0.0)`

Any advice on how to handle these simulation loop timing discrepancies or recommendations on alternative approaches using the available HAL API would be highly appreciated.

Thank you in advance for your support!

Hi Harold,

Welcome to the forum! The erratic behavior you’re experiencing is completely normal.

Trying to perform high-precision navigation (like a lawnmower or zigzag pattern) relying strictly on time thresholds is very fragile. What you are noticing with the simulation clock variations is exactly what happens when deploying on a real robot: motor noise, friction, wheel slippage, and floor imperfections mean a turn is never exactly 90 degrees.

For this Vacuum Cleaner exercise, we are simulating a low-end vacuum. These devices are more affordable and common in homes precisely because they lack expensive, computationally heavy localization systems (maps, SLAM, high-end sensors). From an engineering perspective, our goal here is to get a good result playing with fewer cards.

  • Less is more: A simple, reactive bump-and-go approach is a much better and more robust solution for this specific case. You can use the laser to guide the robot toward wider open areas, but achieving that perfectly fine-tuned zigzag behavior is virtually impossible given the unlocalized nature of the exercise.
  • If you want to practice coverage algorithms (like BSA, cleaning more area in fewer steps), the robot needs to know where it is. I highly recommend checking out the Localized Vacuum Cleaner exercise for that. If you want to learn how to locate the robot first, you can try the MonteCarlo Laser Loc or Visual Loc exercises.

Good luck with your work!