View Single Post
  #8   Spotlight this post!  
Unread 13-03-2008, 10:56
Ken Streeter's Avatar
Ken Streeter Ken Streeter is offline
Let the MAYHEM begin!
FRC #1519 (Mechanical Mayhem)
Team Role: Engineer
 
Join Date: Feb 2005
Rookie Year: 2005
Location: Team: Milford, NH; Me: Bedford, NH
Posts: 471
Ken Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond repute
Re: Autonomous / Hybrid - Tethered versus Radio?

Shue,

At our regional, we had been encountering similar problems in autonomous mode with the robot not behaving as expected. We had a very difficult time debugging the problem. The fundamental difficulty we had in identifying the problem was that our assumptions about where the problem was occurring were fundamentally wrong, so we were looking in the wrong place(s) for the problem, which made it very hard to find! Taking a step back and asking others on CD for advice is a great approach to get a fresh perspective. Hopefully one of the myriad of replies you get here will help you identify the real problem. I would caution you to consider all the suggestions, even if you "already tried" one of them -- on our team quick conclusions arrived at while debugging "under the gun" during the little time in between matches are sometimes incorrect due to being based upon incorrect data.

I think that the key issue is that you need to determine what the robot is doing when it goes astray. It sounds like the three most likely candidates are either (1) that the robot is trying to drive straight, guided by the gyro, but has an incorrect bias due to a problem with the bias calculation not being invoked as expected due to differences in the disabled -> autonomous transition sequence between your practice field testing and the real field, or (2) that the robot is trying to drive straight, but has suddenly started receiving incorrect sensor data causing it think that one wheel has suddenly stopped turning and that it then remedies the situation by turning sharply in the other direction, or (3) that the robot thinks it has finished driving straight and is prematurely performing the left turn planned for at the other end of the field. Determining which of these is actually occurring (or if even a fourth event is taking place) should be a priority.

We grappled with the same issue (identifying what the robot is trying to do without telemetry information) at our regional this year. We ended up locating the problem by testing in the pits (our problem turned out to be a flaky sensor) when we could use "printf()" output to our laptop to identify what the robot was trying to do at the time the problem occurred. However, in a real match, you don't have the luxury of live "printf()" output from the controller.

Having learned a few things since our regional, though, I can now suggest to you two ways to be able to get "printf()" output during operation on the real field:

1 - Use a "serial port logging device" on the robot to record serial port information. Phil Malone of Team 1629 wrote a white paper on doing this using the SparkFun Logomatic Serial Datalogger. His white paper explaining how to use this product is published as a PDF file on the SparkFun site. We have since ordered one of these from SparkFun but haven't yet received it to play with it. This device has the advantage of being fully FIRST legal for competition rounds.

