001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.wpilibj2.command; 006 007import static edu.wpi.first.util.ErrorMessages.requireNonNullParam; 008 009import edu.wpi.first.util.sendable.SendableBuilder; 010import java.util.function.BooleanSupplier; 011 012/** 013 * A command composition that runs one of two commands, depending on the value of the given 014 * condition when this command is initialized. 015 * 016 * <p>The rules for command compositions apply: command instances that are passed to it cannot be 017 * added to any other composition or scheduled individually, and the composition requires all 018 * subsystems its components require. 019 * 020 * <p>This class is provided by the NewCommands VendorDep 021 */ 022public class ConditionalCommand extends CommandBase { 023 private final Command m_onTrue; 024 private final Command m_onFalse; 025 private final BooleanSupplier m_condition; 026 private Command m_selectedCommand; 027 028 /** 029 * Creates a new ConditionalCommand. 030 * 031 * @param onTrue the command to run if the condition is true 032 * @param onFalse the command to run if the condition is false 033 * @param condition the condition to determine which command to run 034 */ 035 public ConditionalCommand(Command onTrue, Command onFalse, BooleanSupplier condition) { 036 m_onTrue = requireNonNullParam(onTrue, "onTrue", "ConditionalCommand"); 037 m_onFalse = requireNonNullParam(onFalse, "onFalse", "ConditionalCommand"); 038 m_condition = requireNonNullParam(condition, "condition", "ConditionalCommand"); 039 040 CommandScheduler.getInstance().registerComposedCommands(onTrue, onFalse); 041 042 m_requirements.addAll(m_onTrue.getRequirements()); 043 m_requirements.addAll(m_onFalse.getRequirements()); 044 } 045 046 @Override 047 public void initialize() { 048 if (m_condition.getAsBoolean()) { 049 m_selectedCommand = m_onTrue; 050 } else { 051 m_selectedCommand = m_onFalse; 052 } 053 m_selectedCommand.initialize(); 054 } 055 056 @Override 057 public void execute() { 058 m_selectedCommand.execute(); 059 } 060 061 @Override 062 public void end(boolean interrupted) { 063 m_selectedCommand.end(interrupted); 064 } 065 066 @Override 067 public boolean isFinished() { 068 return m_selectedCommand.isFinished(); 069 } 070 071 @Override 072 public boolean runsWhenDisabled() { 073 return m_onTrue.runsWhenDisabled() && m_onFalse.runsWhenDisabled(); 074 } 075 076 @Override 077 public InterruptionBehavior getInterruptionBehavior() { 078 if (m_onTrue.getInterruptionBehavior() == InterruptionBehavior.kCancelSelf 079 || m_onFalse.getInterruptionBehavior() == InterruptionBehavior.kCancelSelf) { 080 return InterruptionBehavior.kCancelSelf; 081 } else { 082 return InterruptionBehavior.kCancelIncoming; 083 } 084 } 085 086 @Override 087 public void initSendable(SendableBuilder builder) { 088 super.initSendable(builder); 089 builder.addStringProperty("onTrue", m_onTrue::getName, null); 090 builder.addStringProperty("onFalse", m_onFalse::getName, null); 091 builder.addStringProperty( 092 "selected", 093 () -> { 094 if (m_selectedCommand == null) { 095 return "null"; 096 } else { 097 return m_selectedCommand.getName(); 098 } 099 }, 100 null); 101 } 102}