Behaviors#
Environment state#
Behaviors must expose their local environment state through get_environment_state to let other user update it. The returned type should be a sub-class of EnvironmentState (C++, Python), which is an empty base class.
Therefore, if your behavior needs a new type of environment state, start by defining the new class
#include "navground/core/state.h"
struct MyEnvironmentState : public EnvironmentState {
  using EnvironmentState::EnvironmentState;
  // ...
};
from navground import core
class  MyEnvironmentState(core.EnvironmentState):
    def __init__(self):
        super().__init()
Preparation/Termination#
Override prepare  (C++, Python) with any custom logic to initialize the behavior: it should be called before the first command is computed. For instance, specialize this function to setup a centralized group behavior that explicitly coordinates multiple individual behaviors, or to load a resource that requires the behavior being configured (e.g., to load an environment from a file path stored in a behavior property).
Clean-up any step you perform by overriding close (C++, Python) which should be called once the behavior stop being evaluated.
Compute a command#
Behaviors are complex objects that can be specialized in different ways.
The public method compute_cmd (C++, Python) calls the virtual method compute_cmd_internal (C++, Python), which in turn calls forwards the request to different methods depending on which targets are currently in use:
- position along a path: - cmd_twist_along_path
- pose: - cmd_twist_towards_pose
- position: - cmd_twist_towards_point
- orientation: - cmd_twist_towards_orientation
- velocity: - cmd_twist_towards_velocity
- angular speed: - cmd_twist_towards_angular_speed
- none: - cmd_twist_towards_stopping.
To specialize a behavior, users may override compute_cmd_internal or
any of the methods listed above.
They may also override the following internal methods:
- desired_velocity_towards_point, used by the base- cmd_twist_towards_point
- desired_velocity_towards_velocity, used by the base- cmd_twist_towards_velocity
- twist_towards_velocity, use by by the base- cmd_twist_towards_pointand- cmd_twist_towards_velocity.
The command produced by compute_cmd_internal should be kinematically feasible, but it is not strictly required.
Virtual methods#
| C++ method | Python method | override | 
|---|---|---|
| must | ||
| can | ||
| can | ||
| can | ||
| can | ||
| can | ||
| can | ||
| can | ||
| can | ||
| can | ||
| can | ||
| can | ||
| can | 
Class skeleton#
#include "navground/core/behavior.h"
namespace core = navground::core;
// May use a custom environment state
struct MyEnvironmentState {
};
struct MyBehavior : public core::Behavior {
  MyEnvironmentState _env_state;
  // MUST override ... the base returns an null pointer.
  EnvironmentState *get_environment_state() const {return &_env_state; }
  // CAN override
  // executed before the first evaluation
  // void prepare() override;
  // CAN override
  // executed after the last evaluation
  // void close() override;
  // CAN override
  // core::Twist2 compute_cmd_internal(ng_float_t time_step) override;
  
  // CAN override
  // core::Twist2 cmd_twist_along_path(Path &path, ng_float_t speed, ng_float_t time_step) override;
  
  // CAN override
  // core::Twist2 cmd_twist_towards_pose(const Pose2 &pose, ng_float_t speed, Radians angular_speed, ng_float_t time_step) override;
  
  // CAN override
  // core::Twist2 cmd_twist_towards_point(const core::Vector2 &point, ng_float_t speed, ng_float_t time_step) override;
 
  // CAN override
  // core::Twist2 cmd_twist_towards_velocity(const core::Vector2 &velocity, ng_float_t time_step) override;
  
  // CAN override
  // core::Twist2 cmd_twist_towards_orientation(Radians orientation, ng_float_t angular_speed, ng_float_t time_step) override;
  
  // CAN override
  // core::Twist2 cmd_twist_towards_angular_speed(ng_float_t angular_speed, ng_float_t time_step) override;
  
  // CAN override
  // core::Twist2 cmd_twist_towards_stopping(ng_float_t time_step) override;
  
  // CAN override
  // core::Vector2 desired_velocity_towards_point(const core::Vector2 &point, ng_float_t speed, ng_float_t time_step) override;
  
  // CAN override
  // core::Vector2
  // desired_velocity_towards_velocity(const core::Vector2 &velocity, ng_float_t time_step) override;
  
  // CAN override
  // core::Twist2 twist_towards_velocity(const core::Vector2 &velocity) override;
};
from navground import core
# May use a custom environment state
class MyEnvironmentState(core.EnvironmentState):
    ...
class MyBehavior(core.Behavior):
    def __init__(self, kinematics: core.Kinematics | None = None, radius: float = 0):
        super().__init__(kinematics, radius)
        self._env_state = MyEnvironmentState()
    def get_environment_state(self) -> core.EnvironmentState:
        return self._env_state
    # CAN override
    # executed before the first evaluation
    # def prepare(self) -> None: ...
    # CAN override
    # executed after the last evaluation
    # def close(self) -> None: ...
    # CAN override
    # def compute_cmd_internal(self, time_step: float) -> core.Twist2: ...
    # CAN override
    # def cmd_twist_along_path(self, path: core.Path, speed: float , time_step: float) -> core.Twist2: ...
    # CAN override
    # def cmd_twist_towards_pose(self, pose: core.Pose2, speed: float , angular_speed: float, time_step: float , frame: core.Frame ) -> core.Twist2: ...
    # CAN override
    # def cmd_twist_towards_point(self, point: core.Vector2, speed: float , time_step: float) -> core.Twist2: ...
    # CAN override
    # def  cmd_twist_towards_velocity(self, velocity: core.Vector2, time_step: float) -> core.Twist2: ...
    # CAN override
    # def cmd_twist_towards_orientation(self, orientation: float, angular_speed: float, time_step: float ) -> core.Twist2: ...
    # CAN override
    # def cmd_twist_towards_angular_speed(self, angular_speed: float, time_step: float) -> core.Twist2: ...
    # CAN override
    # def cmd_twist_towards_stopping(self, time_step: float) -> core.Twist2: ...
    # CAN override
    # def desired_velocity_towards_point(self, point: core.Vector2, speed: float , time_step: float) -> core.Vector2: ...
    # CAN override
    # def  desired_velocity_towards_velocity(self, velocity: core.Vector2, time_step: float) -> core.Vector2: ...
    # CAN override
    # def twist_towards_velocity(self, velocity: core.Vector2) -> core.Twist2: ...