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 CommandBase { 023 protected 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 public RepeatCommand(Command command) { 033 m_command = requireNonNullParam(command, "command", "RepeatCommand"); 034 CommandScheduler.getInstance().registerComposedCommands(command); 035 m_requirements.addAll(command.getRequirements()); 036 setName("Repeat(" + command.getName() + ")"); 037 } 038 039 @Override 040 public void initialize() { 041 m_ended = false; 042 m_command.initialize(); 043 } 044 045 @Override 046 public void execute() { 047 if (m_ended) { 048 m_ended = false; 049 m_command.initialize(); 050 } 051 m_command.execute(); 052 if (m_command.isFinished()) { 053 // restart command 054 m_command.end(false); 055 m_ended = true; 056 } 057 } 058 059 @Override 060 public boolean isFinished() { 061 return false; 062 } 063 064 @Override 065 public void end(boolean interrupted) { 066 // Make sure we didn't already call end() (which would happen if the command finished in the 067 // last call to our execute()) 068 if (!m_ended) { 069 m_command.end(interrupted); 070 m_ended = true; 071 } 072 } 073 074 @Override 075 public boolean runsWhenDisabled() { 076 return m_command.runsWhenDisabled(); 077 } 078 079 @Override 080 public InterruptionBehavior getInterruptionBehavior() { 081 return m_command.getInterruptionBehavior(); 082 } 083 084 @Override 085 public void initSendable(SendableBuilder builder) { 086 super.initSendable(builder); 087 builder.addStringProperty("command", m_command::getName, null); 088 } 089}