Behavior modulations#
Behavior modulation calls virtual method pre
(C++
, Python
)
before and virtual method post
(C++
, Python
) after a behavior is evaluated.
Specializing a new behavior modulation is a simpler alternative to specialize a new behavior, when the specialization should not change the actual methods called to compute a behavior but modulates the parameters (or even state) based on the state and/or the computed command.
Like for behavior, the command produced by post
should be kinematically feasible, but it is not strictly required.
You should also take into account that modulation are performed as a stack: when behavior b
is associated to a sequence of modulations [m_1, m_2, ..., m_n]
, b.compute_cmd
will call them like
m_1(b, time_step)
...
m_n(b, time_step)
cmd <- b.compute_cmd_internal(...)
cmd <- m_n(n, time_step, cmd)
...
cmd <- m_1(n, time_step, cmd)
Note
Although not enforced, each other, modulations should reset in post
any change they have performed on the behavior in pre
.
Virtual methods#
Class skelethon#
#include "navground/core/behavior_modulation.h"
namespace core = navground::core;
struct MyBehaviorModulation : public core::BehaviorModulation {
// CAN override
// modulates the behavior by setting parameters while caching their original value
// void pre(core::Behavior &behavior, ng_float_t time_step) override;
// CAN override
// modulates the cmd and resets parameters to their original values
// core::Twist2 post(core::Behavior &behavior, ng_float_t time_step, const core::Twist2 & cmd) override;
};
from navground import core
class MyBehaviorModulation(core.PyBehaviorModulation):
# CAN override
# modulates the behavior by setting parameters while caching their original value
# def pre(self, behavior: core.Behavior, time_step: float) -> None: ...
# CAN override
# modulates the cmd and resets parameters to their original values
# def post(self, behavior: core.Behavior, time_step: float, cmd: core.Twist2) -> core.Twist2: ...