OCCRA
Go to Post But we all just have to do what we can and are willing to, to keep our teams going. - Adrienne E. [more]
Home
Go Back   Chief Delphi > Technical > Programming > WindRiver C++
CD-Events   CD-Media   CD-Spy   FRC-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 04-06-2010, 05:07 AM
mikets's Avatar
mikets mikets is offline
Software Engineer
FRC #0492 (Titan Robotics)
Team Role: Mentor
 
Join Date: Jan 2010
Rookie Year: 2008
Location: Bellevue, WA
Posts: 596
mikets is a glorious beacon of lightmikets is a glorious beacon of lightmikets is a glorious beacon of lightmikets is a glorious beacon of lightmikets is a glorious beacon of lightmikets is a glorious beacon of light
Re: Unexpected results from Encoder::GetRate()

Quote:
Originally Posted by vamfun View Post
We integrated dt = 1/(Update_Rate) and checked that the computed time matched real time so this led us to the double encoder GetRate() error which we verified independently using motor rpm measurements.
But what is Update_Rate? If it's derived from the period of some periodic loop, you need to verify the real interval of the periodic loop. How did you compute real time? I use the following code to measure my periodic intervals:
Code:
UINT32 timeCurr = GetFPGATime(); // in usec
float period = (float)(timeCurr - m_timestamp)/1000000.0;
m_timestamp = timeCurr;
__________________
Reply With Quote
  #17   Spotlight this post!  
Unread 04-06-2010, 03:17 PM
vamfun vamfun is offline
Mentor :Contol System Engineer
AKA: Chris
FRC #0599 (Robodox)
Team Role: Engineer
 
Join Date: Jan 2009
Rookie Year: 2003
Location: Van Nuys, California
Posts: 178
vamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of light
Send a message via AIM to vamfun
Re: Unexpected results from Encoder::GetRate()

Quote:
Originally Posted by mikets View Post
But what is Update_Rate? If it's derived from the period of some periodic loop, you need to verify the real interval of the periodic loop. How did you compute real time?
Update_Rate is a define... say 100. hz.
dt = 1/Update_rate;

We use iterative class SetPeriod(dt);

Then we measure cumulative time rather than loop period:
We put this in the loop : time = time + dt :
and simply compare time print out with a stop watch. Since we were looking for a factor of 2 this was accurate enough. We easily checked within a few %.

Last edited by vamfun : 04-06-2010 at 04:20 PM.
Reply With Quote
  #18   Spotlight this post!  
Unread 04-06-2010, 04:31 PM
mikets's Avatar
mikets mikets is offline
Software Engineer
FRC #0492 (Titan Robotics)
Team Role: Mentor
 
Join Date: Jan 2010
Rookie Year: 2008
Location: Bellevue, WA
Posts: 596
mikets is a glorious beacon of lightmikets is a glorious beacon of lightmikets is a glorious beacon of lightmikets is a glorious beacon of lightmikets is a glorious beacon of lightmikets is a glorious beacon of light
Re: Unexpected results from Encoder::GetRate()

I am sorry. I am probably not helping with your particular problem. I am merely trying to point out that in the iterative robot class, don't count on the period being accurate and use it as dt for differentiation or integration. You said your Update_Rate is 100 Hz. That makes the period 10 ms. If you put "time = time + 1/Update_Rate" in your loop, your time is really summing a constant 10 ms on every loop period, not real time. If you do this instead:
Code:
class MyRobot: public IterativeRobot
{
private:
    UINT32 m_timestamp;
    ....

public:
    void AutonomousInit()
    {
        m_timestamp = GetFPGATime();
        ....
    }
    void AutonomousPeriodic()
    {
        UINT32 timeCurr = GetFPGATime(); // in usec
        float period = (float)(timeCurr - m_timestamp)/1000000.0;
        m_timestamp = timeCurr;
        printf("loop period is %f\n", period);
        ...
    }
};
"period" will be the accurate loop interval that can be used as dt in your differentiation or integration. In theory period should print out 0.01s (10 ms), but in our case, it is way off. It could be because our loop execution took longer than the 10ms to execute that may cause a period to be skipped in some cases. Therefore, as a good practice, never use the period you set in any time critical calculations.
__________________

Last edited by mikets : 04-06-2010 at 04:52 PM.
Reply With Quote
  #19   Spotlight this post!  
Unread 04-06-2010, 05:40 PM
vamfun vamfun is offline
Mentor :Contol System Engineer
AKA: Chris
FRC #0599 (Robodox)
Team Role: Engineer
 
