One of the main challenges with developing drones, is the amount of physical testing required. Back in 2015-2016 when we were in the most intense period of development of the Staaker drone, I realized that if we could make our testing and verification more effective, we could improve our development speed drastically. This spawned the simulator project.
2 Demo videos
2.1 Continous integration
This video demonstrates some of the automatic tests that run in our CI solution. The tests are scripted in a DSL, embedded in C++, letting us express arbitrary missions, assertions that lead to test failure, and arbitrary events that happens to the simulated world during the mission.
2.2.1 Smooth terrain
This smooth terrain is used to simulate visual navigation in 3D environments. It is generated by first creating smooth 3D Perlin noise, then interpreting this noise as a signed distance field. A marching cubes algorithm is run on this signed distance field to generate a meshing of a contour in the field. Correct normals and tangents are computed, as well as a automatically generated UV-map using the ARAP algorithm.
2.2.2 Voxel grid
Voxel grid datastructure, with accompanying GPU-visualization. Uses a dynamic index buffer, together with a static vertex buffer, which saves quite some CPU-GPU memory traffic. Supports raycasting for dynamically building probabilistic occupancy maps, much like the technique used in Google Cartographer
2.3 Simulated sensors
This video demonstrates what happens with the drone state estimates and control system when unrealistically large noise is injected into the GPS position and velocity estimates.
3 Some features I implemented
- Focus separation between rendering and simulation/physics.
- Rolled our own C++ entity component system system.
- Rendering engine: Filament physically based renderer, after a survey spanning everything from Unreal to Ogre 3D.
- Physics motor: developed from scratch in C++ using Eigen.
- Very accurate integration of multirotor ODEs using Runge-Kutta methods for linear parts and quaternion exponential maps for orientation.
- As a proof of concept I integrated DART physics motor, but as we are flying, we did not have that much use for its advanced support of contacts.
- Ended up just rolling my own rudamentary collision simulation.
- Would integrate DART or similar if advanced collision handling was needed.
- Continuous integration:
- Developed a domain specific language embedded in C++ for specifying flight scenarios.
- Very flexible language, executed by the simulator when run in test mode, able to express:
- What to do, eg. a mission and its sub-steps
- Abnormal behaviour, like suddenly removing a motor mid flight or receiving garbled gyro-data
- What to check, arbitrary assertions that can be run at any time during the simulation, and that has ability to inspect the whole simulator state.
- This language was used to create a large test suite, that was run on each commit software in the loop.
- This made it possible to develop autopilot code changes with great confidence, and accelerated our development process enormously
- Colored point clouds
- Marching cubes on smooth signed distance functions for arbitrary 3D terrain generation
- 3D cubic splines
- Simulated sensors:
- Gyroscope, accelerometer, barometer and magnetometer with realistic noise characteristics
- GPS with a complex noise model simulating not just standard Gaussian noise
- RGB cameras, available for visual navigation algorithms
- Depth cameras, available for visual navigation algorithms
- LIDAR, rudamentary simulation, available for navigation algorithms