Intentionally Disabling Drivetrain for Certain Parts of Code

This is our team’s first year in Vex, and we’ve encountered a problem with our autonomous programming. We’re using an X-drive for our base, and we haven’t had any issues with it so far. The programming for the user control driving is done without using the drivetrain configuration which is built into the V5 pro editor. For autonomous, however, we used the drivetrain, for the integral sensor that it provides, as well as the programming ease that it provides. Unfortunately, configuring the drivetrain for the autonomous makes it interfere while controlling the user control, which is programmed without the drivetrain. Is there any way to have the drivetrain enabled for the autonomous period, but disabled for the user control? Ideally it would be a fix like that, but if that isn’t possible, what else could I do to make the autonomous programming work using the inertial sensor? The current autonomous code is test code.

Code is as follows:

/*----------------------------------------------------------------------------*/
/*                                                                            */
/*    Module:       main.cpp                                                  */
/*    Author:       VEX                                                       */
/*    Created:      Thu Sep 26 2019                                           */
/*    Description:  Clawbot Competition Template                              */
/*                                                                            */
/*----------------------------------------------------------------------------*/

// ---- START VEXCODE CONFIGURED DEVICES ----
// Robot Configuration:
// [Name]               [Type]        [Port(s)]
// Controller1          controller                    
// Drivetrain           drivetrain    1, 2, 8, 9, 4   
// ---- END VEXCODE CONFIGURED DEVICES ----

#include "vex.h"

using namespace vex;

// A global instance of competition
competition Competition;

vex::motor frontRight(vex::PORT8, vex::gearSetting::ratio18_1);
vex::motor frontLeft(vex::PORT2, vex::gearSetting::ratio18_1);
vex::motor backRight(vex::PORT9, vex::gearSetting::ratio18_1);
vex::motor backLeft(vex::PORT1, vex::gearSetting::ratio18_1);

vex::motor armRight(vex::PORT19, vex::gearSetting::ratio36_1);
vex::motor armLeft(vex::PORT12, vex::gearSetting::ratio36_1);

vex::motor clawBottom(vex::PORT5, vex::gearSetting::ratio36_1);

// define your global instances of motors and other devices here

/*---------------------------------------------------------------------------*/
/*                          Pre-Autonomous Functions                         */
/*                                                                           */
/*  You may want to perform some actions before the competition starts.      */
/*  Do them in the following function.  You must return from this function   */
/*  or the autonomous and usercontrol tasks will not be started.  This       */
/*  function is only called once after the V5 has been powered on and        */
/*  not every time that the robot is disabled.                               */
/*---------------------------------------------------------------------------*/

void pre_auton(void) {
  // Initializing Robot Configuration. DO NOT REMOVE!
  vexcodeInit();
  
  // All activities that occur before the competition starts
  // Example: clearing encoders, setting servo positions, ...

}

/*---------------------------------------------------------------------------*/
/*                                                                           */
/*                              Autonomous Task                              */
/*                                                                           */
/*  This task is used to control your robot during the autonomous phase of   */
/*  a VEX Competition.                                                       */
/*                                                                           */
/*  You must modify the code to add your own robot specific commands here.   */
/*---------------------------------------------------------------------------*/

void autonomous(void) { 
  // Insert autonomous user code here.

  //test code.

  Drivetrain.driveFor(12, inches);
  Drivetrain.turnFor(right, 90, degrees);

  Drivetrain.driveFor(18, inches);
  Drivetrain.turnFor(right, 90, degrees);

  Drivetrain.driveFor(12, inches);
  Drivetrain.turnFor(right, 90, degrees);

  Drivetrain.driveFor(18,inches);
  Drivetrain.turnFor(right, 90, degrees);
}

/*---------------------------------------------------------------------------*/
/*                                                                           */
/*                              User Control Task                            */
/*                                                                           */
/*  This task is used to control your robot during the user control phase of */
/*  a VEX Competition.                                                       */
/*                                                                           */
/*  You must modify the code to add your own robot specific commands here.   */
/*---------------------------------------------------------------------------*/

