关闭

开源HSM学习笔记---状态机的运行

710人阅读 评论(0) 收藏 举报
分类:

1、状态机的创建

/************************************
State Table(下面每个状态的parent state需要在create中实现),状态列表中成员信息依次为当前状态id、父母状态id、跳转列表、入口动作、出口动作、行为动作、父母状态

************************************/
static state m_stateList_SampleHSM[MAX_STATEID]=
{
{0,0,0,0,0,0},//STATEID_NULL
{ROOT_STATE,STATEID_NULL,&transitionTable_SampleHSM[ROOT_STATE],0,0,0,0},//ROOT_STATE


{STATE_1,ROOT_STATE,&transitionTable_SampleHSM[STATE_1],State1_Entry,State1_Exit,State1_Do,0},//STATE_1


{STATE1_1,STATE_1,&transitionTable_SampleHSM[STATE1_1],State1_1_entry,State1_1_Exit,0,0},//STATE1_1


{STATE1_2,STATE_1,&transitionTable_SampleHSM[STATE1_2],State1_2_entry,State1_2_exit,State1_2_Do,0},//STATE1_2


{STATE_2,ROOT_STATE,&transitionTable_SampleHSM[STATE_2],State2_entry,State2_exit,0,0},//STATE_2


{STATE2_1,STATE_2,&transitionTable_SampleHSM[STATE2_1],State2_1Entry,State2_1Exit,0,0},//STATE2_1


{STATE2_1_1,STATE2_1,&transitionTable_SampleHSM[STATE2_1_1],State2_1_1_Entry,State2_1_1_Exit,0,0},//STATE2_1_1


{STATE_3,ROOT_STATE,&transitionTable_SampleHSM[STATE_3],State3_Entry,State3_Exit,0,0},//STATE_3


{State4,ROOT_STATE,&transitionTable_SampleHSM[State4],State4Entry,State4Exit,State4_Do,0}//State4
};


用户创建状态机函数
/************************************/
/*!
   \fn void SampleHSM_HSM_Create(void)
*  \brief Creating the HSM
*  \return void
*/
/************************************/
void SampleHSM_HSM_Create(void)
{
 hsm_create(m_stateList_SampleHSM,9);

}


基本创建函数

/*! \fn void hsm_create(state *stateList,unsigned int noOfStates) 
*  \brief This function creates the HSM
*  \param *stateList The pointer to the statelist.
*  \param noOfStates Number of states in the HSM
*  \return void
*/
void hsm_create(state *stateList,unsigned int noOfStates)
{
unsigned int stateID = 0;
unsigned int parentID = 0;
hsm_stateList = stateList;


for (stateID = 0; stateID <= noOfStates ;stateID++)
{
parentID = hsm_stateList[stateID].parentID;
hsm_stateList[stateID].parentState = &hsm_stateList[parentID];    //指定其parent state
//printf(" state = %d  ",hsm_stateList[stateID].stateID);
//printf(" state parent = %d \n ",(hsm_stateList[stateID].parentState)->stateID);


}
if(noOfStates > 0)      //指定初始状态
{
hsm_currentState = &hsm_stateList[STATE_START];//set the current state as the root state. the root state shall be the first state.
}


}



2、状态机的开启

/************************************/
/*!
   \fn void SampleHSM_HSM_Start(void)
*  \brief Starting the HSM
*  \return void
*/
/************************************/
void SampleHSM_HSM_Start(void)
{
 hsm_start();
}



/*! \fn void hsm_start(void) 
*  \brief This function is used to start the HSM. 
*   Here ROOT state enters to the Default child state
*  \param void
*  \return void
*/
void hsm_start(void)
{

//printf(" state before = %d  ",hsm_currentState->stateID);
hsm_onEvent(EV_DEFAULT);


}


激活状态机的触发事件

/*! \fn void hsm_onEvent(EventID eventId) 
*  \brief This function is used to fire events to HSM
*  From here the Event Processing function is called 
*  \param eventId The ID of the Current Event
*  \return void
*/
void hsm_onEvent(EventID eventId)
{
   hsm_ProcessEvent(eventId);
   
}


