- height: h - hMSL_ft (height measured from MSL, units in feet)
- time: t - timeFreeFlight_s (time started at free flight start, units in seconds)
- time: currentTime - currentTime_UnixEpoch_s (time started at Unix epoch, units in seconds)
- date: currentDate - currentDate_UTC (date in UTC)
- velocity: v - v_bc_Fn_mps (velocity of body fixed frame Fb wrt ground fixed frame Fc, with components expressed in NED frame, units in m/s)
- speed: v - speed_Mach
- acceleration: a - a_bi_noG_Fb_mps2 (acceleration of Fb wrt inertial frame Fi, without gravity components, expressed in Fb, units in m/s^2)
- Euler angles: euler - euler_Fn2FbRFB321_rpy_rad (321 yaw pitch roll sequence rotated frame based Euler angles that convert a vector in Fn to a vector in Fb, array index order is roll pitch yaw, units in radians)
- Azimuth: az - azimuthTrueNorth_deg (azimuth angle measured from True North, units in degrees)
C++ and MATLAB Simulink tips for HWIL simulation software engineers
Tuesday, December 3, 2024
Simulation variable names
Thursday, October 31, 2024
Handling long operations in observer chains
Sunday, September 22, 2024
Using code from Simulink model in HIL
- Checkout/pull Simulink model from repository to your local.
- Run Simulink model and confirm it finishes as expected. If not, inform the model maintainer and ask them to commit/push the model with correct settings to repo.
- Confirm that C/C++ code can be generated from model. Sometimes an s-function build file (mexw64) exists but its source code is missing, which allows the model to run but prevents code generation.
- Copy code to Visual Studio and verify that you can build and run it. There are cases where Simulink is more forgiving of errors like uninitialized variables, or missing #include <cmath> but Visual Studio cannot build the code.
- Copy code to real time Linux PC and verify code can be build there too.
- Commit code to its own repo.
- Run HIL with new code and verify HIL works as expected.
Monday, September 9, 2024
Why is file hash comparison faster than byte-wise comparison
- Hash comparison = reading file + 1 comparison.
- Byte-wise comparison = reading file + N comparisons.
Tuesday, March 26, 2024
When do you need HIL tests?
- Concept of Operation
- Requirements
- Design
- Ground tests
- Test components
- Test system
- Flight tests
- Deployment
- Maintenance/Updates
- Your system might work in SIL but since certain bugs only manifest themselves on a particular OS - compiler - hardware configuration, you cannot be sure with just SIL tests that your software is bug-free. Note: Instead of bug-free, the term 'tolerable' might be more appropriate because, for complex software, it is statistically improbable to achieve an entirely bug-free state.
- Resource constraints (memory, processing power, network speed, etc.) of real hardware might differ from those in SIL which might cause a working system in SIL to fail in HIL due to missed timings etc.
- Electromagnetic conditions (interference, noise, etc.) might differ from those in SIL. Components that work individually in isolation might cause problems when integrated together.
- Although you can't test as extensively as with SIL, you can still conduct far more tests than with flight tests.
Friday, January 19, 2024
The curse of band-aid solutions
double factorial(size_t a) {
return a;
}
Then, during live tests, you realize that the function should return 6 for an input of 3, and 24 for an input of 4. Instead of investigating the correct mathematical approach, you modify your code by adding if statements, because that is what you know:
double factorial(size_t a) {
if (a < 3) return a;
else if (a < 4) return a*(a-1);
else return a*(a-1)*(a-2);
}
You add new if conditions as failed tests pile up. For such a simple case, all developers agree that this is not the way to go. However, as problems become more complex, they often lack straightforward solutions that a single line prompt to ChatGPT can provide. Also, there is always pressure to get things done quickly and you don't have time to get to the bottom of things. Most engineers yield under pressure which over time leads to a growing mess, dissatisfaction, burnout and resignation.Thursday, December 28, 2023
The unbearable lightness of C
static void mdlInitializeConditions(SimStruct *S) {
real_T *states = ssGetRealDiscStates(S);
for (int i=0; i < 48; i++) {
*(states + i) = 0;
}
}
Friday, October 13, 2023
Sanity checks
Wednesday, October 5, 2022
Reducing maintenance effort
Thursday, July 28, 2022
Dealing with legacy projects
- Convince me: Why are you asking for my help, why don't you continue as before? Are you trying to please the quality department with documentation fluff? Where did you get stuck, what are the concrete issues you think I can help? Are there any standards that must to be followed or are these standards nice to have?
- Interview the developers and create a document on Confluence, write what problem the project solves, what its current status is, what the current problems are and what more features will be added. Add a diagram showing the hardware and software components and their interfaces, especially external interfaces. Later on you can add more details, making it a proper developer handbook.
- Let the developers do a live demonstration of the current capabilities.
- Upload code and tools necessary for build to a repository.
- On a clean PC, build code. Add repository links and build steps to document.
- Add unit tests starting with the simplest sections. Update document as you add more and more tests and become acquainted with the code/design.
- Add automated nightly build scripts, update document.
- Add steps of hardware assembly and test to document.
- If there are manual tests, create a test plan document detailing test steps on Confluence. It should include links to documents on how to assemble and test the hardware and how to build the code and upload to hardware.
- Create a deployment document (or add to existing document) detailing the steps of how the product is delivered to the end user and how user will share issues/requests with the developers.
Thursday, June 23, 2022
Benefits of wiki style documentation
Wiki style (no signatures/approvals) documentation of complex software projects (lines of code > 10K) has the following benefits:
- Wiki approach saves you from wasting time in publication and approval process. It enables quick updates which increases quality of content.
- You as the developer will be able to remember important details of design, especially if long time has passed since you last worked on it.
- You can hand-off the project to junior developers without wasting your time.
- You can easily extract a user manual from existing content and users won't bother you with questions.
- Code reviewers get a better idea of overall design which increases the quality of review comments.
Tuesday, January 25, 2022
Development phases of aerospace flight software
When developing embedded software for a complex system, it is not advisable to do the development primarily on target hardware because a test that might take a single developer 5 minutes on a PC might take 4 people half a day on target hardware. We are talking about 100x of efficiency difference. To minimize time spent on target hardware, the following six phases of aerospace flight software development might help:
Wednesday, December 1, 2021
Vectors for Software Engineers
Vectors are common in simulations but software engineers can forget the basics of vector operations. Here is a quick refresher:
In equation (1), we have a velocity vector of point m with respect to point c, expressed as a sum of two vectors.In equation (2), we have the same equation but in scalar form. The "(n)" represents the reference frame in which the components of the vectors are expressed. In order to perform addition, all vector components must be expressed in the same reference frame.
If you want more detail, check out my advanced dynamics lecture notes (PDF).
Tuesday, November 9, 2021
Simple way/pattern to separate GUI from model
Prepare your model as a separate executable that reads input from file and writes output to a file. Then you can code your GUI in whatever language you like (e.g. Excel macros) that takes input from user, writes them to file, runs the model executable and reads outputs from file when executable finishes.
This completely decouples GUI from implementation. Compared to a DLL, it has a simpler interface, it will not crash your JVM if there is an error in model, and let's you run models in parallel much easier and also facilitates easy batch run of model executable via scripts.Wednesday, November 3, 2021
Debugging Effort
The hardest part of debugging is finding the root cause of the problem, therefore it is wise to optimize code for debugging, see clean code:
Friday, December 18, 2020
Software inertia
Imagine software as a snow ball that you want to move forward. As uncle Bob said, if you don't put aside time to clean software, in time its inertia will increase. In the beginning the ball will be light and you will add features, i.e. move the ball easily. With time the code will become messier and changes that took 1 day in the beginning start to take first a couple of days and later weeks. The snow ball gets heavier whenever you move it further. In other engineering disciplines, the more you work on a product, the better it gets, at least it doesn't get much worse. Good luck to software project managers who try to estimate when the project will be done, because the further down the road, the less reliable the estimates are. For any non-trivial project, you can only come up with reasonable time estimates if the code is continuously cleaned up.
Monday, November 30, 2020
Letters to a novice programmer
When the problem you need to solve has only two states, don't create a monster (e.g. FizzBuzz Enterprise), with state machine builders, polymorphism and templates sprinkled around! Use simple switch statements so that a developer can easily move through code with ctrl+left clicks, without ever needing to use ctrl+F.
Friday, August 21, 2020
Clean Code
Software project requirements are often not fully known in advance, requiring teams to learn a significant portion of the necessary information during the development process. This frequently leads to the addition of new features after the initial requirements and design phases, as well as extensive debugging. A key property of software is its ability to improve a system without changing the hardware. To take advantage of this flexibility, software must be designed in such way that it is easily modifiable. Otherwise, it risks becoming as inflexible as hardware. Since most of the development time is spent reading and modifying code, it is imperative to optimize for this fact which means writing clean code, i.e. code that is easy to understand.
Clean Code - Uncle Bob / Lesson 1:
- [28:51] It is not the old people training the new people it is the old code training the new people.
- [31:06] No one writes clean code first because it is just too hard to get the code to work... Cleaning code requires as much time as making it work in the first place. Nobody wants to put that extra effort in. You are not done when it works, you are done when it's right/clean.
- Clean code should read like well written prose.
- [46:30] Every line in a function must be at the same abstraction level.
- [58:45] A function should do one thing, i.e. you should not be able to extract another function from it.
- Don't pass a boolean to a function. Bad: setCentered(true, false). OK: setVisible(true). Using enumeration variables or constants rather than a boolean variable, you make your code more readable, e.g.repaint (PAINT :: immediate).
- Replace switch/if with polymorphism
- Command and query separation: A function returning void must have a side effect [change system state], a function returning a value should have no side effect. With this convention, when you see a function that returns a value, you assume it is safe to call it because it should leave the system in the same state before you called it.
- [31:27] The design and code should get better with time, not get worse [continuous improvement].
- [32:15] If you touch it [the messy code], you will break it. If you break it, it becomes yours(!) Minimize personel risk vs improving a messy system.
- Unit tests results in fearless competence.
- [35:32] Always check it in a little bit better than you found it.
Friday, July 17, 2020
Friday, June 19, 2020
Letters to a novice programmer
myAlgo.setInputs(inputStruct);The correct way is to refactor calculate() method as follows:
myAlgo.calculate();
myAlgo.getOutputs(outputStruct);
outputStruct out = calculate(inputStruct)Using this version would save the user of myAlgo from a couple of lines, he would not face the risk of forgetting to set inputs. In the previous version, if you forget to call setInputs(), the compiler will happily build your code and you will waste time finding the bug at run time. In the new version, if you forget to pass inputs to calculate(), it won't build and you will instantly see the bug.
Whenever you have multiple public initialization functions, try to combine them into a constructor. Your design should be such that when your code builds successfully, you should be confident that it has no initialization or finalizations related bugs. Let the compiler help you.


