Help with the turnAngle function in okapilib

Hey all,

When using chassis.turnAngle in my autonomous with okapilib in PROS, even if I change the value of the degree to a negative value or back to positive, the robot always turns to the left. This is okay for the blue side, but it’s a problem for red. Does anyone have a solution for this?

Thanks in advance!

Are you sure you put negative sign?

What chassis type are you using? We had something similar for turnToAngle, a method using the odom controller. We fixed this by setting the state to 0, 0, 0 before every turn. Better support for OkapiLib exists on the Vex Unofficial Discord Server, I recommend asking in the #software channel there if you can’t find a solution.

Yes, I’m sure I put the negative sign. I even tried going all the way around, but it doesn’t work. I’m fairly new to PROS and completely new to okapilib, so I don’t understand much of what you’re saying. I do know that my version of okapi is slightly outdated, but everything breaks when I try to update it, so I kept it as is. Here is my auton code:

void blue_stack() {
  //imu.reset();
  chassis.setMaxVelocity(35);

  //move forward before releasing tray
  //so that robot won't flip over
  chassis.moveDistanceAsync(6_in);
  release_tray();

  //drive forward to intake cubes
  intake_drive(200, 200);
  chassis.moveDistance(8_in);
  chassis.setMaxVelocity(75);
  chassis.moveDistance(28_in);
  pros::delay(200);
  intake_drive(0, 0);

  //back up, rotate towards goal,
  //and move towards it
  chassis.setMaxVelocity(120);
  //intake_drive(100, 100);
  chassis.moveDistance(-20_in);
  chassis.setMaxVelocity(75);
  chassis.turnAngle(140_deg);
  chassis.setMaxVelocity(100);
  pros::delay(150);
  chassis.moveDistance(16_in);

  //stack the cubes and back away
  chassis.setMaxVelocity(100);
  stack(90, 55, 100);
  chassis.moveDistance(-10_in);
  intake_drive(0, 0);
}

void red_stack() {
  //imu.reset();
  chassis.setMaxVelocity(35);

  //move forward before releasing tray
  //so that robot won't flip over
  chassis.moveDistanceAsync(6_in);
  release_tray();

  //drive forward to intake cubes
  intake_drive(200, 200);
  chassis.moveDistance(8_in);
  chassis.setMaxVelocity(75);
  chassis.moveDistance(28_in);
  pros::delay(200);
  intake_drive(0, 0);

  //back up, rotate towards goal,
  //and move towards it
  chassis.setMaxVelocity(120);
  //intake_drive(100, 100);
  chassis.moveDistance(-20_in);
  chassis.setMaxVelocity(75);
  chassis.turnAngle(-140_deg);
  chassis.setMaxVelocity(100);
  pros::delay(150);
  chassis.moveDistance(16_in);

  //stack the cubes and back away
  chassis.setMaxVelocity(100);
  stack(90, 55, 100);
  chassis.moveDistance(-10_in);
  intake_drive(0, 0);
}

This is my robot.hpp:

#ifndef __ROBOT_HPP
#define __ROBOT_HPP

#include "main.h"
#include "pros/misc.h"
#include "okapi/api.hpp"

//chassis motor ports
const int CHASSIS_LEFT_FRONT  = 10;
const int CHASSIS_LEFT_REAR   = 7;
const int CHASIIS_RIGHT_FRONT = 8;
const int CHASSIS_RIGHT_REAR  = 17;

//inkate motor ports
const int INTAKE_MOTOR_LEFT   = 9;
const int INTAKE_MOTOR_RIGHT  = 5;

//lever motor
const int LEVER_MOTOR = 11;

//arm motor
const int ARM_MOTOR = 1;


//arm varibles
const int ARM_PRESETS[5]  = {0, -666, -734, -845, -1025};
const int ARM_PRESETS_LEN = 5;

