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; 010 011/** 012 * A command that runs another command repeatedly, restarting it when it ends, until this command is 013 * interrupted. Command instances that are passed to it cannot be added to any other groups, or 014 * scheduled individually. 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 RepeatCommand extends Command { 023 private final Command m_command; 024 private boolean m_ended; 025 026 /** 027 * Creates a new RepeatCommand. Will run another command repeatedly, restarting it whenever it 028 * ends, until this command is interrupted. 029 * 030 * @param command the command to run repeatedly 031 */ 032 @SuppressWarnings("this-escape") 033 public RepeatCommand(Command command) { 034 m_command = requireNonNullParam(command, "command", "RepeatCommand"); 035 CommandScheduler.getInstance().registerComposedCommands(command); 036 m_requirements.addAll(command.getRequirements()); 037 setName("Repeat(" + command.getName() + ")"); 038 } 039 040 @Override 041 public void initialize() { 042 m_ended = false; 043 m_command.initialize(); 044 } 045 046 @Override 047 public void execute() { 048 if (m_ended) { 049 m_ended = false; 050 m_command.initialize(); 051 } 052 m_command.execute(); 053 if (m_command.isFinished()) { 054 // restart command 055 m_command.end(false); 056 m_ended = true; 057 } 058 } 059 060 @Override 061 public boolean isFinished() { 062 return false; 063 } 064 065 @Override 066 public void end(boolean interrupted) { 067 // Make sure we didn't already call end() (which would happen if the command finished in the 068 // last call to our execute()) 069 if (!m_ended) { 070 m_command.end(interrupted); 071 m_ended = true; 072 } 073 } 074 075 @Override 076 public boolean runsWhenDisabled() { 077 return m_command.runsWhenDisabled(); 078 } 079 080 @Override 081 public InterruptionBehavior getInterruptionBehavior() { 082 return m_command.getInterruptionBehavior(); 083 } 084 085 @Override 086 public void initSendable(SendableBuilder builder) { 087 super.initSendable(builder); 088 builder.addStringProperty("command", m_command::getName, null); 089 } 090}