Skip to content

Program Documentation

main.cpp
#include "functions.hpp"
#include "okapi/api/util/logging.hpp"
#include "okapi/impl/chassis/controller/chassisControllerBuilder.hpp"
#include "robot.hpp"

// defining the controller
pros::Controller prosController(pros::E_CONTROLLER_MASTER);

// initialize pneumatic pistons
pros::ADIDigitalOut leftPiston(LEFT_DIGITAL_SENSOR_PORT);
pros::ADIDigitalOut rightPiston(RIGHT_DIGITAL_SENSOR_PORT);
pros::ADIDigitalOut catapultLock(CATAPULT_DIGITAL_SENSOR_PORT);
pros::ADIDigitalOut jerry(EXTENSION_DIGITAL_SENSOR_PORT);

// initialize limit switch for catapult windback
pros::ADIDigitalIn windbackLimit(PULLLIMIT_DIGITAL_SENSOR_PORT);

// defining the PTO motors
pros::Motor lUFM(LEFT_DRIVE_MOTOR3_PORT, PROS_DRIVE_GEARSET, 0,
                 PROS_DRIVE_MEASURE);
pros::Motor rUFM(RIGHT_DRIVE_MOTOR3_PORT, PROS_DRIVE_GEARSET, 1,
                 PROS_DRIVE_MEASURE);

// defining the rest of the motors
pros::Motor lUBM(LEFT_DRIVE_MOTOR4_PORT, PROS_DRIVE_GEARSET, 0,
                 PROS_DRIVE_MEASURE);
pros::Motor rUBM(RIGHT_DRIVE_MOTOR4_PORT, PROS_DRIVE_GEARSET, 1,
                 PROS_DRIVE_MEASURE);
pros::Motor lLFM(LEFT_DRIVE_MOTOR1_PORT, PROS_DRIVE_GEARSET, 0,
                 PROS_DRIVE_MEASURE);
pros::Motor rLFM(RIGHT_DRIVE_MOTOR1_PORT, PROS_DRIVE_GEARSET, 1,
                 PROS_DRIVE_MEASURE);
pros::Motor lLBM(LEFT_DRIVE_MOTOR2_PORT, PROS_DRIVE_GEARSET, 0,
                 PROS_DRIVE_MEASURE);
pros::Motor rLBM(RIGHT_DRIVE_MOTOR2_PORT, PROS_DRIVE_GEARSET, 1,
                 PROS_DRIVE_MEASURE);

// defining the drivetrain motors
pros::Motor_Group prosLDM({LEFT_DRIVE_MOTOR1_PORT, LEFT_DRIVE_MOTOR2_PORT,
                           LEFT_DRIVE_MOTOR4_PORT});
pros::Motor_Group prosRDM({RIGHT_DRIVE_MOTOR1_PORT, RIGHT_DRIVE_MOTOR2_PORT,
                           RIGHT_DRIVE_MOTOR4_PORT});
// motors not included: LEFT_DRIVE_MOTOR3_PORT, RIGHT_DRIVE_MOTOR3_PORT

// defining the drivetrain motors for odometry
// PTO motors are omitted for simplicity
okapi::MotorGroup okapiLDM({LEFT_DRIVE_MOTOR1_PORT, LEFT_DRIVE_MOTOR2_PORT,
                            LEFT_DRIVE_MOTOR4_PORT});
okapi::MotorGroup okapiRDM({RIGHT_DRIVE_MOTOR1_PORT, RIGHT_DRIVE_MOTOR2_PORT,
                            RIGHT_DRIVE_MOTOR4_PORT});

okapi::Motor rMotor(RIGHT_DRIVE_MOTOR3_PORT, true, OKAPI_DRIVE_GEARSET,
                    OKAPI_DRIVE_MEASURE);
okapi::Motor lMotor(LEFT_DRIVE_MOTOR3_PORT, false, OKAPI_DRIVE_GEARSET,
                    OKAPI_DRIVE_MEASURE);

// defining the okapi chassis object
std::shared_ptr<okapi::OdomChassisController> chassis =
    okapi::ChassisControllerBuilder()
        .withMotors(okapiLDM, // left motors
                    okapiRDM  // right motors
                    )
        .withDimensions(
            {
                OKAPI_DRIVE_GEARSET, // drive gearset stored in robot.h
                (DRIVE_GEARWHEEL / DRIVE_GEARMOTOR) // drivetrain gearing
            },
            {
                {
                    CHASSIS_WHEELS, // wheel size stored in robot.h
                    CHASSIS_TRACK   // drivetrain track size (length between
                                    // wheels on same axis) stored in robot.h
                },
                OKAPI_DRIVE_TPR // drivetrain ticks per rotation stored in
                                // robot.h
            })
        .withOdometry()
        .buildOdometry();
