User Guide For Multicopter Design 0.2
User Guide For Multicopter Design 0.2
Contents
1 Introduction 3
1.1 Problem Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Inputs and Outputs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 An Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3.1 Basic Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3.2 Design Panel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3.3 Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3.4 Flight Status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2 Installation 8
2.1 Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2 Build on Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.1 Get the Source Code from GitHub . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2.2 Download Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.3 Generate the Build Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.4 Build and Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3 Build on Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3.1 Install OpenGL libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.2 Get the Source Code from GitHub . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.3 Download Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.4 Generate Makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3.5 Build and Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4 Build on macOS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4.1 Get the Source Code from GitHub . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.4.2 Download Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4.3 Generate Makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4.4 Build and Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1
3 User Interface 17
3.1 Copter Property Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2 IMU Status Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.3 Propeller Data Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.4 Battery Status Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.5 Design Panel Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.5.1 Full Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.5.2 Reduced Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.5.3 Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.6 Keyboard Shortcuts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.7 Mouse Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4 File Format 21
4.1 Basic Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.2 3D Transforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.3 Add Plates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.4 Add Batteries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.5 Add Electronic Devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.6 Add Tubes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.7 Add Connectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.8 Add Propellers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.9 Add Motors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
5 Acknowledgment 27
2
1 Introduction
This project is about developing a design, simulation and optimization tool for casual users to build
their own multicopters. Initially it was a research project led by the Computational Fabrication Group
at MIT CSAIL in 2015. After we published a paper [1] we got inquiries from many different sources so
we decided to release our source code for the benefits of both the research and hobbyist communities.
For those who have read that paper, please note that the code here only covers a subset of our
implementation in the paper, as we are still in the middle of cleaning it up. We expect to release all
features in the next version (0.3).
• What components to use: This includes choosing the right material to build the frame (carbon
fiber, wood, plastic, etc), picking the proper motors and propellers, selecting a good battery, and
many more.
• How to assemble them: You may want to follow standard designs like a quadcopter, or try some
fancy configurations like a tricopter, or even come up with your own, unique configuration, like
the bunny-shaped example in our paper.
• How to control its flight: Normally, you can find a mature controller design for classic quad-
copters, which is typically a multi-layer PID controller, for example. If you want to have more
degrees of freedom in our design, you probably need to develop your own controllers, or at least
spend some time modifying and tweaking an existing controller from similar models.
• How to verify the design: Crashing a real drone is a huge pain and loss, both psychologically
and financially. This is why people turn to software simulation for help. Ideally, it should verify
both the geometry and controller accurately, and it should be embedded in the design loop to
allow for interactive changes.
Obviously, this is a very involved process requiring a diverse set of skills, including mechanical engi-
neering, electrical engineering, programming, control theory, and hands-on experience in building stuff.
The goal of our software is to expedite and simplify this process by hiding low level technical details
so that people can focus more on expressing and exploring the design space. Specifically, we provide:
• A dataset of standard components that users can freely choose from and assemble by defining
their own scripts.
• An easy-to-use user interface to explore designs in an interactive way.
• An automatically determined LQR controller that is generalizable for most existing designs we
have seen so far.
• A real-time simulation tool seamlessly embedded in the design loop to visualize results instantly.
Please keep in mind that this software is not meant to replace all the work involved in building a
customized drone. You are expected to do your own measurement, or at least give a rough estimation of
the physical properties of the motors, propellers and batteries. The output of our software is a hardware
3
specification you can follow, but of course you still need to fabricate or buy these components and
assemble them manually. Finally, we include a controller in the solution, but uploading it into your
own flight controller board is beyond the scope of this software. You are expected to have a working
knowledge of the flight controller (both the hardware and software) you plan to use, and be comfortable
with modifying its code to include a new controller.
1.3 An Example
As a concrete example, here we demonstrate how our software can be used to help design and simulate
a V-Tail copter 1. When the window first pop up, you will see a V-Tail model centered on screen,
and a few windows floating on both sides. Below we will briefly explain the user interface and show a
simple design and simulation loop. A more thorough description can be found in Section 3.
Full Parameters The first panel named “Full Parameters” lists a union of parameters from each
component. When you use a slider, it specifies a desired value of that particular parameter. A linear
least square problem is then solved to find parameters that respect all constraints and are closest to the
desired value. Once a solution is found, the copter design in the middle gets updated automatically,
and usually in real time (Figure 2).
4
Figure 1: Loading the given V-Tail design into our software. The left windows show the current status
of the copter, and the right panel allows you to freely explore and simulate different designs.
1.3.3 Simulation
Once you are satisfied with the current copter, scroll down in the design panel, and you will find a
“Simulate” button. Clicking it will trigger the software to compute a proper LQR controller and start
simulating a virtual flight (Figure 3). Press this button will invalidate the “Full Parameters” and
“Reduced Parameters” windows. The button itself will change to “Reset” so that you can switch back
to the design process if more iterations are needed.
During the flight, this copter will try to track the blue arrow as close as possible. Specifically, it
interprets the tail as the target position and the arrow as the desired heading. You can use the four
5
Figure 2: By adjusting the full parameters, we elongate two tubes and push the front rotors farther
from the center.
arrow keys plus ‘a’, ‘d’, ‘w’ and ‘s’ to adjust the blue arrow and guide your copter to a desired position.
You can also change the camera view by mouse gestures like scrolling or panning.
6
Figure 3: The V-Tail quad is executing a virtual flight in simulation. The copter is trying to follow
the position and heading specified by the blue arrow.
loop.
7
2 Installation
This section provides a step-by-step tutorial about how you can build the software from source code
on a Windows, Linux, or macOS machine.
2.1 Prerequisites
Check the list below before you start building from the source code:
• Update your graphics card driver: OpenGL 3.3 or later version is required to display the
user interface correctly. If your computer is not very old, then you can probably skip this step.
Keep in mind that if any weird display issues occur after you compile the code, you might want
to try updating your graphics card driver first.
• Install Git: Git is a widely used version control system in the open source community. If you
want to modify our code then you probably should install Git. If you are an end user, Git is not
necessary, but we still recommend it, otherwise you will have to download the source code and its
dependencies (for those who know Git, we use submodules in our code base), and manually place
them in the right folder. Moreover, Git allows you to easily track the latest patch we release for
bug fixes, code improvement, etc.
• Install CMake: CMake is a tool for building cross-platform softwares. You specify your building
rules in a file typically named as CMakeLists.txt, and CMake will generate build files depending
on your compiler and platform, which could be a Visual Studio solution file on Windows, or a
Makefile on Linux, for example. If you are an end user, don’t worry about learning how to write
the CMakeLists.txt file, just install CMake and you are good to go.
• Install a C++ compiler: There are multiple options here and this is really up to you. For
Windows users we recommend the free community version of Microsoft Visual Studio. For Linux
users, it is usually gcc/g++. For macOS users we have tested with AppleClang provided in Xcode.
Make sure your computer can run a basic “Hello, world!” C++ program before you move on.
8
Figure 4: (Windows) Cloning the project into an empty folder named test.
9
Figure 5: (Windows) Using CMake to generate the build solution.
10
2.3.1 Install OpenGL libraries
Before you clone our project, make sure all the following libraries have been installed:
> sudo apt-get update
> sudo apt-get upgrade
> sudo apt-get install libgl1-mesa-dev mesa-common-dev xorg-dev
> sudo apt-get install libglu1-mesa libglu1-mesa-dev
Figure 7 is provided for your reference if you encounter any errors and are interested in knowing the
exact version of these libraries we are using:
11
2.3.4 Generate Makefile
Next, you will need CMake to generate a Makefile for compiling the code. As before we recommend an
out-of-source build. In Figure 8, we create an empty folder named test/multicopter design build,
and a Makefile is generated inside.
> mkdir multicopter_design_build
> cd multicopter_design_build
> cmake ../multicopter_design
12
Figure 9: (Ubuntu) Running copter viewer without any arguments.
Figure 10: (Ubuntu) A screenshot of the user interface after we build from the source code.
13
Figure 11: (macOS) Cloning the project into an empty test/ folder.
> cd test
> git clone --recursive https://github.com/mit-gfx/multicopter_design.git
14
Figure 12: (macOS) Using CMake to generate a Makefile.
15
Figure 14: (macOS) A screenshot of the user interface after we build from the source code.
16
3 User Interface
We have briefly covered the user interface in Section 1. Here we provide more instructions on interacting
with each window. We will also explain keyboard shortcuts and mouse operations in this section.
• Mass Computing mass is straightforward as it only requires summing up the mass of each part.
Technically, each component is defined by a closed surface mesh and a density value. We will
assume this mesh is solid and use the divergence theorem to analytically compute its mass.
• Moment of Inertia The moment of inertia is a 3 × 3 symmetric positive semidefinite matrix,
defined on a local frame F rigidly attached to the copter. F is computed and fixed once an
initial design is loaded. The origin of F is the center of mass and its three axes are parallel to
the world frame axes. Recall that the world frame we use is north-east-down, where x, y and
z point to the north (red), east (green) and down (not shown in the window as it is below the
ground) direction.
The moment of inertia determines the torque need to rotate the copter. It is generally recommended
that you place your initial design in a way that its heading is along the x axis with zero roll angle. In
this way the diagonal elements in the matrix reveal the resistance of the copter to rolling, pitching,
and yawing respectively.
• Position These three numbers show where the center of mass is located in the world frame. As
z axis points down to the ground, positive altitude corresponds to a negative z value.
• Euler Angle These are the roll, pitch and yaw angles. Initially the body axes are parallel to
world axes. We first rotate it around z by yaw, then rotate along the new y axis of the body
frame by pitch, then finally rotate around the new x axis of the body frame by roll.
• Velocity The time derivative of position.
• Euler Rate The time derivative of Euler angles.
• Position This shows where the motor is located in the body frame. Their values get updated
during the design process and fixed in simulation.
• Direction This unit vector shows where this motor points to in the body frame. Typically it
is close to (0, 0, −1).
17
• Spinning A string shown here indicates whether the propeller spins clockwisely (CW) or counter-
clockwisely (CCW), defined in a view where the motor is pointing towards you.
• Speed This shows the rotation speed of the propeller, in RPM (round per minute).
• Thrust This is the magnitude of the thrust generated by the propeller.
Both speed and thrust are calculated from fitting measurement data provided in the file. Thrust is
also clamped between 0 and the measured maximum.
min kx − x0 k
x
s.t. Ax = b (1)
Cx ≤ d
In other words, we find in the feasible set the closest solution to the parameter values indicated by
users from the window.
18
The reduced parametric representation brings its own drawbacks though. Perhaps the biggest issue
here is that y does not have a straightforward physical meaning any more. Each element does not
correspond to a single component, but might affect the global design in an unintuitive way.
Unlike the full parameters, it is easier to update the reduced parameters when they get updated
in the window. Let Fy ≤ g be the only inequality constraints on y. When one yi is updated, we fix
other yi s and calculate the feasible range of yi and reflect it in the window. If some yi freezes on the
boundary of Fy ≤ g, its background then becomes red to imply this yi is not changeable.
3.5.3 Simulation
This window contains a button to trigger the simulation process. Your design is then set to track
the position and heading of the blue arrow in the scene, which can be changed by keyboard shortcuts
discussed below. All design parameters are frozen during flight unless you press the button again and
switch back to the design process.
Behind this simulation button we execute a 30Hz loop to control the flight. Within each iteration
we do the following things in order:
• Collect the sensor data and target information.
• Execute the control policy based on them.
• Send control signals to each rotor.
• Use thrust and torque from each rotor to update the motion.
Note that depending on your graphics card the actual FPS (frame per second) may be above or below
30. So the time flow you feel in the window is not exactly the actual motion you expect to see in your
real copter.
19
• Rotation You can press the mouse wheel and drag to rotate the camera.
• Panning Press shift and the mouse wheel and drag your mouse at the same time to change the
camera location.
20
4 File Format
We use XML files to define the copter used in our design and simulation tool. A list of sample files
are provided in the folder resources/copter/ for your reference. To load an XML file, simply use its
name as the first argument when you run copter viewer. For example:
> ./copter_viewer y6copter.xml
will load a Y6 hexacopter defined in y6copter.xml (Figure 15). If no XML file is given, then
pentacopter.xml is used by default.
Figure 15: Loading a Y6 hexacopter from the given XML file y6copter.xml.
The XML file itself its pretty straightforward: once you learn the rules, you are free to create your
own XML files and use the software to design and simulate them. For simplicity, below we will walk
you through quadcopter.xml so that you can get an idea of how to write your own copter file.
21
The whole copter is then wrapped by a pair of tags <copter> and </copter>. You should put all
your components inside these opening and closing tags. To define a complete copter, you will have
to provide definitions for the following components: plates, a battery, an electronic device, tubes,
connectors, propellers, and motors. All meshes used here must be watertight, otherwise we won’t be
able to estimate their moment of inertia.
4.2 3D Transforms
Many of the components are defined in their own frames in the mesh file. To place them correctly
you need to apply a series of transforms. In the XML file you can specify it by using translate and
rotate tags. Scaling is in general not supported except for plates and tubes.
To apply a translation, use the following tag:
In our code, we look for a file named plate.obj in the folder resources/mesh, which we have provided
along with the source code. This mesh is a 1m×1m×0.0024m axis-aligned cuboid centered at the origin,
and the unit of the density value is kg/m3 .
Between <plate> and </plate> you can create multiple plates by using <instance> tag, one for
each plate. An <instance> tag needs you to specify the size of your plate along x and y direction
first, then specify the location and orientation of the plate by applying translation or rotation.
22
<instance size="0.15 0.15">
<translate xyz="0 0 -0.1"/>
</instance>
Here we define our first plate: it is a 0.15m×0.15m×0.0024m cuboid, and it is lifted by 0.1 meters.
The second plate has a smaller size (0.15m×0.07m), and it is lifted by 0.148 meters, leaving a 0.048 −
0.0024 = 0.0456 meters gap between them. This is exactly the size of one connector, which we will
cover shortly:
<instance size="0.15 0.07">
<translate xyz="0 0 -0.1"/>
<!-- 0.0024m is the thickness of the plate. -->
<translate xyz="0 0 -0.0024"/>
<!-- 0.0456m is the size of the connector. -->
<translate xyz="0 0 -0.0456"/>
<!-- Instead of copying and pasting the three translations here, we will
use -0.148 = -0.1 - 0.0024 - 0.0456 below. -->
</instance>
Plates do not have any free parameters in the design. Once they are defined in the XML, they
cannot be changed any more.
23
electronics.obj defines a mesh bounded by a 0.0816m×0.05m×0.0154m box and centered at the
origin.
Like plates and batteries, the location and size of an electronic device are fixed once it is defined
in the XML file.
24
tube.obj and allow the default tube to pass through. It is crucial to place them in the right position,
otherwise our algorithm won’t be able to parse their connection and constraints correctly.
As an example, consider the first connector we defined after <round connector>:
<instance>
<rotate rpy="0 0 90"/>
<translate xyz="0 0 -0.124"/>
</instance>
So we first rotate the connector along z axis by 90 degrees, then place it at (0, 0, −0.124). Recall that
our second tube is placed at (0, 0, −0.124) and points to the y direction. In this way, the tube passes
through the connector precisely. The value −0.124 comes from the half size of the connector (0.0228),
the half of the thickness of the plate (0.0012), and the offset of the lower plate (−0.1), which sums up
to −0.124.
As another example, consider the third connector in quadcopter.xml:
<instance>
<translate xyz="0.23 0 -0.076"/>
</instance>
Recall that the first tube is centered at (0, 0, −0.076) and has a length of 0.5 meters. So placing this
connector at (0.23, 0, −0.076) means it is at the end of the tube (a 0.02 gap is left here because the
connector itself spans 0.04 meters along x axis).
Each connector has 4 faces that can be connected to plates, motors, or other connectors. A
connector is parametrized by its center of mass (three degrees of freedom). If it is attached to a plate
then the connector becomes fixed (zero degrees of freedom). If two connectors, or a connector and a
motor are attached, then their relative position is fixed. Finally, each connector must have a parent
tube, which further limits the possible position of the connector: it can only slide along the tube
bounded by its two endpoints.
You do not have to explicitly specify which connectors are connected, or which is the parent tube.
Our program will parse your XML file and as long as you place them in the world frame in a correct
way, the algorithm will identify the connection automatically.
25
As before, motor.obj defines the default motor mesh which spins around the z axis. Its top and
bottom surfaces are at z = ∓0.018 meters. This offset will be used later to place motors on top of its
supporting connector.
The measurement attribute requires you to provide a file that contains data samples of duty cycle,
torque, thrust, motor speed and current. Relatively accurate torque and thrust samples are needed to
construct a plausible dynamic model, and current samples are used to estimate the battery life. Motor
speed (in round-per-minute, or RPM) is mostly for visualization but a good measurement can help you
do a sanity check on thrust samples. We have provided our measurement in resources/measurement
for you to start using the software, but eventually you should provide your own measurement for your
model.
The last attribute, propeller height, defines the relative height between the center of motor and
its propeller. Since the top surface of the motor is 0.18m tall, we set this value to be 0.19, leaving a
0.01m gap between to avoid any collision in visualization.
Each motor is then defined by using the instance tag. A spinning direction, either clockwise or
counter-clockwise, needs to be specified in the spin dir attribute. The actual location is then defined
by the similar way as above:
<instance spin_dir="cw">
<!-- Location of its parent connector. -->
<translate xyz="0.23 0 -0.076"/>
<!-- Half size of its parent connector. -->
<translate xyz="0 0 -0.0228"/>
<!-- 0.018 is the distance between the bottom surface and the center of
the motor. -->
<translate xyz="0 0 -0.018"/>
</instance>
Each motor, parametrized by its center of mass (three degrees of freedom), must be attached to a
parent connector, and the relative position between the motor and its connector is fixed. Note that
you can rotate the motor along with its parent in the XML file. One example of this can be found in
resources/copter/vtailcopter.xml.
Finally, each motor has an optional attribute named flip prop, which by default is false. This
attribute is used for the case when you want to flip your propeller to provide a downward thrust
(relative to the motor) instead of the usual upward thrust, or if you want to install your motor upside
down. You can refer to resources/copter/y6copter.xml, in which three lower motors are installed
upside down.
26
5 Acknowledgment
We would like to thank Jie Xu for implementing a secondary user interface and Budmonde Duinkhar
for debugging an initial version of the controller. We also thank Ryan Gulland for his comments on
the draft of this user guide.
References
[1] Tao Du, Adriana Schulz, Bo Zhu, Bernd Bickel, and Wojciech Matusik. Computational multicopter
design. ACM Transaction on Graphics, 2016.
27