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 skelethon#
#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.PyScenario):
# 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(core.PyGroup):
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.groups.push_back(std::make_shared<MyGroup>());
// now scenario.init_world(...) will also call this group ``add_to_world``
scenario = MyScenario()
scenario.groups.append(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.