2 - If you have a practice round (this wouldn't be legal for a real round) and you don't have time to order and receive the above datalogger, we learned of another approach to getting "live data" from Team 1307 who used a similar approach when testing their autonomous modes... You can strap a laptop to the robot, and have it connected to the programming port of the controller. I'd suggest using Hyperterminal (or your favorite terminal emulation program) to log all the output data to a file. By adding a lot of "debugging output" to your autonomous program, this will enable you to determine exactly what the controller thinks it is doing (and what sensor input it is seeing) when the problem occurs during the actual practice match. If you try this, make sure that the laptop is extremely well attached to the robot, and preferably in a highly protected spot, as you really don't want it to come loose during the match or have another robot's arm stuck through it!

Now that I've spoken my piece on trying to figure out what the robot is actually doing when the problem occurs, I'll add a few specific suggestions on some of the possibilities that you and others have mentioned.

Quote:
Originally Posted by Shue View Post
We do use the gyro during teleop mode (and hence do process the gyro data in the teleop_spin), and it seems to be working ok there. The bias calculation (we are using Kevin's default code) occurs during the disable-mode handling. One of our experiments was to assure we weren't losing the bias value by calculating it just before a match and hard-coding it in the gyro initialization. Not a perfect solution, but it showed that the bias value calc (or lack of it) wasn't causing the bad robot behavior...
When you made this fix are you sure that you completely turned off the bias calculation code so that if and when the bias calculation code did run, it didn't simply overwrite the hardcoded initial value? (I know that sounds like a stupid error, but I made that exact mistake during the build season when trying to debug the gyro bias calculation...) A possible way to see what would happen if the gyro bias is not calculated would be to turn off the calculation of the gyro bias and then run (on the practice field) the resulting code. When we do this with our robot (i.e. simulating a failed gyro bias calculation), we get a hard turn to one side (I forget which) when trying to drive straight, as the program thinks the robot is spinning quickly due to the gyro bias being radically incorrect.

Quote:
Originally Posted by Shue View Post
As for distance calculations, as I mentioned, we use geartooth sensors on both our wheels. Our autonomous is implemented as a state-machine that runs discrete functions used to "play the game". These are things like "go straight", "turn 90 right", "turn 90 left", "delay X seconds", "raise lift", etc.
This sounds like exactly how our autonomous software works, except that we used absolute magnetic encoders on our driven axles, rather than geartooth sensors. We ended up having multiple contributory causes to our problem. One of the root causes was that we were sometimes getting flaky values from one of our magnetic encoders. The symptoms we would see were that the robot would drive beautifully for a somewhat random distance, and then turn sharply to the right. This ended up being because the left encoder would stop reporting new values, which led to the program thinking that the robot was turning sharply to the left, which resulted in an immediate decrease in right motor power, which caused a sharp turn to the right. Thus, even though our robot was trying to "drive straight," the bad encoder input caused the robot to turn sharply to the right since the incorrect sensor information led to the (incorrect) conclusion that the robot needed to compensate for stoppage of the left wheel.

The other likely scenario is that the robot thinks it has completed traveling the desired distance to make the left turn. You mentioned that the turn works correctly on a practice field, but is that with the robot driving the entire 40 feet and making a left turn, or a shorter "test distance?" The reason I ask is that depending upon the resolution of your encoders, the precision of the variables you are using, and the order of operations in your assignments, you may be seeing overflow on your "40 feet" distance. This problem could manifest itself as the code thinking it only needs to go a much smaller distance to go 40 feet. We've been bitten many times by mathematical operations like the following:

Code:
#define DRIVE_STRAIGHT_DIST_IN FEET 40
#define TICKS_PER_FOOT 12

int dist_to_travel;

dist_to_travel = DRIVE_STRAIGHT_DIST_IN_FEET * TICKS_PER_FOOT;
At first glance, and with most compilers, the above looks perfectly fine. dist_to_travel is a 16-bit signed integer, and 40*12 = 480 which fits very easily into a 16-bit signed integer. However, the microchip compiler, when generating the code for the above, looks at the 40 and 12 and notes that they both fit nicely into 8-bit math, and thus performs the calculation of 40 * 12 in 8-bits, which overflows and gives a very unexpected value. However, if you were to test this code by setting DRIVE_STRAIGHT_DIST_IN_FEET to 6 feet in order to have enough room to test the code out in the practice area, you would have 6 * 12 = 72, which fits nicely in 8-bit math and will work perfectly. Only when trying to drive the full 40 feet does the problem occur, resulting in mayhem during the real round, even though everything worked great on the practice field!

The above, which looks a lot like a bug for those (like myself) accustomed to ANSI-standard C compilers, is actually a documented feature of the microchip compiler:

Quote:
2.7 ISO DIVERGENCES
2.7.1 Integer Promotions
ISO mandates that all arithmetic be performed at int precision or greater. By default, MPLAB C18 will perform arithmetic at the size of the largest operand, even if both operands are smaller than an int. The ISO mandated behavior can be instated via the -Oi command-line option.
For example:
Code:
unsigned char a, b;
unsigned i;
a = b = 0x80;
i = a + b; /* ISO requires that i == 0x100, but in C18 i == 0 */
Note that this divergence also applies to constant literals. The chosen type for constant literals is the first one from the appropriate group that can represent the value of the constant without overflow.

For example:
Code:
#define A 0x10 /* A will be considered a char unless -Oi
specified */
#define B 0x10 /* B will be considered a char unless -Oi
specified */
#define C (A) * (B)
unsigned i;
i = C; /* ISO requires that i == 0x100, but in C18 i == 0 */
Hopefully at least one of these suggestions will pan out for you!
__________________
Ken Streeter - Team 1519 - Mechanical Mayhem (Milford Area Youth Homeschoolers Enriching Minds)
2015 NE District Winners with 195 & 2067, 125 & 1786, 230 & 4908, and 95 & 1307
2013 World Finalists & Archimedes Division Winners with 33 & 469
2013 & 2012 North Carolina Regional Winners with teams 435 & 4828 and 1311 & 2642
2011, 2010, 2006 Granite State Regional Winners with teams 175 & 176, 1073 & 1058, and 1276 & 133
Team 1519 Video Gallery - including Chairman's Video, and the infamous "Speed Racer!"