Join Date: Jan 2009
Rookie Year: 2003
Location: Van Nuys, California
Posts: 178
vamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of light
Send a message via AIM to vamfun
Re: Unexpected results from Encoder::GetRate()

Quote:
Originally Posted by mikets View Post
In theory period should print out 0.01s (10 ms), but in our case, it is way off. It could be because our loop execution took longer than the 10ms to execute that may cause a period to be skipped in some cases.
I've done a lot of real time control systems and never had a problem with interrupt driven loops because we always verify that execution cannot exceed the loop period. So I suspect you have a problem delay in your loop and indeed if you are using a debug console printf(...) in a 10 ms loop then this can easily cause you a problem since it requires about 1ms per char and once you exceed the buffer, this becomes a realized delay.



Quote:
Therefore, as a good practice, never use the period you set in any time critical calculations
... unless you have verified your computations can't exceed the loop time

Edit: Actually this is a design issue rather than good practice. Either you design it as a periodic loop or not. Often programmers don't understand the hardware fully and run into these types of problems and wind up adding the type of compensation programming that you are suggesting. In fact, IMHO, when things are time critical, the periodic loop is often preferred since it is more predictable than non periodic solutions.

Last edited by vamfun : 04-06-2010 at 11:13 PM.
Reply With Quote
  #20   Spotlight this post!  
Unread 04-08-2010, 11:53 PM
vamfun vamfun is offline
Mentor :Contol System Engineer
AKA: Chris
FRC #0599 (Robodox)
Team Role: Engineer
 
Join Date: Jan 2009
Rookie Year: 2003
Location: Van Nuys, California
Posts: 178
vamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of light
Send a message via AIM to vamfun
Re: Unexpected results from Encoder::GetRate()

