We thought to experiment with the Modern Robotics Gyro and we are seeing a huge lag in readings, pretty consistently in the 200 to 260 mSec range. Has anyone else ever seen this and is there a known cause or simple mistake we should avoid making?
We wrote a simple test loop to isolate the problem, as shown in the code below. When viewing the log output on the Android monitor screen, you'll see the timetamps for each log each time through the loop. You'll see several loop iterations and then the heading value will take a big jump, after not given any of the readings in between
The problem occurs whether or not the code with the motors and range sensor is used. Those were added for convenience and a source of double checking. The Thread.sleep was put in to keep log output down. The problem happens with or without it. The opmode.idle() call was added in hopes that it would help. It didn't. When adding the range sensor, we see the range sensor values changing every ~50 mSec, which seems okay. A not unreasonable 20 Hz rate. The extra timer was added to make sure we weren't being fooled by the logging timer somehow.
Gyro documentation says it updates the raw values at 750 Hz, but doesn't say how fast it updates the integrated Z values. Assumption was every time the data changes, but certainly faster than 4 Hz, which is unusable.
Further information. We tested this app with our robot and with a new hardware setup with new sensor, new DIM, new PDM, new cables. The gyro works as expected in this setup. We then moved the gyro, DIM and cable to the PDM on our robot. It doesn't work. It works exactly the same as it does with the sensor, DIM and cable already on the robot. The only difference is the configuration file is configured for 4 motor controllers and 2 servo controllers and some additional sensors, all of which seem to work perfectly fine to run our robot.
All modules in the system have been upgraded by MR
We are using SDK version 2.2
@Autonomous(name="VerifyGyro",group="VV")
public class VerifyMRGyroLag extends LinearOpMode{
public ModernRoboticsI2cGyro gyro;
public ModernRoboticsI2cRangeSensor rangeSensor;
private DcMotor motorRightFront;
private DcMotor motorRightBack;
private DcMotor motorLeftFront;
private DcMotor motorLeftBack;
@Override
public void runOpMode() throws InterruptedException {
motorRightFront = hardwareMap.dcMotor.get("FrontRightMotor");
motorRightBack = hardwareMap.dcMotor.get("BackRightMotor");
motorLeftFront = hardwareMap.dcMotor.get("FrontLeftMotor");
motorLeftBack = hardwareMap.dcMotor.get("BackLeftMotor");
//REVERSE the RIGHT drive motors for Autonomous
motorLeftFront.setDirection(DcMotor.Direction.FORW ARD);
motorLeftBack.setDirection(DcMotor.Direction.FORWA RD);
motorRightFront.setDirection(DcMotor.Direction.REV ERSE);
motorRightBack.setDirection(DcMotor.Direction.REVE RSE);
motorRightFront.setMode(DcMotor.RunMode.RUN_WITHOU T_ENCODER);
motorRightBack.setMode(DcMotor.RunMode.RUN_WITHOUT _ENCODER);
motorLeftFront.setMode(DcMotor.RunMode.RUN_WITHOUT _ENCODER);
motorLeftBack.setMode(DcMotor.RunMode.RUN_WITHOUT_ ENCODER);
gyro = (ModernRoboticsI2cGyro)hardwareMap.gyroSensor.get( "gyro");
// get the range sensor
rangeSensor = hardwareMap.get(ModernRoboticsI2cRangeSensor.class , "BeaconDistanceSensor");
// calibrate the gyro
gyro.calibrate();
// make sure the gyro is calibrated.
while (gyro.isCalibrating()) {
Thread.sleep(50);
idle();
}
waitForStart();
// start the Timer
ElapsedTime timer = new ElapsedTime();
setMotors(-0.6,-0.6,0.6,0.6);
while(opModeIsActive()){
RobotLog.a("T: " + timer.time() +" Gyro" + gyro.getHeading());
RobotLog.a("T: " + timer.time() +" Range" + rangeSensor.getDistance(DistanceUnit.INCH));
Thread.sleep(10);
idle();
}
setMotors(0.0,0.0,0.0,0.0);
}
void setMotors(double lf, double lb, double rf, double rb){
motorRightFront.setPower(rf);
motorRightBack.setPower(rb);
motorLeftFront.setPower(lf);
motorLeftBack.setPower(lb);
}
}
We wrote a simple test loop to isolate the problem, as shown in the code below. When viewing the log output on the Android monitor screen, you'll see the timetamps for each log each time through the loop. You'll see several loop iterations and then the heading value will take a big jump, after not given any of the readings in between
The problem occurs whether or not the code with the motors and range sensor is used. Those were added for convenience and a source of double checking. The Thread.sleep was put in to keep log output down. The problem happens with or without it. The opmode.idle() call was added in hopes that it would help. It didn't. When adding the range sensor, we see the range sensor values changing every ~50 mSec, which seems okay. A not unreasonable 20 Hz rate. The extra timer was added to make sure we weren't being fooled by the logging timer somehow.
Gyro documentation says it updates the raw values at 750 Hz, but doesn't say how fast it updates the integrated Z values. Assumption was every time the data changes, but certainly faster than 4 Hz, which is unusable.
Further information. We tested this app with our robot and with a new hardware setup with new sensor, new DIM, new PDM, new cables. The gyro works as expected in this setup. We then moved the gyro, DIM and cable to the PDM on our robot. It doesn't work. It works exactly the same as it does with the sensor, DIM and cable already on the robot. The only difference is the configuration file is configured for 4 motor controllers and 2 servo controllers and some additional sensors, all of which seem to work perfectly fine to run our robot.
All modules in the system have been upgraded by MR
We are using SDK version 2.2
@Autonomous(name="VerifyGyro",group="VV")
public class VerifyMRGyroLag extends LinearOpMode{
public ModernRoboticsI2cGyro gyro;
public ModernRoboticsI2cRangeSensor rangeSensor;
private DcMotor motorRightFront;
private DcMotor motorRightBack;
private DcMotor motorLeftFront;
private DcMotor motorLeftBack;
@Override
public void runOpMode() throws InterruptedException {
motorRightFront = hardwareMap.dcMotor.get("FrontRightMotor");
motorRightBack = hardwareMap.dcMotor.get("BackRightMotor");
motorLeftFront = hardwareMap.dcMotor.get("FrontLeftMotor");
motorLeftBack = hardwareMap.dcMotor.get("BackLeftMotor");
//REVERSE the RIGHT drive motors for Autonomous
motorLeftFront.setDirection(DcMotor.Direction.FORW ARD);
motorLeftBack.setDirection(DcMotor.Direction.FORWA RD);
motorRightFront.setDirection(DcMotor.Direction.REV ERSE);
motorRightBack.setDirection(DcMotor.Direction.REVE RSE);
motorRightFront.setMode(DcMotor.RunMode.RUN_WITHOU T_ENCODER);
motorRightBack.setMode(DcMotor.RunMode.RUN_WITHOUT _ENCODER);
motorLeftFront.setMode(DcMotor.RunMode.RUN_WITHOUT _ENCODER);
motorLeftBack.setMode(DcMotor.RunMode.RUN_WITHOUT_ ENCODER);
gyro = (ModernRoboticsI2cGyro)hardwareMap.gyroSensor.get( "gyro");
// get the range sensor
rangeSensor = hardwareMap.get(ModernRoboticsI2cRangeSensor.class , "BeaconDistanceSensor");
// calibrate the gyro
gyro.calibrate();
// make sure the gyro is calibrated.
while (gyro.isCalibrating()) {
Thread.sleep(50);
idle();
}
waitForStart();
// start the Timer
ElapsedTime timer = new ElapsedTime();
setMotors(-0.6,-0.6,0.6,0.6);
while(opModeIsActive()){
RobotLog.a("T: " + timer.time() +" Gyro" + gyro.getHeading());
RobotLog.a("T: " + timer.time() +" Range" + rangeSensor.getDistance(DistanceUnit.INCH));
Thread.sleep(10);
idle();
}
setMotors(0.0,0.0,0.0,0.0);
}
void setMotors(double lf, double lb, double rf, double rb){
motorRightFront.setPower(rf);
motorRightBack.setPower(rb);
motorLeftFront.setPower(lf);
motorLeftBack.setPower(lb);
}
}
Comment