/*
std::shared_ptr<okapi::ChassisController> driveController =
    okapi::ChassisControllerBuilder()
        .withMotors(okapiLDM, // left motors
                    okapiRDM  // right motors
                    )
        .withDimensions(
            {
                OKAPI_DRIVE_GEARSET, // drive gearset stored in robot.h
                (DRIVE_GEARWHEEL / DRIVE_GEARMOTOR) // drivetrain gearing
            },
            {
                {
                    CHASSIS_WHEELS, // wheel size stored in robot.h
                    CHASSIS_TRACK   // drivetrain track size (length between
                                    // wheels on same axis) stored in robot.h
                },
                OKAPI_DRIVE_TPR // drivetrain ticks per rotation stored in
                                // robot.h
            })
        .withOdometry()
        .buildOdometry();

std::shared_ptr<okapi::AsyncPositionController<double, double>> cataController =
    okapi::AsyncPosControllerBuilder()
        .withMotor({lMotor, rMotor})
        .withGains({0.001, 0.0001, 0.0001})
        .build();*/
// boolean value for PTO activation state
bool ptoActivated = false;
bool extensionActivated = true;
// boolean value for windback process
bool windingBack = false;
// boolean value for intake toggle state
bool intakeActivated = false;

/**
 * Runs initialization code. This occurs as soon as the program is started.
 *
 * All other competition modes are blocked by initialize; it is recommended
 * to keep execution time for this mode under a few seconds.
 */
void initialize() {
  // creates buttons on the cortex lcd display
  // pros::lcd::initialize();
  prosRDM.set_reversed(true);
  prosLDM.set_gearing(PROS_DRIVE_GEARSET);
  prosRDM.set_gearing(PROS_DRIVE_GEARSET);
  rightPiston.set_value(ptoActivated);
  leftPiston.set_value(ptoActivated);
  jerry.set_value(extensionActivated);
}

/**
 * Runs while the robot is in the disabled state of Field Management System or
 * the VEX Competition Switch, following either autonomous or opcontrol. When
 * the robot is enabled, this task will exit.
 */
void disabled() {}

/**
 * Runs after initialize(), and before autonomous when connected to the Field
 * Management System or the VEX Competition Switch. This is intended for
 * competition-specific initialization routines, such as an autonomous selector
 * on the LCD.
 *
 * This task will exit when the robot is enabled and autonomous or opcontrol
 * starts.
 */
void competition_initialize() {}

/**
 * Runs the user autonomous code. This function will be started in its own task
 * with the default priority and stack size whenever the robot is enabled via
 * the Field Management System or the VEX Competition Switch in the autonomous
 * mode. Alternatively, this function may be called in initialize or opcontrol
 * for non-competition testing purposes.
 *
 * If the robot is disabled or communications is lost, the autonomous task
 * will be stopped. Re-enabling the robot will restart the task, not re-start it
 * from where it left off.
 */
void autonomous() {
  // setting the default values for the odometry
  // our team uses a placement guide so this number stays consistent
  chassis->setState({0_in, 0_in});
  chassis->turnAngle(45_deg);
  chassis->turnAngle(45_deg);
  chassis->driveToPoint({0_in, 6_in}, false, 0_in);
}

/**
 * Runs the operator control code. This function will be started in its own task
 * with the default priority and stack size whenever the robot is enabled via
 * the Field Management System or the VEX Competition Switch in the operator
 * control mode.
 *
 * If no competition control is connected, this function will run immediately
 * following initialize().
 *
 * If the robot is disabled or communications is lost, the
 * operator control task will be stopped. Re-enabling the robot will restart the
 * task, not resume it from where it left off.
 */
void opcontrol() {
  // main while loop
  while (true) {
    // sets the speed of the drivetrain motors according to the controller
    // joystick positions ranges -127 to 127
    update_drivetrain();
    // extension
    extension();
    // roller mech
    roll_roller();
    // temperature rumble
    // temp_rumble();
    // final delay
    // lUFM = prosController.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_Y);
    // rUFM = prosController.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_Y);
    pros::delay(20);
  }
}
robot.hpp
#pragma once // prevents the file from being included multiple times

#include <memory>

// includes all needed files
#include "functions.hpp"

