Scenarios#
Override init_world (C++, Python) with the logic to initialize a world: create/modify/delete entities, set termination criteria, set the bounding box, setup a lattice, …).
If you need to sample from random distribution, use the provided random generator (C++, Python), that will guarantee that the world initialization will be deterministic.
Virtual methods#
| C++ method | Python method | override | 
|---|---|---|
| should | 
Class skeleton#
#include "navground/sim/scenario.h"
namespace sim = navground::sim;
struct MyScenario : public sim::Scenario {
  // SHOULD override
  // add here the logic to initialize the world
  void init_world(sim::World *world, seed = std::nullopt) override {
    // call the super class: when the scenario is configured thought YAML, 
    // it will add agents and obstacles as specified in the configuration.
    sim::Scenario::init_world(world, seed);
    // use the world random generator to sample random variable. 
    auto & rng = world->get_random_generator();
    // manipulate the world: create/add/modify/delete agents and obstacles
  }
};
from navground import sim
class MyScenario(sim.Scenario):
    # SHOULD override
    # executed during the the simulation, should update the state
    # update the environment state according to the agent and world
    def init_world(self, world: sim.World, seed: int | None = None) -> None:
        # call the super class: when the scenario is configured thought YAML,
        # it will add agents and obstacles as specified in the configuration.
        super().init_world(world, seed)
        # use the world random generator to sample random variable.
        rng = world.random_generator
        # manipulate the world: create/add/modify/delete agents and obstacles
Groups#
Another way to customize a scenario, without subclassing, is to add a group of agent, i.e., a sub-class of Group (C++, Python), that has a virtual method add_to_world
| C++ method | Python method | override | 
|---|---|---|
| must | 
which should spawn the group to the world, but is not restricted to that. if required, define a new type of group
#include "navground/sim/scenario.h"
namespace sim = navground::sim;
struct MyGroup : public sim::Scenario::Group {
  // add here the logic to populate the world
  void add_to_world(sim::World *world, seed = std::nullopt) override {
    // use the world random generator to sample random variable.
    auto & rng = world->get_random_generator();
    // manipulate the world, in particular create and add agents
    // but you are not restricted to that.
  }
};
from navground import sim
class  MyGroup(sim.Scenario.Group):
    def add_to_world(self, world: sim.World) -> None:
        # use the world random generator to sample random variable.
        rng = world.random_generator
        # manipulate the world, in particular create and add agents
        # but you are not restricted to that.
Then, you add the group to your scenario
MyScenario scenario;
scenario.add_group(std::make_shared<MyGroup>());
// now scenario.init_world(...) will also call this group ``add_to_world``
scenario = MyScenario()
scenario.add_group(MyGroup())
# now scenario.init_world(…) will also call this group add_to_world
Note
This is a weaker way to extend a scenario than registering a sub-class as the new groups will not be exposed to YAML.
Initializers#
Similar to groups, you can add an initializer (C++, Python) to your scenario, which is a procedure taking a mutable world at argument.
MyScenario scenario;
scenario.add_init([](World * world, std::optional<unsigned> seed) {
   ...
});
// now scenario.init_world(...) will also call this function.
scenario = MyScenario()
scenario.add_init(lambda world, seed: ...)
# now scenario.init_world(...) will also call this function
Note
Like for groups, initializers are not exposed to YAML and must therefore be added through the API.