TLDR: sensors returning 0 values when they shouldn't, looking for help
Ok, I'm usually good at finding some of the subtle hardware interactions that crop up from time to time. They make good educational opportunities. Unfortunately, this one has me a bit stumped as our team has been working on improving their autonomous line follow routine.
Symptom: Using the Color sensor (properly mounted) to detect crossing the white line. Occasionally (but with too high of a frequency to ignore) their robot would miss the white line. So I had them show me their threshold values and they added code to their programs to show values during init. All looked proper. They're moving faster this year than last and the Color sensor only has an output rate of 30 Hz. Perhaps the dwell time over the line was too short. Back of the envelope showed 2 to 3 sample opportunities, but still, perhaps they were unlucky. They wrote an automated program to read the color sensor while driving back and forth across the line. Hmm, about 70% successful detection, way too low. A little digging suggested using an ODS instead as it has a sample rate of 1000 Hz and better resolution as well.
The swap was made, code updated, and alas, still a problem, and at about the same failure rate. Again thresholds checked for the new sensor. All looked good (and much better resolution compared to the Color sensor). So looking at testing code (I'm not a java programmer, but an old C hack so I can read most of it), it looks like perhaps they are in a tight fast loop while probing the sensor module. Could there be a blocking issue? Could idle() be holding too long? How many samples were they taking and how many were they seeing white on when successfully detecting the line? Add more diagnostics to the code (see below). Turns out the max latency was about 25 milliseconds with idle(). That should be fine. Average time was really fast (<1 ms) so perhaps they were flooding the CDI with requests and nothing was getting updated? Had them insert a sleep(5). Now average loops was just over 5ms, max latency still less than 30 ms. Yet we were still getting crossings where no line was seen, but on crossings where it was seen, it would take about 200-400ms between first and last white sighting, with perhaps 20-40 "white" counts (numbers from memory). Ok, so the sensor was seeing "white", and frequently enough even with sleep(5) on a majority of the crossings (sensor was 0.15 mat, 0.99 white, detection set at 0.3). Had them run it over the plain mat and it reported no white hits at all, so it seems to be working well on that case.
I'm at a loss. Does anyone know the how fast the CDI can respond to requests? We For that matter, what about the entire USB bus? Consider a drive loop where the users are grabbing gyro, reading sensors & encoders, adjusting power, etc while driving, and putting it in a tight loop. Add in telemetry and this seems like a potential traffic jam. Or is the bandwidth plenty high?
Below is the fragment of test code that might prove useful if I've missed anything. We also swapped the USB cable just in case we were getting disconnects but no improvement. The only thing we didn't swap was the CDI itself.
Ok, I'm usually good at finding some of the subtle hardware interactions that crop up from time to time. They make good educational opportunities. Unfortunately, this one has me a bit stumped as our team has been working on improving their autonomous line follow routine.

Symptom: Using the Color sensor (properly mounted) to detect crossing the white line. Occasionally (but with too high of a frequency to ignore) their robot would miss the white line. So I had them show me their threshold values and they added code to their programs to show values during init. All looked proper. They're moving faster this year than last and the Color sensor only has an output rate of 30 Hz. Perhaps the dwell time over the line was too short. Back of the envelope showed 2 to 3 sample opportunities, but still, perhaps they were unlucky. They wrote an automated program to read the color sensor while driving back and forth across the line. Hmm, about 70% successful detection, way too low. A little digging suggested using an ODS instead as it has a sample rate of 1000 Hz and better resolution as well.
The swap was made, code updated, and alas, still a problem, and at about the same failure rate. Again thresholds checked for the new sensor. All looked good (and much better resolution compared to the Color sensor). So looking at testing code (I'm not a java programmer, but an old C hack so I can read most of it), it looks like perhaps they are in a tight fast loop while probing the sensor module. Could there be a blocking issue? Could idle() be holding too long? How many samples were they taking and how many were they seeing white on when successfully detecting the line? Add more diagnostics to the code (see below). Turns out the max latency was about 25 milliseconds with idle(). That should be fine. Average time was really fast (<1 ms) so perhaps they were flooding the CDI with requests and nothing was getting updated? Had them insert a sleep(5). Now average loops was just over 5ms, max latency still less than 30 ms. Yet we were still getting crossings where no line was seen, but on crossings where it was seen, it would take about 200-400ms between first and last white sighting, with perhaps 20-40 "white" counts (numbers from memory). Ok, so the sensor was seeing "white", and frequently enough even with sleep(5) on a majority of the crossings (sensor was 0.15 mat, 0.99 white, detection set at 0.3). Had them run it over the plain mat and it reported no white hits at all, so it seems to be working well on that case.
I'm at a loss. Does anyone know the how fast the CDI can respond to requests? We For that matter, what about the entire USB bus? Consider a drive loop where the users are grabbing gyro, reading sensors & encoders, adjusting power, etc while driving, and putting it in a tight loop. Add in telemetry and this seems like a potential traffic jam. Or is the bandwidth plenty high?
Below is the fragment of test code that might prove useful if I've missed anything. We also swapped the USB cable just in case we were getting disconnects but no improvement. The only thing we didn't swap was the CDI itself.
Code:
private void moveByInches(double inches, double drivingPower) throws InterruptedException{ // moves 26.5 in one rotation telemetry(); int counts = motorRight1.getCurrentPosition(); double sign = Math.round(inches/Math.abs(inches)); powerMotors(sign*drivingPower, sign*drivingPower); int counter = 0; int iters = 0; long ms = System.currentTimeMillis(); long cms; long maxdiff = 0; long sumdiff = 0; long firsttime = -1; long endtime = -1; while (opModeIsActive() && Math.abs(motorRight1.getCurrentPosition() - counts) < Math.abs(ENCODER_COUNTS_PER_ROTATION*inches/26.5)){ idle(); sleep(5); // to delay between readings in hopes of not flooding CDI with requests cms = System.currentTimeMillis(); if (opticalSensor.getLightDetected() > 0.3){ // ODS is 0.15 on mat, 0.99 on white line counter++; if (firsttime == -1){ firsttime = System.currentTimeMillis(); } }else{ if (firsttime != -1){ endtime = System.currentTimeMillis(); } } sumdiff += cms - ms; if (cms - ms > maxdiff) maxdiff = cms - ms; ms = cms; iters++; } telemetry.addData("WhiteTime: ", endtime - firsttime); telemetry.addData("Maxdiff: ", maxdiff); telemetry.addData("Avgdiff: ", (double)sumdiff / (iters)); telemetry.addData("Counter: ", counter); telemetry.addData("Iterations: ", iters); telemetry.update(); powerMotors(0,0); }
Comment