Announcement

Collapse
No announcement yet.

Hardware Thread Safety

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

  • Hardware Thread Safety

    Is any thread protection mechanisms in place for accessing the robot hardware? Or should lock mechanisms be employed if different threads are going to issue command and/or read the status of the hardware?

  • #2
    Though not exactly an answer to your question, here's a link to a discussion on the forum about multithreading (and single-thread alternatives) from three years ago:

    https://ftcforum.usfirst.org/forum/f...multithreading

    It would be great to have an up-to-date statement about this topic from someone involved in the development of the SDK.

    Comment


    • #3
      The Lynx part of the SDK (i.e. the portions related to the REV Hub) are completely thread-safe and are protected by synchronized blocks and a low-level ReentrantLock for controlling access to the USB bus. This means that not only is it guaranteed that only one thread can have a command in flight to a particular REV Hub at any one point in time, but also that only one thread can be talking to ANY REV Hub at any one point in time. This is done because the RS-485 bus does not have any collision prevention. Any messages on the bus would be garbled if two modules were trying to talk at the same time. So thus the host is responsible for ensuring this doesn't happen. Additionally, for I2C read/write requests which actually take more than one command to accomplish, there is a lock in place to ensure that I2C commands are properly synchronized such that, say, an I2C write command cannot be issued while the response to a previous I2C read command is being awaited.

      HOWEVER - it is NOT more efficient to have, say, one thread talking to each REV Hub, because the two threads will be fighting for bus time (Or, even worse, one thread could starve the other). Not only that, but also if you start another thread in your OpMode, YOU are responsible for stopping that other thread. If you forget to stop it, it will keep running in the background, introducing possibly very unhappy consequences. Worse, while if your main OpMode thread crashes, you can simply recover by restarting robot, if your secondary thread crashes, the entire Robot Controller application will crash irrecoverably - not something you want to have happen during competition.

      I personally would recommend you look into cooperative multitasking with state machines. This allows you to run multiple things "simultaneously" while avoiding the gotchas of using a separate thread.

      Comment


      • #4
        I second 4634 Programmer's recommendation to look at using state machines rather than spawning additional threads in your op mode. I think this is a more efficient approach, and this technique can be applied to other controllers (arduino's, Pi's, etc.).

        Comment


        • #5
          Actually, I like that idea much better. Any chance someone could point me to some example code?


          My team is just starting out and they are working through programming the bod to move through a small series of movements. Forward, turn, forward. They are making use of RUN_TO_POSITON, but using if statements in the loop is already looking like the road to hades. (And using a while to monitor for the next command flopped.)


          As a C# developer I started thinking this through as to a direction to nudge the team and two thoughts came to mind. My first through was to place the commands into a list or queue and execute them in order. That was quickly followed by the thought that some of my coworkers would find such confusion.


          Then came to mind that if these could be made to be blocking they could be executed one after another from something equivalent to our BackgroundWorker or a Timer. But

          Comment


          • #6
            Originally posted by ftcsachse0 View Post
            Actually, I like that idea much better. Any chance someone could point me to some example code?
            Here are some nice intro videos:
            https://www.youtube.com/watch?v=Pu7PMN5NGkQ
            https://www.youtube.com/watch?v=-J_m-FdO45c
            https://www.youtube.com/watch?v=cPgJ8bbBj_o


            Comment


            • #7
              So basically the idea is that you want to keep your main loop (which calls all your state machine) spinning as fast as possible, so that each state machine can be run as often as possible. If a state machine needs to wait for a condition or a certain amount of time to elapse, then it needs to do so in a non-blocking way.

              Here's a snippet from my asynchronous auto-transfer code for the intake on my robot last year that shows both waiting for a condition and for an amount of time before switching to the next state:

              Screenshot from 2019-09-07 08-32-20.png
              Attached Files

              Comment


              • #8
                Originally posted by ftcsachse0 View Post
                Actually, I like that idea much better. Any chance someone could point me to some example code?

                My team is just starting out and they are working through programming the bod to move through a small series of movements. Forward, turn, forward. They are making use of RUN_TO_POSITON, but using if statements in the loop is already looking like the road to hades. (And using a while to monitor for the next command flopped.)
                I like state machines etc, but if you are looking for a simple approach, you can switch to using LinearOpMode, rather than OpMode, and then you don't have to worry about all the looping in Autonomous. LinearOpMode is created as it's own thread which is run as one sequential (linear) program that does any number of steps in sequence using simple Sleep() commands or while loops to regulate the progression of the opmode.

                We used OpMODE and state machines exclusively in 2015 before the LinearOpMode was proven. But from 2016 we have used LinearOpMode for both Teleop and Auto exclusively.
                The great thing about LinearOpMode is you can intermingle linear and looping behavior just by adding while loops where you want them.

                Check out the "PushbotAutoDriveByEncoder_Linear" sample in the external samples folder for a way to build an auto from sequential moves..
                Likewise "PushbotAutoDriveByTime_Linear" for an even simpler example

                And don't think that it's only useful for simple Autos.... We've had menu driven path planning autos for the last couple of years, and LinearOpMode is still the way to go.

                Comment


                • #9
                  To make sure I am getting this correct, a team could block the loop while the motor moved to its next position? (I realize that you have to fit within the 30 second window.)

                  Though after seeing the reveal, I am thinking that spending time moving based on images would be way more useful.

                  Comment


                  • #10
                    I can second the recommendation to use LinearOpMode for autonomous (and teleop too). That's what my team has done for the last couple of years. It has been WAY easier to explain to the students than to teach them about state machines and making darn sure there is never anything blocking.

                    This past year they even implemented some state machines to allow multiple things to be going on simultaneously and used cooperative multi-tasking (i.e. calling a checkStuff() method periodically in a loop) rather than go with opMode. Me looking at it as an SW engineer thinks that this latest iteration may have been better using OpMode - but they were able to understand what they wanted, create it, debug and maintain it. So whom am I to argue.

                    This is coming from an embedded software engineer who has used state machines for everything for decades - so I love them - I just see the LinearOpMode as a way easier way for the beginning programmers to get to their robots working well.

                    Comment


                    • #11
                      We like LinearOpMode, too, especially for autonomous. We can do some multi-tasking using neither a separate thread nor a state machine.

                      Our typical autonomous op mode is a series of calls to navigation methods, such as driveDirectionGyro(...). Most of those methods have (among other things) a parameter of type Predicate (our version of Predicate has a single method, "isTrue()"). We create the Predicate object using an anonymous local class created when the navigation method is called. The isTrue() method of the Predicate object gets called during each iteration of the control loop in the navigation method; when the isTrue() method returns true, that causes the navigation method to exit. That provides a lot of flexibility as any desired "stop condition" can be provided to one navigation method.

                      This approach allows for simple multitasking, as well. For example, code to control the robot's arm can be placed in the isTrue() method of the Predicate object. That code will run during each iteration of the internal while-loop of the navigation method. That way, we don't need a separate thread to control the arm while navigating.

                      Comment


                      • #12
                        I think we can all agree that to continue on the robotics career path, and the programming career path in general, it is essential to be proficient in state machine programming. I can't think of a better way for kids to learn state machine programming than using iterative OpMode.

                        You don't need very many states to do meaningful autonomous state machine programming with iterative OpMode. Once you get the hang of a small state machine, you will be able to advance very quickly to larger machines.

                        The main issue I have with the linear pattern is that it might mislead kids into thinking they can get away with not having to learn the state pattern. Another issue is that once kids become proficient in designing in the linear pattern, they often have great difficulties transitioning to the state pattern for a variety of reasons.

                        IF the linear pattern is easier to learn for someone just learning how to program, I highly recommend switching to the state pattern as soon as possible. The pre-season is FOUR months long. Use this time to convert last season's autonomous to iterative OpMode. The "easier" path is not in the best interests of aspiring programmers and roboticists in my opinion.

                        Comment


                        • #13
                          Originally posted by Alec View Post
                          I think we can all agree that to continue on the robotics career path, and the programming career path in general, it is essential to be proficient in state machine programming. I can't think of a better way for kids to learn state machine programming than using iterative OpMode.

                          IF the linear pattern is easier to learn for someone just learning how to program, I highly recommend switching to the state pattern as soon as possible. The pre-season is FOUR months long. Use this time to convert last season's autonomous to iterative OpMode. The "easier" path is not in the best interests of aspiring programmers and roboticists in my opinion.
                          I still stand by my assertion that LinearOpMode is good, because it allows you to choose where you want to implement a state machine, and were you don't.

                          eg: In Relic Recovery, we used LinearOpMode to allow us to write each possible autonomous sequence as a series of motion segments (move methods) called one after each other to form a path. The code for this was very straightforward since each line of code was one segment of the path. This made path development and student understanding quite simple. Using a state machine would have required constant state and transition modifications every time the Auto path needed to be tweaked. We would have needed a separate state machine for each of our half dozen auto paths. Super overkill.

                          However, during any of those motions, we also may have needed our arm's shoulder, elbow and wrist joints to go through a sequence of safe motion profiles to get from pickup to placement.. We used a State Machine to run this sequence in the background. Once developed it was hardly ever changed, and it was a classic application.

                          Again... If you use OpMode, you are forced to use state machines for EVERY sequence that happens over time.
                          With LinearOpMode you can choose when to use a state machine, and when to just use while calls with a couple of exit conditions.

                          I like options...

                          I know this is counter to your stated opinion, but I think of the standard OpMode fine for Teleop, but once a team starts doing auto they should definitely switch.
                          Save the State Machine lesson for the manipulator

                          Phil.


                          Comment


                          • #14
                            Originally posted by Philbot View Post
                            If you use OpMode, you are forced to use state machines for EVERY sequence that happens over time.
                            Agreed... This is why I wrote "it is essential to be proficient in state machine programming. I can't think of a better way for kids to learn state machine programming than using iterative OpMode."

                            Originally posted by Philbot View Post
                            With LinearOpMode you can choose when to use a state machine, and when to just use while calls with a couple of exit conditions.

                            I like options...
                            Please keep in mind, however, that when you are tasked with writing a control system program out in the real world, you don't have the luxury of designing and programming in Java. I imagine that in most cases you won't even have the option of creating a thread to linearize your control program. Thus it is necessary to be proficient in state machine programming. It takes lots of practice to be proficient (well, for me anyway).

                            Comment


                            • #15
                              As someone who has done a "few" years of embedded software - I understand the importance of state machines and being able to create and use one proficiently.

                              However - for many of the programmers this is their very first experience in programming. And even if it isn't their first, they are probably still beginners. Forcing them to use the Iterative OpMode because it is good for them to learn state machines will just end up frustrating them.

                              In my experience the programmers for over 50% of the teams do not need to create a single state machine. They are happy just to have a functional teleop and an autonomous that does a simple drive, turn and move the arm. Having success in programming is more important than forcing them to learn more advanced concepts like state machines.

                              For those programmers / teams that get to the point that they need more advanced things - they will learn state machines. They will learn about multiple threads. But they'll do that having gained confidence with the simpler things that they succeeded at before. Let the teams crawl and walk before forcing them to run.

                              Comment

                              Working...
                              X