Creating World
Now we are going to create a World.
In Godot Gym API World (RLEnvWorld
node) is assumed to be everything in the environment
the agent can interact with. For this tutotial, the World is a room with an apple inside.
The apple can be located anywhere inside the room and its location is assigned on the World reset.
Open
World.tscn
file.Change
World
node type fromSpatial
toRLEnvWorld
.Open
World
node script.Change script as follows:
extends RLEnvWorld onready var apple = $Apple onready var spawn_areas = $SpawnAreas onready var apple_caught: bool = false func _ready(): apple.get_node("AppleCatchArea").connect("body_entered", self, "_on_catch_apple") func reset(arguments=null): apple_caught = false apple.set_global_translation(_sample_initial_position()) func _on_catch_apple(_body): apple_caught = true func get_data(observation_request, storage) -> void: storage.set_apple_caught(apple_caught) func _sample_initial_position() -> Vector3: var i = randi() % spawn_areas.get_children().size() return spawn_areas.get_child(i).get_global_translation()
extends Spatial onready var apple = $Apple onready var spawn_areas = $SpawnAreas func _ready(): apple.get_node("AppleCatchArea").connect("body_entered", self, "_on_catch_apple") func reset(): apple.set_global_translation(_sample_initial_position()) func _on_catch_apple(_body): reset() func _sample_initial_position() -> Vector3: var i = randi() % spawn_areas.get_children().size() return spawn_areas.get_child(i).get_global_translation()
Let’s examine what we changed.
We changed parent class from
Spatial
toRLEnvWorld
.We introduced new variable to store current world state since we want to know it.
onready var apple_caught: bool = false
3. RLEnvWorld
class have optional method reset
to reset world that does nothing be default.
In original game we already had it implemented.
However, we need to modify it to match RLEnvWorld
signature.
func reset(arguments=null):func reset():Then we need to add reset of our new variable:
apple_caught = false
Original game is reseted once robot touches the apple. Now we want our new variable to be set on this event.
func _on_catch_apple(_body): apple_caught = true
func _on_catch_apple(_body): reset()
5. By default, RLEnvWorld.get_data
method raise an error, since no data to return is specified.
Here, we override it to set storage.apple_caught
field with apple_caught
value.
storage
is world_data
field in protobuf message we have defined earlier.
In case you define various possible observations but you want to experiment with particular ones,
you can define logic of the storage filling with help of observation keys in observation_request
.
# The method does not depend on `observation_request` argument in this example. func get_data(observation_request, storage) -> void: storage.set_apple_caught(apple_caught)
Thats’s it for World
! Let’s summarize:
RLEnvWorld
must haveget_data
method implemented.RLEnvWorld
can havereset
method implemented.