Go to Post We can help FIRST improve the system, but we can't just blame them and wait. - Siri [more]
Home
Go Back   Chief Delphi > ChiefDelphi.com Website > Extra Discussion
CD-Media   CD-Spy  
portal register members calendar search Today's Posts Mark Forums Read FAQ rules

 
Reply
Thread Tools Rate Thread Display Modes
  #16   Spotlight this post!  
Unread 26-07-2013, 17:35
JamesTerm's Avatar
JamesTerm JamesTerm is offline
Terminator
AKA: James Killian
FRC #3481 (Bronc Botz)
Team Role: Engineer
 
Join Date: May 2011
Rookie Year: 2010
Location: San Antonio, Texas
Posts: 298
JamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to behold
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

Quote:
Originally Posted by apalrd View Post
Example C code is in the zip (culverdrive_sw_release.zip). It isn't great, and isn't tested like the LV implementation, but should illustrate how the logic works.
I have taken the example into one file all in this reply, and made modification to something that can be tested in visual studio (I use 2008). I've made a second version of the culver drive which should be identical functionality from my tests. It does not call interp_2d() and keeps units in radians using atan2() and keeps the sign. There are some subtle bug fixes mentioned within this code too. The testing mechanism simply iterates from -pi to pi incrementing to an arbitrary number of iterations... from this I put macrod out tests like half magnitude or no Y component to see how the numbers turn out. From what I can tell... it linear interpolates between 90-115 degrees... from 1.0 - 0.0... for the filtering mechanism. I wasn't sure if the wheel drive was suppose to go past -90 - 90... but the tables suggest that it should... Under this assumption it appears if the driver accidentally hits slightly down.. the sharper angles will get filtered out... That is very clever how the magnitude of the angle comes into play with the final result.

Code:
#include "stdafx.h"
#include <math.h>

#undef __AlternateRawImplementation__

inline double sgn(double x)
{
	return (x>=0)?1:-1;
}

const double PI=3.14159265358979323846;
const double PI2=PI*2.0;
const double PI_2=PI/2.0;

inline double DEG_2_RAD(double x) 
{	
	return	((x)*PI/180.0); 
}
inline double RAD_2_DEG(double x) 
{
	return ((x)*180.0/PI); 
}

//INTERPOLATION CURVES (CONST DATA)

//Since these go past 90 I'm assuming it intended to steer past 90 on the wheel and filter to 115 from 1 to 0
const double c_radius_theta_x[] = {0, 90, 115, 180};
const double c_radius_theta_z[] = {1,  1,   0,   0};
//This table appears to have no effect since z is 1 all across
const double c_r_warp_x[] = {0, 45, 90, 135, 180};
const double c_r_warp_z[] = {1, 1, 1, 1, 1};

//These appear to only yield 1.0 from 115-170 degrees... I have not tested this alternate implementation
#ifdef __AlternateRawImplementation__
const double c_raw_theta_x[] = {0, 90, 115, 170, 180};
const double c_raw_theta_z[] = {0,  0,   1,   1, 0};
#endif

//CALIBRATIONS (CAL DATA)
double c_gain_radius = 1.2;
double c_gain_raw = 1.5;

//Note for Palardy size is now cardinal ;)
double interp_2d(double x,const double *x_tbl,const double *z_tbl, size_t size)
{
	size_t num_cur = 0;
	//num_cur index will point to the element that is closest to number in table without going over
	while((x_tbl[num_cur] <= x) && (num_cur < (size-1)))
		num_cur++;

	//we assume x fits within range of table
	assert(num_cur);

	int num_last = num_cur - 1;
	//Find fraction between num_cur and num_cur--
	double x_frac;
	{
		const double lt = x_tbl[num_last];
		const double gt = x_tbl[num_cur];
		const double tmp = x - lt;
		const double range = gt - lt;
		x_frac = tmp / range;

		//printf("Interpolation: Found X:%f between lt:%f and gt:%f (pts %d and %d) frac=%f",x,lt,gt,num_last,num_cur,x_frac);
	}

	//Find the two points on the z table
	double z_out;
	{
		const double lt = z_tbl[num_last];
		const double gt = z_tbl[num_cur];
		const double range = gt - lt;
		z_out = (range * x_frac) + lt;
		//printf(" z: lt:%f gt:%f zout:%f\n",lt,gt,z_out);
	}

	return z_out;
}

//This version of it clamps the range... but also will change any NAN cases to zero (This is a generic solution over _isnan() )
inline double limit_motor(double x)
{
	//Clamp range
	if (x>0.0)
	{
		if (x>1.0)
			x=1.0;
	}
	else if (x<0.0)
	{
		if (x<-1.0)
			x=-1.0;
	}
	else
	{
		x=0.0;  //is nan case
		assert(false);  //Sanity check, This shouldn't happen with the simple math in this example
	}
	return x;
}

