Manejando el Robot con Modo Tanque y Controles

Un caso de uso común es tener un joystick que debería controlar algunos actuadores que forman parte de un subsistema. El problema es que el joystick se crea en la clase RobotContainer y los motores a controlar están en el subsistema. La idea es crear un comando que, cuando esté programado, lea la entrada del joystick y llame a un método que se crea en el subsistema que impulsa los motores.

En este ejemplo se muestra un subsistema de base de conducción que funciona en la conducción de un tanque usando un par de controles.

Crear un Subsistema del Chasis

../../../../../_images/driving-with-joysticks-subsystem.png

Cree un subsistema llamado Drive Train. Su responsabilidad será manejar la conducción de la base del robot.

../../../../../_images/driving-with-joysticks-differential-drive.png

Dentro del tren de transmisión/Drive Train, cree un objeto de transmisión diferencial para una transmisión de dos motores. Hay un motor izquierdo y un motor derecho como parte de la clase Differential Drive de transmisión diferencial.

../../../../../_images/driving-with-joysticks-speed-controller-group.png

Since we want to use more then two motors to drive the robot, inside the Differential Drive, create two Motor Controller Groups. These will group multiple motor controllers so they can be used with Differential Drive.

../../../../../_images/driving-with-joysticks-speed-controller.png

Finally, create two Motor Controllers in each Motor Controller Group.

Agregar los controles a la Interfaz Operadora

../../../../../_images/driving-with-joysticks-joysticks.png

Agregar dos controles a la Interfaz Operadora, uno es la palanca izquierda y el otro es la palanca derecha. El eje Y de los dos controles se usa para manejar los robots a la izquierda y a la derecha.

Nota

Asegúrese de exportar su programa a C++ o Java antes de continuar con el siguiente paso.

Crear un método para escribir los motores en el subsistema

 11// ROBOTBUILDER TYPE: Subsystem.
 12
 13package frc.robot.subsystems;
 14
 15
 16import frc.robot.commands.*;
 17import edu.wpi.first.wpilibj.livewindow.LiveWindow;
 18import edu.wpi.first.wpilibj2.command.SubsystemBase;
 19
 20// BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=IMPORTS
 21import edu.wpi.first.wpilibj.AnalogGyro;
 22import edu.wpi.first.wpilibj.AnalogInput;
 23import edu.wpi.first.wpilibj.CounterBase.EncodingType;
 24import edu.wpi.first.wpilibj.Encoder;
 25import edu.wpi.first.wpilibj.drive.DifferentialDrive;
 26import edu.wpi.first.wpilibj.motorcontrol.MotorController;
 27import edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup;
 28import edu.wpi.first.wpilibj.motorcontrol.PWMVictorSPX;
 29
 30    // END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=IMPORTS
 31
 32
 33/**
 34 *
 35 */
 36public class Drivetrain extends SubsystemBase {
 37    // BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=CONSTANTS
 38public static final double PlaceDistance = 0.1;
 39public static final double BackAwayDistance = 0.6;
 40
 41    // END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=CONSTANTS
 42
 43    // BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=DECLARATIONS
 44private PWMVictorSPX left1;
 45private PWMVictorSPX left2;
 46private MotorControllerGroup leftMotor;
 47private PWMVictorSPX right1;
 48private PWMVictorSPX right2;
 49private MotorControllerGroup rightMotor;
 50private DifferentialDrive drive;
 51private Encoder leftencoder;
 52private Encoder rightencoder;
 53private AnalogGyro gyro;
 54private AnalogInput rangefinder;
 55
 56    // END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=DECLARATIONS
 57
 58    /**
 59    *
 60    */
 61    public Drivetrain() {
 62        // BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=CONSTRUCTORS
 63left1 = new PWMVictorSPX(0);
 64 addChild("left1",left1);
 65 left1.setInverted(false);
 66
 67left2 = new PWMVictorSPX(1);
 68 addChild("left2",left2);
 69 left2.setInverted(false);
 70
 71leftMotor = new MotorControllerGroup(left1, left2  );
 72 addChild("Left Motor",leftMotor);
 73
 74
 75right1 = new PWMVictorSPX(5);
 76 addChild("right1",right1);
 77 right1.setInverted(false);
 78
 79right2 = new PWMVictorSPX(6);
 80 addChild("right2",right2);
 81 right2.setInverted(false);
 82
 83rightMotor = new MotorControllerGroup(right1, right2  );
 84 addChild("Right Motor",rightMotor);
 85
 86
 87drive = new DifferentialDrive(leftMotor, rightMotor);
 88 addChild("Drive",drive);
 89 drive.setSafetyEnabled(true);
 90drive.setExpiration(0.1);
 91drive.setMaxOutput(1.0);
 92
 93
 94leftencoder = new Encoder(0, 1, false, EncodingType.k4X);
 95 addChild("left encoder",leftencoder);
 96 leftencoder.setDistancePerPulse(1.0);
 97
 98rightencoder = new Encoder(2, 3, false, EncodingType.k4X);
 99 addChild("right encoder",rightencoder);
100 rightencoder.setDistancePerPulse(1.0);
101
102gyro = new AnalogGyro(0);
103 addChild("gyro",gyro);
104 gyro.setSensitivity(0.007);
105
106rangefinder = new AnalogInput(1);
107 addChild("range finder", rangefinder);
108
109
110
111    // END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=CONSTRUCTORS
112    }
113
114    @Override
115    public void periodic() {
116        // This method will be called once per scheduler run
117
118    }
119
120    @Override
121    public void simulationPeriodic() {
122        // This method will be called once per scheduler run when in simulation
123
124    }
125
126    // Put methods for controlling this subsystem
127    // here. Call these from Commands.
128
129    public void drive(double left, double right) {
130        drive.tankDrive(left, right);
131    }
132}

