Deadband Help

Hello we have a working mecanum code but we need to add dead band for a little better control. can any one help?


#include "WPILib.h"

// Team 1721 mecanum code 2013 By: Zakary Tobine at 2/11/13 10:33am

// Needs to add 2 relays; one for motor for shooter; one for frishbee pusher 



class RobotDemo : public SimpleRobot
{
	RobotDrive myRobot; // robot drive system
	Joystick stick; // only joystick

public:
	RobotDemo(void):
		myRobot(1, 2, 3, 4),	// these must be initialized in the same order
		stick(1)		// as they are declared above.
	{
		
		
		stick.SetAxisChannel(Joystick::kTwistAxis, 3);// Add the 3rd axis 
		myRobot.SetExpiration(0.1);// The time the motors stop moving after a value is sent  
	}

	
	void Autonomous(void)
	{
		// Commented out till a later date 
		
		//myRobot.SetSafetyEnabled(false);
		//myRobot.Drive(-0.5, 0.0); 	// drive forwards half speed
		//Wait(2.0); 				//    for 2 seconds
		//myRobot.Drive(0.0, 0.0); 	// stop robot
	}

	/**
	 * Runs the motors with one joystick mecanum. 
	 */
	void OperatorControl(void)
	{
		myRobot.SetSafetyEnabled(true);
		while (IsOperatorControl())
		{
		myRobot.MecanumDrive_Cartesian(stick.GetX(), stick.GetY(), stick.GetTwist());// Mecanum drive single joystick drive 
			
		
		
		
		Wait(0.005);				// wait for a motor update time
		}
	}
	
	/**
	 * Runs during test mode
	 */
	void Test() {

	}
};

START_ROBOT_CLASS(RobotDemo);

I described the way our team has been doing it the past few years here.

Hopefully sooner than later we will create a wrapper class for joystick objects so it’s easier for ourselves and others to use this in the future.

Let me know if you have any questions.

That looks great but where/how would I add that into my code?

Give the following a try. I have a more object oriented version but don’t have a robot to test it on so I don’t want to distribute it yet. If it gives you any problems you can’t figure out let me know. I don’t have WindRiver handy to compile it but it should build.

In order to apply a dead band to a given axis you just need to pass the result of get axis method into InputShape. Then use the result that InputShape returns where you were using the get axis methods.

ex.
float x = InputShape(stick->GetX());

#include "WPILib.h"

// Team 1721 mecanum code 2013 By: Zakary Tobine at 2/11/13 10:33am

// Needs to add 2 relays; one for motor for shooter; one for frishbee pusher 

const char inputShape[255] = {0,1,3,4,5,6,7,9,10,11,12,13,15,16,17,18,19,21,22,23,24,25,27,28,29,30,31,
	        33,34,35,36,37,38,40,41,42,43,44,46,47,48,49,50,52,53,54,55,56,58,59,60,61,62,
	        64,65,66,67,68,70,71,72,73,74,76,77,78,79,80,82,83,84,85,86,88,89,90,91,92,94,
	        95,96,97,98,100,101,102,103,104,106,107,108,109,110,112,113,114,115,116,117,
	        118,119,120,121,121,122,123,123,124,124,125,125,125,126,126,126,126,126,127,
	        127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,
	        128,128,128,128,128,129,129,129,130,130,131,131,132,133,133,134,135,136,
	        137,138,139,140,141,142,144,145,146,147,148,150,151,152,153,154,156,157,158,
	        159,160,162,163,164,165,166,168,169,170,171,172,174,175,176,177,178,180,181,
	        182,183,184,186,187,188,189,190,192,193,194,195,196,198,199,200,201,202,204,
	        205,206,207,208,210,211,212,213,214,216,217,218,219,220,221,223,224,225,226,
	        227,229,230,231,232,233,235,236,237,238,239,241,242,243,244,245,247,248,249,
	        250,251,253,254,255};

float InputShape(float userValue)
	{
		int iUserValue;

		iUserValue = (int)(userValue * 127);
		iUserValue += 127;
		iUserValue = inputShape[iUserValue];
		userValue = iUserValue - 127;
		userValue /= 127;
		return userValue;
	}

