diff --git a/vscode/CMakeLists.txt b/vscode/CMakeLists.txt index bb30d7d..198660d 100644 --- a/vscode/CMakeLists.txt +++ b/vscode/CMakeLists.txt @@ -7,7 +7,7 @@ aux_source_directory(${PROJECT_SOURCE_DIR}/FSM_OOP/baseFSM SRC_FSM_OOP) # set(keytest 789) -# set(child_parent 789) +set(child_parent 789) if(DEFINED keytest) include_directories(${PROJECT_SOURCE_DIR}/FSM_OOP/keytest) aux_source_directory(${PROJECT_SOURCE_DIR}/FSM_OOP/keytest SRC_FSM_USR) diff --git a/vscode/FSM_OOP/baseFSM/FSM.c b/vscode/FSM_OOP/baseFSM/FSM.c index 4e49dc1..60319ed 100644 --- a/vscode/FSM_OOP/baseFSM/FSM.c +++ b/vscode/FSM_OOP/baseFSM/FSM.c @@ -69,26 +69,60 @@ void stepBaseFSM(FSM *pFSM) FSMHandler *fcns = &pFSM->privateVars->fcns; int curState = pFSM->privateVars->curState; void *data = pFSM->data; - FSM **childFSM = pFSM->privateVars->childFSM; + FSM **childFSMTable = pFSM->privateVars->childFSMTable; int index = pFSM->privateVars->index; int nextState = pFSM->privateVars->nextState; if(nextState && curState != nextState){ // 状态切换 - fcns->exitActionTable[curState](data, childFSM); + // 退子状态机 + if(childFSMTable[curState] != NULL){ + FSM *cFSM = childFSMTable[curState]; + int cFSMCurState = cFSM->privateVars->curState; + cFSM->privateVars->fcns.exitActionTable[cFSMCurState](cFSM->data); + resetBaseFSM(cFSM); + } + // 退父状态机 + fcns->exitActionTable[curState](data); + + // 转移函数 fcns->transitionTable[index](data); // 有特定的状态转移函数 fcns->transitionGeneralAction(data); // 通用状态转移函数 - fcns->enterActionTable[nextState](data, childFSM); + + // 进父状态机 + fcns->enterActionTable[nextState](data); + + // 进子状态机,必须从默认状态开始 + if(childFSMTable[nextState] != NULL){ + FSM *cFSM = childFSMTable[nextState]; + int cFSMNextState = cFSM->privateVars->defaultState; + cFSM->privateVars->fcns.enterActionTable[cFSMNextState](cFSM->data); + cFSM->privateVars->curState = cFSMNextState; + } pFSM->privateVars->curState = nextState; } else if(curState == 0){ // 处理刚运行进入的默认状态 nextState = pFSM->privateVars->defaultState; - fcns->enterActionTable[nextState](data, childFSM); + // 进父状态机 + fcns->enterActionTable[nextState](data); + // 进子状态机 + if(childFSMTable[nextState] != NULL){ + FSM *cFSM = childFSMTable[nextState]; + int cFSMNextState = cFSM->privateVars->defaultState; + cFSM->privateVars->fcns.enterActionTable[cFSMNextState](cFSM->data); + cFSM->privateVars->curState = cFSMNextState; + } + pFSM->privateVars->curState = nextState; } else // 状态机没动 { - fcns->duringActionTable[curState](data, childFSM); + if(childFSMTable[curState] == NULL){ + fcns->duringActionTable[curState](data); + } + else{ + Step(childFSMTable[curState]); + } } } @@ -100,8 +134,6 @@ void stepBaseFSM(FSM *pFSM) /* -------------------------------------------------------------------------- */ void resetBaseFSM(FSM *pFSM) { - if (pFSM->privateVars->fcns.exitActionTable[pFSM->privateVars->curState] != NULL) - pFSM->privateVars->fcns.exitActionTable[pFSM->privateVars->curState](pFSM->data, pFSM->privateVars->childFSM); pFSM->privateVars->curState = 0; } @@ -120,9 +152,8 @@ int getFSMNextState(FSM *pFSM){ -void registerChildFSM(FSM *parent, FSM *child){ - // parent->privateVars->childFSM[index] = child; - // parent->privateVars->hasChild++; +void registerChildFSM(FSM *parent, FSM *child, int state){ + parent->privateVars->childFSMTable[state] = child; } diff --git a/vscode/FSM_OOP/baseFSM/FSM_private.h b/vscode/FSM_OOP/baseFSM/FSM_private.h index 7f540d2..82b00fb 100644 --- a/vscode/FSM_OOP/baseFSM/FSM_private.h +++ b/vscode/FSM_OOP/baseFSM/FSM_private.h @@ -53,7 +53,8 @@ typedef struct FSMPrivateVars FSMHandler fcns; /**< 状态函数表 */ - FSM *childFSM; /**< 限定只能有一个子状态机 */ + // FSM *childFSM; /**< 限定只能有一个子状态机 */ + FSM **childFSMTable; /**< 每个状态都可配置一个子状态机 */ FSMDataLoader preloader; /**< @deprecated 弃用 */ @@ -82,7 +83,7 @@ FSMPrivateVars* newFMSPrivateVars(int numState, int defaultState){ privateVars->defaultState = defaultState; privateVars->curState = 0; privateVars->nextState = 0; - privateVars->childFSM = NULL; + privateVars->childFSMTable = calloc(numState, sizeof(FSM)); privateVars->preloader.isReady = 0; @@ -114,8 +115,8 @@ FSMPrivateVars* newFMSPrivateVars(int numState, int defaultState){ } -static int hasChildFSM(FSM *pFSM){ - return (pFSM->privateVars->childFSM != NULL); +static int hasChildFSM(FSM *pFSM, int state){ + return (pFSM->privateVars->childFSMTable[state] != NULL); } diff --git a/vscode/FSM_OOP/baseFSM/FSM_protected.h b/vscode/FSM_OOP/baseFSM/FSM_protected.h index 0d58b52..bd222b2 100644 --- a/vscode/FSM_OOP/baseFSM/FSM_protected.h +++ b/vscode/FSM_OOP/baseFSM/FSM_protected.h @@ -70,9 +70,9 @@ typedef struct FSMHandler{ void (**transitionTable)(void *data); /**< 状态转移函数表 */ void (*transitionGeneralAction)(void *data); /**< 通用状态转移函数,不论有没有独立的状态转移函数都会执行。常用来清空内部变量 */ - void (**enterActionTable)(void *data, FSM **cFSM); /**< 进入状态时运行的函数,和plecs对标 */ - void (**duringActionTable)(void *data, FSM **cFSM); /**< 状态不变时运行的函数,和plecs对标 */ - void (**exitActionTable)(void *data, FSM **cFSM); /**< 状态退出时运行的函数,和plecs对标 */ + void (**enterActionTable)(void *data); /**< 进入状态时运行的函数,和plecs对标 */ + void (**duringActionTable)(void *data); /**< 状态不变时运行的函数,和plecs对标 */ + void (**exitActionTable)(void *data); /**< 状态退出时运行的函数,和plecs对标 */ void (**childFSMStepTable)(FSM **cFSM); /**< @deprecated 子状态机暂时弃用 */ }FSMHandler; diff --git a/vscode/FSM_OOP/baseFSM/FSM_public.h b/vscode/FSM_OOP/baseFSM/FSM_public.h index 3be36fa..81cea86 100644 --- a/vscode/FSM_OOP/baseFSM/FSM_public.h +++ b/vscode/FSM_OOP/baseFSM/FSM_public.h @@ -53,6 +53,6 @@ int _getPreloaderOverFlag(FSM *pFSM); void _clearPreloaderOverFlag(FSM *pFSM); /* ---------------------------------- 子状态机 ---------------------------------- */ -void registerChildFSM(FSM *parent, FSM *child); +void registerChildFSM(FSM *parent, FSM *child, int state); #endif diff --git a/vscode/FSM_OOP/childtest/ParentFSM.c b/vscode/FSM_OOP/childtest/ParentFSM.c index a84f4b8..27a61db 100644 --- a/vscode/FSM_OOP/childtest/ParentFSM.c +++ b/vscode/FSM_OOP/childtest/ParentFSM.c @@ -1,123 +1,83 @@ #include #include +#include -#include "parentFSM.h" #include "FSM_protected.h" - -#define DEFAULT_STATE Idle - -typedef struct _ParentFSM -{ - FSM base; -}ParentFSM; - -typedef enum _State{ - Idle, - A, - B, - C, - - Count_State, -}State; - -typedef enum _Event{ - Idle_Event, - Start, - A2B, - B2A, - B2C, - C2A, - - Count_Event, -}Event; - -const static char *stateStr[] = { - "Idle", - "A", - "B", - "C", -}; - -const static char *eventStr[] = { - "Idle", - "Start", - "A2B", - "B2A", - "B2C", - "C2A", -}; +#include "parentFSM.h" +#include "parentFSM_private.h" -State StartHandler(){ - FSM_LOG(" start "); - return A; -} -State A2BHandler(){ - FSM_LOG(" A2B "); - return B; -} -State B2AHandler(){ - FSM_LOG(" B2A "); - return A; -} +/* -------------------------------------------------------------------------- */ +/* 纯虚函数,允许调用privateVars */ +/* -------------------------------------------------------------------------- */ -State B2CHandler(){ - FSM_LOG(" B2C "); - return C; -} - -State C2AHandler(){ - FSM_LOG(" C2A "); - return A; +/** + * @brief + * @deprecated 暂时没用,后续考虑data是否需要加锁再说 + * @param data 主要是外部数据 + */ +static void loadExternalData(ParentFSMData *data){ // 必须重新实现 } -void A_enterAction(){ - FSM_LOG(" enterA "); -} -void A_duringAction(){ - FSM_LOG(" duringA "); -} -void A_exitAction(){ - FSM_LOG(" exitA "); +/** + * @brief 根据条件重置信号 + * @details 清除被响应信号和所有小于被响应信号优先级的信号,具体可以参考notion + * @param signals 状态机接收到的信号 + * @param data 状态机数据 + */ +static void resetSignals(FSMSignals *signals, ParentFSMData *data){ // 必须重新实现 + clearAllSignals(signals); } -void B_enterAction(void *data, FSM **childFSM){ - FSM_LOG(" enterB "); - - FSM *cFSM = childFSM[0]; - cFSM->pureVtbl.step(cFSM); -} -void B_duringAction(void *data, FSM **childFSM){ - FSM_LOG(" duringB "); +/** + * @brief 给所有内部、外部数据分配堆空间 + * + * @param pFSM + */ +static void initData(ParentFSM *pFSM){ // 必须重新实现 + ParentFSMData *data = (ParentFSMData *)malloc(sizeof(ParentFSMData)); - FSM *cFSM = childFSM[0]; - cFSM->pureVtbl.step(cFSM); -} -void B_exitAction(void *data, FSM **childFSM){ - FSM *cFSM = childFSM[0]; - cFSM->pureVtbl.reset(cFSM); + ParentFSMData tempData = { + .external = { + .arrindex = 0, + .x = 0, + }, + .internal = { + .inner1 = 0, + .y1 = 0, + }, + }; + *data = tempData; - FSM_LOG(" exitB "); + pFSM->base.data = data; +} + +/** + * @brief + * @deprecated 弃用 + * @param pFSM + */ +static void initDataLoader(ParentFSM *pFSM){ // 必须重新实现 + // pFSM->base.privateVars->preloader.shadowData = malloc(sizeof(ParentFSMExternalData)); + // pFSM->base.privateVars->preloader.size = sizeof(ParentFSMExternalData); } -void C_enterAction(){ - FSM_LOG(" enterC "); -} -void C_duringAction(){ - FSM_LOG(" duringC "); -} -void C_exitAction(){ - FSM_LOG(" exitC "); -} - - - -static void setupHandler(FSMHandler* fcns){ +/** + * @brief 设置状态选择函数、状态内函数和状态转移函数 + * + * @param fcns 状态机函数表 + */ +static void setupHandler(FSMHandler* fcns){ // 必须重新实现 + /* ------------------------------- 添加下一个状态选择函数 ------------------------------ */ + addSelectNextStateFcn(A); + addSelectNextStateFcn(B); + addSelectNextStateFcn(C); + /* ----------------------- 添加状态中事件,action during exit ----------------------- */ addStateActionFcn(during, A); addStateActionFcn(during, B); addStateActionFcn(during, C); @@ -128,85 +88,63 @@ static void setupHandler(FSMHandler* fcns){ addStateActionFcn(exit, B); addStateActionFcn(exit, C); - addTransitionHandler(Idle, Start); - addTransitionHandler(A, A2B); - addTransitionHandler(B, B2A); - addTransitionHandler(B, B2C); - addTransitionHandler(C, C2A); -} - - - -/* - 用户自定义事件选择逻辑—————————————————begin -*/ -Event peventArr[20] = { - Idle_Event, - Start, - A2B, - Idle_Event, - Idle_Event, - Idle_Event, - Idle_Event, - Idle_Event, - B2C, - C2A, - A2B, - B2A, -}; - -static Event selectEvent(ParentFSMData *data){ - return peventArr[data->arrindex]; -} -/* - 用户自定义事件选择逻辑————————end -*/ - -static void printFSM(ParentFSM* pFSM){ - FSM_LOG("\tParentFSM: "); - - FSM_LOG("当前状态:%s, 当前事件:%s, 动作:", stateStr[pFSM->base.privateVars.curState], eventStr[pFSM->base.privateVars.curEvent]); + /* --------------------------- 添加转移函数和转移函数对应的Delay -------------------------- */ + addTransitionHandler(Idle, A); + addTransitionHandler(A, B); + addTransitionHandler(B, A); + addTransitionHandler(B, C); + addTransitionHandler(C, A); + + fcns->transitionGeneralAction = (Avoid_WARNING_General_Handlers)transitionGeneralAction; } +/* -------------------------------------------------------------------------- */ +/* 其他重新实现的函数,父类已有实现,实现多态 */ +/* -------------------------------------------------------------------------- */ +/** + * @brief 重新实现基类的step函数,添加一些打印信息 + * + * @param pFSM 子类状态机指针 + */ static void step(ParentFSM* pFSM){ printFSM(pFSM); - _stepFSM(BASE_FSM(pFSM)); -} - -static void reset(ParentFSM* pFSM){ - resetBaseFSM(BASE_FSM(pFSM)); - FSM_LOG(" ParentFSM-reset"); -} - -static void initData(ParentFSM *pFSM){ - ParentFSMData *data = (ParentFSMData *)malloc(sizeof(ParentFSMData)); - data->arrindex = 0; - - pFSM->base.data = data; -} - -static void initDataLoader(ParentFSM *pFSM){ // 必须重新实现 - pFSM->base.privateVars.preloader.in = malloc(sizeof(ParentFSMData)); - pFSM->base.privateVars.preloader.preloadSize = sizeof(ParentFSMData); + stepBaseFSM(BASE_FSM(pFSM)); + FSM_LOG("下次状态:%s", stateStr[getFSMNextState((FSM *)pFSM)]); } +// 绑定子状态机 +void bindChildFSM(FSM *pFSM, FSM *cFSM){ + registerChildFSM(pFSM, cFSM, B); +} + + +/* -------------------------------------------------------------------------- */ +/* 子类构造函数 */ +/* -------------------------------------------------------------------------- */ + +/** + * @brief Create a Parent FSM object + * @details 子类状态机细节对外隐藏,外部只能访问基类的公有函数来操作子类变量 + * @return ParentFSM* + */ ParentFSM *createParentFSM(){ - ParentFSM *pFSM; - pFSM = (ParentFSM *)newBaseFSM(Count_State, Count_Event, DEFAULT_STATE); + pFSM = (ParentFSM *)newBaseFSM(Count_State, DEFAULT_STATE); + + // 重新实现的函数 + pFSM->base.publicFcns.step = (Avoid_WARNING_Overrider_Fcns)step; + pFSM->base.pureVtbl.initData = (Avoid_WARNING_Overrider_Fcns)initData; + pFSM->base.pureVtbl.initDataLoader = (Avoid_WARNING_Overrider_Fcns)initDataLoader; + pFSM->base.pureVtbl.setupHandler = (Avoid_WARNING_void_fcns)setupHandler; + pFSM->base.pureVtbl.resetSignals = (Avoid_WARNING_ResetSignals_Fcns)resetSignals; + pFSM->base.pureVtbl.loadExternalData = (Avoid_WARNING_loadData_Fcns)loadExternalData; + + // 调用父类构造函数 + constructFSM((FSM *)pFSM); + + FSM_LOG("ok\n"); - pFSM->base.pureVtbl.step = step; - pFSM->base.pureVtbl.selectNextState = selectEvent; - pFSM->base.pureVtbl.initData = initData; - pFSM->base.pureVtbl.setupHandler = setupHandler; - pFSM->base.pureVtbl.initDataLoader = initDataLoader; - - constructFSM((FSM *)pFSM); return pFSM; -} - - - - +} \ No newline at end of file diff --git a/vscode/FSM_OOP/childtest/ParentFSM_private.h b/vscode/FSM_OOP/childtest/ParentFSM_private.h new file mode 100644 index 0000000..b9f2683 --- /dev/null +++ b/vscode/FSM_OOP/childtest/ParentFSM_private.h @@ -0,0 +1,166 @@ +#ifdef __PARENTFSM_PRIVATE_FSM_H_ +#error This file can only be included once!!! + +#else +#define __PARENTFSM_PRIVATE_FSM_H_ +#endif + +#include "FSM_protected.h" +#include "parentFSM.h" +#include + + +/* -------------------------------------------------------------------------- */ +/* 继承基类 */ +/* -------------------------------------------------------------------------- */ +typedef struct ParentFSM +{ + FSM base; +}ParentFSM; + +/* -------------------------------------------------------------------------- */ +/* 状态定义 */ +/* -------------------------------------------------------------------------- */ + +/** + * @brief 状态机内状态定义,Idle和Count_State必须占据开头和结尾两个位置 + * + */ +typedef enum _State +{ + Idle, /**< 必须在开头,并且枚举值=0 */ + A, + B, + C, + + Count_State, /**< 必须在结尾,用来统计状态数量 */ +} State; +#define DEFAULT_STATE A /**< 默认状态,Idle状态会先跳转到默认状态 */ + +/* -------------------------------------------------------------------------- */ +/* 下一个状态选择函数 */ +/* -------------------------------------------------------------------------- */ + + +static State selectNextStateFcn(A)(ParentFSM *data, FSMSignals *signals){ + if(getSignal(signals, Signal_toB)){ + signals->lastTriggeredSignal = Signal_toB; + return B; + } + return Idle; +} + +static State selectNextStateFcn(B)(ParentFSM *data, FSMSignals *signals){ + if(getSignal(signals, Signal_toA)){ + signals->lastTriggeredSignal = Signal_toA; + return A; + } + else if(getSignal(signals, Signal_toC)){ + signals->lastTriggeredSignal = Signal_toC; + return C; + } + return Idle; +} + +static State selectNextStateFcn(C)(ParentFSM *data, FSMSignals *signals){ + if(getSignal(signals, Signal_toA)){ + signals->lastTriggeredSignal = Signal_toA; + return A; + } + return Idle; +} + +/* -------------------------------------------------------------------------- */ +/* 对应的 action, exit, during 函数 */ +/* -------------------------------------------------------------------------- */ +static void actionFcn(enter, A)() +{ + FSM_LOG(" enterA "); +} +static void actionFcn(during, A)() +{ + FSM_LOG(" duringA "); +} +static void actionFcn(exit, A)() +{ + FSM_LOG(" exitA "); +} + +static void actionFcn(enter, B)() +{ + FSM_LOG(" enterB "); +} +static void actionFcn(during, B)() +{ + FSM_LOG(" duringB "); +} +static void actionFcn(exit, B)() +{ + FSM_LOG(" exitB "); +} + +static void actionFcn(enter, C)() +{ + FSM_LOG(" enterC "); +} +static void actionFcn(during, C)() +{ + FSM_LOG(" duringC "); +} +static void actionFcn(exit, C)() +{ + FSM_LOG(" exitC"); +} + + +/* -------------------------------------------------------------------------- */ +/* 转移函数 */ +/* -------------------------------------------------------------------------- */ +static void transitionGeneralAction(FSM pFSM){ + // FSM_LOG("general"); +} + +// static void transitionGeneralAction(TemplateFSMData *data){ +// FSM_LOG("general"); +// } + +static void transitionHandler(Idle, A)() +{ + FSM_LOG(" Idle2A "); +} + + +static void transitionHandler(A, B)() +{ + FSM_LOG(" A2B "); +} + +static void transitionHandler(B, A)() +{ + FSM_LOG(" B2A "); +} + +static void transitionHandler(B, C)() +{ + FSM_LOG(" B2C "); +} + +static void transitionHandler(C, A)() +{ + FSM_LOG(" C2A "); +} + +/* -------------------------------------------------------------------------- */ +/* 打印调试 */ +/* -------------------------------------------------------------------------- */ +const static char *stateStr[] = { + "Idle", + "A", + "B", + "C", +}; + +static void printFSM(ParentFSM* pFSM){ + FSM_LOG(" \tParent: "); + FSM_LOG("当前状态:%s, 动作:", stateStr[getFSMCurState((FSM *)pFSM)]); +} diff --git a/vscode/FSM_OOP/childtest/childFSM.c b/vscode/FSM_OOP/childtest/childFSM.c index e887f19..e795b48 100644 --- a/vscode/FSM_OOP/childtest/childFSM.c +++ b/vscode/FSM_OOP/childtest/childFSM.c @@ -1,82 +1,142 @@ #include #include +#include #include "FSM_protected.h" #include "childFSM.h" #include "childFSM_private.h" -/* - 重载函数,有些是纯虚的必须重新实现,有些可以不重新实现直接用父类的 -*/ -Event ceventArr[20] = { - Idle_Event, - Idle_Event, - Idle2D, - Idle_Event, - Idle_Event, - D2E, - E2D, - D2E, - Idle_Event, - Idle_Event, - Idle_Event, - Idle_Event, -}; -static Event selectEvent(ChildFSMData *data){ // 必须重新实现 - return ceventArr[data->arrindex]; + + +/* -------------------------------------------------------------------------- */ +/* 纯虚函数,允许调用privateVars */ +/* -------------------------------------------------------------------------- */ + +/** + * @brief + * @deprecated 暂时没用,后续考虑data是否需要加锁再说 + * @param data 主要是外部数据 + */ +static void loadExternalData(ChildFSMData *data){ // 必须重新实现 } -static void step(ChildFSM* pFSM){ - printFSM(pFSM); - _stepFSM(BASE_FSM(pFSM)); + +/** + * @brief 根据条件重置信号 + * @details 清除被响应信号和所有小于被响应信号优先级的信号,具体可以参考notion + * @param signals 状态机接收到的信号 + * @param data 状态机数据 + */ +static void resetSignals(FSMSignals *signals, ChildFSMData *data){ // 必须重新实现 + clearAllSignals(signals); } +/** + * @brief 给所有内部、外部数据分配堆空间 + * + * @param pFSM + */ static void initData(ChildFSM *pFSM){ // 必须重新实现 ChildFSMData *data = (ChildFSMData *)malloc(sizeof(ChildFSMData)); - data->arrindex = 0; - pFSM->base.privateVars.preloader.in = malloc(sizeof(ChildFSMData)); - pFSM->base.privateVars.preloader.preloadSize = sizeof(ChildFSMData); + ChildFSMData tempData = { + .external = { + .arrindex = 0, + .x = 0, + }, + .internal = { + .inner1 = 0, + .y1 = 0, + }, + }; + *data = tempData; pFSM->base.data = data; } +/** + * @brief + * @deprecated 弃用 + * @param pFSM + */ static void initDataLoader(ChildFSM *pFSM){ // 必须重新实现 - pFSM->base.privateVars.preloader.in = malloc(sizeof(ChildFSMData)); - pFSM->base.privateVars.preloader.preloadSize = sizeof(ChildFSMData); + // pFSM->base.privateVars->preloader.shadowData = malloc(sizeof(ChildFSMExternalData)); + // pFSM->base.privateVars->preloader.size = sizeof(ChildFSMExternalData); } + +/** + * @brief 设置状态选择函数、状态内函数和状态转移函数 + * + * @param fcns 状态机函数表 + */ static void setupHandler(FSMHandler* fcns){ // 必须重新实现 - addStateActionFcn(during, E); + /* ------------------------------- 添加下一个状态选择函数 ------------------------------ */ + addSelectNextStateFcn(D); + addSelectNextStateFcn(E); + + /* ----------------------- 添加状态中事件,action during exit ----------------------- */ addStateActionFcn(during, D); + addStateActionFcn(during, E); addStateActionFcn(enter, D); - addStateActionFcn(exit, D); addStateActionFcn(enter, E); + addStateActionFcn(exit, D); addStateActionFcn(exit, E); - addTransitionHandler(Idle, Idle2D); - addTransitionHandler(Idle, Idle2E); - addTransitionHandler(D, D2E); - addTransitionHandler(E, E2D); + /* --------------------------- 添加转移函数和转移函数对应的Delay -------------------------- */ + addTransitionHandler(Idle, D); + addTransitionHandler(Idle, E); + addTransitionHandler(D, E); + addTransitionHandler(E, D); + + fcns->transitionGeneralAction = (Avoid_WARNING_General_Handlers)transitionGeneralAction; } -/* - 唯一外界调用的函数 + +/* -------------------------------------------------------------------------- */ +/* 其他重新实现的函数,父类已有实现,实现多态 */ +/* -------------------------------------------------------------------------- */ +/** + * @brief 重新实现基类的step函数,添加一些打印信息 + * + * @param pFSM 子类状态机指针 */ +static void step(ChildFSM* pFSM){ + printFSM(pFSM); + stepBaseFSM(BASE_FSM(pFSM)); + FSM_LOG("下次状态:%s", stateStr[getFSMNextState((FSM *)pFSM)]); +} + + + + +/* -------------------------------------------------------------------------- */ +/* 子类构造函数 */ +/* -------------------------------------------------------------------------- */ + +/** + * @brief Create a Child FSM object + * @details 子类状态机细节对外隐藏,外部只能访问基类的公有函数来操作子类变量 + * @return ChildFSM* + */ ChildFSM *createChildFSM(){ - ChildFSM *pFSM; - pFSM = (ChildFSM *)newBaseFSM(Count_State, Count_Event, DEFAULT_STATE); + pFSM = (ChildFSM *)newBaseFSM(Count_State, DEFAULT_STATE); - pFSM->base.pureVtbl.step = step; - pFSM->base.pureVtbl.selectNextState = selectEvent; - pFSM->base.pureVtbl.initData = initData; - pFSM->base.pureVtbl.setupHandler = setupHandler; - pFSM->base.pureVtbl.initDataLoader = initDataLoader; + // 重新实现的函数 + pFSM->base.publicFcns.step = (Avoid_WARNING_Overrider_Fcns)step; + pFSM->base.pureVtbl.initData = (Avoid_WARNING_Overrider_Fcns)initData; + pFSM->base.pureVtbl.initDataLoader = (Avoid_WARNING_Overrider_Fcns)initDataLoader; + pFSM->base.pureVtbl.setupHandler = (Avoid_WARNING_void_fcns)setupHandler; + pFSM->base.pureVtbl.resetSignals = (Avoid_WARNING_ResetSignals_Fcns)resetSignals; + pFSM->base.pureVtbl.loadExternalData = (Avoid_WARNING_loadData_Fcns)loadExternalData; - constructFSM((FSM *)pFSM); + // 调用父类构造函数 + constructFSM((FSM *)pFSM); + + FSM_LOG("ok\n"); return pFSM; -} +} \ No newline at end of file diff --git a/vscode/FSM_OOP/childtest/childFSM.h b/vscode/FSM_OOP/childtest/childFSM.h index df4e4e8..74b4eb4 100644 --- a/vscode/FSM_OOP/childtest/childFSM.h +++ b/vscode/FSM_OOP/childtest/childFSM.h @@ -1,17 +1,59 @@ #ifndef __CHILD_FSM_H_ #define __CHILD_FSM_H_ +/* -------------------------------------------------------------------------- */ +/* 提前做类型声明 */ +/* -------------------------------------------------------------------------- */ -#define ChildFSM_Input(pFSM) ((ChildFSMData *)_preloadIn((FSM *)pFSM)) -typedef struct _childFSMData +/* -------------------------------------------------------------------------- */ +/* 自定义数据和信号 */ +/* -------------------------------------------------------------------------- */ +/** + * @brief 自定义外部信号,目前最多15个 + * @details 因为是Unint16存储的信号位 + * + */ +enum ChildFSMSignals{ + Signal_toD = 1, /**< 必须从1开始,0预留给Idle信号了*/ + Signal_toE, +}; + +/** + * @brief 自定义外部数据 + * + */ +typedef struct ChildFSMExternalData { int arrindex; + int x; +}ChildFSMExternalData; + + +/** + * @brief 自定义内部数据 + * + */ +typedef struct ChildFSMInnerData +{ + int y1; + int inner1; +}ChildFSMInnerData; + +/* -------------------------------------------------------------------------- */ +/* 下面的改个名字就行了 */ +/* -------------------------------------------------------------------------- */ +#define ChildFSM_Input(pFSM) ((ChildFSMExternalData *)_preloadIn((FSM *)pFSM)) /**< @deprecated 暂时弃用 */ + +typedef struct ChildFSMData +{ + ChildFSMExternalData external; + ChildFSMInnerData internal; }ChildFSMData; -typedef struct _ChildFSM ChildFSM; - +typedef struct ChildFSM ChildFSM; ChildFSM *createChildFSM(); + #endif diff --git a/vscode/FSM_OOP/childtest/childFSM_private.h b/vscode/FSM_OOP/childtest/childFSM_private.h index f51c4f5..f3ac364 100644 --- a/vscode/FSM_OOP/childtest/childFSM_private.h +++ b/vscode/FSM_OOP/childtest/childFSM_private.h @@ -1,121 +1,133 @@ -#ifndef __CHILD_PRIVATE_FSM_H_ -#define __CHILD_PRIVATE_FSM_H_ +#ifdef __CHILDFSM_PRIVATE_FSM_H_ +#error This file can only be included once!!! + +#else +#define __CHILDFSM_PRIVATE_FSM_H_ +#endif #include "FSM_protected.h" #include "childFSM.h" #include -/* - 继承基类 - */ -typedef struct _ChildFSM +/* -------------------------------------------------------------------------- */ +/* 继承基类 */ +/* -------------------------------------------------------------------------- */ +typedef struct ChildFSM { - // 继承父类 FSM base; }ChildFSM; -/* - 状态和对应的 action, exit, during 函数 - */ +/* -------------------------------------------------------------------------- */ +/* 状态定义 */ +/* -------------------------------------------------------------------------- */ +/** + * @brief 状态机内状态定义,Idle和Count_State必须占据开头和结尾两个位置 + * + */ typedef enum _State { - Idle, + Idle, /**< 必须在开头,并且枚举值=0 */ D, E, - Count_State, + Count_State, /**< 必须在结尾,用来统计状态数量 */ } State; -#define DEFAULT_STATE E +#define DEFAULT_STATE D /**< 默认状态,Idle状态会先跳转到默认状态 */ -void actionFcn(enter, D)() +/* -------------------------------------------------------------------------- */ +/* 下一个状态选择函数 */ +/* -------------------------------------------------------------------------- */ + + +static State selectNextStateFcn(D)(ChildFSM *data, FSMSignals *signals){ + if(getSignal(signals, Signal_toE)){ + signals->lastTriggeredSignal = Signal_toE; + return E; + } + return Idle; +} + +static State selectNextStateFcn(E)(ChildFSM *data, FSMSignals *signals){ + if(getSignal(signals, Signal_toD)){ + signals->lastTriggeredSignal = Signal_toD; + return D; + } + return Idle; +} + +/* -------------------------------------------------------------------------- */ +/* 对应的 action, exit, during 函数 */ +/* -------------------------------------------------------------------------- */ +static void actionFcn(enter, D)() { FSM_LOG(" enterD "); } -void actionFcn(during, D)() +static void actionFcn(during, D)() { FSM_LOG(" duringD "); } -void actionFcn(exit, D)() +static void actionFcn(exit, D)() { FSM_LOG(" exitD "); } -void actionFcn(enter, E)() +static void actionFcn(enter, E)() { FSM_LOG(" enterE "); } -void actionFcn(during, E)() +static void actionFcn(during, E)() { FSM_LOG(" duringE "); } -void actionFcn(exit, E)() +static void actionFcn(exit, E)() { FSM_LOG(" exitE "); } -/* - 事件和对应的转移函数 - */ -typedef enum _Event{ - Idle_Event, - Idle2D, - Idle2E, - D2E, - E2D, +/* -------------------------------------------------------------------------- */ +/* 转移函数 */ +/* -------------------------------------------------------------------------- */ +static void transitionGeneralAction(FSM pFSM){ + // FSM_LOG("general"); +} - Count_Event, -}Event; +// static void transitionGeneralAction(TemplateFSMData *data){ +// FSM_LOG("general"); +// } - -State transitionHandler(Idle2D)() +static void transitionHandler(Idle, D)() { FSM_LOG(" Idle2D "); - return D; } -State transitionHandler(Idle2E)() +static void transitionHandler(Idle, E)() { FSM_LOG(" Idle2E "); - return E; } -State transitionHandler(D2E)() +static void transitionHandler(D, E)() { FSM_LOG(" D2E "); - return E; } -State transitionHandler(E2D)() +static void transitionHandler(E, D)() { FSM_LOG(" E2D "); - return D; } - - - -/* - 用户自定义事件选择逻辑—————————————————begin -*/ +/* -------------------------------------------------------------------------- */ +/* 打印调试 */ +/* -------------------------------------------------------------------------- */ const static char *stateStr[] = { "Idle", "D", "E", - }; -const static char *eventStr[] = { - "Idle", - "Idle2D", - "Idle2E", - "D2E", - "E2D", }; + static void printFSM(ChildFSM* pFSM){ - FSM_LOG(" \t\tChildFSM: "); - FSM_LOG("当前状态:%s, 当前事件:%s, 动作:", stateStr[getFSMCurState((FSM *)pFSM)], eventStr[getFSMCurEvent((FSM *)pFSM)]); + FSM_LOG(" \tChild: "); + FSM_LOG("当前状态:%s, 动作:", stateStr[getFSMCurState((FSM *)pFSM)]); } - - -#endif diff --git a/vscode/FSM_OOP/childtest/main.c b/vscode/FSM_OOP/childtest/main.c index dc89bcb..0b0fec2 100644 --- a/vscode/FSM_OOP/childtest/main.c +++ b/vscode/FSM_OOP/childtest/main.c @@ -7,27 +7,25 @@ ChildFSM *cFSM; ParentFSM *pFSM; +enum ParentFSMSignals i[20] = {0, Signal_toA, Signal_toB,0,0,0,0,0, Signal_toC, Signal_toA, Signal_toB, Signal_toA}; +enum ChildFSMSignals j[20] = {0,0,Signal_toD,0,0,Signal_toE, Signal_toD, Signal_toE,0,0,0,0}; + int main(){ cFSM = createChildFSM(); pFSM = createParentFSM(); - setChildNum((pFSM), 1); - registerChildFSM((pFSM), (cFSM), 0); + registerChildFSM(pFSM, cFSM, 2); - for (int i = 0; i < 15; i++) + for (int k = 0; k < 15; k++) { - ParentFSM_Input(pFSM)->arrindex = i; - PreloaderGetReady(pFSM); + printf("第%d次: ",k+1); + SetSignal(pFSM, i[k]); + SetSignal(cFSM, j[k]); - ChildFSM_Input(cFSM)->arrindex = i; - PreloaderGetReady(cFSM); - - ChildFSMData* data = _getData((FSM *)(cFSM)); - printf(" %d ", data->arrindex); + Step(pFSM); - _vptrFSM((FSM *)pFSM)->step((FSM *)pFSM); printf("\n"); } diff --git a/vscode/FSM_OOP/childtest/parentFSM.h b/vscode/FSM_OOP/childtest/parentFSM.h index 49f26bd..4f41fe4 100644 --- a/vscode/FSM_OOP/childtest/parentFSM.h +++ b/vscode/FSM_OOP/childtest/parentFSM.h @@ -1,15 +1,63 @@ #ifndef __PARENT_FSM_H_ #define __PARENT_FSM_H_ +/* -------------------------------------------------------------------------- */ +/* 提前做类型声明 */ +/* -------------------------------------------------------------------------- */ -#define ParentFSM_Input(pFSM) ((ParentFSMData *)_preloadIn((FSM *)pFSM)) -typedef struct _parentFSMData +/* -------------------------------------------------------------------------- */ +/* 自定义数据和信号 */ +/* -------------------------------------------------------------------------- */ +/** + * @brief 自定义外部信号,目前最多15个 + * @details 因为是Unint16存储的信号位 + * + */ +enum ParentFSMSignals{ + Signal_toA = 1, /**< 必须从1开始,0预留给Idle信号了*/ + Signal_toB, + Signal_toC, +}; + +/** + * @brief 自定义外部数据 + * + */ +typedef struct ParentFSMExternalData { int arrindex; -}ParentFSMData; -typedef struct _ParentFSM ParentFSM; + int x; +}ParentFSMExternalData; + +/** + * @brief 自定义内部数据 + * + */ +typedef struct ParentFSMInnerData +{ + int y1; + int inner1; +}ParentFSMInnerData; + + + + +/* -------------------------------------------------------------------------- */ +/* 下面的改个名字就行了 */ +/* -------------------------------------------------------------------------- */ +#define ParentFSM_Input(pFSM) ((ParentFSMExternalData *)_preloadIn((FSM *)pFSM)) /**< @deprecated 暂时弃用 */ + +typedef struct ParentFSMData +{ + ParentFSMExternalData external; + ParentFSMInnerData internal; +}ParentFSMData; + +typedef struct ParentFSM ParentFSM; ParentFSM *createParentFSM(); + + #endif diff --git a/父子状态机测试.plecs b/父子状态机测试.plecs index 2a92ff8..4643e69 100644 --- a/父子状态机测试.plecs +++ b/父子状态机测试.plecs @@ -47,7 +47,7 @@ Plecs { ScriptsDialogGeometry "" ScriptsDialogSplitterPos "0" Schematic { - Location [818, 291; 1460, 717] + Location [147, 417; 789, 840] ZoomFactor 1.71498 SliderPosition [0, 0] ShowBrowser off @@ -139,9 +139,9 @@ Plecs { Show off } FSM { - Location [0, 0; 1918, 923] + Location [661, 192; 2579, 1112] ZoomFactor 0.76361 - SliderPosition [0, 44] + SliderPosition [0, 47] FsmState { Name "A" Position [360, 480] @@ -161,8 +161,8 @@ Plecs { } FsmState { Name "B" - Position [1400, 420] - Frame [-710, -260; 710, 260] + Position [1220, 400] + Frame [-530, -240; 530, 240] Parameter { Name "EnterAction" Value "printf(\" enterB \");" @@ -177,7 +177,7 @@ Plecs { } FsmState { Name "D" - Position [-530, 0] + Position [-350, 20] Frame [-100, -90; 100, 90] Parameter { Name "EnterAction" @@ -194,105 +194,46 @@ Plecs { } FsmState { Name ".Junction" - Position [-380, -150] + Position [-200, -130] } FsmState { Name ".PointState" - Position [-380, -190] + Position [-200, -170] } FsmState { Name "E" - Position [220, 40] - Frame [-400, -130; 400, 130] + Position [230, 20] + Frame [-230, -90; 230, 90] Parameter { Name "EnterAction" Value "printf(\" enterE \");" } Parameter { Name "DuringAction" - Value "" + Value "printf(\" duringE \");" } Parameter { Name "ExitAction" Value "printf(\" exitE \");" } - FsmState { - Name "State" - Position [-130, 30] - Frame [-90, -60; 90, 60] - Parameter { - Name "EnterAction" - Value "/* enter action */" - } - Parameter { - Name "DuringAction" - Value "" - } - Parameter { - Name "ExitAction" - Value "" - } - } - FsmState { - Name ".PointState" - Position [110, -80] - } - FsmState { - Name "State1" - Position [230, 30] - Frame [-90, -60; 90, 60] - Parameter { - Name "EnterAction" - Value "/* enter action */" - } - Parameter { - Name "DuringAction" - Value "" - } - Parameter { - Name "ExitAction" - Value "" - } - } } } FsmState { Name "C" - Position [1100, 1110] - Frame [-550, -150; 550, 150] + Position [850, 1050] + Frame [-300, -90; 300, 90] Parameter { Name "EnterAction" Value "printf(\" enterC \");" } Parameter { Name "DuringAction" - Value "" + Value "printf(\" duringC \");" } Parameter { Name "ExitAction" Value "printf(\" exitC \");" } - FsmState { - Name "D" - Position [-140, 30] - Frame [-100, -90; 100, 90] - Parameter { - Name "EnterAction" - Value "printf(\" enterD \");" - } - Parameter { - Name "DuringAction" - Value "printf(\" duringD \");" - } - Parameter { - Name "ExitAction" - Value "printf(\" exitD \");" - } - } - FsmState { - Name ".PointState" - Position [-10, -100] - } } FsmState { Name ".PointState" @@ -618,70 +559,6 @@ Plecs { Value "2" } } - FsmTransition { - FsmSrcInfo { - StatePath "C/.PointState" - TerminalLoc bottom - TerminalCoord 0.5 - External on - } - FsmDstInfo { - StatePath "C/D" - TerminalLoc top - TerminalCoord 0.414129 - External on - } - SegmentLengths [15,-72.90010560019118,-3] - LabelPosition 0.5 - Parameter { - Name "Trigger" - Value "" - } - Parameter { - Name "Condition" - Value "" - } - Parameter { - Name "Action" - Value "" - } - Parameter { - Name "Priority" - Value "1" - } - } - FsmTransition { - FsmSrcInfo { - StatePath "B/E/.PointState" - TerminalLoc bottom - TerminalCoord 0.5 - External on - } - FsmDstInfo { - StatePath "B/E/State" - TerminalLoc top - TerminalCoord 0.490903 - External on - } - SegmentLengths [18.5] - LabelPosition 0.5 - Parameter { - Name "Trigger" - Value "" - } - Parameter { - Name "Condition" - Value "" - } - Parameter { - Name "Action" - Value "" - } - Parameter { - Name "Priority" - Value "1" - } - } } } Component { @@ -806,17 +683,17 @@ Plecs { Direction up Flipped off LabelPosition south - Location [811, 582; 1161, 833] + Location [849, 525; 1199, 784] State "AAAA/wAAAAD9AAAAAgAAAAEAAAAAAAAAAPwCAAAAA/sAAAAQAFoAbwBvA" "G0AQQByAGUAYQAAAAAA/////wAAADQA////+wAAABQAUwBhAHYAZQBkAFYAaQBlAHcAcwAAAAAA//" "///wAAAGYA////+wAAAAwAVAByAGEAYwBlAHMAAAAAAP////8AAABmAP///wAAAAMAAAAAAAAAAPw" -"BAAAAAfsAAAAUAEQAYQB0AGEAVwBpAGQAZwBlAHQAAAAAAP////8AAABQAP///wAAAV4AAADgAAAA" +"BAAAAAfsAAAAUAEQAYQB0AGEAVwBpAGQAZwBlAHQAAAAAAP////8AAABQAP///wAAAV4AAADoAAAA" "BAAAAAQAAAAIAAAACPwAAAABAAAAAgAAAAEAAAAOAFQAbwBvAGwAQgBhAHIBAAAAAP////8AAAAAA" "AAAAA==" SavedViews "AAAAAgAAAAA=" - HeaderState "AAAA/wAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAL/gMAAAAJAAAAB" -"gAAAGQAAAAHAAAAZAAAAAgAAABkAAAACQAAAGQAAAABAAAAZAAAAAIAAABkAAAAAwAAAGQAAAAEAA" -"AAZAAAAAUAAABkAAAAiwAAAAsBAAABAAAAAAAAAAAAAAAAZP////8AAACBAAAAAAAAAAsAAABzAAA" + HeaderState "AAAA/wAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAL/gMAAAAJAAAAA" +"QAAAGQAAAADAAAAZAAAAAIAAABkAAAABQAAAGQAAAAEAAAAZAAAAAcAAABkAAAABgAAAGQAAAAJAA" +"AAZAAAAAgAAABkAAAAiwAAAAsBAAABAAAAAAAAAAAAAAAAZP////8AAACBAAAAAAAAAAsAAABzAAA" "AAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAA" "AAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAA" "AAYAAAAAQAAAAAAAAPoAAAAABg=" @@ -904,4 +781,4 @@ Plecs { } } } -DemoSignature "3mLOZwvyqmZ1g5qsGftq/0aRPBxKRskpkes5wR/pt1M=" +DemoSignature "GVuBD7S6RWz7S12avKXRuEMLBGx74onrKaOKhUN+KRs="