3D Robotics

Real Time Operating Systems for autopilots [UPDATED]

If you've been following Tom Pyke's progress on his impressive Gluonpilot, you will have seen that he's implementing it with a realtime operating system (RTOS), rather than programming "straight to the iron" the way most autopilots are done, to gain maximum control over interrupts, timing and the like. He's using a relatively powerful dsPIC chip, which can handle the overhead of the RTOS (I think he's using FreeRTOS, but I've pinged him to find outUPDATE: yes, it's FreeRTOS. See below). Here, he makes the case for a RTOS: "The main advantage of a real time OS is that you can use threads (which we will use tasks from now on). You don't need to bother anymore about the delay your telemetry processing can cause to your Kalman filter or PID control. No more need for timed loops or Timer interrupt routines. It looks perfect! There are some things you need to keep in mind: You need to prioritize every task Every task has a separate stack. This stack is used for the task itself AND every interrupt routine that may be called during this task's execution Thats about it! Let's take a look at the different tasks in gluonpilot: --Telemetry: All the output needed for our groundstation --ConsoleInput: Processing and answering all the commands you send to the autopilot --Sensors: Gathers and processes (filters!) all the sensors (gyroscope, accelerometer, gps, pressure sensor) on our autopilot module --Control: Sends the correct position to the servos! This handles both manual, stabilized and full autopilot modes." The prioritization of the tasks is as follows:

Read on here. UPDATE: In an email, Tom explains more: "Yes I'm using FreeRTOS. Whether you should need to consider it [I had asked him if it would work on a 16Mhz Atmega--chris] is not easy to answer. 16MHz doesn't seem a lot. The dsPic runs at 80MHz (40MIPS) and - I think - has more memory. Using an RTOS does not cause an extreme amount of overhead, but you can no longer push the processor to its limits: - You need more memory because interrupts can be executed (and use the stack) of any running task/thread (and you need to assign a stack size to every task) - You need enough spare CPU cycles to make sure all tasks can always be handled in time. - And the RTOS needs memory, flash and CPU time of its own It may sound contradictory, but I started using FreeRTOS to make sure people can easier add code to the autopilot. In the last version without it, the code became complex and critical to change, because of all the timing-critical code and timed loops. Now with the RTOS, people can add lower priority tasks and I'm sure the manual control and time-critical filtering still works. However, you need to keep the design as simple as possible. The only features I'm currently using is the scheduler (because it's easier than a timed loop) and a queue mechanism for pushing data from an interrupt to a sleeping thread. There are some RTOS pitfalls such as priority inversions. But it's really up to you how far you want to go. Replacing your timer interrupt routine by a threads wonn't give you any problems you didn't have already. If you use mutexes for mutual exclusion all over your code, than you're down to a more challenging task :-) In the end, I can only suggest that you play with it for a day or two... port some existing code to FreeRTOS and see how comfortable you are using it. It's not really that complex."
E-mail me when people leave their comments –

You need to be a member of diydrones to add comments!

Join diydrones

Comments

  • Hi all

    Do you mean that there is no need to an RTOS to developp Arduplane software?

    Are you using any soecific librarie for the real time management then?

    otherwise how could you manage the deadlines?

  • Developer
    Sounds like a bunch of unnecessary overhead to me. The 2.5 code is in the branches folder. Feel free to fork that into a RTOS version and lets see what it can do.
  • A team from Argentina has integrated the FreeRTOS with the arduino environment. It is called DuinOS. You spend just a few minutes to convert the current Ardupilot code to a FreeRTOS enabled one.
  • The thing we have to do is run 3rd party libraries like picoc & libjpeg in their own processes so the flight controller doesn't crash when they encounter problems. We fully endorse FreeRTOS for the right uses. It's just not working out for our needs.
  • @Curt: You will need to look at the vTaskDelayUntil function
  • Jack,
    If you look in the FreeRTOS example there is a port to linux in there. what it allows is the same code recompiled to run on linux. Another thing that I have done is write a simple dummy layer remapping the FreeRTOS calls to POSIX calls and running the same code on linux as well, the opposite can be done fairly easily(write a POSIX mapping to FreeRTOS calls).
  • Tom: is that api documented ... I poked around the link that was posted by lionel, but nothing jumped out at me. If it's like you say it is, then that would be pretty slick.

    Curt.
  • @lionel: thanks for the link. That gives some good info on the scheduling / task control parameters that can be set. But please let me state my real question again in a slightly different way.

    Let's say I have task #1 that I want to run at exactly 50hz and lower priority task #2 that I want to run at exactly 25hz (hopefully those are easy numbers since most of the systems I've worked with have a kernel tick rate of 100hz by default.) This is the sort of thing people *say* they want to do in real time systems. The original post implies that multiple tasks can run along side each other without having to worry about each (of course assuming everything fits within the cpu budget.)

    So if I have a task #1 that I want to run at exactly 50hz, what is the mechanism to ensure that. Let's make it even simpler and say that I just have the one single task on the system and I want it to loop at exactly 50hz. What is the mechanism available to ensure that my task is fired off at exactly the desired rate?

    Ok, I'm probably being a bit transparent here ... I've been in debates about the relative merits of threading before, and this is an area I honestly don't understand well ... but I don't think most of the people I've discussed this with understand it well either.

    I want a task to loop at exactly 50hz. What is the best mechanism to do that and does this mechanism have anything to do with threads?

    Hopefully this doesn't come off as adversarial or critical. I'm currently involved in an autopilot project on an embedded system (gumstix right now). I'm hard headed in some ways and if I make a change to my own code and scheduling approach, I want to understand why, and be able to convince myself that the added complexity and bugs-waiting-to-happen with thread based systems are worth enduring. And on the flip side, if I dig my heals in on my current approach, I want to fully understand the other options so I can make a clear and unambiguous defense of my own approach.

    I could blab on ... most of the text book threading examples I've seen have been in the computer science / operating system world. These sorts of programs tend to be reader/writer sorts of tasks that need to take some input on one end, do something, and spit out something on the other end. So tasks that sit around and block on input/output and run when there is something to do can make a lot of sense and work well.

    But in a real time environment where I have a set of possibly independent tasks and the key issue is that I want them to run at a very precise and fixed rate (and possibly a fixed order) ... i.e. 1. read sensor data, 2. estimate attitude/position, 3. drive actuators, 4. communicate with ground station, does a threaded application model really add all that much? Maybe this is a discussion that could/should be split off into a different thread, but I don't know how to do that here.

    Or maybe no one really cares (?) :-) Maybe no one has any idea what I'm talking about ... that's fine too, I lose track of what I'm talking about once in a while myself. :-)

    Thanks,

    Curt.
  • @Curt:

    It's actually a lot simpler. You just tell the scheduler to run this function once every 10ms (for example). The scheduler does the rest (no matter how long your function takes to execute - assuming that your function finished in less than 10ms).
    So I have these tasks:
    - Telemetry: every 50ms
    - UART input: triggered via a mutex on a queue
    - Sensors: every 10ms
    - Control: every 20ms
  • @Curt: you can refer to this: http://www.rtems.com/onlinedocs//doc-current/share/rtems/html/c_use...
This reply was deleted.