No announcement yet.

How do I resolve stuck in loop() error on robot?

  • Filter
  • Time
  • Show
Clear All
new posts

  • How do I resolve stuck in loop() error on robot?

    First time posting on my personal team account

    I am Samuel Tukua of Paulding County team 11857. This is my first year programming with FIRST software and I am on my own for code comprehension and creation. I had to create a code based off of previous years codes, examples, and online help. For this reason I do not all of the code functionalities and get somewhat lost with some of the error reports. One error that has plagued me since the beginning of the year is the "Stuck In loop()" error that I receive when running the autonomous mode. I have tried countless times to try and fix this issue but it continues to happen. I've done enough research to know that the loop() error happens due to a watchdog thread which finds unstopping loops and terminates the running opmode that generates those loops. I have attempted the following solutions to fix the problem:
    -running through the code by hand to find what would generate a loop from my current version
    -checking the directions that the robot is told to turn
    -putting an idle() at the end of every while loop
    -removing sleep(milliseconds) functions
    -checking that the robot is moving appropriately in response to all commands
    -ensuring that no threads are left without termination before the commencement of a new thread
    -changing the execution order of the code
    -removing certain methods of the opmode from the execution list and examining the outcome
    -switching to a new set of phones
    -updating the phones
    -checking that the IMU gyro works properly by using the provided sample code
    -restarting the robot many times
    -checking wire configurations
    -manually creating a new version of the opmode that came from OpMode instead of LinearOpMode
    -looking through the base code to find the requirements for the loop() error to display (nothing of the sort was actually found)
    -checking through the sample codes to ensure that I'm not missing important lines
    -asking other teams to look at our code during competitions
    -looking through the FTC forums for answers

    I am at a loss and am really needing to know what is going on that is causing this to happen. While my attempts have not successfully fixed the code, they have revealed a few things, but first some background. My autonomous mode works very simply, it initializes in one method and then runs the OpMode method. Within the OpMode method are the various "sub methods" that I created for autonomous. These "sub methods" include "Dismount()", "PlaceMarker()", and "IMUDrive()". It also includes some works in progress that are commented out for the time being. The "Dismount()" and "PlaceMarker()" methods are completely self dependent. These two methods can be run on their own without the loop() error appearing. The main issue comes with the IMUDrive() method. The IMUDrive method takes three parameters of speed, distance, and absolute angle. When the IMUDrive method is run, it calls upon another method called "Rotate()", the rotate method then turns the wheels in opposite directions corresponding to the difference between the current angle and desired angle until the REV Expansion Hub IMU senses that the robot is facing that direction. The rest of the IMUDrive method then runs and it uses the encoder wheels to RUN_TO_POSITION. While running to position, it constantly checks the current orientation and ensure that it is corrected by updating the "AdjustOrientation()" sub sub method which returns a positive or negative value that is then sent to the wheels as an increase or decrease in speed which will allow for a lagging wheel to catch up and keep the robot on a forward trajectory. So, from all of the testing I have learned that:
    1. The PlaceMarker() and Dismount() methods do not cause the error when run alone
    2. Commenting out the Rotate() method from being run at the beginning of the IMUDrive() method gets rid of the error for until the end of the method.
    3. Even with the Rotate() method commented out, the error still happens again upon the completion of the IMUDrive() method.

    This is a link to the code on my Github (AVisualExplanation), I am only using the and, and my team's robot is called Opportunity Reborn (Oppreborn for short):

    Autonomous Code:

    Hardware Map:

    This problem has haunted and followed me since the beginning of programming for the team and would be a huge and welcome help if anybody knows any way to fix it. You will earn all of my respect if you can help. If you need any more information or would like to comment on the code then message me or comment asking for it. Thank you so much for your time and consideration to read this and hopefully help me with this issue. Even if you aren't able to help, I still wish you all a great deal of luck in the up coming final set of league matches.

    P.S. As I am new to FIRST programming specific methods, my code likely contains many unnecessary lines, methods, workarounds, and so on. Comments made about this will also be greatly appreciated as well and will be very helpful to me understanding the code.
    Last edited by SamuelTukua11857; 12-15-2018, 11:31 AM.

  • #2
    SamuelTukua11857 Great job putting this code together as a first year programmer for FTC!

    It's not obvious to me what's causing your Stuck In Loop issue, but I do have a couple of thoughts:

    1. Are you using the latest version (4.3) for both the Robot Controller and Driver Station? When we first updated to 4.3 on the Robot Controller, it didn't work (but I don't remember if it was a Stuck in Loop error). Then we realized we were still on v. 4.0 of the Driver Station app. We updated to Driver Station 4.3, and problem fixed.

    2. You are using the "synchronized" keyword for almost all methods in your MyFIRSTJavaOpMode class. You would typically use "synchronized" when you are planning to call methods of the class from different threads. It's not immediately obvious to me that this would cause your problem, but you might want to try eliminating that to see if it helps. We use Linear OpModes, don't do our own multi-threading, and never declare any of our methods "synchronized".

    3. I don't believe this is the source of your Stuck in Loop problem, but I believe there is a segment of "unreachable" code in your Rotate method. The issue is (and someone please correct me if I'm wrong here):

    if (!(dsrangle-1<angles.firstAngle) && !(dsrangle+1>angles.firstAngle)) {do stuff...}

    The following is a rephrasing (logically equivalent) of your existing code:

    if ( angles.firstAngle <= dsrangle-1 && angles.firstAngle >=dsrangle+1 ) {do stuff...}

    But, it is impossible for angles.firstAngle to be BOTH less than or equal to dsrangle-1 AND greater than or equal to dsrangle+1, regardless of the values of dsrangle and angles.firstAngle. So, the stuff will never get done.

    I suspect what you intended was:

    if ( angles.firstAngle<=dsrangle-1 || angles.firstAngle>=dsrangle+1) {do stuff...}

    Hope this helps.


    • #3
      SamuelTukua11857 I agree with jkenney, this code is impressive for a first year programmer. I have noticed that you are calling idle() twice during each loop of IMUDrive(). I don't know if that would cause a problem, but it is definitely unnecessary.


      • #4
        A few suggestions...
        You can definitely simplify some of your logic in the turns. You calculate a signed adjustment angle, and then take the Abs, and then have a if/then that is based on the same things that determined the sign of the adjustment. Just calculate the adjustment, and then set rSpd = speed + adj; and lSpd = speed - adj;. You may have to take a pass to insure if L or R get the +/-. Also check you rotate logic - basically, you want to calculate turn speed while(Math.Abs(curAng - desiredAng) > THRESH).

        I like calling setSpeed once in a block per motor vs. a bunch of times in if/else blocks. So calc a speedToSet variable (which may have a value of 0), and then set once in each logic block.

        ADD LOGGING - this will be your biggest win in tracking down problems - telemetry is nice, but is gone by the time you need to really dig into it. Use a RobotLog.dd call everywhere where you have a Telemetry call (and in other spots in loops and other question spots). These will log to the robotlog.txt file that gets saved on the phone. You can then walk through the log with a fine-tooth comb and find spots that aren't acting as you would expect. Log your current angle, desired angle, calculate L and R motor speeds, L and R isBusy, etc. This may reveal clues in the log.

        You could add a while(opmodeIsActive()) {//print some status; idle();} loop at the end of your path (where you have your Telemetry path complete). Otherwise, runOpMode can exit while there is still time remaining in auton, and you don't really know where things are. Basically eat up all of the 30s in the runOpmode call. If your problem was at the end of the path, this may help.

        You could also put a time based "safety" out in the rotate and drive portions of your IMUdrive method. If you expect your longest turn to take 3s, put a timer check in your loop's while conditions of say 5s. Similar for the drive portion. That way if something is going wrong, it will bail after trying its best for some amount of time.

        You aren't updating your current heading (getting value from IMU) in your straight driving segment loop - only on entry, and in rotate. So your adjustment never has new actual angle value to work with.

        Finally - and prints may help with this... You may want to mess with OR instead of AND in your isBusy check. The API uses a fairly small threshold window on the target counts for determining is busy. If your PID isn't working well (likely the one that is in the REV motor controller), a motor may struggle to reach and stop within that threshold. It can be even more difficult for both wheels to be in that window at the same time. The left side could reach target and stop, and the right side still needs to go. This will be seen as a turn at the end of the drive segment - but the right side can actually "pull" the left side out of its threshold window. Often, when things are close to the window, but not quite at the point where both sides are in, you will here the motors humming - the PIDs are calculating powers small powers because the error is small, but sometimes the calculated power isn't actually enough to overcome friction/inertia and get the wheel moving.

        Also, make sure that the motor type selected in your config on the RC matches the motor use are using. Otherwise, you will be using PID values that aren't appropriate.


        • #5
          DaSadRhino Thank you for the compliment and the suggestion, that may not be the source of the error, but that is definitely some sloppiness that I need to remove


          • #6
            1. We are using the latest versions. Except our program had this issue at one competition where the driver station thought that the robot controller was an out of date version. This would've disqualified us if I didn't show the referee that the robot controller said it was the correct version. I'm wanting to move the code onto a new pair of phones once I'm back from Christmas break.

            2. I was going to implement a multi-threaded portion to the program that allowed for some functions to be more accurate. However, I realized this wasn't necessary because the entire op mode was likely being executed a dozen times per second and so multi-threading wasn't necessary. I just forgot to remove that and I guess I got blind to it, thank you.

            3. Thanks for that haha. I didn't exactly know a way to plot that out logically and so I ended up doing it wrong. The intended purpose is to give the angle a degree of leniency so that the robot doesn't attempt to get 3 decimal point precision. I actually just need to flip the less than and greater than symbols (on your logical equivalent) to fix it, but thank you for pointing it out. However, the loop() error has been around long before this and so I know it isn't the source of the error.

            Thank you for the compliment and the three suggestions.


            • #7
              FTC7253 I'm likely just too tired, but could you explain this in another way?
              "You can definitely simplify some of your logic in the turns. You calculate a signed adjustment angle, and then take the Abs, and then have a if/then that is based on the same things that determined the sign of the adjustment. Just calculate the adjustment, and then set rSpd = speed + adj; and lSpd = speed - adj;. You may have to take a pass to insure if L or R get the +/-. Also check you rotate logic - basically, you want to calculate turn speed while(Math.Abs(curAng - desiredAng) > THRESH).

              I like calling setSpeed once in a block per motor vs. a bunch of times in if/else blocks. So calc a speedToSet variable (which may have a value of 0), and then set once in each logic block."

              Also, THANK YOU. I didn't know that it was possible to log to the phone directly and (as you already clearly know) telemetry is no use because it just ends up disappearing in a few seconds. Could you show me the syntax and features for how to do? A reply post or direct message would both be fine.

              The problem is sadly never at the end. I never make it that far.

              I will definitely put a safety on there. The only issue is that the time taken to rotate may be greater than whatever the timer is looking out for.

              The heading not updating is probably causing some things wrong if not the loop error.

              If that's true then that would actually explain a lot of why the IMUDrive method seems to fail right around its destination, in other words, one wheels has arrived but the other hasn't so they both keep going and it causes an error to be called. Thank you.


              • #8
                You can call RobotLog.a to log to the assert log, or RobotLog.vv to log to the verbose log.


                • #9
                  In case you didn't already try removing those "synchronized" keywords: I put together a simple LinearOpMode whose only purpose is to display the count of seconds since "start" was pressed.
                  Here's the runOpMode method--

                  public synchronized void runOpMode(){
                      telemetry.addData("Press > to Start","");
                      ElapsedTime et = new ElapsedTime();
                      int n = 0;
                      while (opModeIsActive()){
                          if (et.seconds() < 1) continue;
                          telemetry.addData("Count", " %d", n);
                  With the "synchronized" keyword, there was a "Stuck in Loop" failure every time I ran it. After the "synchronized" keyword was removed, it ran with no problems.


                  • #10
                    jkenney Thank you, I am at a build day now and am about to try it with the synchronized keywords removed.

                    EDIT: THANK YOU SO MUCH! The method no longer has the stuck in loop error once I removed the synchronized method.
                    Last edited by SamuelTukua11857; 01-05-2019, 01:37 PM.