//Math function for Culver Drive
void culver_drive(double throttle, double wheelx, double wheely, bool quickturn, double &left, double &right)
{
	//double theta = fabs(atan((wheely/wheelx)));

	//I am confused as part of the code appears that we work only from a range of -90 - 90... while the tables go past 90
	//The original implementation shows any down stick movement is the same as if it were up
	//For this new replacement if we want to support values past 90 we can remove the fabs()... while this idea would support the real model 
	//of a steering wheel. I can see it being an undesirable effect (hence the filtering)... especially since there is the quick turn option

	//Find arctan of wheel stick relative to vertical... note relative to vertical suggests that we swap the x and y components!
	#if 0
	const double theta_native = atan2(wheelx,fabs(wheely));
	#else
	const double theta_native = atan2(wheelx,-wheely);  //I suspect we wanted to go past 90 based from the tables
	#endif

	//Test atan2 against atan... this test only succeeds if we use the fabs(wheely) version
	#if 0
	//note Palardy... there was a bug 59.29577... should be 57.29577
	double test = fabs(atan((wheelx/wheely)));  //if it is relative to vertical the x and y components need to be swapped
	double sign_test = sgn(wheelx);
	assert (fabs(theta - (test * sign_test))<1e-5);  //check for equality within 5 decimal places
	printf("%.2f %.2f %.2f %.2f\n",RAD_2_DEG(theta),RAD_2_DEG(test * sign_test),wheelx,wheely);
	#endif

	// and turn it into degrees
	//convert to absolute value and in degrees (grrrr should never solve code in degrees)  ;)
	const double sign = sgn(theta_native);  //keep the sign to restore it later
	const double theta = fabs(RAD_2_DEG(theta_native));  

	//as it stands this statement has no effect if c_r_warp_z has all 1's
	assert(interp_2d(theta,c_r_warp_x,c_r_warp_z,_countof(c_r_warp_x)) == 1.0);

	//Find the magnitude of the wheel stick
	double r = sqrt(((wheely * wheely) + (wheelx * wheelx))) * interp_2d(theta,c_r_warp_x,c_r_warp_z,_countof(c_r_warp_x));

	//Find the Radius Enablement curve
	double radius_en = interp_2d(theta,c_radius_theta_x,c_radius_theta_z,_countof(c_radius_theta_x));

	printf("%.2f, %.2f, %.2f, %.2f, %.2f\n",theta * sign,r,radius_en,wheelx,wheely);


	//Find the radius component based on r, theta, enablement curve, gain, throttle, sign
	double radius = r * theta/90 * radius_en * c_gain_radius * throttle * sign;

	//Find the raw component based on r, radius enablement curve, gain, sign
	#ifndef __AlternateRawImplementation__
	//double raw = r * radius_en * c_gain_raw * sign;
	double raw = r * theta/90 * radius_en * c_gain_raw * sign;  //this needs theta
	#else
	//Alternate raw implementation
	double raw = r * interp_2d(theta, c_raw_theta_x, c_raw_theta_z, _countof(c_raw_theta_x)) * c_gain_raw * sign;
	#endif

	//Find Left and Right powers as sums
	double tmpleft = throttle;
	double tmpright = throttle;

	//Comment out the entire IF/Else block for alternate raw mode
	if(quickturn)
	{
		#if 1
		tmpleft += raw;
		tmpright -= raw;
		#else
		//Find the left and right powers as the sums - Use for Alternate Raw
		tmpleft += radius + raw;
		tmpright -= radius + raw;
		#endif
	}
	else
	{
		tmpleft += radius;
		tmpright -= radius;
	}

	//clamp value range to +-1
	left = limit_motor(tmpleft);
	right = limit_motor(tmpright);
}

