controlsd: pull out selfdrive state machine (#33477)
	
		
	
				
					
				
			* controlsd: pull out selfdrive state machine * cleanup test * cleanupvw-mqb-aeb
							parent
							
								
									54a2626e44
								
							
						
					
					
						commit
						77f4f57e73
					
				
				 3 changed files with 148 additions and 147 deletions
			
			
		| @ -0,0 +1,98 @@ | ||||
| from cereal import log | ||||
| from openpilot.selfdrive.controls.lib.events import Events, ET | ||||
| from openpilot.common.realtime import DT_CTRL | ||||
| 
 | ||||
| State = log.SelfdriveState.OpenpilotState | ||||
| 
 | ||||
| SOFT_DISABLE_TIME = 3  # seconds | ||||
| ACTIVE_STATES = (State.enabled, State.softDisabling, State.overriding) | ||||
| ENABLED_STATES = (State.preEnabled, *ACTIVE_STATES) | ||||
| 
 | ||||
| class StateMachine: | ||||
|   def __init__(self): | ||||
|     self.current_alert_types = [ET.PERMANENT] | ||||
|     self.state = State.disabled | ||||
|     self.soft_disable_timer = 0 | ||||
| 
 | ||||
|   def update(self, events: Events): | ||||
|     # decrement the soft disable timer at every step, as it's reset on | ||||
|     # entrance in SOFT_DISABLING state | ||||
|     self.soft_disable_timer = max(0, self.soft_disable_timer - 1) | ||||
| 
 | ||||
|     self.current_alert_types = [ET.PERMANENT] | ||||
| 
 | ||||
|     # ENABLED, SOFT DISABLING, PRE ENABLING, OVERRIDING | ||||
|     if self.state != State.disabled: | ||||
|       # user and immediate disable always have priority in a non-disabled state | ||||
|       if events.contains(ET.USER_DISABLE): | ||||
|         self.state = State.disabled | ||||
|         self.current_alert_types.append(ET.USER_DISABLE) | ||||
| 
 | ||||
|       elif events.contains(ET.IMMEDIATE_DISABLE): | ||||
|         self.state = State.disabled | ||||
|         self.current_alert_types.append(ET.IMMEDIATE_DISABLE) | ||||
| 
 | ||||
|       else: | ||||
|         # ENABLED | ||||
|         if self.state == State.enabled: | ||||
|           if events.contains(ET.SOFT_DISABLE): | ||||
|             self.state = State.softDisabling | ||||
|             self.soft_disable_timer = int(SOFT_DISABLE_TIME / DT_CTRL) | ||||
|             self.current_alert_types.append(ET.SOFT_DISABLE) | ||||
| 
 | ||||
|           elif events.contains(ET.OVERRIDE_LATERAL) or events.contains(ET.OVERRIDE_LONGITUDINAL): | ||||
|             self.state = State.overriding | ||||
|             self.current_alert_types += [ET.OVERRIDE_LATERAL, ET.OVERRIDE_LONGITUDINAL] | ||||
| 
 | ||||
|         # SOFT DISABLING | ||||
|         elif self.state == State.softDisabling: | ||||
|           if not events.contains(ET.SOFT_DISABLE): | ||||
|             # no more soft disabling condition, so go back to ENABLED | ||||
|             self.state = State.enabled | ||||
| 
 | ||||
|           elif self.soft_disable_timer > 0: | ||||
|             self.current_alert_types.append(ET.SOFT_DISABLE) | ||||
| 
 | ||||
|           elif self.soft_disable_timer <= 0: | ||||
|             self.state = State.disabled | ||||
| 
 | ||||
|         # PRE ENABLING | ||||
|         elif self.state == State.preEnabled: | ||||
|           if not events.contains(ET.PRE_ENABLE): | ||||
|             self.state = State.enabled | ||||
|           else: | ||||
|             self.current_alert_types.append(ET.PRE_ENABLE) | ||||
| 
 | ||||
|         # OVERRIDING | ||||
|         elif self.state == State.overriding: | ||||
|           if events.contains(ET.SOFT_DISABLE): | ||||
|             self.state = State.softDisabling | ||||
|             self.soft_disable_timer = int(SOFT_DISABLE_TIME / DT_CTRL) | ||||
|             self.current_alert_types.append(ET.SOFT_DISABLE) | ||||
|           elif not (events.contains(ET.OVERRIDE_LATERAL) or events.contains(ET.OVERRIDE_LONGITUDINAL)): | ||||
|             self.state = State.enabled | ||||
|           else: | ||||
|             self.current_alert_types += [ET.OVERRIDE_LATERAL, ET.OVERRIDE_LONGITUDINAL] | ||||
| 
 | ||||
|     # DISABLED | ||||
|     elif self.state == State.disabled: | ||||
|       if events.contains(ET.ENABLE): | ||||
|         if events.contains(ET.NO_ENTRY): | ||||
|           self.current_alert_types.append(ET.NO_ENTRY) | ||||
| 
 | ||||
|         else: | ||||
|           if events.contains(ET.PRE_ENABLE): | ||||
|             self.state = State.preEnabled | ||||
|           elif events.contains(ET.OVERRIDE_LATERAL) or events.contains(ET.OVERRIDE_LONGITUDINAL): | ||||
|             self.state = State.overriding | ||||
|           else: | ||||
|             self.state = State.enabled | ||||
|           self.current_alert_types.append(ET.ENABLE) | ||||
| 
 | ||||
|     # Check if openpilot is engaged and actuators are enabled | ||||
|     enabled = self.state in ENABLED_STATES | ||||
|     active = self.state in ACTIVE_STATES | ||||
|     if active: | ||||
|       self.current_alert_types.append(ET.WARNING) | ||||
|     return enabled, active | ||||
| 
 | ||||
					Loading…
					
					
				
		Reference in new issue