Back to Code and Software Demo

C – Airbus® Fly-by-Wire Control Simulation

Goal

This project simulates the core control logic of an Airbus®-style Fly-by-Wire flight control system. The goal is to reproduce, in a clean and demonstrative format, a simplified real-time flight control loop that converts pilot inputs (sidestick, rudder pedals) into surface deflections (elevator, ailerons, rudder) while integrating automatic flight envelope protections such as alpha-floor, high-speed protection, and g-load limiting. The simulation highlights the philosophy behind digital flight control laws, where the pilot no longer directly drives the control surfaces — instead, the aircraft interprets pilot intent and enforces safe behavior.

Engineering Approach and Tools

The system is designed using a structured, avionics-inspired architecture: sensor acquisition, pilot input processing, control law computation, protection logic, and virtual actuator dispatch. Protections are represented using a bitmask flag system (0x01, 0x02, 0x04), mimicking how real aircraft systems encode status and fault conditions. Mechanical constraints and authority limits are applied to all commands to reflect actuator boundaries found in real flight control surfaces. The simulation uses controlled pseudo-random variation to generate different flight situations while preserving deterministic behavior — a common method in embedded aerospace testing environments.

Execution Behavior and Output Interpretation

During execution, each cycle outputs the computed surface commands along with a binary protection status flag, allowing clear visualization of when the Fly-by-Wire logic takes corrective action. Some cycles show raw pilot authority, while others demonstrate automatic intervention when flight limits are exceeded. This behavior effectively showcases how modern airliners intelligently filter and modify pilot commands to ensure flight safety. The result is a convincing demonstration of real-world flight computer behavior — precisely the kind of logic expected in professional aerospace simulation systems.

Code

// fly_by_wire.c - Airbus® A320 Flight Control Laws (Demo) // This demo simulates a simplified fly-by-wire system. // Author: Hamza Bendahmane #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <stdbool.h> #include <math.h> #include <time.h> // ---------------- Sensors ---------------- typedef struct { float pitch_angle; // Aircraft pitch angle (degrees) float roll_angle; // Aircraft roll angle (degrees) float yaw_angle; // Aircraft yaw angle (degrees) float airspeed; // Aircraft airspeed (knots) float angle_of_attack; // Angle of attack (degrees) float load_factor; // G-load (g) } Sensors; // ---------------- Pilot Inputs ---------------- typedef struct { float sidestick_pitch; // Pilot input on pitch float sidestick_roll; // Pilot input on roll float rudder; // Pilot input on rudder } PilotInput; // ---------------- Control Outputs ---------------- typedef struct { float elevator; // Command to elevator (degrees) float aileron; // Command to aileron (degrees) float rudder; // Command to rudder (degrees) uint8_t protections; // Active protections (bitfield): // bit0: alpha-floor, bit1: high-speed, bit2: g-limit } ControlOutput; // ---------------- Protection Limits ---------------- #define MAX_ALPHA 15.0f // Max safe angle of attack (stall protection) #define MAX_SPEED 350.0f // Max safe airspeed (knots) #define MAX_G 2.5f // Max positive G load #define MIN_G -1.0f // Max negative G load #define MAX_ELEVATOR 30.0f // Mechanical limit for elevator #define MAX_AILERON 25.0f // Mechanical limit for aileron #define MAX_RUDDER 30.0f // Mechanical limit for rudder // ---------------- Utility Functions ---------------- // Generate a random float in the range [min, max] float randFloat(float min, float max) { return min + ((float)rand() / (float)RAND_MAX) * (max - min); } // ---------------- Sensor Reading Simulation ---------------- void readSensors(Sensors* s) { // Populate sensor values with realistic random numbers for demo s->pitch_angle = randFloat(-5.0f, 5.0f); // Pitch in degrees s->roll_angle = randFloat(-3.0f, 3.0f); // Roll in degrees s->yaw_angle = randFloat(-2.0f, 2.0f); // Yaw in degrees s->airspeed = randFloat(230.0f, 370.0f); // Airspeed (knots) s->angle_of_attack = randFloat(0.0f, 20.0f); // Angle of attack (deg) s->load_factor = randFloat(-1.5f, 3.5f); // G-load (g) } // ---------------- Pilot Input Simulation ---------------- void readPilot(PilotInput* p) { // Populate pilot inputs with small random values for demo p->sidestick_pitch = randFloat(-2.0f, 2.0f); // Pitch input p->sidestick_roll = randFloat(-1.5f, 1.5f); // Roll input p->rudder = randFloat(-0.5f, 0.5f); // Rudder input } // ---------------- Compute Control Outputs ---------------- void computeControl(const Sensors* s, const PilotInput* p, ControlOutput* out) { float pitch = p->sidestick_pitch; // Start with raw pilot input float roll = p->sidestick_roll; float rud = p->rudder; uint8_t prot = 0; // Protection bits initially zero // --- Alpha-Floor Protection (prevent stall) --- if(s->angle_of_attack > MAX_ALPHA) { pitch -= 0.5f * (s->angle_of_attack - MAX_ALPHA); // Reduce pitch if above safe alpha prot |= 0x01; // Activate alpha-floor bit } // --- High-Speed Protection --- if(s->airspeed > MAX_SPEED) { pitch += 0.3f * (s->airspeed - MAX_SPEED); // Adjust pitch to limit speed prot |= 0x02; // Activate high-speed bit } // --- G-Load Protection --- if(s->load_factor > MAX_G) { pitch -= 0.5f * (s->load_factor - MAX_G); // Reduce pitch for high G prot |= 0x04; // Activate G-limit bit } else if(s->load_factor < MIN_G) { pitch += 0.5f * (MIN_G - s->load_factor); // Increase pitch for negative G prot |= 0x04; // Activate G-limit bit } // --- Mechanical Limits --- if(pitch > MAX_ELEVATOR) pitch = MAX_ELEVATOR; if(pitch < -MAX_ELEVATOR) pitch = -MAX_ELEVATOR; if(roll > MAX_AILERON) roll = MAX_AILERON; if(roll < -MAX_AILERON) roll = -MAX_AILERON; if(rud > MAX_RUDDER) rud = MAX_RUDDER; if(rud < -MAX_RUDDER) rud = -MAX_RUDDER; // Store final control outputs out->elevator = pitch; out->aileron = roll; out->rudder = rud; out->protections = prot; } // ---------------- Send Outputs to Actuators ---------------- void sendToActuators(const ControlOutput* out) { // Print actuator commands and active protection flags printf("Elevator: %6.2f | Aileron: %6.2f | Rudder: %6.2f | Protections: 0x%02X\n", out->elevator, out->aileron, out->rudder, out->protections); } // ---------------- Main Flight Loop ---------------- void flightLoop(void) { Sensors s; PilotInput p; ControlOutput out; readSensors(&s); // 1. Sample sensors readPilot(&p); // 2. Sample pilot inputs computeControl(&s, &p, &out); // 3. Compute outputs with protections sendToActuators(&out); // 4. Output results } // ---------------- Main Program ---------------- int main() { srand((unsigned int)time(NULL)); // Seed RNG printf("Fly-by-wire demo started\n\n"); // Run 5 simulation cycles for(int i = 0; i < 5; i++){ printf("Cycle %d:\n", i + 1); flightLoop(); printf("\n"); } printf("Fly-by-wire demo finished\n"); return 0; }
© 2025 – Hamza Bendahmane. All rights reserved.