void usercontrol(void) {
  // User control code here, inside the loop
  int leftX = 0, rightY = 0, rightX = 0;   //left axis 4, right axis 1 & 2
  bool lTop = false, lBottom = false; //left buttons, top and bottom
  int leftY = 0;
  bool rBottom = false;
  double driveSpeedMult = 1;
  
  while (1) {

    leftX = Controller1.Axis4.value();
    rightY = Controller1.Axis2.value();
    rightX = Controller1.Axis1.value();

    lTop = Controller1.ButtonL1.pressing();
    lBottom = Controller1.ButtonL2.pressing();

    rBottom = Controller1.ButtonR2.pressing();

    leftY = Controller1.Axis3.value();

    //keep motors locked in place
    armRight.stop(brakeType::hold);
    armLeft.stop(brakeType::hold);
    clawBottom.stop(brakeType::hold);


    //reduce motor speed on right bottom press
    if (rBottom) {
      driveSpeedMult = 0.02;
    }
    else {
      driveSpeedMult = 1;
    }

    //xDrive
    frontLeft.spin(directionType::fwd, (leftX+rightY+rightX)*driveSpeedMult, voltageUnits::volt);
    backLeft.spin(directionType::fwd, (leftX+rightY-rightX)*driveSpeedMult, voltageUnits::volt);
    frontRight.spin(directionType::fwd, (leftX-rightY+rightX)*driveSpeedMult, voltageUnits::volt);
    backRight.spin(directionType::fwd, (leftX-rightY-rightX)*driveSpeedMult, voltageUnits::volt);

    //arm
    if (lTop) {
      if (rBottom)  {
        armLeft.spin(directionType::fwd, (-5), voltageUnits::volt);
        armRight.spin(directionType::fwd, (5), voltageUnits::volt);
      }
      else {
        armLeft.spin(directionType::fwd, (-15), voltageUnits::volt);
        armRight.spin(directionType::fwd, (15), voltageUnits::volt);
      }
    }
    else if (lBottom) {
      if (rBottom) {
        armLeft.spin(directionType::fwd, 1, voltageUnits::volt);
        armRight.spin(directionType::fwd, -1, voltageUnits::volt);
      }
      else {
      armLeft.spin(directionType::fwd, 5, voltageUnits::volt);
      armRight.spin(directionType::fwd, -5, voltageUnits::volt);
      }
    }

   

    //claw
    if (leftY > 50) {
      if (rBottom) {
        clawBottom.spin(directionType::fwd, 2, voltageUnits::volt);
      }
      else {
        clawBottom.spin(directionType::fwd, 6, voltageUnits::volt);
      }
    }
    else if (leftY < -50) {
      if (rBottom) {
        clawBottom.spin(directionType::fwd, -0.5, voltageUnits::volt);
      }
      else {
        clawBottom.spin(directionType::fwd, -4, voltageUnits::volt);
      }
    }
  
    // This is the main execution loop for the user control program.
    // Each time through the loop your program should update motor + servo
    // values based on feedback from the joysticks.

    // ........................................................................
    // Insert user code here. This is where you use the joystick values to
    // update your motors, etc.
    // ........................................................................

    wait(20, msec); // Sleep the task for a short amount of time to
                    // prevent wasted resources.
  }
}

//
// Main will set up the competition functions and callbacks.
//
int main() {
  // Set up callbacks for autonomous and driver control periods.
  Competition.autonomous(autonomous);
  Competition.drivercontrol(usercontrol);

  // Run the pre-autonomous function.
  pre_auton();

  // Prevent main from exiting with an infinite loop.
  while (true) {
    wait(100, msec);
  }
}

It’s not obvious to me why it would be the case that the Drivetrain would cause issues in usercontrol. If you don’t mind, you could enable the “Expert” option (forget the actual words, but the one that removes the graphical configuration of devices). You can then define the Drivetrain control inside the scope of autonomous rather than the global scope, where it defaults.

