cyberbotics / webots

Webots Robot Simulator
https://cyberbotics.com
Apache License 2.0
3.2k stars 1.68k forks source link

References to PROTO regenerated nodes not updated in Supervisor API #1885

Closed stefaniapedrazzi closed 4 years ago

stefaniapedrazzi commented 4 years ago

After regenerating a PROTO node, the reference in the Supervisor API doesn't seem to be updated and wb_supervisor_node_get_from_def still returns the previous (before PROTO regeneration) node reference.

World file:

#VRML_SIM R2020b utf8
WorldInfo {
}
Viewpoint {
}
RectangleArena {
  floorAppearance PBRAppearance {
    baseColorMap DEF TEST_NODE ImageTexture {
      url [
        "textures/parquetry/chequered_parquetry_base_color.jpg"
      ]
    }
  }
}
Robot {
  controller "modify_proto_template_field"
  supervisor TRUE
}

C Controller:

#include <stdio.h>
#include <webots/robot.h>
#include <webots/supervisor.h>

#define TIME_STEP 32

int main(int argc, char **argv) {
  wb_robot_init();
  WbNodeRef node = wb_supervisor_node_get_from_def("TEST_NODE");
  printf("Node before: %p \n", node);
  WbFieldRef filteringField = wb_supervisor_node_get_field(node, "filtering");

  // If the url field reference is requested before regeneration,
  // then it is cached and returned after regeneration even if invalid
  //WbFieldRef urlFieldBefore = wb_supervisor_node_get_field(node, "url");
  //printf("Url field before: %p \n", urlFieldBefore);

  wb_robot_step(TIME_STEP);

  // trigger RectangleArena regeneration
  wb_supervisor_field_set_sf_int32(filteringField, 2);

  wb_robot_step(TIME_STEP);

  node = wb_supervisor_node_get_from_def("TEST_NODE");
  printf("Node after: %p \n", node);
  // Invalid node reference returned and url field is not found 
  WbFieldRef urlField = wb_supervisor_node_get_field(node, "url");
  printf("Url field after: %p \n", urlField);

  wb_robot_cleanup();
  return 0;
}
stefaniapedrazzi commented 4 years ago

The real problem is that unique ids of PROTO parameter nodes are not restored after PROTO regeneration but the correct run of controllers in case of regenerated PROTO nodes is based on the assumption that a node unique ID doesn't change. In fact nodes (and fields) are cached on the libController side and not updated during PROTO regeneration.

If we want that node and field references previously retrieved by the user are still valid after PROTO regeneration, the reset of the unique id should be fixed.