Create a method that takes the joystick inputs, in this case the the left and right driver joystick. The values are passed to the DifferentialDrive object that in turn does tank steering using the joystick values. Also create a method called stop() that stops the robot from driving, this might come in handy later.

Nota

Se ha eliminado parte de la salida de RobotBuilder para este ejemplo para mayor claridad

Leer los valores de las palancas y llamar los métodos del subsistema

../../../../../_images/driving-with-joysticks-command.png

Cree un comando, en este caso llamado Tank Drive. Su propósito será leer los valores del joystick y enviarlos al subsistema Drive Base. Tenga en cuenta que este comando requiere el subsistema Drive Train. Esto hará que deje de funcionar cada vez que cualquier otra cosa intente utilizar el tren de transmisión.

Nota

Asegúrese de exportar su programa a C++ o Java antes de continuar con el siguiente paso.

Añada el Código para hacer la conducción

11// ROBOTBUILDER TYPE: Command.
12
13package frc.robot.commands;
14import edu.wpi.first.wpilibj.Joystick;
15import edu.wpi.first.wpilibj2.command.CommandBase;
16import frc.robot.RobotContainer;
17// BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=IMPORTS
18import frc.robot.subsystems.Drivetrain;
19
20    // END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=IMPORTS
21
22/**
23 *
24 */
25public class TankDrive extends CommandBase {
26
27    // BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=VARIABLE_DECLARATIONS
28        private final Drivetrain m_drivetrain;
29
30    // END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=VARIABLE_DECLARATIONS
31
32    private Joystick leftJoystick = RobotContainer.getInstance().getJoystick1();
33    private Joystick rightJoystick = RobotContainer.getInstance().getJoystick2();
34
35    // BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=CONSTRUCTORS
36
37
38    public TankDrive(Drivetrain subsystem) {
39
40
41    // END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=CONSTRUCTORS
42        // BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=VARIABLE_SETTING
43
44    // END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=VARIABLE_SETTING
45        // BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=REQUIRES
46
47        m_drivetrain = subsystem;
48        addRequirements(m_drivetrain);
49
50    // END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=REQUIRES
51    }
52
53    // Called when the command is initially scheduled.
54    @Override
55    public void initialize() {
56    }
57
58    // Called every time the scheduler runs while the command is scheduled.
59    @Override
60    public void execute() {
61        m_drivetrain.drive(leftJoystick.getY(), rightJoystick.getY());
62    }
63
64    // Called once the command ends or is interrupted.
65    @Override
66    public void end(boolean interrupted) {
67        m_drivetrain.drive(0.0, 0.0);
68    }
69
70    // Returns true when the command should end.
71    @Override
72    public boolean isFinished() {
73        return false;
74    }
75
76    @Override
77    public boolean runsWhenDisabled() {
78        // BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=DISABLED
79        return false;
80
81    // END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=DISABLED
82    }
83}

Add code to the execute method to do the actual driving. All that is needed is to get the Joystick objects for the left and right drive joysticks and pass them to the Drive Train subsystem. The subsystem just uses them for the tank steering method on its DifferentialDrive object. And we get tank steering.

También completamos el método end() para que cuando este comando se interrumpa o se detenga, los motores se detendrán como medida de seguridad.

Hacer el Comando por defecto

../../../../../_images/driving-with-joysticks-default-command.png

El último paso es hacer que el comando Tank Drive sea el «Comando predeterminado» para el subsistema Drive Train. Esto significa que siempre que ningún otro comando esté usando Drive Train, los Joysticks tendrán el control. Este es probablemente el comportamiento deseable. Cuando el código autónomo se está ejecutando, también requerirá el tren de transmisión e interrumpirá el comando Tank Drive. Cuando finalice el código autónomo, el comando DriveWithJoysticks se reiniciará automáticamente (porque es el comando predeterminado) y los operadores volverán a tener el control. Si escribe cualquier código que haga teleoperación automática, esos comandos también deberían «requerir» el DriveTrain para que también interrumpan el comando Tank Drive y tengan control total.

Nota

Asegúrese de exportar su programa a C++ o Java antes de continuar.