我在机器人应用程序中使用 boost::msm 进行状态管理。我有一个外部状态机,用于控制主流程并包括空闲、操作和错误等状态。操作状态本身是一个具有多个子状态的内部状态机。
我在外部状态机中有一个方法来设置上下文对象(TrajectoryManagerComponent* m_component)。该对象需要由内部状态机访问,以便子状态内的操作可以调用其方法。
挑战:我无法将上下文直接传递给内部状态机的构造函数,因为我不直接实例化内部状态机 - 它由 boost::msm 管理。这是我当前代码的简化版本:
struct ComponentStateMachine_ : public msm::front::state_machine_def<ComponentStateMachine_>
{
public:
TrajectoryManagerComponent* m_component;
void link_component(hyro::guidance::TrajectoryManagerComponent* component) { m_component = component; }
struct Operating_ : public msm::front::state_machine_def<Operating_>
{
template <typename Event, typename SM>
void on_entry(Event const&, SM& fsm)
{
m_logger->info("Accessing component, we might now use its methods. Component is {}", **fsm.m_component**);
在内部状态机的操作或状态中从外部状态机访问上下文(m_component)的最佳方式是什么?我考虑过通过构造函数传递它,但由于内部状态机是由 boost::msm 创建的,所以我无法直接控制它的实例化。
有没有办法在 Boost.MSM 中实现此目的,或者是否有替代模式允许我从内部状态机访问上下文?
阅读文档我得到了答案。 正如其所写:
输入动作的另一个可能用途是将数据传递到子状态/子机器。 Launching 是一个包含数据属性的子状态:
struct launcher_ : public msm::front::state_machine_def<launcher_>{
Data current_calculation;
// state machines also have entry/exit actions
template <class Event, class Fsm>
void on_entry(Event const& evt, Fsm& fsm)
{
launcher_::Launching& s = fsm.get_state<launcher_::Launching&>();
s.data = fsm.current_calculation;
}
...
};
因此,在我的例子中,我要做的是在状态机 on_entry 方法中获取子状态机,并将其
.m_component
值设置为状态机 var 处的值,如下所示:
struct ComponentStateMachine_ : public msm::front::state_machine_def<TrajectoryManagerStateMachine_>
{
public:
TrajectoryManagerComponent* m_component;
template <typename Event, typename FSM>
void on_entry(Event const&, FSM& fsm)
{
m_logger->info("Starting the state machine");
// getting a reference to the operating submachine
ComponentStateMachine_::Operating& submachine
= fsm.template get_state<TrajectoryManagerStateMachine_::Operating&>();
submachine.m_component = m_component;
}
...
struct Operating_ : public msm::front::state_machine_def<Operating_>
{
TrajectoryManagerComponent* m_component;
...