//reciprocal
const double c_half_pi_reciprocal=1.0 / (PI_2);  //its more efficient to multiply than to divide... this is around 0.6366...
const double c_taper_limit=DEG_2_RAD(115.0);
const double c_taper_length_recip=1.0 / (c_taper_limit-PI_2);
void culver_drive2(double throttle, double wheelx, double wheely, bool quickturn, double &left, double &right)
{
	//Find arctan of wheel stick relative to vertical... note relative to vertical suggests that we swap the x and y components!
	const double theta = atan2(wheelx,-wheely);

	//Find the magnitude of the wheel stick
	double r = sqrt(((wheely * wheely) + (wheelx * wheelx)));

	//taper off past 90 - 115 using simple linear interpolation 
	double radius_filter=1.0;
	if (fabs(theta)>PI_2)
	{
		const double abs_theta=fabs(theta);
		if (abs_theta<c_taper_limit)
			radius_filter=(1.0-((abs_theta-PI_2) * c_taper_length_recip));
		else
			radius_filter=0;
	}

	//convert to degrees for UI viewing
	//printf("%.2f, %.2f, %.2f, %.2f, %.2f\n",RAD_2_DEG(theta),r,radius_filter,wheelx,wheely);


	//Find Left and Right powers as sums
	double tmpleft = throttle;
	double tmpright = throttle;

	if(quickturn)
	{
		//Find the raw component based on r, radius filter curve, gain, sign
		#ifndef __AlternateRawImplementation__
		const double raw = r * theta*c_half_pi_reciprocal * radius_filter * c_gain_raw; 
		#else
		//Alternate raw implementation
		const double raw = r * interp_2d(theta, c_raw_theta_x, c_raw_theta_z, _countof(c_raw_theta_x)) * c_gain_raw);
		#endif

		printf("%.2f, %.2f, %.2f  -->  X(%.2f) Y(%.2f)\n",r,RAD_2_DEG(theta),raw,wheelx,wheely);

		//here is a separate alternate raw case
		#if 1
		tmpleft += raw;
		tmpright -= raw;
		#else
		const double radius = r * theta*c_half_pi_reciprocal * radius_filter * c_gain_radius * throttle;
		//Find the left and right powers as the sums - Use for Alternate Raw
		tmpleft += radius + raw;
		tmpright -= radius + raw;
		#endif
	}
	else
	{
		//Find the radius component based on r, theta, filter curve, gain, throttle, sign
		const double radius = r * theta*c_half_pi_reciprocal * radius_filter * c_gain_radius * throttle;

		printf("%.2f, %.2f, %.2f  -->  X(%.2f) Y(%.2f)\n",r,RAD_2_DEG(theta),radius,wheelx,wheely);
		tmpleft += radius;
		tmpright -= radius;
	}

	//clamp value range to +-1
	left = limit_motor(tmpleft);
	right = limit_motor(tmpright);
}

void main()
{
	double theta=-PI;
	const double NoIterations=100.0;
	const double rho=PI2 / NoIterations;  //compute step size... by dividing the interval by number of iterations
	const bool DoRaw=false;
	//do a sweep test full forward throttle non quick turn
	while (theta<PI)
	{
		double Left,Right;
		double x=sin(theta);
		double y=-cos(theta);
		//Test with weaker magnitude
		#if 0
		y*=0.5;
		x*=0.5;
		#endif
		//Test with no Y
		#if 0
		y=0;
		#endif
		//swapped as 0 degrees if vertical alignment
		//culver_drive(1.0,x,y,false,Left,Right);
		culver_drive2(1.0,x,y,DoRaw,Left,Right);
		theta+=rho;
	}
	printf("\n");
}
Reply With Quote
  #17   Spotlight this post!  
Unread 26-07-2013, 18:40
apalrd's Avatar
apalrd apalrd is offline
More Torque!
AKA: Andrew Palardy (Most people call me Palardy)
VRC #3333
Team Role: College Student
 
Join Date: Mar 2009
Rookie Year: 2009
Location: Auburn Hills, MI
Posts: 1,347
apalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond repute
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

The alternate vs normal raw mode is interesting. It was our method of removing the 'quick turn' switch, but we decided we liked the switch better.