#include "main.h"
#include "okapi/api/chassis/controller/chassisControllerIntegrated.hpp"
#include "okapi/api/chassis/controller/odomChassisController.hpp"
#include "okapi/api/chassis/model/chassisModel.hpp"
#include "okapi/api/device/motor/abstractMotor.hpp"
#include "okapi/api/units/QLength.hpp"
#include "okapi/api/units/RQuantity.hpp"
#include "okapi/api/util/logging.hpp"
#include "okapi/api/util/mathUtil.hpp"
#include "okapi/impl/chassis/controller/chassisControllerBuilder.hpp"
#include "okapi/impl/device/motor/motorGroup.hpp"
#include "pros/adi.h"
#include "pros/adi.hpp"
#include "pros/misc.h"
#include "pros/motors.h"
#include "pros/rtos.hpp"

// global

// stores motor port values
// motor 3 on both sides is attached to the PTO
#define RIGHT_DRIVE_MOTOR1_PORT 1
#define RIGHT_DRIVE_MOTOR2_PORT 2
#define RIGHT_DRIVE_MOTOR3_PORT 3
#define RIGHT_DRIVE_MOTOR4_PORT 4

#define LEFT_DRIVE_MOTOR1_PORT 5
#define LEFT_DRIVE_MOTOR2_PORT 6
#define LEFT_DRIVE_MOTOR3_PORT 7 // roller mech motor
#define LEFT_DRIVE_MOTOR4_PORT 8

extern int RIGHT_DRIVE_MOTOR_PORTS[4];

// stores the gearing of the drivetrain
#define OKAPI_DRIVE_GEARSET                                                    \
  okapi::AbstractMotor::gearset::blue // blue motor RPM (600)
#define OKAPI_DRIVE_TPR                                                        \
  okapi::imev5BlueTPR // gear ticks per rotation in a blue motor cartridge
#define DRIVE_GEARMOTOR                                                        \
  36.0 // gear tooth count on the axle attached to the motor
#define DRIVE_GEARWHEEL                                                        \
  60.0 // gear tooth count on the axle attached to the wheel

// stores the dimensions of the drivetrain
#define CHASSIS_TRACK                                                          \
  14.25_in // distance between the inside edge of wheels on the same axle
#define CHASSIS_WHEELS 3.25_in // diameter of drivetrain wheels

// stores ports of the pistons used for the PTO mech
#define LEFT_DIGITAL_SENSOR_PORT 'A'
#define RIGHT_DIGITAL_SENSOR_PORT 'B'

// stores port of the piston used for catapult
#define CATAPULT_DIGITAL_SENSOR_PORT 'C' //TODO: remove all code to do with catapult piston

// stores port of the piston used for extension
#define EXTENSION_DIGITAL_SENSOR_PORT 'D'

// stores port of the pullback limit switch
#define PULLLIMIT_DIGITAL_SENSOR_PORT 'H'

// okapilib
extern std::shared_ptr<okapi::Controller>
    okapiController; // okapilib controller
extern std::shared_ptr<okapi::OdomChassisController>
    chassis;                       // okapilib odometry controller
extern okapi::MotorGroup okapiLDM; // drivetrain left motor group
extern okapi::MotorGroup okapiRDM; // drivetrain right motor group

#define OKAPI_DRIVE_MEASURE okapi::AbstractMotor::encoderUnits::degrees

// pros
#define PROS_DRIVE_GEARSET pros::E_MOTOR_GEAR_BLUE // blue motor (600rpm)
#define PROS_DRIVE_MEASURE                                                     \
  pros::E_MOTOR_ENCODER_DEGREES // encoder measures in degrees

// pros object declarations

extern pros::Controller prosController; // pros contorller

// declares pto motors
extern pros::Motor lUFM; // left upper front motor
extern pros::Motor rUFM; // right upper front motor

// declares other motors
extern pros::Motor rUBM; // right upper back motor
extern pros::Motor lUBM; // left upper back motor
extern pros::Motor rLFM; // right lower front motor
extern pros::Motor lLFM; // left lower front motor
extern pros::Motor rLBM; // right lower back motor
extern pros::Motor lLBM; // left lower back motor

// declare motor groups
extern pros::Motor_Group prosLDM; // pros left drive motors
extern pros::Motor_Group prosRDM; // pros right drive motors

// declare pneumatic pistons
extern pros::ADIDigitalOut leftPiston;   // left PTO piston
extern pros::ADIDigitalOut rightPiston;  // right PTO piston
extern pros::ADIDigitalOut catapultLock; // catapult piston
extern pros::ADIDigitalOut jerry;        // extension piston

// declare windback limit switch
extern pros::ADIDigitalIn windbackLimit;

// makes ptoActivated a global variable
extern bool ptoActivated;
extern bool extensionActivated;
extern bool windingBack;
extern bool intakeActivated;


Note

Variables are stored here primarily for readability purposes throughout the codebase, although it also enables modularity through the use of global variables.