class RobotDemo : public SimpleRobot
{
	RobotDrive myRobot; // robot drive system
	Joystick stick; // only joystick

public:
	RobotDemo(void):
		myRobot(1, 2, 3, 4),	// these must be initialized in the same order
		stick(1)		// as they are declared above.
	{
		
		
		stick.SetAxisChannel(Joystick::kTwistAxis, 3);// Add the 3rd axis 
		myRobot.SetExpiration(0.1);// The time the motors stop moving after a value is sent  
	}

	
	void Autonomous(void)
	{
		// Commented out till a later date 
		
		//myRobot.SetSafetyEnabled(false);
		//myRobot.Drive(-0.5, 0.0); 	// drive forwards half speed
		//Wait(2.0); 				//    for 2 seconds
		//myRobot.Drive(0.0, 0.0); 	// stop robot
	}

	/**
	 * Runs the motors with one joystick mecanum. 
	 */
	void OperatorControl(void)
	{
		myRobot.SetSafetyEnabled(true);
		while (IsOperatorControl())
		{
		
			float x = InputShape(stick->GetX());
			float y = InputShape(stick->GetY());
			float t = InputShape(stick->GetTwist()); 
		
			myRobot.MecanumDrive_Cartesian(x, y, t);// Mecanum drive single joystick drive 
			
		
		
		
			Wait(0.005);				// wait for a motor update time
		}
	}
	
	/**
	 * Runs during test mode
	 */
	void Test() {

	}
};

START_ROBOT_CLASS(RobotDemo);

It looks good. but this is the error we are getting when trying to build it…

C:/WindRiver/wrwb-debugmode-workspace/SimpleTemplate/MyRobot.cpp: In member function virtual void RobotDemo::OperatorControl()': C:/WindRiver/wrwb-debugmode-workspace/SimpleTemplate/MyRobot.cpp:69: error: base operand of->’ has non-pointer type Joystick' C:/WindRiver/wrwb-debugmode-workspace/SimpleTemplate/MyRobot.cpp:70: error: base operand of->’ has non-pointer type Joystick' C:/WindRiver/wrwb-debugmode-workspace/SimpleTemplate/MyRobot.cpp:71: error: base operand of->’ has non-pointer type `Joystick’
C:\WindRiver\vxworks-6.3\host\x86-win32\bin\make.exe: *** [SimpleTemplate_partialImage/Debug/Objects/SimpleTemplate/MyRobot.o] Error 1
Build Failed in Project ‘SimpleTemplate’ (Process Exit Value was 2): 2013-02-15 09:38:49 (Elapsed Time: 00:06)

Alright i just fixed it. All i did was instead of stick->get… i did stick.get…

thanks!

Sorry about that. Glad you were able to figure it out. I guess that’s what I get for copy and pasting.

How would you adjust the dead band in this?

Let “J” be your joystick value, in the range -1 to +1.

Let “d” be your desired +/- deadband.

Let “out” be your modified joystick command (incorporating the deadband).

Then:

if (J>d) out = (J-d)/(1-d);

else if (J>-d) out = 0;

else out = (J+d)/(1-d);

“d” is the deadband tuning parameter in the range 0 <= d < 1
*
*

You would need to re create the array. We have a spreadsheet that does it somewhere I think. That is 6 year old code that we’ve been using as is.

Attached is a graph of what the above code produces for d=0.2:

deadband.png


deadband.png

Another way to create deadzone-behaviour is to square the joystick X, Y, or Z value (and preserve the original sign, so a negative joystick value gives a negative result). For example, a js value of 0.5 gives a square of 0.25, but the maximum value of 1.0 still gives 1.0.

The way I learned this is an example of why I love to be a mentor. I’d written the algebra to implement a dead zone and with two slopes - it was complicated and when I tried to teach it at a WRRF programming workshop I confused most of the students. Afterwards a student (I think from FRC1700, Gatorbotics) told me about the square trick - it did what I wanted and was far easier to teach and implement.

Or use a simple function as shown in the attachment and you can adjust the sensitivity to suit your taste.