Arcade Drive Troubles in Autonomous

Hi all,

I’m almost done with reprogramming this year’s robot in C++ instead of LabVIEW. The only thing holding me back from marking it done is the autonomous.

In autonomous I’m telling the robot to go forward like so:


static const float autonomousForwardPower = -0.5;

//Move forward!
drivetrain->ArcadeDrive(autonomousForwardPower, 0.0);

Same exact drivetrain I use for teleop. I even use the function in teleop. Though it seems no matter what I do the robot turns left at full speed instead of going straight.

I even tried it in teleop and it does the same thing.

So, yeah - I’m confused why this is happening. Thoughts?

-Tanner

Have you checked the hardware? Does it work if you re-load the LabVIEW code?

Hardware is fine as far as I know. Like it drives in teleop fine.

In teleop the code is:


//Drive the robot
drivetrain->ArcadeDrive(driverJoystick->GetRawAxis(4),driverJoystick->GetRawAxis(2));

Which works perfectly fine. The robot drives straight and turns where I want it to.

The LabVIEW code would probably work if I hadn’t lost my flash drive with it on it.

-Tanner

Are you using Simple Robot or Iterative Robot ?

What other code do you have in autonomous besides what you posted ?

Iterative.


void AutonomousContinuous(void) {
	printf("Running in autonomous continuous...
");

	GetWatchdog().Feed();

	if (kicker->HasBall())
	{
		//We have a ball, thus stop moving and kick the ball
		drivetrain->Drive(0.0, 0.0);
		kicker->SetKickerMode(KICKER_MODE_KICK);
	} else {
		//We do not have a ball
		if (kicker->IsKickerInPosition())
		{
			//Move forward!
			drivetrain->ArcadeDrive(autonomousForwardPower, 0.0);
		} else {
			//If not in position, wait for it to be there...
			drivetrain->ArcadeDrive(0.0, 0.0);
			kicker->SetKickerMode(KICKER_MODE_ARM);
		}
	}

	//Run the kicker
	kicker->Act();
}

-Tanner

Save what you’ve got, then get rid of everything in autonomous except

drivetrain->ArcadeDrive(autonomousForwardPower, 0.0);

…and see if it drives properly.

If it does, then you’ve got a weird problem somewhere else in your code. Like for example, are you protecting kicker->Act(); from re-entering?

Edit: I just saw your other post. Uncontrolled re-entry could cause a stack overflow and crash your code.

Protecting kicker->Act(); from re-entering? Sorry, but what do you mean by that? I’ve never heard of that.

-Tanner

re-entering is when a function is called again before it finishes being called the first time. The variables in your kicker object may not be in a clean state for the second call, causing a crash

Ah. How would one prevent this?

I think though re-entering has more to do with the robot crashing than the robot not being able to drive straight from arcadeDrive(). Unless they’re somehow weirdly related and the kicker is affecting the drivetrain.

-Tanner

You are running AutonomousContinuous, which means the cRIO is repeatedly running your autonomous code as fast as it possibly can. You are calling the kicker->Act() method each time. I haven’t seen the rest of your code; if there’s another concurrent thread which also calls kicker->Act() it might cause a problem.

Removing everything except
drivetrain->ArcadeDrive(autonomousForwardPower, 0.0);
and testing to see if that fixes the problem is a quick way to help pinpoint the problem.

That’s why you should remove all the code except

drivetrain->ArcadeDrive(autonomousForwardPower, 0.0);

and see if it fixes the problem.

I’ll have to see tomorrow as I’m done with the robot for today.

I’m not sure how I would rethink to fix this. How would I protect the function from reentry? A google search on the topic didn’t bring up anything other than NASA links.

-Tanner

It’s pretty easy. Here’s some pseudocode:

Declare a static boolean within the method, say "kicker_busy".

if kicker_busy exit;

kicker_busy=1;

// put your code here.  It's now protected from re-entry.

kicker_busy=0;

//return

But before you do that, please see what happens when you remove everything except
drivetrain->ArcadeDrive(autonomousForwardPower, 0.0);

Ah. That seems pretty simple. I was so over thinking it.

I’ll take a look at that tomorrow and then get back.

Thanks for the help.

-Tanner

I suspect that your problem is that your RobotDrive class is not set up properly for the way your robot is wired (one side is either not inverted (using RobotDrive::SetInvertedMotor()), or inverted when it shouldn’t be).

It’s probably just working in teleop mode by lucky coincidence, because your joystick setup looks strange - you’re feeding what seems to be the twist axis (4) into the moveValue parameter of ArcadeDrive, and the Y-axis (2) into the rotateValue parameter.

I doubt the non-reentrancy of your kicker function is the issue, because non-reentrant functions only cause problems when they’re called more than once at the same time (i.e. by different threads), and I’m pretty sure all the Periodic/Continuous methods in IterativeRobot execute in the same thread.

I’m not sure how that would work, cause then wouldn’t teleop not drive correctly at all? There’s only one way a drivetrain will correctly work, yeah (unless the joystick values are strange)?

Well, I’m not using the kit joysticks. I’m using two XBox 360 controllers, so the numbers don’t exactly correspond to the names in the WPI library.

-Tanner

Okay, that makes sense, then. If you haven’t already, maybe you should check the outputs of those axes directly with printf statements to make sure they are doing what you think they are doing in terms of axis and polarity.

Good point.

Yeah, I should do that. I kinda just took it directly from LabVIEW thinking that things would be the same, but you never really know. I’ll write that down to check as well.

-Tanner

Haven’t been able to get to the office to test on the robot. Worked overtime today.

Yeah…

-Tanner