393 lines
16 KiB
Java
393 lines
16 KiB
Java
package com.tuoheng.machine.config;
|
||
|
||
import com.tuoheng.machine.events.DroneEvent;
|
||
import com.tuoheng.machine.platform.factory.PlatformStrategyFactory;
|
||
import com.tuoheng.machine.platform.strategy.DronePlatformStrategy;
|
||
import com.tuoheng.machine.status.DroneState;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.springframework.context.annotation.Bean;
|
||
import org.springframework.context.annotation.Configuration;
|
||
import org.springframework.statemachine.StateMachine;
|
||
import org.springframework.statemachine.config.StateMachineBuilder;
|
||
import org.springframework.statemachine.config.StateMachineFactory;
|
||
|
||
import java.util.EnumSet;
|
||
import java.util.UUID;
|
||
|
||
/**
|
||
* 无人机状态机配置(多平台支持版本)
|
||
* 通过PlatformStrategyFactory动态获取平台特定的Guard、Action和Listener
|
||
*/
|
||
@Configuration
|
||
@Slf4j
|
||
public class DroneMachineConfig {
|
||
|
||
@Bean(name = "droneStateMachineFactory")
|
||
public StateMachineFactory<DroneState, DroneEvent> droneStateMachineFactory(
|
||
PlatformStrategyFactory platformStrategyFactory) throws Exception {
|
||
return new StateMachineFactory<DroneState, DroneEvent>() {
|
||
@Override
|
||
public StateMachine<DroneState, DroneEvent> getStateMachine() {
|
||
return null;
|
||
}
|
||
|
||
@Override
|
||
public StateMachine<DroneState, DroneEvent> getStateMachine(String machineId) {
|
||
try {
|
||
// 根据无人机SN获取平台策略
|
||
DronePlatformStrategy strategy = platformStrategyFactory.getDroneStrategy(machineId);
|
||
|
||
StateMachineBuilder.Builder<DroneState, DroneEvent> builder = StateMachineBuilder.builder();
|
||
configureStateMachine(builder, strategy);
|
||
configureStates(builder);
|
||
configureTransitions(builder, strategy);
|
||
|
||
StateMachine<DroneState, DroneEvent> stateMachine = builder.build();
|
||
stateMachine.getExtendedState().getVariables().put("machineId", machineId);
|
||
return stateMachine;
|
||
} catch (Exception e) {
|
||
log.error("创建DRONE状态机失败 - 机器ID: {}", machineId, e);
|
||
throw new RuntimeException("Failed to create drone state machine for: " + machineId, e);
|
||
}
|
||
}
|
||
|
||
@Override
|
||
public StateMachine<DroneState, DroneEvent> getStateMachine(UUID uuid) {
|
||
return null;
|
||
}
|
||
};
|
||
}
|
||
|
||
private void configureStateMachine(
|
||
StateMachineBuilder.Builder<DroneState, DroneEvent> builder,
|
||
DronePlatformStrategy strategy) throws Exception {
|
||
builder.configureConfiguration()
|
||
.withConfiguration()
|
||
.autoStartup(true)
|
||
.listener(strategy.getListener());
|
||
}
|
||
|
||
private void configureStates(StateMachineBuilder.Builder<DroneState, DroneEvent> builder) throws Exception {
|
||
builder.configureStates()
|
||
.withStates()
|
||
.initial(DroneState.UNKNOWN)
|
||
.states(EnumSet.of(
|
||
DroneState.UNKNOWN,
|
||
DroneState.OFFLINE,
|
||
DroneState.PREPARING,
|
||
DroneState.FLYING_PARENT,
|
||
DroneState.RETURNING_PARENT,
|
||
DroneState.POINTING_PARENT
|
||
))
|
||
// 飞行阶段子状态
|
||
.and()
|
||
.withStates()
|
||
.parent(DroneState.FLYING_PARENT)
|
||
.initial(DroneState.FLYING)
|
||
.states(EnumSet.of(
|
||
DroneState.FLYING,
|
||
DroneState.EMERGENCY_STOP,
|
||
DroneState.ARRIVED
|
||
))
|
||
// 返航阶段子状态
|
||
.and()
|
||
.withStates()
|
||
.parent(DroneState.RETURNING_PARENT)
|
||
.initial(DroneState.RETURNING)
|
||
.states(EnumSet.of(
|
||
DroneState.RETURNING,
|
||
DroneState.RETURN_EMERGENCY_STOP,
|
||
DroneState.RETURN_COMPLETED
|
||
))
|
||
// 指点操作子状态
|
||
.and()
|
||
.withStates()
|
||
.parent(DroneState.POINTING_PARENT)
|
||
.initial(DroneState.POINT_PREPARING)
|
||
.states(EnumSet.of(
|
||
DroneState.POINT_PREPARING,
|
||
DroneState.POINT_FLYING,
|
||
DroneState.POINT_COMPLETED,
|
||
DroneState.POINT_CANCELLED
|
||
));
|
||
}
|
||
|
||
private void configureTransitions(
|
||
StateMachineBuilder.Builder<DroneState, DroneEvent> builder,
|
||
DronePlatformStrategy strategy) throws Exception {
|
||
builder.configureTransitions()
|
||
// ========== 从 UNKNOWN 到所有状态的转换(服务器重启后状态同步) ==========
|
||
// UNKNOWN -> OFFLINE
|
||
.withExternal()
|
||
.source(DroneState.UNKNOWN)
|
||
.target(DroneState.OFFLINE)
|
||
.event(DroneEvent.DRONE_OFFLINE)
|
||
.and()
|
||
|
||
// UNKNOWN -> PREPARING
|
||
.withExternal()
|
||
.source(DroneState.UNKNOWN)
|
||
.target(DroneState.PREPARING)
|
||
.event(DroneEvent.START_PREPARE)
|
||
.and()
|
||
|
||
// UNKNOWN -> FLYING_PARENT
|
||
.withExternal()
|
||
.source(DroneState.UNKNOWN)
|
||
.target(DroneState.FLYING_PARENT)
|
||
.event(DroneEvent.START_FLYING)
|
||
.and()
|
||
|
||
// UNKNOWN -> RETURNING_PARENT
|
||
.withExternal()
|
||
.source(DroneState.UNKNOWN)
|
||
.target(DroneState.RETURNING_PARENT)
|
||
.event(DroneEvent.START_RETURN)
|
||
.and()
|
||
|
||
// ========== 基本状态转换 ==========
|
||
// OFFLINE -> PREPARING
|
||
.withExternal()
|
||
.source(DroneState.OFFLINE)
|
||
.target(DroneState.PREPARING)
|
||
.event(DroneEvent.START_PREPARE)
|
||
.action(strategy.getStartPrepareAction())
|
||
.and()
|
||
|
||
// PREPARING -> FLYING_PARENT
|
||
.withExternal()
|
||
.source(DroneState.PREPARING)
|
||
.target(DroneState.FLYING_PARENT)
|
||
.event(DroneEvent.PREPARE_COMPLETED)
|
||
.action(strategy.getPrepareCompletedAction())
|
||
.and()
|
||
|
||
// ========== 飞行阶段内部转换 ==========
|
||
// FLYING -> EMERGENCY_STOP
|
||
.withExternal()
|
||
.source(DroneState.FLYING)
|
||
.target(DroneState.EMERGENCY_STOP)
|
||
.event(DroneEvent.EMERGENCY_STOP)
|
||
.action(strategy.getEmergencyStopAction())
|
||
.and()
|
||
|
||
// EMERGENCY_STOP -> FLYING (恢复飞行)
|
||
.withExternal()
|
||
.source(DroneState.EMERGENCY_STOP)
|
||
.target(DroneState.FLYING)
|
||
.event(DroneEvent.RESUME_FLYING)
|
||
.action(strategy.getResumeFlyingAction())
|
||
.and()
|
||
|
||
// FLYING -> ARRIVED
|
||
.withExternal()
|
||
.source(DroneState.FLYING)
|
||
.target(DroneState.ARRIVED)
|
||
.event(DroneEvent.ARRIVE)
|
||
.action(strategy.getArriveAction())
|
||
.and()
|
||
|
||
// 注意:EMERGENCY_STOP 不能直接到 ARRIVED(根据注释限制)
|
||
|
||
// ========== 飞行阶段 -> 指点操作 ==========
|
||
// FLYING -> POINTING_PARENT
|
||
.withExternal()
|
||
.source(DroneState.FLYING)
|
||
.target(DroneState.POINTING_PARENT)
|
||
.event(DroneEvent.START_POINTING)
|
||
.action(strategy.getStartPointingAction())
|
||
.guard(strategy.getCanPointGuard())
|
||
.and()
|
||
|
||
// EMERGENCY_STOP -> POINTING_PARENT
|
||
.withExternal()
|
||
.source(DroneState.EMERGENCY_STOP)
|
||
.target(DroneState.POINTING_PARENT)
|
||
.event(DroneEvent.START_POINTING)
|
||
.action(strategy.getStartPointingAction())
|
||
.guard(strategy.getCanPointGuard())
|
||
.and()
|
||
|
||
// ARRIVED -> POINTING_PARENT
|
||
.withExternal()
|
||
.source(DroneState.ARRIVED)
|
||
.target(DroneState.POINTING_PARENT)
|
||
.event(DroneEvent.START_POINTING)
|
||
.action(strategy.getStartPointingAction())
|
||
.guard(strategy.getCanPointGuard())
|
||
.and()
|
||
|
||
// ========== 飞行阶段 -> 返航 ==========
|
||
// FLYING -> RETURNING_PARENT
|
||
.withExternal()
|
||
.source(DroneState.FLYING)
|
||
.target(DroneState.RETURNING_PARENT)
|
||
.event(DroneEvent.START_RETURN)
|
||
.action(strategy.getStartReturnAction())
|
||
.and()
|
||
|
||
// EMERGENCY_STOP -> RETURNING_PARENT
|
||
.withExternal()
|
||
.source(DroneState.EMERGENCY_STOP)
|
||
.target(DroneState.RETURNING_PARENT)
|
||
.event(DroneEvent.START_RETURN)
|
||
.action(strategy.getStartReturnAction())
|
||
.and()
|
||
|
||
// ARRIVED -> RETURNING_PARENT
|
||
.withExternal()
|
||
.source(DroneState.ARRIVED)
|
||
.target(DroneState.RETURNING_PARENT)
|
||
.event(DroneEvent.START_RETURN)
|
||
.action(strategy.getStartReturnAction())
|
||
.and()
|
||
|
||
// ========== 返航阶段内部转换 ==========
|
||
// RETURNING -> RETURN_EMERGENCY_STOP
|
||
.withExternal()
|
||
.source(DroneState.RETURNING)
|
||
.target(DroneState.RETURN_EMERGENCY_STOP)
|
||
.event(DroneEvent.RETURN_EMERGENCY_STOP)
|
||
.action(strategy.getReturnEmergencyStopAction())
|
||
.and()
|
||
|
||
// RETURN_EMERGENCY_STOP -> RETURNING (恢复返航)
|
||
.withExternal()
|
||
.source(DroneState.RETURN_EMERGENCY_STOP)
|
||
.target(DroneState.RETURNING)
|
||
.event(DroneEvent.RESUME_RETURN)
|
||
.action(strategy.getResumeReturnAction())
|
||
.and()
|
||
|
||
// RETURNING -> RETURN_COMPLETED
|
||
.withExternal()
|
||
.source(DroneState.RETURNING)
|
||
.target(DroneState.RETURN_COMPLETED)
|
||
.event(DroneEvent.RETURN_COMPLETED)
|
||
.action(strategy.getReturnCompletedAction())
|
||
.and()
|
||
|
||
// 注意:返航中不能指点(根据注释限制)
|
||
// 注意:RETURN_COMPLETED 不能回退到 RETURNING 或 RETURN_EMERGENCY_STOP(根据注释限制)
|
||
|
||
// ========== 返航急停 -> 指点操作 ==========
|
||
// RETURN_EMERGENCY_STOP -> POINTING_PARENT (一键起飞和航线飞行都可以指点)
|
||
.withExternal()
|
||
.source(DroneState.RETURN_EMERGENCY_STOP)
|
||
.target(DroneState.POINTING_PARENT)
|
||
.event(DroneEvent.START_POINTING)
|
||
.action(strategy.getStartPointingAction())
|
||
.guard(strategy.getCanPointGuard())
|
||
.and()
|
||
|
||
// ========== 指点操作内部转换 ==========
|
||
// POINT_PREPARING -> POINT_FLYING
|
||
.withExternal()
|
||
.source(DroneState.POINT_PREPARING)
|
||
.target(DroneState.POINT_FLYING)
|
||
.event(DroneEvent.POINT_PREPARE_COMPLETED)
|
||
.action(strategy.getPointPrepareCompletedAction())
|
||
.and()
|
||
|
||
// POINT_FLYING -> POINT_COMPLETED
|
||
.withExternal()
|
||
.source(DroneState.POINT_FLYING)
|
||
.target(DroneState.POINT_COMPLETED)
|
||
.event(DroneEvent.POINT_FLYING_COMPLETED)
|
||
.action(strategy.getPointFlyingCompletedAction())
|
||
.and()
|
||
|
||
// 任何指点阶段 -> POINT_CANCELLED
|
||
.withExternal()
|
||
.source(DroneState.POINT_PREPARING)
|
||
.target(DroneState.POINT_CANCELLED)
|
||
.event(DroneEvent.CANCEL_POINT)
|
||
.action(strategy.getCancelPointAction())
|
||
.and()
|
||
|
||
.withExternal()
|
||
.source(DroneState.POINT_FLYING)
|
||
.target(DroneState.POINT_CANCELLED)
|
||
.event(DroneEvent.CANCEL_POINT)
|
||
.action(strategy.getCancelPointAction())
|
||
.and()
|
||
|
||
.withExternal()
|
||
.source(DroneState.POINT_COMPLETED)
|
||
.target(DroneState.POINT_CANCELLED)
|
||
.event(DroneEvent.CANCEL_POINT)
|
||
.action(strategy.getCancelPointAction())
|
||
.and()
|
||
|
||
// ========== 指点操作 -> 飞行/返航 ==========
|
||
// POINT_COMPLETED -> FLYING
|
||
.withExternal()
|
||
.source(DroneState.POINT_COMPLETED)
|
||
.target(DroneState.FLYING)
|
||
.event(DroneEvent.POINT_TO_FLYING)
|
||
.action(strategy.getPointToFlyingAction())
|
||
.and()
|
||
|
||
// POINT_CANCELLED -> FLYING
|
||
.withExternal()
|
||
.source(DroneState.POINT_CANCELLED)
|
||
.target(DroneState.FLYING)
|
||
.event(DroneEvent.POINT_TO_FLYING)
|
||
.action(strategy.getPointToFlyingAction())
|
||
.and()
|
||
|
||
// POINT_COMPLETED -> RETURNING_PARENT
|
||
.withExternal()
|
||
.source(DroneState.POINT_COMPLETED)
|
||
.target(DroneState.RETURNING_PARENT)
|
||
.event(DroneEvent.POINT_TO_RETURN)
|
||
.action(strategy.getPointToReturnAction())
|
||
.and()
|
||
|
||
// POINT_CANCELLED -> RETURNING_PARENT
|
||
.withExternal()
|
||
.source(DroneState.POINT_CANCELLED)
|
||
.target(DroneState.RETURNING_PARENT)
|
||
.event(DroneEvent.POINT_TO_RETURN)
|
||
.action(strategy.getPointToReturnAction())
|
||
.and()
|
||
|
||
// POINT_COMPLETED -> RETURN_EMERGENCY_STOP
|
||
.withExternal()
|
||
.source(DroneState.POINT_COMPLETED)
|
||
.target(DroneState.RETURN_EMERGENCY_STOP)
|
||
.event(DroneEvent.RETURN_EMERGENCY_STOP)
|
||
.action(strategy.getReturnEmergencyStopAction())
|
||
.and()
|
||
|
||
// POINT_COMPLETED -> RETURN_COMPLETED
|
||
.withExternal()
|
||
.source(DroneState.POINT_COMPLETED)
|
||
.target(DroneState.RETURN_COMPLETED)
|
||
.event(DroneEvent.RETURN_COMPLETED)
|
||
.action(strategy.getReturnCompletedAction())
|
||
.and()
|
||
|
||
// ========== 离线处理 ==========
|
||
// 任何状态 -> OFFLINE
|
||
.withExternal()
|
||
.source(DroneState.FLYING_PARENT)
|
||
.target(DroneState.OFFLINE)
|
||
.event(DroneEvent.DRONE_OFFLINE)
|
||
.action(strategy.getOfflineAction())
|
||
.and()
|
||
|
||
.withExternal()
|
||
.source(DroneState.RETURNING_PARENT)
|
||
.target(DroneState.OFFLINE)
|
||
.event(DroneEvent.DRONE_OFFLINE)
|
||
.action(strategy.getOfflineAction())
|
||
.and()
|
||
|
||
.withExternal()
|
||
.source(DroneState.POINTING_PARENT)
|
||
.target(DroneState.OFFLINE)
|
||
.event(DroneEvent.DRONE_OFFLINE)
|
||
.action(strategy.getOfflineAction());
|
||
}
|
||
} |