Ok, back to Encoder Problem:
I got hold of a CRIO finally and ran some encoder outputs while we bench drove the robot. I set the iterative loop rate to 10 hz and printed to the console :
printf( ..... ", GetDistance(), GetRate(), Derived rate) where derived rate was the avg rate over the 100ms period.

Ran full forward, full reverse, partial forward, partial reverse cases for 1x,2x,4x.

Data can be downloaded from
http://www.scribd.com/doc/29635300/5...er-4-7-09-Test
I recommend downloading and viewing the plots since they are cutoff on scrid site.

For some reason the encoder counts were about 1/5.7 of what they should have been... ie the avg derived rate was 1.2 fps rather than 6.8 fps. So the encoder might be broken but it did register linear GetDistance().
Aside from this, the GetRate() was consistent for 1x,2x,4x and showed plots with basically two interwoven levels. One close to the derived rate of 1.2 fps and the other around 12 fps when running max speed. So there is definitely something odd for all modes.

So, today, I tried some more direct debug of encoder.cpp. I disconnected the encoder inputs and replaced them with a periodic pulse on the A channel and open (pull up value) on the B channel. We figured we could manually cause the counters to increment by alternating between open and ground on the A input. Well, something really weird happened. The 0 input caused a 1 count and the 1 input caused the count to decrement to 0 count again. Huh?? So the GetRaw() just alternated between 1 and 0 rather than accumulate.

So must be some good explaination... right?

Maybe more on Monday.

Last edited by vamfun : 04-09-2010 at 12:01 AM.
Reply With Quote
  #21   Spotlight this post!  
Unread 04-09-2010, 12:02 AM
Joe Ross's Avatar Unsung FIRST Hero
Joe Ross Joe Ross is offline
Registered User
FRC #0330 (Beachbots)
Team Role: Engineer
 
Join Date: Jun 2001
Rookie Year: 1997
Location: Los Angeles, CA
Posts: 7,859
Joe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond reputeJoe Ross has a reputation beyond repute
Re: Unexpected results from Encoder::GetRate()

Quote:
Originally Posted by vamfun View Post
So, today, I tried some more direct debug of encoder.cpp. I disconnected the encoder inputs and replaced them with a periodic pulse on the A channel and open (pull up value) on the B channel. We figured we could manually cause the counters to increment by alternating between open and ground on the A input. Well, something really weird happened. The 0 input cause a 1 count and the 1 input caused the count to decrement rather than accumulate. Huh?? So the GetRaw() just alternated between 1 and 0.
That would be expected for quadrature decoding. With the B channel stuck at a value, it looks like it's constantly changing directions.
Reply With Quote
  #22   Spotlight this post!  
Unread 04-09-2010, 12:26 AM
vamfun vamfun is offline
Mentor :Contol System Engineer
AKA: Chris
FRC #0599 (Robodox)
Team Role: Engineer
 
Join Date: Jan 2009
Rookie Year: 2003
Location: Van Nuys, California
Posts: 178
vamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of light
Send a message via AIM to vamfun
Re: Unexpected results from Encoder::GetRate()

Quote:
Originally Posted by Joe Ross View Post
That would be expected for quadrature decoding. With the B channel stuck at a value, it looks like it's constantly changing directions.
Joe, I would expect that for 2x and 4x but not 1x, since with 1x only A channel leading edge determines the count and the B channel is always the same value on the leading edge. Unless I'm missing something.

Last edited by vamfun : 04-09-2010 at 02:23 AM.
Reply With Quote
  #23   Spotlight this post!  
Unread 04-09-2010, 06:52 AM
Jared Russell's Avatar
Jared Russell Jared Russell is offline
I feel better now.
AKA: Jared341
FRC #0254 (The Cheesy Poofs)
Team Role: Engineer
 
Join Date: Nov 2002
Rookie Year: 2001
Location: San Francisco, CA
Posts: 2,631
Jared Russell has a reputation beyond reputeJared Russell has a reputation beyond reputeJared Russell has a reputation beyond reputeJared Russell has a reputation beyond reputeJared Russell has a reputation beyond reputeJared Russell has a reputation beyond reputeJared Russell has a reputation beyond reputeJared Russell has a reputation beyond reputeJared Russell has a reputation beyond reputeJared Russell has a reputation beyond reputeJared Russell has a reputation beyond repute
Re: Unexpected results from Encoder::GetRate()

Quote:
Originally Posted by vamfun View Post
Joe, I would expect that for 2x and 4x but not 1x, since with 1x only A channel leading edge determines the count and the B channel is always the same value on the leading edge. Unless I'm missing something.
There are many ways that one could implement a 1x quadrature decoder.

For a few reasons, a 1x decoder that requires a transition on both phases prior to incrementing the count is advantageous (namely, it can discriminate between the constantly changing direction vs. constant direction case).
Reply With Quote
  #24   Spotlight this post!  
Unread 04-09-2010, 04:12 PM
vamfun vamfun is offline
Mentor :Contol System Engineer
AKA: Chris
FRC #0599 (Robodox)
Team Role: Engineer
 
Join Date: Jan 2009
Rookie Year: 2003
Location: Van Nuys, California
Posts: 178
vamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of light
Send a message via AIM to vamfun
Re: Unexpected results from Encoder::GetRate()

Quote:
Originally Posted by Jared341 View Post
There are many ways that one could implement a 1x quadrature decoder.

For a few reasons, a 1x decoder that requires a transition on both phases prior to incrementing the count is advantageous (namely, it can discriminate between the constantly changing direction vs. constant direction case).
Ok, lets get specific. When we write our own interrupt encoder routines, the B channel is just looked at when a TEU pulse occurs on the A chan to get the direction. However, the tcounters in CRIO are a bit of a mystery to me still and I need some more tutoring.

Here, the upSource is A chan and the downSource is B chan. This is called by encoder.cpp.

Counter::Counter(EncodingType encodingType, DigitalSource *upSource, DigitalSource *downSource, bool inverted)
{
wpi_assert(encodingType == k1X || encodingType == k2X);
InitCounter(kExternalDirection);
SetUpSource(upSource);
SetDownSource(downSource);

if (encodingType == k1X)
SetUpSourceEdge(true, false); // THis is clear to me
else
SetUpSourceEdge(true, true); // This is clear to me

SetDownSourceEdge(inverted, true); // This needs explanation
}


As I understand it, the tcounters have independent sources than can be set to count up or down. How does setting the B chan to always count down on a TED and down on TEU if inverted=true set up the counter to give the proper direction?
Reply With Quote
  #25   Spotlight this post!  
Unread 04-10-2010, 12:56 AM
Bigcheese Bigcheese is offline
C++0x FTW!
AKA: Michael Spencer
FRC #1771
Team Role: Mentor
 
Join Date: Feb 2008
Rookie Year: 2008
Location: GA
Posts: 36
Bigcheese is a jewel in the roughBigcheese is a jewel in the roughBigcheese is a jewel in the roughBigcheese is a jewel in the rough
Re: Unexpected results from Encoder::GetRate()

Quote:
Originally Posted by vamfun View Post
For some reason the encoder counts were about 1/5.7 of what they should have been... ie the avg derived rate was 1.2 fps rather than 6.8 fps. So the encoder might be broken but it did register linear GetDistance().
Aside from this, the GetRate() was consistent for 1x,2x,4x and showed plots with basically two interwoven levels. One close to the derived rate of 1.2 fps and the other around 12 fps when running max speed. So there is definitely something odd for all modes.
That's definitely not what I get. How do you get a negative value when going full forward?

Here's the data I got for a bump test I did about a week ago. The setup is really weird because we were rushing to get it before we had to leave for a week (spring break). There are two different encoders on the left and right drive trains (I don't remember which is which at the moment). We set the robot on its butt and set the jags to output 0.6, waited for 2 seconds, and then set them back to 0.

