Skip to end of metadata
Go to start of metadata

You are viewing an old version of this content. View the current version.

Compare with Current View Version History

« Previous Version 8 Next »

This page details the high-level design behind the autopilot code.


Highest level:

The autopilot will consist of 3 threads that each manage a state machine and many other threads that manage sensor data acquisition. The 3 state machines are the attitude manager; responsible for putting and keeping the aircraft in some desired attitude, the path manager; responsible for instructing the attitude manager to achieve some attitude in order to navigate the aircraft to some particular location, and the telemetry manager, responsible for all communications with the ground station. At the same time, there will be a thread for each sensor, ensuring data is collected at well timed intervals.



Path Manager

  • The sensors relevant to the path manager are the GPS, altitude sensors, and anything responsible for communicating to/from the ground.
  • As with the lower level, this architecture is also interrupt based.
  • Not sure how we should manage loop period. Should this be run more or less often then the lower level loop ? And how to keep loop periods constant when we have 2 separate loops running.
  • Gps stuff comes around fairly slowly and can be fairly inaccurate. As mentioned in Asana, seems like a good idea to fuse measurements made by the lower level with it to figure out what is going on. I don’t think this was implemented in PicPilot.
  • The PicPilot does a ton of really cool waypoint tracking stuff. I think most of it is fine to port over.
  • A couple things not included in these documents: Battery level checkers, led managers... Not sure where these things should go.
  • Autonomous takeoff/landing is still a whiles away, but not sure how it would fit into such an architecture. Probably want another state machine that takes control from this one when we deal with take offs/landings.
  • Not sure how often data needs to be sent to/received from the ground. We should make sure that uncertainty is accounted for when figuring out how often to run this loop. Surely FreeRtos gives us methods for doing things like this.
  • Actually, I’m having second thoughts about having ground communications be part of this module. What does path managing have to do with ground communication anyway ? Maybe a third module should exist, feeding this one with relevant ground data and figuring out what to give the ground.

Attitude/airspeed manager

  • The sensors relevant to the attitude manager are the IMU and the airspeed sensor.
  • This architecture is purely interrupt based and we need spend no time polling.
  • The “trigger new measurements” state exists to begin the I2C/uart/spi/whatever exchanges with the appropriate sensors. These exchanges should all be interrupt based so we are free to process data in the mean time (this is different then PicPilot, where IMU data is polled for).
  • Some sensors are faster than others. The “trigger new measurements” state is simplified. Ideally, we have various tasks assigned to FreeRtos that all fire at set periods to trigger the given sensor’s measurements.
  • The control period should be the slower of: the fastest sensor’s refresh rate or the time it takes to perform all the computations ( not quite sure how to keep things at a regular period, considering there is a higher level state machine also running??? Freertos surely has ways for this to work).
  • Any time we don’t have a new measurement (if we even run that fast), maybe we should extrapolate what’s going on based on previous measurements.
  • Looks like most of the data processing algorithms used by the PicPilot can be ported. Pid gains have even already been tuned for Spike it seems.
  • Stall protection / verifying whether the higher level is asking for garbage belongs in this module.
  • The whole “gather new instructions” and “Communicate results” thing might not need to actually be operations done. We may want to have key things shared between higher and lower levels. This was done across multiple chips via DMA on the PicPilot. Things would be much simpler here since we’ve only got one big autopilot chip.
  • Autonomous take offs/landings should be opaque to this module. If a higher level module tells it what speed and attitude the plane needs to be at, this module just obliges, having no idea whether we’re at 10 000 feet or about to land/on the ground.


Sensor interfaces


As an example, here is the GPSinterface. Interfaces to all sensors should look very similar.

class Gps
{
	public:

		/**
		* Initialises internal parameters.
		* Should be called exactly once before anything is attempted to be done with the module.
		*/
		virtual void Init(void) = 0;

		/**
		* Begins the process of collecting the sensor's data.
		* This is a non blocking function that returns right away.
		*/
        virtual void BeginMeasuring(void) = 0;

		/**
		* Gets the information about the aircraft's position (See GpsData_t struct).
		* This is a non blocking function that returns right away, either with new data,
		* or with old data (in case of old data, the dataIsNew flag of the result struct will be cleared).
		* @param[out]		Data 		pointer to the result struct.
		* @return			AAQUAD_SUCCEEDED, AAQUAD_BUSY or AAQUAD_FAILED
		*/
        virtual void GetResult(GpsData_t *Data) = 0;
};

The design is such that a "GPS" thread would periodically call BeginMeasuring, which would begin the process of collecting the data from the sensor. That data should be available by the time the appropriate state machine thread gets around to calling GetResult to collect it.

The Data struct that gets populated by the GetResult function will contain, along with the fields that store the sensor specific data, an "isDataNew" field that indicates whether the sensor data has indeed been refreshed since the last time the caller called GetResult, and a "sensorStatus" field that indicates any sensor specific failures.

None of the methods in the interface should be blocking. This means all communications with the sensor will be internally interrupt (and possibly DMA) based. As a result, we can guarantee the processor spends it's time doing meaningful work rather than polling sensors.

The interface is made up entirely of pure virtual methods. This allows many implementations of the module (for many different parts). This way, we would be able to easily select which part is available to us at the time of flight without having to modify any of he calling code.


Note: We might find it useful to add a 4th function to the interface: “Sensor_Calibrate” which might either load calibration values we stored earlier or execute a calibration or something.

RTOS

The main autopilot systems are built on FreeRTOS, an open-source Real-Time Operating System. FreeRTOS gives us the ability to run multiple concurrent tasks on a single embedded system, each of which has a priority and can "block" for a period of time while they wait for data. At any given time, the highest priority task that is not blocking will be running.

A few notes about developing for real-time systems:

  • Treat timeouts as a design error. Most blocking OS functions on the autopilot allow (or require) specifying a timeout for the blocking operation.

Autopilot Drivers

Required:

  • GPS
  • XBee
  • Altimeter
  • IMU
  • Interchip
  • EEPROM

Optional:

  • Airspeed
  • Battery
  • Ultrasonic

Safety Drivers

Required:

  • PWM
  • PPM
  • Interchip

Autopilot Logic

Required:

  • Task management
  • PID
  • Waypoint management
  • Navigation
  • Telemetry
  • Autonomous level
  • EEPROM storage
  • Startup codes

Optional:

  • Sensor fusion
  • Landing/take off
  • Multi-vehicle

Safety Logic

Required:

  • Anonymous level
  • Safety switch
  • PPM disconnect
  • Startup codes
  • SPI heartbeat
  • No labels

0 Comments

You are not logged in. Any changes you make will be marked as anonymous. You may want to Log In if you already have an account.