Log in

View Full Version : Deadband Help


MoMo
13-02-2013, 14:46
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);

kylelanman
13-02-2013, 15:29
I described the way our team has been doing it the past few years here (http://www.chiefdelphi.com/forums/showpost.php?p=1230408&postcount=5).

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.

MoMo
13-02-2013, 15:59
That looks great but where/how would I add that into my code?

kylelanman
13-02-2013, 20:15
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,11 0,112,113,114,115,116,117,
118,119,120,121,121,122,123,123,124,124,125,125,12 5,126,126,126,126,126,127,
127,127,127,127,127,127,127,127,127,127,127,127,12 7,127,127,127,127,127,127,
128,128,128,128,128,129,129,129,130,130,131,131,13 2,133,133,134,135,136,
137,138,139,140,141,142,144,145,146,147,148,150,15 1,152,153,154,156,157,158,
159,160,162,163,164,165,166,168,169,170,171,172,17 4,175,176,177,178,180,181,
182,183,184,186,187,188,189,190,192,193,194,195,19 6,198,199,200,201,202,204,
205,206,207,208,210,211,212,213,214,216,217,218,21 9,220,221,223,224,225,226,
227,229,230,231,232,233,235,236,237,238,239,241,24 2,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);

MoMo
15-02-2013, 09:40
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)

MoMo
15-02-2013, 09:43
Alright i just fixed it. All i did was instead of stick->get... i did stick.get..

thanks!

kylelanman
15-02-2013, 15:47
Sorry about that. Glad you were able to figure it out. I guess that's what I get for copy and pasting.

MoMo
16-02-2013, 17:32
How would you adjust the dead band in this?

Ether
16-02-2013, 19:22
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

kylelanman
16-02-2013, 23:51
How would you adjust the dead band in this?

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.

Ether
17-02-2013, 09:36
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


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

garyk
19-02-2013, 19:33
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.

Ether
19-02-2013, 20:11
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).

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