Webots多E-puck机器人项目报错:仅允许创建一个Robot类实例
Webots多机器人项目错误排查:Robot实例重复创建问题
问题背景
开发Webots项目时,使用四个E-puck机器人推送箱子至目标位置,代码采用Environment类、Robot类加主控制循环的结构。运行时出现错误:Only one instance of the Robot class should be created,同时收到警告:'Supervisor' controller exited with status: -1。相关代码片段如下:
_robot_instance = None _supervisor_instance = None def __init__(self, use_supervisor=False): self.use_supervisor = use_supervisor self.TIME_STEP = 32 self.receiver = None self.webots_supervisor = None if use_supervisor: if Environment._supervisor_instance is None: Environment._supervisor_instance = Supervisor() self.webots_supervisor = Environment._supervisor_instance self.robot = self.webots_supervisor.getFromDef("agent1") else: if Environment._robot_instance is None: Environment._robot_instance = Robot() self.robot = Environment._robot_instance def reset(self): print(f"Supervisor: {self.webots_supervisor}") # Release existing Robot/Supervisor instance if it exists if self.use_supervisor: if Environment._supervisor_instance is not None: self.webots_supervisor = None self.robot = None del Environment._supervisor_instance else: if Environment._robot_instance is not None: self.robot = None # Create a new Robot/Supervisor instance if use_supervisor: Environment._supervisor_instance = Supervisor() self.webots_supervisor = Environment._supervisor_instance self.robot = self.webots_supervisor.getFromDef("agent1") else: if Environment._robot_instance is None: Environment._robot_instance = Robot() self.robot = Environment._robot_instance try: # Ensure that Supervisor instance is used when appropriate root = ( self.webots_supervisor.getRoot() if self.use_supervisor else self. robot.getRoot() ) self.print_node_names(root) except AttributeError as e: print(f"Error getting nodes: {e}")
错误原因分析
- Robot实例重复创建:
reset方法的非Supervisor分支中,删除旧实例后未置空类变量_robot_instance,导致下次创建时if Environment._robot_instance is None判断失效,实际旧实例已被销毁,重新赋值时会创建新的Robot实例,违反Webots一个控制器只能有一个Robot实例的规则。 - Supervisor分支逻辑漏洞:
reset方法创建新Supervisor实例时未检查类变量是否已存在,直接赋值可能导致重复创建;删除实例后也未置空_supervisor_instance类变量。 - 拼写错误:
self. robot.getRoot()中多了空格,会触发AttributeError,进而导致控制器异常退出。
修复方案
修复后的代码片段
_robot_instance = None _supervisor_instance = None def __init__(self, use_supervisor=False): self.use_supervisor = use_supervisor self.TIME_STEP = 32 self.receiver = None self.webots_supervisor = None if use_supervisor: if Environment._supervisor_instance is None: Environment._supervisor_instance = Supervisor() self.webots_supervisor = Environment._supervisor_instance self.robot = self.webots_supervisor.getFromDef("agent1") else: if Environment._robot_instance is None: Environment._robot_instance = Robot() self.robot = Environment._robot_instance def reset(self): print(f"Supervisor: {self.webots_supervisor}") # Release existing Robot/Supervisor instance if it exists if self.use_supervisor: if Environment._supervisor_instance is not None: self.webots_supervisor = None self.robot = None del Environment._supervisor_instance Environment._supervisor_instance = None # 置空类变量 else: if Environment._robot_instance is not None: self.robot = None del Environment._robot_instance Environment._robot_instance = None # 置空类变量 # Create a new Robot/Supervisor instance if self.use_supervisor: if Environment._supervisor_instance is None: # 增加存在性检查 Environment._supervisor_instance = Supervisor() self.webots_supervisor = Environment._supervisor_instance self.robot = self.webots_supervisor.getFromDef("agent1") else: if Environment._robot_instance is None: Environment._robot_instance = Robot() self.robot = Environment._robot_instance try: # 修复空格拼写错误 root = ( self.webots_supervisor.getRoot() if self.use_supervisor else self.robot.getRoot() ) self.print_node_names(root) except AttributeError as e: print(f"Error getting nodes: {e}")
关键修复点
- 置空类变量:删除实例后必须将
_robot_instance和_supervisor_instance置为None,确保下次创建时的判断逻辑正确。 - 增加实例存在性检查:Supervisor分支创建新实例前先检查类变量是否为空,避免重复创建。
- 修复拼写错误:去掉
self. robot中的空格,改为self.robot,防止AttributeError导致控制器异常退出。
额外注意事项
- Webots中每个控制器进程只能创建一个Robot/Supervisor实例,多机器人场景下每个机器人对应独立的控制器进程,不要在同一个控制器里尝试创建多个Robot实例。
- 若使用Supervisor控制多机器人,确保通过
getFromDef或getFromId正确获取各个机器人节点,而非重复创建Supervisor实例。
内容的提问来源于stack exchange,提问作者Kazmi
相关产品推荐
相关产品推荐