事件处理流程中,丢一个触发事件进来,当前状态根据该触发事件进行跳转处理,当前状态无法处理触发事件的,则丢给其父母节点进行处理
/*! \fn void hsm_ProcessEvent(EventID eventId) 
*  \brief This function is used to process events fired to HSM
*  First it is found  who will be consuming the event. 
*  If the current state is not consuming the event the parent state is checked for it.
*  If nobody in the state hierarchy consumes the event the function does not perform any action. 
*  if the event consumer state is found state transition is executed.
*  \param eventId The ID of the Current Event
*  \return void
*/
void hsm_ProcessEvent(EventID eventId)
{
/*
*First find who will consume the event. If the current state is not consuming the event find the parent state
* who will be consuming it.If nobody in the state hierarchy consumes it do not perform any action. 
*if the state is found execute the exit and entry action sequence.
定义
#ifndef HSM_RESULT_NOK
#define HSM_RESULT_NOK 0
#endif
首先判断该事件是否能触发当前状态发生跳转,如果不能(result=0(HSM_RESULT_NOK)),在触发事件id不为null(EV_DEFAULT)的情况下,当前状态返回到其父母状态,否则,退出循环;

找到当前状态的跳转,则保存其下一次跳转的状态,并执行跳转动作hsm_doTransition

*/
unsigned int result = HSM_RESULT_NOK;
state * currentStateBackUp = hsm_currentState;
state *currentState = hsm_currentState;
unsigned int transitionID = 0;
while(
!result &&
currentState->stateID != STATEID_NULL
)                                                                                                                                    // 查找当前状态到目的状态的跳转路径
{
result = hsm_isEventConsumed(currentState,eventId,&transitionID) ;//checking if the event is consumed by the state,查找当前状态在触发事件下发生跳转的transitionID是否存在
if(HSM_RESULT_OK == result)
{
#ifdef SYSTEM_SIMULATION
printf(" Event consumed %d\n",eventId);
#endif
}
if(!result && eventId != EV_DEFAULT)
{
currentState = currentState->parentState;//setting the current state to parent state   ,当前状态到目的状态的直接路径不存在,且触发事件存在(表明当前状态无法处理该事件),则退出到当前状态的父母节点,查找该父母节点到目的状态的路径是否存在
}
else if(!result && eventId == EV_DEFAULT)          //跳转路径不存在,则退出循环,后面需要恢复当前状态的值
{
break;
}
else
{
hsm_nextState = &hsm_stateList[currentState->smTransition->transition[transitionID].toState];//setting the next state,找到跳转路径,保存目的状态
//printf(" next state  = %d\n  ",hsm_nextState->stateID);
}
}
if(result)
{


hsm_doTransition(transitionID,currentState);// if the event is consumed by the current state do the transition.       找到跳转路径,则执行状态的跳转处理流程

}
else
{
hsm_currentState = currentStateBackUp;
}


}

判断事件是否能触发状态机发生跳转

/*! \fn void hsm_isEventConsumed(state *currentState, EventID eventId,unsigned int *transitionIndex) 
*  \brief This functionchecks if the evnet is consumed by the state indicated by the currentState param.
*   If the event is consumed by a transition the return value is set to HSM_RESULT_OK and the 
*  *transitionIndex is set to the ID of the Transition consuming the event
*
*  \param[in] *currentState pointer to the current state
*  \param[in]  eventId ID of the current Event to be checked for
*  \param[out] *transitionIndex pointer to transitionIndex ID of the transition to be set by the function
*  where the event is consumed. (Here it is assumed that an event can be consumed by  multiple transitions based on transition condition)
*  \return result can be HSM_RESULT_OK or HSM_RESULT_NOK. If the event is consumed by a transition the return value is set to HSM_RESULT_OK and the 
*  *transitionIndex is set to the ID of the Transition consuming the event
*/
unsigned int hsm_isEventConsumed(state *currentState, EventID eventId,unsigned int *transitionIndex)
{
unsigned int result = HSM_RESULT_NOK;
unsigned int transitionID = 0;
unsigned int transitionCount = currentState->smTransition->transitionCount;    //获取当前状态的允许跳转的次数,一个状态根据不同的触发事件会发生多次跳转到不同的目的状态
for(transitionID = 0;transitionID < transitionCount;transitionID++)
{
if(eventId == currentState->smTransition->transition[transitionID].triggerID)          //找到当前状态满足该触发事件的跳转id----transitionID
{
if(currentState->smTransition->transition[transitionID].condition != 0)//execute the transition condition to know if the conditions are correct.,当前触发事件下,是否满足跳转条件
{
if(currentState->smTransition->transition[transitionID].condition()== HSM_RESULT_OK)
{
*transitionIndex = transitionID;//return the current transition Identifier to event processor      //满足触发条件,返回跳转id给事件处理流程
result = HSM_RESULT_OK;
break;
}
}
else
{
*transitionIndex = transitionID;//return the current transition Identifier to event processor     //满足触发事件,无跳转条件时,直接返回跳转id给事件处理流程
result = HSM_RESULT_OK;
break;
}


}
}
return result;


}


跳转处理

/*! \fn void hsm_doTransition(unsigned int transitionID) 
*  \brief This function actually performs the stateTransition. For the state transition execution,
*   the exit functions corresponding to the current and its parent states(which is not the common parent for source and destination) 
*   are to be executed. and Entry function to be executed in the hierarchy order
*  \param transitionID The Id of the transition that need to be perfoemd by the current State
*  \return void
*/
void hsm_doTransition(unsigned int transitionID,state *currentState)
{


if ( hsm_nextState->stateID!= STATEID_NULL)
{
//call the exit hierarchically
executeExit();                           //出口动作,退出当前状态
//execute the state transition
if(NULL != currentState->smTransition)
{
if(NULL != currentState->smTransition->transition[transitionID].action)
{
  currentState->smTransition->transition[transitionID].action();//assuming only one action is there during transition,执行转换动作
}
}
//call the entry hierarchically ,入口动作,进入目的状态
executeEntry();

//execute state transition action
hsm_currentState = hsm_nextState;//do the state transition to next state ,进入目的状态后,就将目的状态设置为当前状态
hsm_nextState = STATEID_NULL;//change the next State  to NULL ,当前状态更新后,目的状态先初始化
//Call the DO action of the state
if(NULL != hsm_currentState )
{
if(NULL != hsm_currentState->doAction)
{
hsm_currentState->doAction();       //执行最新当前状态(即原来的目的状态)的行为动作
}
}
hsm_ProcessEvent(EV_DEFAULT);      //跳转到事件处理流程,进行状态转换
}

}




0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场