In any case, the Radius component should be active from 0 to 90 degrees, plus a little for driver forgiveness. R allows us to return to 0 when the stick is centered, and the math works out such that you can drive it like a halo/cheesy drive if you want (although that's not quite ideal, the math works out the same). I am aware that above 90 slightly more turning power is possible, but I didn't really care. I also probably mistyped the radians to degrees, I actually used 180/Pi in the LV implementation and didn't precalculate it.

The initial ('alternate') raw implementation was designed to provide 'quick turn' functionality (steering without throttle for turn-in-place moves) by allowing the driver to move the stick in a fairly binary way around the bottom of the stick bounds (near +-180). It did not use theta at all (except for the enablement curves). We did not like this behavior, and decided to use the 'quick turn' button to switch.

It's interesting to see some SW design choices you made in your implementation.
__________________
Kettering University - Computer Engineering
Kettering Motorsports
Williams International - Commercial Engines - Controls and Accessories
FRC 33 - The Killer Bees - 2009-2012 Student, 2013-2014 Advisor
VEX IQ 3333 - The Bumble Bees - 2014+ Mentor

"Sometimes, the elegant implementation is a function. Not a method. Not a class. Not a framework. Just a function." ~ John Carmack
Reply With Quote
  #18   Spotlight this post!  
Unread 26-07-2013, 21:15
JamesTerm's Avatar
JamesTerm JamesTerm is offline
Terminator
AKA: James Killian
FRC #3481 (Bronc Botz)
Team Role: Engineer
 
Join Date: May 2011
Rookie Year: 2010
Location: San Antonio, Texas
Posts: 298
JamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to behold
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

Quote:
Originally Posted by apalrd View Post
In any case, the Radius component should be active from 0 to 90 degrees, plus a little for driver forgiveness. I am aware that above 90 slightly more turning power is possible, but I didn't really care.
Ok... the key here is anything above 90 you didn't care... the original code reflects how I illustrate in this diagram below... so if the user went above 90 it would start to drop back down to 0 like this:
..........0
....-45.....45
-90.....+.... 90
....-45.....45
...........0

here is that implementation using atan2;

Code:
	//Find arctan of wheel stick relative to vertical (i.e. swap the x and y components)
	const double theta = atan2(wheelx,fabs(wheely));

	//Find the magnitude of the wheel stick
	double r = sqrt(((wheely * wheely) + (wheelx * wheelx)));
This should have identical functionality to what you have written... assuming this is how you intended to do it. It is a great idea and can offer forgiveness if user accidentally goes past 90... or if they don't want to push up it would still work if the stick Y was accidentally done below center.

Now then assuming this is true... both calls to interp_2d() are no longer needed as they will always return 1.0. Especially the Radius Enablement curve. So really the theta and r (magnitude) are the heart of the culver drive. Just using these by themselves can be a nice sweet substitute for anyone's function that takes an x-axis. I'll give this a shot in our drive and perhaps post it on you tube this weekend... the other cool thing is doing it like this... after obtaining the normalized value (i.e. theta * r )... it can be used with Ether's equations for even greater control of the distribution of the curve.

Here's a little snip of that...
Code:
if (AnalogEvents)
{
	//Now to use the attributes to tweak the value
	//First evaluate dead zone range... if out of range subtract out the offset for no loss in precision
	//The /(1.0-filter range) will restore the full range
	
	double Temp=fabs(Value); //take out the sign... put it back in the end
	Temp=(Temp>=key.FilterRange) ? Temp-key.FilterRange:0.0; 

	Temp=key.Multiplier*(Temp/(1.0-key.FilterRange)); //apply scale first then
	if (key.CurveIntensity<=1.0)
		Temp=key.CurveIntensity*pow(Temp,3) + (1.0-key.CurveIntensity)*Temp; //apply the curve intensity
	else
		Temp=pow(Temp,key.CurveIntensity); //apply the curve intensity

	//Now to restore the sign
	Value=(Value<0.0)?-Temp:Temp;

	std::vector<std::string>::iterator pos;
	for (pos = AnalogEvents->begin(); pos != AnalogEvents->end(); ++pos)
		m_controlledEventMap->EventValue_Map[*pos].Fire(key.IsFlipped?-Value:Value);
}

Quote:
Originally Posted by apalrd View Post
R allows us to return to 0 when the stick is centered, and the math works out such that you can drive it like a halo/cheesy drive if you want (although that's not quite ideal, the math works out the same).
When you say halo/cheesy drive in this context... do you mean driving the steering without using the y component?
Reply With Quote
  #19   Spotlight this post!  
Unread 26-07-2013, 21:27
apalrd's Avatar
apalrd apalrd is offline
More Torque!
AKA: Andrew Palardy (Most people call me Palardy)
VRC #3333
Team Role: College Student
 
Join Date: Mar 2009
Rookie Year: 2009
Location: Auburn Hills, MI
Posts: 1,347
apalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond repute
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

Quote:
Originally Posted by JamesTerm View Post
When you say halo/cheesy drive in this context... do you mean driving the steering without using the y component?
Yup. At y=0 the math works out the same for x-only movement as the Halo drive did.

The intent for Radius was to replace the x-axis input in the Cheesy Drive with the theta*r input. We provisioned a lot more to place the raw/quick turn elsewhere on the stick range (the negative half) in the alternate-raw implementation, but the normal raw is just a cheesy drive with a quick turn button.

In fact, the entire reason we used the interp curves was to support the alternate raw implementation. We never revisited the math when we decided we didn't like it.
__________________
Kettering University - Computer Engineering
Kettering Motorsports
Williams International - Commercial Engines - Controls and Accessories
FRC 33 - The Killer Bees - 2009-2012 Student, 2013-2014 Advisor
VEX IQ 3333 - The Bumble Bees - 2014+ Mentor

"Sometimes, the elegant implementation is a function. Not a method. Not a class. Not a framework. Just a function." ~ John Carmack
Reply With Quote
  #20   Spotlight this post!  
Unread 28-07-2013, 07:59
JamesTerm's Avatar
JamesTerm JamesTerm is offline
Terminator
AKA: James Killian
FRC #3481 (Bronc Botz)
Team Role: Engineer
 
Join Date: May 2011
Rookie Year: 2010
Location: San Antonio, Texas
Posts: 298
JamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to behold
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

Hi Palardy,
So I have started to integrate the Culver drive controls in our simulation and I have found some interesting findings:

When I started testing this, I found that not all circular controllers have the same diagonal intensity as the LogicTech F310. I tested the AirFlo which is also circular, but in testing, it reached full x and y intensity at the corners. I am not sure if there is a spec yet for identifying this, but it should probably be in a form that shows the full x and y intensity ratio (when diagonal), because the F310 I have tested if you normalize x and y readings and move the joystick to its full diagonal where they are equal...it is more than (sin(45) / 70.7...) it's around 80. I believe though that controllers like the AirFlo can still benefit from the Culver drive, because the faster speeds really shouldn't matter as much.

So using just the theta and magnitude and testing this with full y component magnitude. I put a UI feedback that shows what the value would have been if I just used the x component right beside the new value of (theta * r). It turns out they were equal (at first)! This means anyone can simply use halo drive code and control the wheel in the same manner to get the same effect. Now then in regards to the 80% normalized value I mentioned above... as you rotate the wheel closer to 90... the magnitude will actually exceed 1.0... to around 1.14... so as it gets closer and the magnitude increases you lose precision you would have had otherwise, but at these faster speeds it doesn't really matter.

So I have some good news though... I'd recommend you try the same tests if you can and see if you are getting the same results. If I scale the magnitude to around 0.875... this works out perfect where it starts with a magnitude of this (0.875) moving joystick to full Y with x centered... and then by the time it reaches the corner it will be around 1.01. With this you can finally achieve a greater precision for the slower speeds. The derivative of the distribution looks like a "soft" x^2 when compared testing against the x components raw value otherwise.

One other interesting note is that I tested the halo drive scenario (i.e. no Y component)... this turned out to lose more precision than otherwise, but not by much. That said, this solution cannot substitute the need to filter out the dead zone of the joystick, and it should be virtually the same amount as otherwise. This loss of precision could be a benefit for an alternate quick-turn solution. For our setup the workflow may be to use halo drive for most quick turns, and then the Culver wheel drive to fine tune the turns. On Monday I'll try to show a demo of this and these number findings on YouTube.

Last edited by JamesTerm : 28-07-2013 at 08:03.
Reply With Quote
  #21   Spotlight this post!  
Unread 29-07-2013, 15:04
JamesTerm's Avatar
JamesTerm JamesTerm is offline
Terminator
AKA: James Killian
FRC #3481 (Bronc Botz)
Team Role: Engineer
 
Join Date: May 2011
Rookie Year: 2010
Location: San Antonio, Texas
Posts: 298
JamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to behold
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

Here is a quick demo... I have changed how the magnitude is computed in this demo. It blends from 0.87 when theta is 0 to (1/(pi/2)) when theta is 90. Let me know what you think.

http://youtu.be/NKd6inx9OH8

Last edited by JamesTerm : 29-07-2013 at 21:57.
Reply With Quote
  #22   Spotlight this post!  
Unread 29-07-2013, 20:41
BJC's Avatar
BJC BJC is offline
Simplicity is Complicated!
AKA: Bryan Culver
FRC #0033 (The Killer Bees)
Team Role: Alumni
 
Join Date: Jan 2010
Rookie Year: 2009
Location: Kettering/Greenville
Posts: 705
BJC has a reputation beyond reputeBJC has a reputation beyond reputeBJC has a reputation beyond reputeBJC has a reputation beyond reputeBJC has a reputation beyond reputeBJC has a reputation beyond reputeBJC has a reputation beyond reputeBJC has a reputation beyond reputeBJC has a reputation beyond reputeBJC has a reputation beyond reputeBJC has a reputation beyond repute
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

I really like this demo, it does a good job of explaining the jist of how "Culver drive" works. I'll leave the magnitude computation change assessing to Andrew.

If you look up at my name you'll see that the second one is "Culver." I just wanted to explain why this is named after me (I'm not egocentric, I promise.) Last summer I picked up a controller to drive the 2012 robot and was very disappointed by my inability to do arcing turns using Cheesy drive. Walking out of Chrysler that evening I explained to Andrew what I would rather have -- point the stick forward and move it around the way you would if you were driving a car with one hand on 12o'clock, keeping the throttle the same. Andrew coded it from there and after we tested it on a robot and liked it we were trying to think of a catchy name for it (WASPdrive was already in development and named at this point.) We couldn't think of anything and Andrew already had it named after me in the code at this point so, much to my displeasure, left it "Culver drive."

In any case, our driver really liked it this year and we'll probably be using it again next year.

Cheers, Bryan
__________________
robot robot robot? Robot. Robot? Robot!
-----------------Team 33------------------
Reply With Quote
  #23   Spotlight this post!  
Unread 30-07-2013, 00:03
apalrd's Avatar
apalrd apalrd is offline
More Torque!
AKA: Andrew Palardy (Most people call me Palardy)
VRC #3333
Team Role: College Student
 
Join Date: Mar 2009
Rookie Year: 2009
Location: Auburn Hills, MI
Posts: 1,347
apalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond repute
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

The demo is interesting.

The question of how to deal with the quick turns comes up a lot, not just for Culverdrive but also for Cheesy vs Halo drives (I've usually defined them as the same algorithm, but the switch from including Throttle to not including throttle is done via a button in Cheesy and when throttle = 0 in Halo). One design logic is that the quick turn button is an additional button that can be optimized out, the other is that with the button it's possible to slow down to 0 speed while in an arc turn without suddenly spinning.

We initially used the design logic that the enablement curves would sum to 1 so as soon as the driver exceeded 95 degrees it would pull throttle out of the equation but the rest of the result would remain the same, to allow turning in place without the throttle. That is the 'alternate raw' implementation, which is actually the original. The current raw implementation is more similar to the original cheesy drive, and we just switch based on quick turn switch.

There's still more optimization we can do. I like the interp curve function because I can plugin a set of points and map the curve as I want, however nonlinear or strange it is, without finding a mathematical way to represent it, and it's not that inefficient for relatively small tables.
__________________
Kettering University - Computer Engineering
Kettering Motorsports
Williams International - Commercial Engines - Controls and Accessories
FRC 33 - The Killer Bees - 2009-2012 Student, 2013-2014 Advisor
VEX IQ 3333 - The Bumble Bees - 2014+ Mentor

"Sometimes, the elegant implementation is a function. Not a method. Not a class. Not a framework. Just a function." ~ John Carmack
Reply With Quote
  #24   Spotlight this post!  
Unread 30-07-2013, 12:15
magnets's Avatar
magnets magnets is offline
Registered User
no team
 
Join Date: Jun 2013
Rookie Year: 2012
Location: United States
Posts: 748
magnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond reputemagnets has a reputation beyond repute
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

That's pretty cool. I like the idea of automatically switching to quick turn after the driver pushes the stick far enough to the side. This is similar to a team who used an actual steering wheel to control their robot one year!

How do your drivers feel about this setup? In the past we've tried some similar things (cheesydrive/right stick steering wheel), but our drivers preferred a tank drive setup, claiming that the cheesy drive was better for driving around an empty field, but when in pushing matches and having to line up, tank drive was better.

Also, do you know if anybody has come up with a way to use these style algorithms on swerve/meccanum, or with the sort of drive that 148 used in 2010 (I forget what it's called).
Reply With Quote
  #25   Spotlight this post!  
Unread 30-07-2013, 14:55
apalrd's Avatar
apalrd apalrd is offline
More Torque!
AKA: Andrew Palardy (Most people call me Palardy)
VRC #3333
Team Role: College Student
 
Join Date: Mar 2009
Rookie Year: 2009
Location: Auburn Hills, MI
Posts: 1,347
apalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond repute
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

-Drivers did not complain. I personally loved it, and I drove a Halo style drive in 2012. High speed driving performance is WAY better than with a tank setup, and alighment is easier by optimizing it when the quick turn button is pressed.
--Driving with a steering wheel is not uncommon, we tried to emulate it with this, as we believe it is a superior HMI to a two-stick tank drive.

-Purely subjective driver analysis has shown that it's MUCH easier/faster to master the graceful high speed arc maneuvers we want with a culver or cheesy drive than the two-stick tank. We actually have a lot of code in our 2011 robot (two stick tank) to modify the inner wheels to arc nicely when the driver lets go of one stick to turn, but that code was quite a bit of work to develop fully and not a good solution, since it really makes driving three-state (both sticks same direction, one stick full one stick zero, both sticks opposite direction) and the driver bumps it on and off a lot for jerky turns.

-Judges loved it, noted 'Culver Drive' in championship award speech

-We used a Halo drive with a slide drive in Vex (what 148 in 2010 had, except without the droppable traction wheels and bump crossing ability), we just used the left stick for translation and right stick for rotation. Since the left/right wheels control steering, we simply ran a normal Halo drive and mapped the slide wheel to left X (left Y was throttle for left/right wheels, right X was wheel). This ran three Vex robots and all drivers loved it for that drivetrain, one was able to pick up some 'fancy' moves like circling around a point in front of him or spinning around off a defender extremely quickly. For a mecanum, I would find theta/R of both sticks, and use left theta for translation angle, left R for throttle, and right stick would determine the rotation as it does now. Then you would just have to solve the mecanum math and warp everything back into the +-1 range nicely.
__________________
Kettering University - Computer Engineering
Kettering Motorsports
Williams International - Commercial Engines - Controls and Accessories
FRC 33 - The Killer Bees - 2009-2012 Student, 2013-2014 Advisor
VEX IQ 3333 - The Bumble Bees - 2014+ Mentor

"Sometimes, the elegant implementation is a function. Not a method. Not a class. Not a framework. Just a function." ~ John Carmack
Reply With Quote
  #26   Spotlight this post!  
Unread 30-07-2013, 18:24
JamesTerm's Avatar
JamesTerm JamesTerm is offline
Terminator
AKA: James Killian
FRC #3481 (Bronc Botz)
Team Role: Engineer
 
Join Date: May 2011
Rookie Year: 2010
Location: San Antonio, Texas
Posts: 298
JamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to behold
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

Quote:
Originally Posted by apalrd View Post
There's still more optimization we can do. I like the interp curve function because I can plugin a set of points and map the curve as I want, however nonlinear or strange it is, without finding a mathematical way to represent it, and it's not that inefficient for relatively small tables.


I have made a graphical representation of 3 different setups that try to illustrated the distribution. The one on the right is halo drive with just x and no y, and the top left is the culver theta * r where r is just magnitude with no scale. The bottom left is the blend of 0.875 to (1/(pi/2)=.64ish).

The green tries to highlight the smaller numbers and how they are spread out. The spread of numbers between the 1.0 magnitude and the halo are virtually identical for the precision workflow (i.e. when using the max y stick up)... This means the actual benefit of precision (using 1.0) is a mechanical solution and could be accomplished using the halo drive. It does however have brighter red and blue intensity on the sides this is because when you get there your range will exceed past 1.0 to 1.57 (half a pi). The bottom one will keep the range 0-1 intact for halo while spreading out the centered area for Culver. This makes it both mechanical and functional benefit of precision. This suggestion makes the Y component a bit more interesting in that when Y is centered... it is identical distribution as the halo graph (therefore a perfect fit for anyone's driving system), and then when Y is used for Culver steering... the x distribution is greater for precise turning and then curves down quick to meet up with 1.0 at the end. I hope this makes sense... I can see a work flow solution to use halo drive for quick turns and culver drive for precise turns without need of a button. Quick turns in this context are in terms of what the x axis submits to another function... this means it is possible to use this for some other kind of control (e.g. arm) when it is broken down to just this functionality.

I'll save the actual drive implementation for a separate post.
Reply With Quote
  #27   Spotlight this post!  
Unread 30-07-2013, 21:47
JamesTerm's Avatar
JamesTerm JamesTerm is offline
Terminator
AKA: James Killian
FRC #3481 (Bronc Botz)
Team Role: Engineer
 
Join Date: May 2011
Rookie Year: 2010
Location: San Antonio, Texas
Posts: 298
JamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to behold
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

Quote:
Originally Posted by BJC View Post
We couldn't think of anything and Andrew already had it named after me in the code at this point so, much to my displeasure, left it "Culver drive."
I think this name is fine... its first impression was.. what is this? So it works.


Thanks for the feedback on the demo... (Thanks Palardy and Magnets too). Sometimes I feel like no one appreciates the effort and thought that goes into this... so it means a lot.
Reply With Quote
  #28   Spotlight this post!  
Unread 30-07-2013, 22:20
JamesTerm's Avatar
JamesTerm JamesTerm is offline
Terminator
AKA: James Killian
FRC #3481 (Bronc Botz)
Team Role: Engineer
 
Join Date: May 2011
Rookie Year: 2010
Location: San Antonio, Texas
Posts: 298
JamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to behold
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

Quote:
Originally Posted by magnets View Post
That's pretty cool. I like the idea of automatically switching to quick turn after the driver pushes the stick far enough to the side. This is similar to a team who used an actual steering wheel to control their robot one year!

Also, do you know if anybody has come up with a way to use these style algorithms on swerve/meccanum, or with the sort of drive that 148 used in 2010 (I forget what it's called).
I am not sure if this was for Palardy or me... but since it has the word "automatically" I'll assume it was in response to the demo. With that said... it doesn't really switch to quick turn but rather the x axis controls the angular velocity of the robot. Mechanical engineers (except for Jim Zondag) think I'm crazy for wanting to control velocity, but I got the idea from Ether way back when we were talking about swerve drives here. This thread listing has equations that work for swerve drive, but also with some modification can work (and do for us) for tank, and slide drive (or nona drive if it has the extra set of wheels). Also included in here is a link to a demo of the swerve drive simulation. If you go down this path for skid steering drives like tank... be sure to factor skid into the equations to be correct (if you neglect this it will still work fine, but if you want to tune angular rotation to encoders you'll need it then).

I should add that I have incorporated the culver drive into some simulated swerve and nona drive code and they work great because this is solving the x-axis method, and passes the value as if it was the x-axis.

Quote:
Originally Posted by magnets View Post
How do your drivers feel about this setup? In the past we've tried some similar things (cheesydrive/right stick steering wheel), but our drivers preferred a tank drive setup, claiming that the cheesy drive was better for driving around an empty field, but when in pushing matches and having to line up, tank drive was better.
I get a mix of feelings as the feel is subjective... some like to have full manual control of it (like driving a standard)... others like it to be intuitive. I like the idea of driving with encoders in a pushing match. There I said it! I know a lot of people disagree with that. But I get the physics behind what it means, and I'll stand by that idea... getting our team to use it is another story.
Reply With Quote
  #29   Spotlight this post!  
Unread 31-07-2013, 03:12
apalrd's Avatar
apalrd apalrd is offline
More Torque!
AKA: Andrew Palardy (Most people call me Palardy)
VRC #3333
Team Role: College Student
 
Join Date: Mar 2009
Rookie Year: 2009
Location: Auburn Hills, MI
Posts: 1,347
apalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond reputeapalrd has a reputation beyond repute
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

Quote:
Originally Posted by JamesTerm View Post
Mechanical engineers (except for Jim Zondag) think I'm crazy for wanting to control velocity
-Jim is actually an electrical engineer

-We do like velocity controls as well, but we haven't implemented them since 2011. I think that would be a logical improvement to this system.

-That said, a simple PI controller to speed does not have a fast enough response time for drivetrain usage. We did this in 2011 and turned the gains WAY up for fast response, and oscillations weren't very good, but it worked.

-A better solution is one of the better speed control algorithms designed for shooter flywheel speed control (2012 was especially big on this, 2013 less). We ran a PI-FF algorithm with a feed forward equation (now we would just use a table), which is an improvement
__________________
Kettering University - Computer Engineering
Kettering Motorsports
Williams International - Commercial Engines - Controls and Accessories
FRC 33 - The Killer Bees - 2009-2012 Student, 2013-2014 Advisor
VEX IQ 3333 - The Bumble Bees - 2014+ Mentor

"Sometimes, the elegant implementation is a function. Not a method. Not a class. Not a framework. Just a function." ~ John Carmack
Reply With Quote
  #30   Spotlight this post!  
Unread 31-07-2013, 11:00
JamesTerm's Avatar
JamesTerm JamesTerm is offline
Terminator
AKA: James Killian
FRC #3481 (Bronc Botz)
Team Role: Engineer
 
Join Date: May 2011
Rookie Year: 2010
Location: San Antonio, Texas
Posts: 298
JamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to beholdJamesTerm is a splendid one to behold
Re: paper: FRC #33 The Killer Bees 2013 Software - BuzzXVIII (Buzz18)

Quote:
Originally Posted by apalrd View Post
-Jim is actually an electrical engineer
Ah ha... now it all makes sense.

Mechanical engineers like to solve the controlling aspects of the drive and leave little for software to do... they are happy with just raw voltage input from the controls... and from this whatever non-intuitive issue arise it is left for the driver to get use to them and overcome them. This goes against the mentality of a software engineer which figures out intuitive solutions for all users to be able to pick up and use. If we cannot make it intuitive people will not buy our stuff.

Quote:
Originally Posted by apalrd View Post
-We do like velocity controls as well, but we haven't implemented them since 2011. I think that would be a logical improvement to this system.

-That said, a simple PI controller to speed does not have a fast enough response time for drivetrain usage. We did this in 2011 and turned the gains WAY up for fast response, and oscillations weren't very good, but it worked.

-A better solution is one of the better speed control algorithms designed for shooter flywheel speed control (2012 was especially big on this, 2013 less). We ran a PI-FF algorithm with a feed forward equation (now we would just use a table), which is an improvement
Yup... I've been through the ringer of that as well as shown below... in 2011 we didn't know the value of linearization of the victors... which I guess is no longer an issue with the 888's. In 2012 we used the polynomial equation from Simbotics which worked out very well. In 2013 we applied the gain assist.... without gain assist the drive takes around 210 - 300 ms of latency. Using a closed loop solution brings that down to around 60ms. Using gain assist makes it virtually 0. This test shown here is a setpoint test using the drive like a turret... where each pixel column represents a 10ms iteration. The Magenta is the velocity line the green is the voltage, then Cyan is the encoder reading, and the yellow is PID error correct (which is not used in these tests).

Reply With Quote
Reply


Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -5. The time now is 00:36.

The Chief Delphi Forums are sponsored by Innovation First International, Inc.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi