webots: Emitter/Receiver communication between nodes not working after controller and simulation reset

Description Main Issue: I’m using a supervisor node to reset a robot controller and the simulation. The supervisor node and the robot node communicate with receivers/emitters. They work ok up until i reset the robot controller. In the dumbed down example below the robot is sending a counter to the supervisor, who resets the simulation and the robot controller when it receives the value 10.

After resetting the robot controller and it is restarted and properly broadcasting, it seems that the supervisor receiver stops receiving the messages (the queue length stays at 0). After several steps (12 for me in the example below) the supervisor receiver starts to pick up the old messages (after reset) in order, thus they get badly desynchronized. The send method in the robot emitter properly returns 1.

What i found: The issue seems to happen when the simulation is also reset via the supervisor.simulationReset() method is called (it is irrelevant if its called before or after resetting the robot controller. If removed, the expected behavior happens.

Side issue: Moreover, after the robot controller reset, the supervisor receives an extra value that it probably shouldn’t. According to the docs, the sent messages are received instantly and the emitter/receiver queues are cleared by the simulationReset() method.

Based on the main + side issues my guess is that the receiver/emitter queues are messed up after the simulationReset() method.

Note: In the very first step, the supervisor doesn’t receive a value, probably depending on the order the step functions of the two controllers are called.

Steps to Reproduce World .wbt file:

#VRML_SIM R2020a utf8
WorldInfo {
}
Viewpoint {
  orientation -0.6931032800836722 0.6931032800836722 0.1980295085953349 0.75
  position 1.2 1.6 2.3
}
TexturedBackground {
}
TexturedBackgroundLight {
}
RectangleArena {
}
DEF ROBOT Robot {
  translation 0.16 0.08 0
  children [
    Receiver {
    }
    Emitter {
    }
  ]
  controller "robot_controller"
}
DEF SUPERVISOR Robot {
  translation -0.22 0.08 0.1
  children [
    Receiver {
    }
    Emitter {
    }
  ]
  name "supervisor"
  controller "supervisor_controller"
  supervisor TRUE
}

robot_controller.py

from controller import Robot


class RobotEmitter:
    def __init__(self):
        self.robot = Robot()

        self.timestep = int(self.robot.getBasicTimeStep())

        self.emitter = self.robot.getEmitter("emitter")

        self.data = 0

    def get_timestep(self):
        return self.timestep

    def run(self):
        while self.robot.step(self.timestep) != -1:
            self.data += 1
            self.handle_emitter()

    def handle_emitter(self):
        string_message = str(self.data)
        string_message = string_message.encode("utf-8")
        print("robot handle emitter string message to send:", string_message)
        if self.emitter.send(string_message):
            print("message sent")
        else:
            print("emitter queue full")


robot_controller = RobotEmitter()
robot_controller.run()

supervisor_controller.py

from controller import Supervisor


class SupervisorReceiver:
    def __init__(self):
        self.supervisor = Supervisor()
        self.timestep = int(self.supervisor.getBasicTimeStep())

        self.robot = self.supervisor.getFromDef("ROBOT")
        
        self.receiver = self.supervisor.getReceiver("receiver")
        self.receiver.enable(self.timestep)
        self.receivedData = ""

    def get_timestep(self):
        return self.timestep

    def run(self):
        while self.supervisor.step(self.timestep) != -1:
            self.handle_receiver()

            if self.receivedData == "10":
                print("RESET")
                self.supervisor.simulationReset()  # This causes the issue, if you comment it out it works as expected
                self.robot.restartController()

    def handle_receiver(self):
        if self.receiver.getQueueLength() > 0:
            self.receivedData = self.receiver.getData().decode("utf-8")
            print("supervisor handle receiver data:", self.receivedData)
            self.receiver.nextPacket()
        else:
            print("supervisor receiver q is empty")


supervisor = SupervisorReceiver()
supervisor.run()

Expected behavior The supervisor receives the values the robot is emitting when they are emitted after resetting the robot controller and the simulation

System

  • Windows 10
  • Webots version R2020a rev 1

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 21 (21 by maintainers)

Most upvoted comments

I inspected the message transmission in more details. The third reset message received is clearly a bug of the reset functionality and I could easily fix it.

About the second reset message (the “11” message), it is currently consistent with the reset procedure where the simulation reset is applied at the very end of the step after sending the step updates to the controller, i.e. after forwarding the “11” or second reset message to the controller.

I agree this could not be the expected behavior and I’m now analyzing the implications of resetting the simulation before sending the step updates to the controller (but it seems this breaks other simulations).

I will check the issue and see what are the options to fix it. I had a quick look and it seems reasonable that also the messages on the way to be transmitted should be cleared during the reset.

Well, for our specific use case this is not possible unfortunately. We are running a reinforcement learning agent on the supervisor and we need the supervisor to control the simulation and reset it without it being reset too.

We already have a different implementation of resetting, which is more cumbersome and less general but works for now. Thank you for taking the time to find a workaround though.

I merged the fix this morning in the R2021a revision1 and I will now port the changes to the R2021b version so that tomorrow it will be available in both the 10/2 nightlies.

Thank you very much! I have used physics engines, etc., in the past and have an idea of how they do stuff.

This is fixed in #1385, the patch will be available in the nightly build from tomorrow.

Thank you for the precise bug report, I can indeed reproduce the issue.