This file contains the variable definitions used in the odometry controller constructor in main.cpp.

We utilized global objects at the bottom of the file for modularity, allowing for multiple files to utilize the same objects.

graph LR
A[#include] --> B{Already included?};
B --->|Yes| C(Ignore);
B --->|No| D(Include);
C --> E(No double inclusion);

Info

#pragma serves as way to give the compiler a configuration setting before compiling the program.

This chart illustrates the importance of the use of #pragma once at the beginning of the header file.

#pragma once acts very similarly to a #ifndef header guard.

graph LR
A(Header file)
B(File A)
C(File B)
D[#pragma once in header file]
%%E(Header only included once)
A -->|#include| B;
B -->|#include| D;
A -->|#include| C;
C --> E;
D -->|Header not included again| C;
E --> F(No double inclusion);
functions.cpp
#include "pros/adi.h"
#include "robot.hpp"

// toggles the PTO mechanism
void toggle_pto() {
  // if controller's front right bumper is pressed, toggles the PTO mechanism
  if (prosController.get_digital_new_press(pros::E_CONTROLLER_DIGITAL_X)) {
    ptoActivated = !ptoActivated;
    rightPiston.set_value(ptoActivated);
    leftPiston.set_value(ptoActivated);
  }
}

/* utility function to shorten code
 * sets the speed of the pto motors.
 * @param speed The speed that the PTO motors will be set to.
 * 127 to -127
 */
void set_ptom_speed(int speed) {
  lUFM = speed;
  rUFM = speed;
}
void update_controller() {
  std::string on = "t";
  std::string off = "f";
  const char *onValue = on.c_str();
  const char *offValue = off.c_str();
  if (ptoActivated) {
    prosController.print(0, 3, onValue);
  } else {
    prosController.print(0, 3, offValue);
  }
}
// the set of controls used when the PTO is activated
void pto_controls() {
  // if the PTO is activated, check for a controller input to move the motors
  // attached to the PTO, otherwise, don't move motors

  // Input logic
  if (prosController.get_digital_new_press(
          pros::E_CONTROLLER_DIGITAL_R2)) { // check if r2 has been pressed
    windingBack = true; // update value, user wants to windback catapult
  }
  if (prosController.get_digital_new_press(pros::E_CONTROLLER_DIGITAL_L1)) {
    intakeActivated = !intakeActivated;
  }
  pros::delay(300);
  // activation logic
  if (!ptoActivated) { // check if PTO is engaged into windback/intake mode
    if (windingBack &&
        !windbackLimit
             .get_new_press()) { // check if the user wants to windback the
                                 // catapult and if the catapult cant be wound
      set_ptom_speed(127);       // windback the catapult
    } else {
      if (intakeActivated) {
        set_ptom_speed(-127);
      } else {
        set_ptom_speed(0);
      }
      windingBack = false;
    }
  }
}

void extension() {
  if (prosController.get_digital_new_press(pros::E_CONTROLLER_DIGITAL_A)) {
    jerry.set_value(!extensionActivated);
    extensionActivated = !extensionActivated;
  }
}

// only rumbles once to not annoy the driver
bool firstRumble = true;

// array of motors to iterate through.
pros::Motor motors[8] = {rLFM, rLBM, rUFM, rUBM, lLFM, lLBM, lUFM, lUBM};

void temp_rumble() {
  if (firstRumble) {
    for (int i = 0; i < sizeof(motors); i++) {
      if (motors[i].get_temperature() > 40) {
        firstRumble = false;
        prosController.rumble("...");
        break;
      }
    }
  }
}
// function to actuate drivetrain. uses 6 vs 8 motors depending on status of
// pto.
void update_drivetrain() {
  /* if (ptoActivated) {
     lUFM = prosController.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_Y);
     rUFM = prosController.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_Y);
   } */
  prosLDM = prosController.get_analog(pros::E_CONTROLLER_ANALOG_LEFT_Y);
  prosRDM = prosController.get_analog(pros::E_CONTROLLER_ANALOG_RIGHT_Y);
}

// function to actuate the roller mech. uses up and down arrows to spin the
// roller mech
void roll_roller() {
  lUFM = 100 * (prosController.get_digital(pros::E_CONTROLLER_DIGITAL_UP) -
                prosController.get_digital(pros::E_CONTROLLER_DIGITAL_DOWN));
}
functions.hpp
#pragma once // explanation under robot.h

// functions in functions.cpp
void toggle_pto();
void pto_controls();
void extension();
void temp_rumble();
void update_drivetrain();
void update_controller();
void roll_roller();

Last update: 2023-09-25 00:51:18
Created: 2023-09-25 00:51:18