Gray Matter LogoGray Matter Workshop

State-Based Control

State-Based Control - Structured Subsystem Management

State-based control organizes subsystem behavior into discrete, well-defined states. Each state encapsulates target positions, tolerances, and specific configurations, making robot code more organized and maintainable.

🎯 Key Concept: Instead of manually setting positions and tolerances everywhere, define states that encapsulate all the information needed for each subsystem configuration.

Understanding State-Based Architecture

🏗️ State Pattern Benefits

State-based control provides structure and predictability to subsystem behavior:

Encapsulation: Each state contains its target and tolerance
Maintainability: Easy to add new states and modify existing ones
Readability: Code clearly shows subsystem intentions

⚙️ State Components

State Enum

Defines all possible subsystem states with targets

Current State

Tracks which state the subsystem is currently in

setState() Method

Changes state and applies the new configuration

State-Based Implementation in Code

🔧 State-Based Configuration Example
State Enum and ImplementationJAVA
1// Define possible states with targets and tolerances
2public enum ArmState {
3    LOW(Degrees.of(0), Degrees.of(1)),           // Ground pickup
4    HIGH(Degrees.of(90), Degrees.of(2)),          // High scoring
5    BACKWARD(Degrees.of(180), Degrees.of(3));     // Defense position
6
7    private final Angle targetPosition;
8    private final Angle tolerance;
9
10    ArmState(Angle targetPosition, Angle tolerance) {
11        this.targetPosition = targetPosition;
12        this.tolerance = tolerance;
13    }
14
15    public Angle getTargetPosition() { return targetPosition; }
16    public Angle getTolerance() { return tolerance; }
17}
18
19// In your subsystem class
20private ArmState currentState = ArmState.LOW;
21
22public void setState(ArmState state) {
23    currentState = state;
24    setPosition(state.getTargetPosition());
25}
26
27public boolean atState() {
28    return Math.abs(getPosition().in(Degrees) -
29                   currentState.getTargetPosition().in(Degrees))
30           < currentState.getTolerance().in(Degrees);
31}
32
33public ArmState getCurrentState() {
34    return currentState;
35}
36

Workshop Implementation: State-Based Control

🔄 Before → After: Implementation

📋 Before

  • • Manual position and tolerance management
  • • Hard-coded values scattered throughout code
  • • Difficult to add new arm positions
  • • No clear organization of arm configurations
  • • Tolerance values repeated in multiple places

✅ After

  • • Well-defined states: LOW, HIGH, BACKWARD
  • • Each state encapsulates target position and tolerance
  • • Easy to add new states by extending the enum
  • • Clear, readable code with semantic state names
  • • Centralized configuration management

Loading file...

🔍 Code Walkthrough

State-Based Architecture:

  • ArmState Enum: Defines LOW, HIGH, and BACKWARD states
  • Encapsulated Targets: Each state contains its target position
  • State-Specific Tolerances: Different tolerance for each position
  • Current State Tracking: Always know which state the arm is in

Enhanced Features:

  • setState() Method: Simple way to change arm configuration
  • atState() Check: Easy validation using state-specific tolerance
  • Semantic Names: Code clearly shows intent (HIGH vs 0.25 rotations)
  • Extensible Design: Add new states without changing existing code

💡 Next Step: State-based control makes our arm subsystem much more organized and maintainable! This pattern scales well as we add more complex behaviors.

⚖️ State-Based vs Manual Control

Manual Control Issues:

  • Hard-coded values scattered everywhere
  • Difficult to maintain and modify
  • No clear organization of configurations
  • Prone to inconsistencies and bugs
  • Hard to understand code intent

State-Based Benefits:

  • Centralized configuration management
  • Easy to add and modify states
  • Clear, semantic code that shows intent
  • Consistent tolerance and target handling
  • Scales well with complex behaviors
💡 State Design Best Practices

🏷️ State Naming Guidelines

Use Descriptive Names:
  • HIGH instead of STATE_1
  • SHOOTING instead of FAST
  • STARTING_POSITION instead of STATE_2
Group Related States:
  • Arm: LOW, HIGH, MIDDLE, BACKWARD
  • Flywheel: STARTING_POSITION, MID_FIELD, FULL_FIELD
  • Elevator: INTAKE, HAND_OFF, LEVEL_4

📋 State Organization Tips

Include All Necessary Data:
  • Target position/velocity
  • State-specific tolerance
  • Optional: timing constraints
  • Optional: safety limits
Design for Extensibility:
  • Start with basic states, add complexity later
  • Use constructor parameters for flexibility
  • Consider state transitions and validation
  • Plan for debugging and telemetry

🎯 Why This Approach Works:

State-based control provides a clean separation between configuration (what the states are) and behavior (how to reach them). This makes code easier to understand, test, and maintain as your robot becomes more complex.

We use PostHog analytics with user-identifying features disabled to improve our site. Data is aggregated and not used to identify you. You can accept or reject analytics.