The code is set to 2x decoding and a 0.005 period (200 HZ) between every sample.

https://docs.google.com/leaf?id=0B3I...NTFjM2Iz&hl=en

Again, I don't know exactly what value should be returned, but obviously there is a difference in what our GetRate()s are returning.

I should have access to the bot tomorrow, so I'll try adding a plot of the derived rate.
Reply With Quote
  #26   Spotlight this post!  
Unread 04-10-2010, 02:16 AM
vamfun vamfun is offline
Mentor :Contol System Engineer
AKA: Chris
FRC #0599 (Robodox)
Team Role: Engineer
 
Join Date: Jan 2009
Rookie Year: 2003
Location: Van Nuys, California
Posts: 178
vamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of light
Send a message via AIM to vamfun
Re: Unexpected results from Encoder::GetRate()

Quote:
Originally Posted by Bigcheese View Post
That's definitely not what I get. How do you get a negative value when going full forward?

Here's the data I got for a bump test I did about a week ago.
Again, I don't know exactly what value should be returned, but obviously there is a difference in what our GetRate()s are returning.

I should have access to the bot tomorrow, so I'll try adding a plot of the derived rate.
Well, this data looks better... I suspect we had a bad encoder or maybe hardware problem.

Only thing clear is a factor of 2 difference in your data so far.

What are the units?
How did you acquire data?
Can you also print GetDistance or GetRaw?
Was SetDistancePerPulse checked for each encoder?
Can you run a 1x case if you have time?

Last edited by vamfun : 04-10-2010 at 02:20 AM.
Reply With Quote
  #27   Spotlight this post!  
Unread 04-10-2010, 10:07 AM
Bigcheese Bigcheese is offline
C++0x FTW!
AKA: Michael Spencer
FRC #1771
Team Role: Mentor
 
Join Date: Feb 2008
Rookie Year: 2008
Location: GA
Posts: 36
Bigcheese is a jewel in the roughBigcheese is a jewel in the roughBigcheese is a jewel in the roughBigcheese is a jewel in the rough
Re: Unexpected results from Encoder::GetRate()

Quote:
Originally Posted by vamfun View Post
Only thing clear is a factor of 2 difference in your data so far.
The factor of two difference between the encoders is because one is about twice the pulses per rev as the other.

Quote:
Originally Posted by vamfun View Post
What are the units?
How did you acquire data?
Can you also print GetDistance or GetRaw?
Was SetDistancePerPulse checked for each encoder?
Can you run a 1x case if you have time?
  • The units are in feet per second.
  • Using a notifier that printed GetFPGATime(),GetJagOutput(),GetLeftRate(),GetRigh tRate() at 200Hz
  • Hopefully today.
  • The same value was used for both and was correct for one of them.
  • I think I have one, but I'm not sure which it was (we were rushing to see the data, didn't mark any of it). The data was almost identical except for a little less noise. I'll run it again though.

I will do this today if I can get into the school.
Reply With Quote
  #28   Spotlight this post!  
Unread 04-11-2010, 08:16 PM
Bigcheese Bigcheese is offline
C++0x FTW!
AKA: Michael Spencer
FRC #1771
Team Role: Mentor
 
Join Date: Feb 2008
Rookie Year: 2008
Location: GA
Posts: 36
Bigcheese is a jewel in the roughBigcheese is a jewel in the roughBigcheese is a jewel in the roughBigcheese is a jewel in the rough
Re: Unexpected results from Encoder::GetRate()

Ok, I finally have good data. First, I edited Encoder.cpp, here's the diff.

Code:
Index: Encoder.cpp
===================================================================
--- Encoder.cpp	(revision 2130)
+++ Encoder.cpp	(working copy)
@@ -258,7 +258,7 @@
 {
 	if (m_counter)
 	{
-		return m_counter->GetPeriod() * DecodingScaleFactor();
+		return m_counter->GetPeriod() / DecodingScaleFactor();
 	}
 	else
 	{
@@ -275,7 +275,7 @@
 			value = (double)output.Period / (double)output.Count;
 		}
 		wpi_assertCleanStatus(status);
-		return value * 1.0e-6  / (DecodingScaleFactor() * 4.0);
+		return value * 1.0e-6 / DecodingScaleFactor();
 	}
 }
 