//motor, contoller, and sensors
extern pros::Motor chassis_left_front;
extern pros::Motor chassis_left_rear;
extern pros::Motor chassis_right_front;
extern pros::Motor chassis_right_rear;
extern pros::Motor intake_motor_left;
extern pros::Motor intake_motor_right;
extern pros::Motor lever_motor;
extern pros::Motor arm_motor;
extern pros::Controller master;
extern okapi::ChassisControllerIntegrated chassis;
extern okapi::AsyncPosIntegratedController arm;
extern okapi::AsyncPosIntegratedController lever;
extern pros::Imu imu;

//auto selection
extern int autonSelection;

//autons
void cube_1();
void blue_stack();
void red_stack();
void skill5();
void skill10();
void skill16();

//functions
void chassis_tank_drive(float left, float right);

void chassis_control();
void intake_drive(float left_intake_speed, float right_intake_speed);
void arm_drive(int pos);

void intake_control();

void lever_drive(float lever_speed);
void lever_control();
void arm_control();
void arm_control2();

void driver_release_tray();

//auton functions
void translate(float inches, float voltage);
void rotate(float degrees, float voltage);
void trans_intake(float inches, float voltage, float intake_speed);
void stack(float lever_speed, float outtake_speed, float voltage);
void release_tray();
void lowTower();
void highTower();
float avgChassEncoder();
//void rotate_until_straight();

#endif

And this is my initialize.cpp:

#include "api.h"

#include "robot.hpp"

#include "okapi/api.hpp"

using namespace pros;

using namespace okapi;

pros::Motor intake_motor_left(INTAKE_MOTOR_LEFT);

pros::Motor intake_motor_right(INTAKE_MOTOR_RIGHT);

pros::Motor lever_motor(LEVER_MOTOR);

pros::Motor arm_motor(ARM_MOTOR);

pros::Controller master (E_CONTROLLER_MASTER);

/* choose only one of the following: either separated chassis motors, or the chassis controller */

//chassis motors

pros::Motor chassis_right_rear(CHASSIS_RIGHT_REAR);

pros::Motor chassis_right_front(CHASIIS_RIGHT_FRONT);

pros::Motor chassis_left_rear(CHASSIS_LEFT_REAR);

pros::Motor chassis_left_front(CHASSIS_LEFT_FRONT);

const auto WHEEL_DIAMETER = 4_in;

const auto CHASSIS_WIDTH = 9_in;

// chassis controller

okapi::ChassisControllerIntegrated chassis = ChassisControllerFactory::create(

  {-CHASSIS_LEFT_FRONT, -CHASSIS_LEFT_REAR},

  {CHASIIS_RIGHT_FRONT, CHASSIS_RIGHT_REAR},

    // IterativePosPIDController::Gains{0.003, 0.0012, 0.000012}, // distance args

    // IterativePosPIDController::Gains{0.0004, 0.0005, 0.0002},  // angle args (keeps robot straight)

    // IterativePosPIDController::Gains{0.003, 0.0065, 0.000045},  // turn args

  AbstractMotor::gearset::green,

  {WHEEL_DIAMETER, CHASSIS_WIDTH}

);

/* choose only one of the following: either separated chassis motors, or the chassis controller */

AsyncPosIntegratedController arm = AsyncControllerFactory::posIntegrated(ARM_MOTOR);

AsyncPosIntegratedController lever = AsyncControllerFactory::posIntegrated(LEVER_MOTOR);

int autonSelection = 10;

int autonPark = 0;

static lv_res_t redBtnmAction(lv_obj_t *btnm, const char *txt)

{

    printf("red button: %s released\n", txt);

    //if (txt == "Stack")

  if (strcmp(txt, "Stack") == 0)

    {

        autonSelection = -1; // or whatever red close is

    }

    if (strcmp(txt, "1 Cube") == 0)

    {

        autonSelection = -2;

    }

  if (strcmp(txt, "Disable") == 0)

  {

    autonSelection = -3;

  }

    return LV_RES_OK; // return OK because the button matrix is not deleted

}

static lv_res_t blueBtnmAction(lv_obj_t *btnm, const char *txt)

