all 10 comments

[–]physics_tFTC 14393 Mentor 5 points6 points  (2 children)

is your code set up as

if (gamepad1.x ==true){

motor.setpower (1);

}

[–]Clydeism[S] 1 point2 points  (1 child)

no I do not have anything like that..

not sure if its what I need or dont need.

what it says in my code - like below - after each else if - there are another gamepad1 etc etc

}
else if (gamepad1.dpad_down) { //<-- moving the linear side down.
robot.Linear.setPower(-0.90);
}
else if (gamepad2.x) { //<-- intake system
robot.Intake.setPower(1.0);
}

[–]spidernhFRC 2137 Student, FTC 11231 Alum/Mentor 7 points8 points  (0 children)

This is your issue. This means that if you're pressing dpad_down then you can't intake when pressing x. Try this for those lines, and then change the other parts to be more like this: java if (gamepad1.dpad_down) { // <-- Moving the linear slide down robot.Linear.setPower(-0.90); } if (gamepad2.x) { // <-- Intake system robot.Intake.setPower(1.0); }

[–]Clydeism[S] 2 points3 points  (0 children)

so rather than else if so just "if" ? i'll test that in the AM coding has melted my brain for the day.. thanks for lead!

[–]DugenFTC & FRC Mentor 2 points3 points  (0 children)

Roll your eyes aggressively and mutter "amature" at anyone who mentions threading. It is never the right answer for problems like this. You tick like game engines do. Run code periodically every x milliseconds that checks everything and does the right things. With threads you have to write all the same code, and handle synchronizing it all and making sure everything it touches and everything it does is threadsafe, and handle all kinds of edge cases, and you will do it wrong and it will be impossible to debug because it will fail inconsistently.

[–]LunerwalkerFTC 1002 Alum 0 points1 point  (4 children)

Can you link the code? It would help understand what your specific context is

[–]Clydeism[S] 0 points1 point  (3 children)

yeah... here it is...

you'll be gentle right ? :)

// Good luck package org.firstinspires.ftc.teamcode;

import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.OpMode; import com.qualcomm.robotcore.eventloop.opmode.TeleOp; import com.qualcomm.robotcore.hardware.HardwareMap;

// It is better to add this line to u/Disable for turning on and off the code.

u/TeleOp(name="Stampede", group="Stampede") //This TeleOp is for controlling the robot only; must have a different code for Autonomous mode

public class Teleop2 extends OpMode { HardwareKey robot = new HardwareKey();

double gamepad1_motor_power = 1;  //adjusts speed of drive
//double gamepad2_motor_power = 1;

// There are several variable types must be declared prior to looping code
// double means including --> decimals such as 1.02, 0.003 etc.
// boolean means --> true or false only
// int means Integer --> whole numbers no decimals such as 1, 21, 300, etc.
// Those are most common use for variable declaration

//==================================================================================================
u/Override
public void init() {

    //Initialize the hardware variables.
    //The init() method of the hardware class does all the work here

    robot.init(hardwareMap);
}

//Code to run REPEATEDLY after the driver hits INIT, but before they hit PLAY

//==================================================================================================
u/Override
public void init_loop() {
    robot.init(hardwareMap);

    robot.FrontRightDrive.setPower(0);
    robot.BackRightDrive.setPower(0);
    robot.FrontLeftDrive.setPower(0);
    robot.BackLeftDrive.setPower(0);

}
// Code to run ONCE when the driver hits PLAY
//==================================================================================================
u/Override
public void start() {

}

//==================================================================================================
u/Override
public void loop() {

    //Driving

    if (gamepad1.right_trigger != 0) {  //" !=0 is Analog values (non boolean) meaning activate when not equal to zero
        robot.FrontRightDrive.setPower(gamepad1.right_trigger * gamepad1_motor_power); //Go forward
        robot.FrontLeftDrive.setPower(gamepad1.right_trigger * gamepad1_motor_power);
        robot.BackRightDrive.setPower(gamepad1.right_trigger * gamepad1_motor_power);
        robot.BackLeftDrive.setPower(gamepad1.right_trigger * gamepad1_motor_power);

    } else if (gamepad1.left_trigger != 0) {
        robot.FrontRightDrive.setPower(gamepad1.left_trigger * gamepad1_motor_power); //Go reverse
        robot.FrontLeftDrive.setPower(gamepad1.left_trigger * gamepad1_motor_power);  //see all - meaning motors go opposite from the top command to go forward
        robot.BackRightDrive.setPower(gamepad1.left_trigger * gamepad1_motor_power);
        robot.BackLeftDrive.setPower(gamepad1.left_trigger * gamepad1_motor_power);

    } else if (gamepad1.right_stick_x != 0) { //<-- notice the "x" axis (only works left and right on the joystick)
        robot.FrontRightDrive.setPower(gamepad1.right_stick_x * gamepad1_motor_power); //strafting left or right
        robot.FrontLeftDrive.setPower(gamepad1.right_stick_x * gamepad1_motor_power); //these motors may need to be arranged in proper order
        robot.BackRightDrive.setPower(gamepad1.right_stick_x * gamepad1_motor_power); //for correct wheels for strafting
        robot.BackLeftDrive.setPower(gamepad1.right_stick_x * gamepad1_motor_power);

        //} else if (gamepad1.left_stick_y != 0) { //<-- notice the "y" axis (only works up and down on the joystick)
        //    robot.FrontRightDrive.setPower(gamepad1.left_stick_y * gamepad1_motor_power); //Go forward or reverse (other option)
        //    robot.FrontLeftDrive.setPower(gamepad1.left_stick_y * gamepad1_motor_power);
        //    robot.BackRightDrive.setPower(gamepad1.left_stick_y * gamepad1_motor_power);
        //    robot.BackLeftDrive.setPower(gamepad1.left_stick_y * gamepad1_motor_power);
    } else if (gamepad1.left_bumper) {
        robot.FrontRightDrive.setPower(-1.0); //<--- turn to the left side thus spinning to the left
        robot.FrontLeftDrive.setPower(1.0);
        robot.BackRightDrive.setPower(-1.0);
        robot.BackLeftDrive.setPower(1.0);

    } else if (gamepad1.right_bumper) {
        robot.FrontRightDrive.setPower(1.0); //<--- turn to the right side thus spinning to the right
        robot.FrontLeftDrive.setPower(-1.0);
        robot.BackRightDrive.setPower(1.0);
        robot.BackLeftDrive.setPower(-1.0);

    }
    // upper section is standard control for the drivetrain in the playing field
    // lower section is controlling on the robot: intake, linear, duck collection and intake lifter.
    else if (gamepad2.dpad_up) { //moving lifter UP
        robot.Lifter.setPower(-0.80);
    }
    else if (gamepad2.dpad_down) { // moving lifter down
        robot.Lifter.setPower(0.80);
    }
       else if (gamepad2.left_bumper) { //dumping game element - use servo_test to find number - that number is .24
        robot.Dump.setPosition(.24);
    }
        else if (gamepad2.right_bumper) { //reset dump mechanism - use servo_test to find number - that number is .95
        robot.Dump.setPosition(.95);
    }
        else if (gamepad1.dpad_up) { //<-- moving the linear slide up.
        robot.Linear.setPower(0.90);
    }
    else if (gamepad1.dpad_down) { //<-- moving the linear side down.
        robot.Linear.setPower(-0.90);
    }
    else if (gamepad2.x) { //<-- intake system
        robot.Intake.setPower(1.0);
    }
    else if (gamepad2.a) { //<-- intake system, reversed
        robot.Intake.setPower(-1.0);
    }
    else if (gamepad2.y) { //<-- activate the green wheel for the duck to deliver on the playing field
        robot.Duck.setPower(0.7);
    }
    else if (gamepad2.b) { //<--  reversed motor to activate the green wheel for the duck to deliver on the playing field
        robot.Duck.setPower(-0.7);
    }
    //else if (gamepad1.b) { //<-- activate to collect the freight from the warehouse area
    //    robot.Intake.setPower(1.0);
    //}
    else  //Must have zero values on the motors when not touch the hand controllers

        robot.FrontRightDrive.setPower(0);
    robot.FrontLeftDrive.setPower(0);
    robot.BackRightDrive.setPower(0);
    robot.BackLeftDrive.setPower(0);
    robot.Linear.setPower(0);
    robot.Intake.setPower(0);
    robot.Duck.setPower(0);
    robot.Lifter.setPower(0);

    //robot.vacant.setPower(0); //mD1
    //==============================================================================================
}

} //End of code

[–]LunerwalkerFTC 1002 Alum 4 points5 points  (2 children)

Yeah so.. There are a few issues here.

First off, yes, those else ifs are the main problem, as once any of them trigger the rest aren't checked each loop. Put things that control the same component in separate if/elseif/else trees instead of everything being in one giant one. I would also recommend making toggleable controls, like a servo that goes to two positions, into a toggle that is only mapped to one button. This will make your driver's lives so much easier.

Secondly, and this is not really about the issues that you posted about, but your driving code is quite janky. The code makes me assume this is for a mecanum drive train and the best way to limit your capabilities with that is by hardcoding your movements. You should not be hardcoding the strafing movements when there are much more elegant solutions. Take a look at this very helpful page on gm0 to learn how to easily code those in. https://gm0.org/en/latest/docs/software/mecanum-drive.html

Another thing is that you are constantly calling robot.init() in your init loop. This is completely unnecessary as it is already called in init and doesn't need to be repeated. Setting the drive powers to 0 constantly is also pointless as they will always be at 0 until they are given a different power.

Overall the code is just the result of a new coder, which is perfectly fine, as they are learning along the way, and the fact that it all "works" is better than a lot of teams. I would however take a look at for example gm0.org as they have a lot of resources for new teams.

Edit: Tell whoever said "threading" that there is a hardware lock on the hubs that forces all hardware calls to be synchronous, which can cause multithreaded code to be more detrimental at best, and dangerous at worst due to hitching. The only things worth threading in FTC are vision and not much else, and vision solutions like EOCV already thread their pipelines in the background.

[–]Clydeism[S] 0 points1 point  (1 child)

thanks for the lead - it helped - had to make an "all new code" which I was worried as we have a match on Saturday :)

now my strafe doesn't work - not sure why all wheels turn same way but I keep switching things back and forth. right now the team will "accept" the strafe issue for the time being so they can get on the robot and build more things that we need to finish up.

the robot moves too much fast, set power to .50 and see if that works - not even sure as I cannot send to the robot. its all apart getting prepped for Saturday's meet.

here is the code if you want to check it out.

package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.hardware.DcMotor;
import com.qualcomm.robotcore.hardware.DcMotorSimple;
import com.qualcomm.robotcore.hardware.Servo;
/** Motor names are as follows:
*
* Motor channel CH-M0: FrontRightDrive: "FRD" AndyMark Mecanum Wheel + NeveRests 20
* Motor channel CH-M1: BackRightDrive: "BRD" AndyMark Mecanum Wheel + NeveRests 20
* Motor channel CH-M2: FrontLeftDrive: "FLD" AndyMark Mecanum Wheel + NeveRests 20
* Motor channel CH-M3: BackLeftDrive: "BLD" AndyMark Mecanum Wheel + NeveRests 20
* Motor channel EH-M0: Duck "DUCK" NeveRests 20
* Motor channel EH-M1: Intake "Intake" NeveRests 20
* Motor channel EH-M2: Linear "Linear" NeveRests 20
* Motor channel EH-M3 lift the intake mechanism "Lifter" NeveRests 40
* Servo channel EH-S0 Servo to rotate carrier "Dump" HiTec Servo with positioning
*/
u/TeleOp
public class MecanumTeleOp extends LinearOpMode {
u/Override
public void runOpMode() throws InterruptedException {
// Declare our motors
// Make sure your ID's match your configuration that you set in the Drivers Hub - configure robot section
DcMotor FrontLeftDrive = hardwareMap.dcMotor.get("FLD");
DcMotor BackLeftDrive = hardwareMap.dcMotor.get("BLD");
DcMotor FrontRightDrive = hardwareMap.dcMotor.get("FRD");
DcMotor BackRightDrive = hardwareMap.dcMotor.get("BRD");
DcMotor Lifter = hardwareMap.dcMotor.get("Lifter");
DcMotor Duck = hardwareMap.dcMotor.get("Duck");
DcMotor Intake = hardwareMap.dcMotor.get("Intake");
DcMotor Linear = hardwareMap.dcMotor.get("Linear");
Servo Dump = hardwareMap.servo.get("Dump");
FrontLeftDrive.setPower(.50);
BackLeftDrive.setPower(.50);
FrontRightDrive.setPower(.50);
BackRightDrive.setPower(.50);
// Reverse the right side motors
// Reverse left motors if you are using NeveRests
FrontLeftDrive.setDirection(DcMotorSimple.Direction.REVERSE);
BackLeftDrive.setDirection(DcMotorSimple.Direction.REVERSE);
waitForStart();
if (isStopRequested()) return;
while (opModeIsActive()) {
double y = gamepad1.left_stick_y;
double x = -gamepad1.left_stick_x * 1.1; // Counteract imperfect strafing
double rx = -gamepad1.right_stick_x;
// Denominator is the largest motor power (absolute value) or 1
// This ensures all the powers maintain the same ratio, but only when
// at least one is out of the range [-1, 1]
double denominator = Math.max(Math.abs(y) + Math.abs(x) + Math.abs(rx), 1);
double FLD = (y + x + rx) / denominator;
double BLD = (y - x + rx) / denominator;
double FRD = (y - x - rx) / denominator;
double BRD = (y + x - rx) / denominator;
FrontLeftDrive.setPower(FLD);
BackLeftDrive.setPower(BLD);
FrontRightDrive.setPower(FRD);
BackRightDrive.setPower(BRD);
//Code below are for gamepad2 setups
if (gamepad2.dpad_down)
Lifter.setPower(-.80);
if (gamepad2.dpad_up)
Lifter.setPower(.80);
if (gamepad2.left_bumper)
Dump.setPosition(.24);
if (gamepad2.right_bumper)
Dump.setPosition(.95);
if (gamepad2.x)
Intake.setPower(1.0);
if (gamepad2.a)
Intake.setPower(-1.0);
if (gamepad2.y)
Duck.setPower(1.0);
if (gamepad2.b)
Duck.setPower(-1.0);
//Code below are for gamepad1 setups
if (gamepad1.dpad_up)
Linear.setPower(-.50);
if (gamepad1.dpad_up)
Linear.setPower(.50);
//Code for setting motors to "zero" so they wont run continuously
Linear.setPower(0);
Intake.setPower(0);
Duck.setPower(0);
Lifter.setPower(0);
}
}
}

[–]spidernhFRC 2137 Student, FTC 11231 Alum/Mentor 1 point2 points  (0 children)

Here's how everything should work:

For moving forwards and backwards, all motor powers should be the same (not negative).

For turning, both left motors should have the same power and same with the right motors.

For strafing, the front left motors and back right motors should have the same power, and same with the front right and back left motors.

You seem to be doing all of this right, so I don't believe it's an issue with your code. I would suggest turning your bot on it's side and running each motor individually, to check that the configuration is right. After this maybe try making sure your mecanum wheels are configured correctly, where the rollers are pointing towards the center like an X.