@@ -380,7 +380,7 @@
  */
 double Encoder::GetRate()
 {
-	return m_distancePerPulse / GetPeriod() * (GetDirection() ? 1.0 : -1.0);
+	return (m_distancePerPulse / GetPeriod() * (GetDirection() ? 1.0 : -1.0)) / 2;
 }
 
 /**
The following data is in 1x and 2x mode. I didn't do a 4x test.

https://spreadsheets.google.com/ccc?...0JZe UE&hl=en

Looks perfect to me
Reply With Quote
  #29   Spotlight this post!  
Unread 04-12-2010, 03:15 AM
vamfun vamfun is offline
Mentor :Contol System Engineer
AKA: Chris
FRC #0599 (Robodox)
Team Role: Engineer
 
Join Date: Jan 2009
Rookie Year: 2003
Location: Van Nuys, California
Posts: 178
vamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of light
Send a message via AIM to vamfun
Re: Unexpected results from Encoder::GetRate()

Quote:
Originally Posted by Bigcheese View Post
The following data is in 1x and 2x mode. I didn't do a 4x test.

https://spreadsheets.google.com/ccc?...0JZe UE&hl=en

Looks perfect to me
Thanks for running a nice data set. So this is what I get from it:
1) Confirmed that the 1x is off by factor of 2.
2) Confirmed that 2x is off by same factor of 2 if corrected for inverted Decoding scale factor error. 2x rate exhibits more noise as expected.
3) We have not explained why the counter GetPeriod() is off by 2.
4)TBD for 4x. If the problem is in the counter GetPeriod() we might expect that the factor of 2 used in GetRate() will not be correct for 4x since it uses the FPGA. So this needs confirmation.

The next step is to find out where the counter period problem is. This is where the factor of 2 should be fixed rather than in the GetRate() function. In the counter.cpp
period = (double)output.Period / (double)output.Count;
So either output.Period is wrong or output.Count is defaulting to 2 instead of 1. I suspect the latter and will try to check this today.

Also still waiting for Joe or other expert to explain how B channel works to set count direction in WPI libs .
post http://www.chiefdelphi.com/forums/sh...3&postcount=24
Edit: Looking at the counter constructor for the quad encoder...seems that if
InitCounter(kExternalDirection);
is present then
SetDownSourceEdge(inverted, true);
has a special meaning. It sets direction externally with chan B rather than actually change the down count with chan B edges as the name implies. If this is the case, I really have the urge to yell at an overworked WPI programmer for this style of coding.

Mike: can you post a snippit of your notifier code and tell us how the printf data was sent to the console? We might try that tomorrow.

Last edited by vamfun : 04-12-2010 at 12:10 PM.
Reply With Quote
  #30   Spotlight this post!  
Unread 04-12-2010, 08:14 PM
vamfun vamfun is offline
Mentor :Contol System Engineer
AKA: Chris
FRC #0599 (Robodox)
Team Role: Engineer
 
Join Date: Jan 2009
Rookie Year: 2003
Location: Van Nuys, California
Posts: 178
vamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of lightvamfun is a glorious beacon of light
Send a message via AIM to vamfun
Re: Unexpected results from Encoder::GetRate()

Quote:
Originally Posted by vamfun View Post
Thanks for running a nice data set. So this is what
The next step is to find out where the counter period problem is. This is where the factor of 2 should be fixed rather than in the GetRate() function. In the counter.cpp
period = (double)output.Period / (double)output.Count;
So either output.Period is wrong or output.Count is defaulting to 2 instead of 1. I suspect the latter and will try to check this today.
Todays runs showed that output.Count = 1 as it should.... so output.Period is the remaining suspect.
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

Similar Threads
Thread Thread Starter Forum Replies Last Post
[BB] An unexpected change in plans yodameister General Forum 22 12-01-2009 08:26 PM
Inconsistent reading from encoder get rate rwood359 National Instruments LabVIEW and Data Acquisition 5 01-13-2009 06:10 PM
Results from Drexel, thanks from 365. archiver 2001 1 06-24-2002 01:44 AM
Results from GLR? archiver 2001 0 06-24-2002 01:44 AM
results from regionals archiver 2000 0 06-23-2002 09:31 PM


All times are GMT -5. The time now is 09:21 PM.

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


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