{

    printf("blue button: %s released\n", txt);

    if (strcmp(txt, "Stack") == 0)

    {

        autonSelection = 1;

    }

    if (strcmp(txt, "1 Cube") == 0)

    {

        autonSelection = 2;

    }

  if (strcmp(txt, "Disable") == 0)

  {

    autonSelection = 3;

  }

    return LV_RES_OK;

}

static lv_res_t skillsBtnAction(lv_obj_t *btn, const char *txt)

{

    printf("blue button: %s released\n", txt);

    if (strcmp(txt, "Skill 5pt") == 0)

    {

        autonSelection = 0;

    }

    if (strcmp(txt, "Skill 10pt") == 0)

    {

        autonSelection = 10;

    }

    if (strcmp(txt, "Skill 16pt") == 0)

    {

        autonSelection = 20;

    }

    return LV_RES_OK;

}

//Create a button descriptor string array

static const char *btnmMap[] = {"Stack", "1 Cube", "Disable", ""};

static const char *btnSkillsMap[] = {"Skill 5pt", "Skill 10pt", "Skill 16pt", ""};

void initialize()

{

    pros::delay(50); // sometimes LVGL won't draw the screen if there is no delay or it is not inverted on the brain

  //inertial sensor

  pros::Imu imu(6);

  imu.reset();

  pros::delay(2500);

  /*manual lever brake mode

  lever_motor.set_brake_mode(E_MOTOR_BRAKE_HOLD);*/

    // lvgl theme

    lv_theme_t *th = lv_theme_alien_init(280, NULL); //Set a HUE value and keep font default

    lv_theme_set_current(th);

    // create a tab view object

    lv_obj_t *tabview;

    tabview = lv_tabview_create(lv_scr_act(), NULL);

    // add 3 tabs (the tabs are page (lv_page) and can be scrolled

    lv_obj_t *redTab = lv_tabview_add_tab(tabview, "Red");

    lv_obj_t *blueTab = lv_tabview_add_tab(tabview, "Blue");

    lv_obj_t *skillsTab = lv_tabview_add_tab(tabview, "Skills");

    // add content to the tabs

    // red tab

    // button matrix

    lv_obj_t *redBtnm = lv_btnm_create(redTab, NULL);

    lv_btnm_set_map(redBtnm, btnmMap);

    lv_btnm_set_toggle(redBtnm, true, 0);

    lv_btnm_set_action(redBtnm, redBtnmAction);

    lv_obj_set_size(redBtnm, 450, 50);

    lv_obj_set_pos(redBtnm, 0, 100);

    lv_obj_align(redBtnm, NULL, LV_ALIGN_CENTER, 0, 0);

    // blue tab

    lv_obj_t *blueBtnm = lv_btnm_create(blueTab, NULL);

    lv_btnm_set_map(blueBtnm, btnmMap);

    lv_btnm_set_toggle(blueBtnm, true, 0);

    lv_btnm_set_action(blueBtnm, blueBtnmAction);

    lv_obj_set_size(blueBtnm, 450, 50);

    lv_obj_set_pos(blueBtnm, 0, 100);

    lv_obj_align(blueBtnm, NULL, LV_ALIGN_CENTER, 0, 0);

    // skills tab

    lv_obj_t *skillsBtnm = lv_btnm_create(skillsTab, NULL);

    lv_btnm_set_map(skillsBtnm, btnSkillsMap);

    lv_btnm_set_toggle(skillsBtnm, true, 0);

    lv_btnm_set_action(skillsBtnm, skillsBtnAction);

    lv_obj_set_size(skillsBtnm, 450, 50);

    lv_obj_set_pos(skillsBtnm, 0, 100);

    lv_obj_align(skillsBtnm, NULL, LV_ALIGN_CENTER, 0, 0);

}

I might also ask this question on the discord. Can someone link it to me?

I have an example of okapi on github which i posted here:

It was updated from PROS-3.2.0 & Okapi 3.3.13 to PROS 3.2.1 & Okapi 4.0.3. It may help you update. These are tagged and if you are used to git you can see the difference between the to tags.

Also, it has a test of turnAngle in mar.cpp that shows 90,90,180,-360 and they turn the direction expected.

1 Like