Announcement

Collapse

Technology Forum Has Moved!

The FIRST Tech Challenge Technology forum has moved to a new location! Please take a look at our forum blog for links and instructions on how to access the new forum.

The official blog of the FIRST Tech Challenge - a STEM robotics programs for students grades 7-12.


Note that volunteers (except for FTA/WTA/CSA will still access their role specific forum through this site. The blog also outlines how to access the volunteer forums.
See more
See less

App Crash at end of 30 seconds

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • App Crash at end of 30 seconds

    We are seeing a situation where the robot application crashes at the end of autonomous. We haven't been able to pin down why yet, but we are wondering if anyone out in FTC land has seen this issue and solved it?

    1) We are using a linear op mode
    2) Often, the op mode hasn't completed yet. We are still moving some robot component and waiting for it to complete
    3) We captured a video of it happening at the last tournament. It was clear enough to see an error dialog pop up and not clear enough to see what it said. And the drivers cleared it before we got a chance to take note.

    We hoping it is just some 'duh' thing we are doing since we haven't heard about anyone else having this problem.

    Any ideas?

  • #2
    We've experienced crashes when stopping linearOp mode apps while they are in a while loop. First noticed with utility programs to continuously read sensors (derived from the auto linearOpmode code). But at our last tournament, when when the bot got stuck on top of blocks, it continued to run looking for lines. It also crashed the robot when pressing stop and needed the field folks to restart the phone. On the long list of things to chase down, but low priority.

    Comment


    • #3
      This does sound like the same thing. Unfortunately for us, they wouldn't restart the robot during the match, so we sat dead the full teleop. I think this happened to us at a previous tournament, too, but at that one, they re-started the app on the phone during the match.

      So, anybody out there know of the root cause for the crash while in a while loop or how to work around it?

      Comment


      • #4
        Can you post your code for that autonomous LinearOpMode?

        Comment


        • #5
          Are you using the 30 second timer and does the crash happen at exactly the 30 second mark?

          Comment


          • #6
            The 30 second timer was enabled when the crash occurred. We are using a gyro sensor and encoders in autonomous so the length of execution time for a particular program is not constant. The crash usually occur during the end of autonomous. The robot is still moving or is nearing the end of its autonomous run at this time. The log sometime indicated that an emergency stop was invoked when the crash occurred.

            Comment


            • #7
              I'm not a fan of LinearOpMode but it seems to me that things may be working as intended, even if it is a bit harsh. The robot really needs to stop moving at the end of the 30 second autonomous period - otherwise you may get penalized - and the 30 second timer needs a way of killing the LinearOpMode even if it's in the middle of doing something. Let's say at 29 seconds you set power to motors and then sleep for 3 seconds. The robot controller app is going to need to somehow terminate the opmode thread. If your OpMode has a tight while (opModeIsActive()) loop at least it would have a chance of exiting cleanly.

              Comment


              • #8
                Originally posted by Cheer4FTC View Post
                Can you post your code for that autonomous LinearOpMode?
                here's a bare minimum which still exhibits the crash. Phones on beta 1.6, but I think this was present in previous versions.

                I agree at 30seconds the robot should stop, that's not the issue. The problem is that the Robot Controller app crashes. Either if the stop button is pressed, or if the 30 second timer runs out. Teams at that point cannot touch the robot, and if they don't notice (or the fta's won't restart the phones or app - which I don't think is correct) the robot will not function for teleop.

                Can someone else try this on their phones? We added a 60 second timer as a compromise to our sensor tester - it was better to wait and let it exit gracefully than have to do the 35 second MR meditation every time...

                So you could do the same and add your own 29 second timer for your autonomous if you're still competing where FTA's will be unwilling to restart your app.




                Code:
                package com.ftc8045;
                
                import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
                
                import com.qualcomm.robotcore.util.ElapsedTime;
                
                public class Looptest extends LinearOpMode {
                
                    public ElapsedTime Etime = new ElapsedTime();
                
                    @Override
                    public void runOpMode() throws InterruptedException {
                
                        waitForStart();
                
                        int i = 0;
                
                        Etime.reset();
                        while (Etime.time() < 60 ) {
                            i += 1;
                
                            telemetry.addData("1 I : ", i);
                        }
                    }
                }

                Comment


                • #9
                  Does it make any difference if you add a waitOneFullHardwareCycle() inside the loop? waitOneFullHardwareCycle() will throw an InterruptedException if needed. Your runOpMode() properly claims that it might throw that exception but as far as I can see only waitForStart() might actually throw the exception.

                  Comment


                  • #10
                    yes, that does cure it.


                    eye opening to see just how slow the counts of cycles are compared to just executing code...

                    So - Sensor readings will only be updated at the end of each cycle - is that correct?


                    Linear Op Mode arguments aside, This seems like a problem that is likely to haunt many teams - Isn't it reasonable that the FTC SDK take care of this by default?

                    Comment


                    • #11
                      Originally posted by korimako View Post

                      Code:
                      public class Looptest extends LinearOpMode {
                      
                          public ElapsedTime Etime = new ElapsedTime();
                      
                          @Override
                          public void runOpMode() throws InterruptedException {
                      
                              waitForStart();
                      
                              int i = 0;
                      
                              Etime.reset();
                              while (Etime.time() < 60 ) {
                                  i += 1;
                      
                                  telemetry.addData("1 I : ", i);
                              }
                          }
                      }
                      The above code is missing an important check for a request for an OpMode to stop. It would be better written as:

                      Code:
                      public class Looptest extends LinearOpMode {
                      
                          public ElapsedTime Etime = new ElapsedTime();
                      
                          @Override
                          public void runOpMode() throws InterruptedException {
                      
                              waitForStart();
                      
                              int i = 0;
                      
                              Etime.reset();
                              while (opModeIsActive() && Etime.time() < 60 ) {
                                  i += 1;
                      
                                  telemetry.addData("1 I : ", i);
                              }
                          }
                      }
                      When a stop request is received from the driver station, that request is passed on to a LinearOpMode by having opModeIsActive() return false; if you're not checking for that, your code won't exit gracefully when the driver station requests that it should.

                      If a LinearOpMode continues to ignore a stop request for a certain amount of time (I forget the exact duration), the robot controller application is forcefully terminated; that's a likely cause of the symptoms you see. This can be verified by looking at the logcat logs: a big banner is written to the log when such termination is carried out.

                      Comment


                      • #12
                        Originally posted by FTC0417 View Post
                        The above code is missing an important check for a request for an OpMode to stop. It would be better written as:

                        When a stop request is received from the driver station, that request is passed on to a LinearOpMode by having opModeIsActive() return false; if you're not checking for that, your code won't exit gracefully when the driver station requests that it should.

                        If a LinearOpMode continues to ignore a stop request for a certain amount of time (I forget the exact duration), the robot controller application is forcefully terminated; that's a likely cause of the symptoms you see. This can be verified by looking at the logcat logs: a big banner is written to the log when such termination is carried out.
                        Yes, that all looks to be the case, thanks for the explanation. So, can the parent LinearOpMode class not handle this better and kill itself instead of robot controller application?

                        Fine for those in the know to code 'properly' but I'm thinking of the many teams that will run into this... Could the entire linearopmode just be wrapped in a
                        while (opModeIsActive(){ loop or such?

                        Comment


                        • #13
                          Originally posted by korimako View Post
                          Yes, that all looks to be the case, thanks for the explanation. So, can the parent LinearOpMode class not handle this better and kill itself instead of robot controller application?

                          Fine for those in the know to code 'properly' but I'm thinking of the many teams that will run into this... Could the entire linearopmode just be wrapped in a
                          while (opModeIsActive(){ loop or such?
                          You pays your money, you takes your choice: non-linear OpModes you can think of as having the 'while' outside your code, your loop() method gets repeatedly called until the OpMode should end, at which time stop() is called (there's also an init() phase). For linear opmodes, a thread is instead started for the OpMode, and you write the loop / loops / whatever you like yourself, with the only thing to remember is that you need to periodically call opModeIsActive() and exit from runOpMode() if that returns false.

                          Unfortunately, the Java runtime is such that there's no real in-between here: there is simply no way from the outside of a given thread to cause that thread to terminate: thread's can only be asked to terminate themselves. So if the thread is effectively stuck in an infinite loop, there's no way to shut it down short of terminating the whole app.

                          Comment


                          • #14
                            Key concepts for LinearOpModes:
                            • Put an "opModeIsActive" check in every loop so that the loop will end when the opMode stops even if your other custom terminating condition never happens.
                            • Put a "waitOneFullHardwareCycle();" call inside each loop at the end right before the final "}". This way the hardware updates each time before your loop returns to the top and your code doesn't endlessly run with the same hardware settings, wasting cycles for no purpose and possibly stalling out other tasks. I believe that waitOneFullHardwareCycle() is also interruptable so the opMode will stop when it hits this call if the opMode is over.

                            If you do these things, the opModes should stop fine. Unfortunately, these things weren't required in RobotC so folks used to RobotC may be missing these items.

                            Comment


                            • #15
                              Originally posted by Cheer4FTC View Post
                              Key concepts for LinearOpModes:
                              • Put an "opModeIsActive" check in every loop so that the loop will end when the opMode stops even if your other custom terminating condition never happens.
                              • Put a "waitOneFullHardwareCycle();" call inside each loop at the end right before the final "}". This way the hardware updates each time before your loop returns to the top and your code doesn't endlessly run with the same hardware settings, wasting cycles for no purpose and possibly stalling out other tasks. I believe that waitOneFullHardwareCycle() is also interruptable so the opMode will stop when it hits this call if the opMode is over.

                              If you do these things, the opModes should stop fine. Unfortunately, these things weren't required in RobotC so folks used to RobotC may be missing these items.

                              This is exactly right, but you might still want to put a short-circuit in your move() and turn() methods that are called from your primary LinearOpMode. The reason for this is if you do anything in your methods other than immediately going into a
                              Code:
                              while (! opModeIsActive() && ... ) { }
                              then you might be spending "too much" time in that method before the close out of the loop. You only have 500 ms (e.g., 1/2 of a second) to terminate the LinearOpMode after the stop timer/stop button is pressed before the RobotController will kill itself to force the opMode to stop. Most LinearOpModes are coded like this:

                              Code:
                              move(blah);
                              turn(blah);
                              moveTo(blah);
                              checkGyro(blah);
                              move(blah);
                              turn(blah);
                              And if you're on step 3 when the timer expires and you don't have a short-circuit, like the first line of the turn() and move*() methods being:
                              Code:
                              if ( ! opModeIsActive() ) return;
                              then you might waste "too much" time trying to fall through all of those methods and you'll get nailed by the 500 ms timer. Having that short-circuit should ensure that regardless of where the timer expires (or the stop button is pressed) in your linear steps, you'll fall through the rest as quickly as possible and the LinearOpMode will stop and avoid the sacrificing of the entire Robot Controller application.

                              -- Gordon.

                              Comment

                              Working...
                              X