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.wpilibj.motorcontrol;
006
007import edu.wpi.first.util.sendable.Sendable;
008import edu.wpi.first.util.sendable.SendableBuilder;
009import edu.wpi.first.util.sendable.SendableRegistry;
010import java.util.Arrays;
011
012/**
013 * Allows multiple {@link MotorController} objects to be linked together.
014 *
015 * @deprecated Use {@link PWMMotorController#addFollower(PWMMotorController)} or if using CAN motor
016 *     controllers, use their method of following.
017 */
018@SuppressWarnings("removal")
019@Deprecated(forRemoval = true, since = "2024")
020public class MotorControllerGroup implements MotorController, Sendable, AutoCloseable {
021  private boolean m_isInverted;
022  private final MotorController[] m_motorControllers;
023  private static int instances;
024
025  /**
026   * Create a new MotorControllerGroup with the provided MotorControllers.
027   *
028   * @param motorController The first MotorController to add
029   * @param motorControllers The MotorControllers to add
030   */
031  @SuppressWarnings("this-escape")
032  public MotorControllerGroup(
033      MotorController motorController, MotorController... motorControllers) {
034    m_motorControllers = new MotorController[motorControllers.length + 1];
035    m_motorControllers[0] = motorController;
036    System.arraycopy(motorControllers, 0, m_motorControllers, 1, motorControllers.length);
037    init();
038  }
039
040  /**
041   * Create a new MotorControllerGroup with the provided MotorControllers.
042   *
043   * @param motorControllers The MotorControllers to add.
044   */
045  @SuppressWarnings("this-escape")
046  public MotorControllerGroup(MotorController[] motorControllers) {
047    m_motorControllers = Arrays.copyOf(motorControllers, motorControllers.length);
048    init();
049  }
050
051  private void init() {
052    for (MotorController controller : m_motorControllers) {
053      SendableRegistry.addChild(this, controller);
054    }
055    instances++;
056    SendableRegistry.addLW(this, "MotorControllerGroup", instances);
057  }
058
059  @Override
060  public void close() {
061    SendableRegistry.remove(this);
062  }
063
064  @Override
065  public void set(double speed) {
066    for (MotorController motorController : m_motorControllers) {
067      motorController.set(m_isInverted ? -speed : speed);
068    }
069  }
070
071  @Override
072  public void setVoltage(double outputVolts) {
073    for (MotorController motorController : m_motorControllers) {
074      motorController.setVoltage(m_isInverted ? -outputVolts : outputVolts);
075    }
076  }
077
078  @Override
079  public double get() {
080    if (m_motorControllers.length > 0) {
081      return m_motorControllers[0].get() * (m_isInverted ? -1 : 1);
082    }
083    return 0.0;
084  }
085
086  @Override
087  public void setInverted(boolean isInverted) {
088    m_isInverted = isInverted;
089  }
090
091  @Override
092  public boolean getInverted() {
093    return m_isInverted;
094  }
095
096  @Override
097  public void disable() {
098    for (MotorController motorController : m_motorControllers) {
099      motorController.disable();
100    }
101  }
102
103  @Override
104  public void stopMotor() {
105    for (MotorController motorController : m_motorControllers) {
106      motorController.stopMotor();
107    }
108  }
109
110  @Override
111  public void initSendable(SendableBuilder builder) {
112    builder.setSmartDashboardType("Motor Controller");
113    builder.setActuator(true);
114    builder.setSafeState(this::stopMotor);
115    builder.addDoubleProperty("Value", this::get, this::set);
116  }
117}