The driver control code in the automatically generated robot-config.cpp is run as a task. If you add rc_auto_loop_task_Controller1.stop(); before the while loop in user control, the conflict between your driver code and the task code should end.

3 Likes

Thank you! I think this will be what I end up doing. I’m assuming that it would be as simple as copy and pasting certain parts of the automatically generated “robot-config.cpp” file into the autonomous section. Which parts would involve the drivetrain? It looks like around lines 12 - 46, but I don’t want to do anything rash.

robot-config.cpp:

#include "vex.h"

using namespace vex;
using signature = vision::signature;
using code = vision::code;

// A global instance of brain used for printing to the V5 Brain screen
brain  Brain;

// VEXcode device constructors
controller Controller1 = controller(primary);
motor leftMotorA = motor(PORT1, ratio18_1, false);
motor leftMotorB = motor(PORT2, ratio18_1, false);
motor_group LeftDriveSmart = motor_group(leftMotorA, leftMotorB);
motor rightMotorA = motor(PORT8, ratio18_1, true);
motor rightMotorB = motor(PORT9, ratio18_1, true);
motor_group RightDriveSmart = motor_group(rightMotorA, rightMotorB);
inertial DrivetrainInertial = inertial(PORT4);
smartdrive Drivetrain = smartdrive(LeftDriveSmart, RightDriveSmart, DrivetrainInertial, 299.24, 320, 40, mm, 1);

// VEXcode generated functions
// define variable for remote controller enable/disable
bool RemoteControlCodeEnabled = true;

/**
 * Used to initialize code/tasks/devices added using tools in VEXcode Pro.
 * 
 * This should be called at the start of your int main function.
 */
void vexcodeInit( void ) {
  Brain.Screen.print("Device initialization...");
  Brain.Screen.setCursor(2, 1);
  // calibrate the drivetrain Inertial
  wait(200, msec);
  DrivetrainInertial.calibrate();
  Brain.Screen.print("Calibrating Inertial for Drivetrain");
  // wait for the Inertial calibration process to finish
  while (DrivetrainInertial.isCalibrating()) {
    wait(25, msec);
  }
  // reset the screen now that the calibration is complete
  Brain.Screen.clearScreen();
  Brain.Screen.setCursor(1,1);
  wait(50, msec);
  Brain.Screen.clearScreen();
}

I tried this, and it displayed an error, and then crashed V5.

Generally, @DougMoyers 's suggestion is more sound. Given you’ve tried it already and it didn’t quite work, I forgot how much VEX Code does for you on the drivetrain object. It might be the case that simply changing bool RemoteControlCodeEnabled = true; to bool RemoteControlCodeEnabled = false; would help, but it’s been a long time since i’ve looked at VEX Code Pro…

That said, you’ll want something akin to:

void autonomous(void) { 
  // Declare the drivetrain in this scope (along with the intertial sensor); these were from the global scope of robot-config.cpp
inertial DrivetrainInertial = inertial(PORT4);
smartdrive Drivetrain = smartdrive(LeftDriveSmart, RightDriveSmart, DrivetrainInertial, 299.24, 320, 40, mm, 1);

  // Calibrate it, these are from inside the vexcodeInit function
  DrivetrainInertial.calibrate();
  // wait for the Inertial calibration process to finish
  while (DrivetrainInertial.isCalibrating()) {
    wait(25, msec);
  }
  // End lines copied from robot-config.cpp; remove the corresponding lines from robot-config.cpp

  Drivetrain.driveFor(12, inches);
  Drivetrain.turnFor(right, 90, degrees);
  // ... the rest of your code
}

If this fails to compile, especially after removing Drivetrain from the global scope, the compiler should tell you where Drivetrain is being referenced (e.g. autogenerated usercontrol code). It might be better at that point to remove it from there and revert back to the global definition.

Always keep a backup when doing things like this, so you can go back-and-forth between approaches.

2 Likes

facinating. @jpearman is there an appropriate way to bypass the rc task?

Is the official way, but to be honest, I would just avoid using it at all, I see no point in using the controller to automatically control motors and/or drivetrain when programming using text.

5 Likes