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.Sendable; 010import edu.wpi.first.util.sendable.SendableBuilder; 011import edu.wpi.first.util.sendable.SendableRegistry; 012import java.util.HashSet; 013import java.util.Set; 014 015/** 016 * A {@link Sendable} base class for {@link Command}s. 017 * 018 * <p>This class is provided by the NewCommands VendorDep 019 */ 020public abstract class CommandBase implements Sendable, Command { 021 protected Set<Subsystem> m_requirements = new HashSet<>(); 022 023 protected CommandBase() { 024 String name = getClass().getName(); 025 SendableRegistry.add(this, name.substring(name.lastIndexOf('.') + 1)); 026 } 027 028 /** 029 * Adds the specified subsystems to the requirements of the command. The scheduler will prevent 030 * two commands that require the same subsystem from being scheduled simultaneously. 031 * 032 * <p>Note that the scheduler determines the requirements of a command when it is scheduled, so 033 * this method should normally be called from the command's constructor. 034 * 035 * @param requirements the requirements to add 036 */ 037 public final void addRequirements(Subsystem... requirements) { 038 for (Subsystem requirement : requirements) { 039 m_requirements.add(requireNonNullParam(requirement, "requirement", "addRequirements")); 040 } 041 } 042 043 @Override 044 public Set<Subsystem> getRequirements() { 045 return m_requirements; 046 } 047 048 @Override 049 public String getName() { 050 return SendableRegistry.getName(this); 051 } 052 053 /** 054 * Sets the name of this Command. 055 * 056 * @param name name 057 */ 058 @Override 059 public void setName(String name) { 060 SendableRegistry.setName(this, name); 061 } 062 063 /** 064 * Gets the subsystem name of this Command. 065 * 066 * @return Subsystem name 067 */ 068 public String getSubsystem() { 069 return SendableRegistry.getSubsystem(this); 070 } 071 072 /** 073 * Sets the subsystem name of this Command. 074 * 075 * @param subsystem subsystem name 076 */ 077 public void setSubsystem(String subsystem) { 078 SendableRegistry.setSubsystem(this, subsystem); 079 } 080 081 /** 082 * Initializes this sendable. Useful for allowing implementations to easily extend SendableBase. 083 * 084 * @param builder the builder used to construct this sendable 085 */ 086 @Override 087 public void initSendable(SendableBuilder builder) { 088 builder.setSmartDashboardType("Command"); 089 builder.addStringProperty(".name", this::getName, null); 090 builder.addBooleanProperty( 091 "running", 092 this::isScheduled, 093 value -> { 094 if (value) { 095 if (!isScheduled()) { 096 schedule(); 097 } 098 } else { 099 if (isScheduled()) { 100 cancel(); 101 } 102 } 103 }); 104 builder.addBooleanProperty( 105 ".isParented", () -> CommandScheduler.getInstance().isComposed(this), null); 106 builder.addStringProperty( 107 "interruptBehavior", () -> getInterruptionBehavior().toString(), null); 108 builder.addBooleanProperty("runsWhenDisabled", this::runsWhenDisabled, null); 109 } 110}