1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
|
\documentclass[a4paper, 11pt, pdftex]{article}
\usepackage[pdftex]{graphicx}
\usepackage{ae}
\usepackage{latexsym}
\usepackage{rotating}
\usepackage[intlimits, sumlimits]{amsmath}
\usepackage[pdftex, bookmarks]{hyperref}
\pdfcompresslevel=9
\newcommand{\unit}[1]{\textrm{#1}}
\newcommand{\vi}[1]{_{\textrm{#1}}}
\newcommand{\EtaProp}{\eta_{\textrm{prop}}}
\newcommand{\EtaSteller}{\eta_{\textrm{steller}}}
\def\jwwTitle{How to adjust multicopter parameters, multicopter model version 1}
\def\jwwSubject{}
\def\jwwKeywords{multicopter, quadrocopte, CRRCSim}
\def\jwwAuthor{Jens Wilhelm Wulf}
\hypersetup{pdftitle={\jwwTitle},%
pdfsubject={\jwwSubject},%
pdfkeywords={\jwwKeywords},%
pdfauthor={\jwwAuthor}}
\author{\jwwAuthor}
\title{\jwwTitle}
\date{06.12.2009}
\begin{document}
\numberwithin{equation}{section}
\maketitle
\tableofcontents
\clearpage
\setlength{\parindent}{0pt}
\setlength{\parskip}{5pt plus 2pt minus 1pt}
\section{General file format}
Take a look at {\tt qc01.xml} as an example.
Hard points/wheels, mass, inertia are just like with fixed wing models
(see \cite{l:C_FILE}),
the only difference is about aerodynamic data and controllers.
You need to define where propellers are mounted. Describe x- and
y-offsets to center of gravity and whether props are spinning
counter-clockwise ({\tt dir="-1"}).
All motors/propellers are assumed to be of the same type (except for
direction of rotation) and defined in the power-section as it is done
for fixed-wing models. Note that the simulation uses one battery for
every motor, so its capacity defined in the file is smaller than you
might think. {\tt qc01.xml} does not use the automagic type of description in
order to allow a more detailed fit to the real model.
Coordinate system: x positive forward, y positive right, z positive
down. Rotation rates around these axes are $p$, $q$, $r$.
In order to adjust the CRRCSim model to my real one, I used the
following steps. Beware: this is NOT easy, and some parts even plain
dangerous. I guess that people who are able to do this are able to
do the math themselves and much more.
\section{Statics}
Hover data measured on the real copter and used for some of the calculations here:
\begin{tabular}{r|r|r|r|r}
PWM-ratio & battery voltage & rpm & mass & $M$ (calculated, see below)\\
\hline
80/255 & 11,2 V & 2768 rpm & 405 g & 0.02 N\\
96/255 & 10,8 V & 3100 rpm & 505 g & 0.02494 N\\
110/255 & 10,6 V & 3397 rpm & 612 g & 0.03022 N\\
\end{tabular}
First of all, prop positions, mass and inertia should be quite accurate.
All this can simply be measured and calculated.
Describe your power plant.
Set {\tt yaw.dist} and {\tt roll.dist} to zero.
\subsection{Propeller}
Weight is 400\,g, so every motor/prop needs to create
$F = 0.1\,\unit{kg} \cdot 9.81\,\unit{m}/\unit{s}^2=0.981\,\unit{N}$.
Take a look at the source code to see how propeller force is calculated:
{\tt src/mod\_fdm/power/propeller.cpp}. When hovering, this is
\begin{subequations}
\begin{eqnarray}
\EtaProp &=& 0.65\\
\varrho &=& 1.225\,\unit{kg}/\unit{m}^3\\
F &=& \pi \cdot 0.25 \cdot D^2 \varrho \left(H n\right)^2 \cdot 1/2\, \EtaProp \label{f:PROP_F}
\end{eqnarray}
\end{subequations}
I know that my setup needs around 2800\,rpm to hover, $D$=0.235\,m.
Using these values and equation~\eqref{f:PROP_F} results in $H$=0.162\,m.
I recalculated using all the numbers from the table above, the mean
value is $H$=0.1644\,m.
You may ask about why I didn't just use the propeller's $H$ as defined by
the manufacturer. First, my prop is a modified standard one, so usual
rules don't apply. Secondly, I often read that manufacturers $H$ is not
accurate.
Set {\tt engine.log} to 1 and hover at fixed altitude using an attitude
controlled setup. CRRCSim will write lots of data to stdout: one line
per timestep and motor. Redirect this output to a file (is automatically
done on windows) in order to not slow your PC down.
Testing shows that the copter hovers at 2800\,rpm now. Fine.
Motor parameters need to be adjusted. Also see \cite{l:C_POWER}. However,
in this case I have some data at three operating points, but it does not
include motor current. Going back to the propeller code, lets calculate
the torque needed. Equations found in the code are:
\begin{subequations}
\begin{eqnarray}
P &=& F_X \, V_p / (2 \, \EtaProp) \\
P &=& F_X \, H \, n / (2 \, \EtaProp) \\
M &=& P / \omega \\
M &=& P / (2 \, \pi \, n) \\
M &=& F_X \, H \, n / (2 \, \EtaProp \, 2 \, \pi \, n)\\
M &=& F_X \, H / (4 \, \pi \, \EtaProp)
\end{eqnarray}
\end{subequations}
With $F_X = m/4 \cdot 9.81\,\unit{m}/\unit{s}^2$ this results in $M$ as
written into the table above.
\subsection{Engine}
So let's take a look at the engine's equations.
{\tt src/mod\_fdm/power/engine\_dcm.cpp} reveals
\begin{subequations}
\begin{eqnarray} \label{f:MOTOR}
\EtaSteller &=& 0.95 \\
U\vi{K} &=& \textrm{throttle} \cdot U \cdot \EtaSteller \\
U\vi{Gen} &=& \omega \cdot k\vi{M} \\
I\vi{M} &=& (U\vi{K} - U\vi{Gen}) / R\vi{I} \\
M\vi{M} &=& k\vi{M} \cdot I\vi{M} - k\vi{r} \cdot \omega - M\vi{r} \\
M\vi{r} &=& k\vi{M} \cdot I_0 \\
k\vi{r} &=& 0 \\
\end{eqnarray}
\end{subequations}
Which boils down to
\begin{equation}
M\vi{M} = k\vi{M} \cdot (\textrm{throttle} \cdot U \cdot 0.95 - \omega \cdot k\vi{M}) / R\vi{I} - I_0 \cdot k\vi{M}
\end{equation}
for us. There are three unknown parameters here and luckily I have three sets of data,
which solves to $k_M=0.0131$ Vs, $R_I=0.1839\,\Omega$, $I_0=-4.013$\,A. Of course a negative
$I_0$ is bullshit. Something wrong with the simulation equations? However,
I continue and force $I_0$ to be zero and solve again. Due to three data sets, I get
three solutions:
$k\vi{M}$ = 0.0081483226538728\,Vs, $R\vi{I}$ = 0.39817956295345\,$\Omega$ \\
$k\vi{M}$ = 0.0085130006948808\,Vs, $R\vi{I}$ = 0.37102864543948\,$\Omega$ \\
$k\vi{M}$ = 0.0089455381882278\,Vs, $R\vi{I}$ = 0.34435633250623\,$\Omega$ \\
Now motor current and voltage used are right. Don't be surprised because current
is high according to log output: this is the current flowing through the motor,
not the one which has to be delivered by the battery. The latter is lower
(we use PWM here).
\section{Dynamics}
I measured the real one's behaviour using step responses. This is
dangerous and you might need special firmware! However, I did it and
will use the results to tweak simulation parameters.
I used a firmware which records raw sensor data of every control cycle.
In this case motor voltage (as commanded to the controller) and rate
gyro output is important. After turning a switch, it turns of the
controller of the axis to be examined for a defined time (about 500\,ms in
my case). Afterwards, commands a predefined voltage to this axis for a
defined time (some hundred milliseconds). By turning the switch back,
the process can be interrupted at any time.
Of course you can only do this on a calm day. If you're out of luck, the
copter already leaves its attitude while the commanded voltage is zero.
However, it will do this once the predefined voltage is applied. React
quickly, it will go down and crash otherwise.
I tried getting the parameters from data gathered while the control loop
was closed. This is not dangerous at all, but only gave sane parameters
for rotation about the z-axis.
For x-axis, my controller commands voltage like this:
\begin{subequations} \label{f:U}
\begin{eqnarray}
u\vi{MotLeft} &=& u_0 + u\vi{ControllerX}\\
u\vi{MotRight} &=& u_0 - u\vi{ControllerX}
\end{eqnarray}
\end{subequations}
y-axis is the same.
So the controller is turned of for some time, $u\vi{ControllerX}$=0.
Afterwards $u\vi{ControllerX}$=const for some time. Rotation rate around
x-axis is recorded, let's call it $p$. For shortness, $u\vi{ControllerX}$=$u$.
I searched for parameters to make the following equation fit measurements (in laplace domain):
\begin{equation}
s \, p = a \, u/(\tau\,s+1)^2 - b \, p
\end{equation}
For x and y I found $a$=20\,rad/s$^2$/V, $b$=0, $\tau$=15\,ms.
For z I found $a$=5.3\,rad/s$^2$/V, $b$=0.5/s, $\tau$=5\,ms. $\tau$ is not that important and may be wrong here.
\subsection{Motor}
There is something undefined up to now: inertia of motor and propeller.
I approximate that from the x axis transfer function. The motors
acceleration is $M\vi{M} / J\vi{M}$; using equations~\eqref{f:MOTOR}:
\begin{equation}
\frac{d\,\omega}{dt} = k\vi{M}\,\left( U - \omega \, k\vi{M} \right) / (R\vi{I}\,J\vi{M})
\end{equation}
Bringing that from time domain to laplace and solving for $\omega/U$ gives
\begin{equation}
\omega/U = 1/k\vi{M}^2 \, \frac{1}{(R\vi{I} \, J\vi{M} / k\vi{M}^2) \, s + 1}
\end{equation}
So there is a PT1 (I guess its called first order time lag in
english) with $\tau=R\vi{I} \, J\vi{M} / k\vi{M}^2$.
I assume the motor speed as proportional to the copter's rotational
acceleration. But the motor's transfer function contains a PT1 while my
copter's rotation transfer function (see above) contains a PT2. Well, I
just say that a PT2 with $\tau\vi{pt2}$ is similar to a PT1 with
$\tau\vi{pt1}=\tau\vi{pt2} \cdot 1.7$. Therefore,
$15\,\unit{ms} \cdot 1.7=\tau \cdot 1.7=R\vi{I} \, J\vi{M}/k\vi{M}^2$.
Solving this for $J\vi{M}$ gives $J\vi{M}=5\cdot 10^{-6} \, \unit{kg} \, \unit{m}^2$.
Of course, all this assumed that only the motor's inertia is active
here, but there is the propeller's inertia, too. However, for the
simulation, only their sum is important, therefore I set {\tt
propeller.J=0}
and {\tt engine.J\_M=5E-6}.
The sum of both inertias could of course also be measured by applying a
fixed voltage to the motor and recording its rotational speed. However,
when getting to much details from the real system very accurately, keep
in mind that CRRCSim doesn't model everything that accurately -- so
using 'wrong' values might result in a more realistic simulation. In the
case of a multicopter this is very important, because for example the
time lag from measuring a rotation rate, calculating the controller,
transferring a new setpoint to the motor's speed controller, until this
speed controller applies the new voltage to the motor does depend on
software heavily. And it depends on software of at least two different
embedded electronics usually (main flight control and brushless
controller). Furthermore, different copter firmwares use different
filters here and there and so on...
So in this regard CRRCSim's multicopter model can't realistically model
every real one. It would be possible to do, but I guess noone would be
willing to find all those parameters...
\subsection{Aerodynamics}
For yaw I found $b$=0.5/s.
The simulator uses
\begin{subequations}
\begin{eqnarray}
\frac{d\,r}{dt} &=& M\vi{z} \, \frac{I\vi{xx}}{I\vi{xx}\,I\vi{zz} - I\vi{xz}^2}\\
M\vi{z} &=& - \texttt{yaw.damp1} \cdot r - \texttt{yaw.damp2} \cdot |r| \, r
\end{eqnarray}
\end{subequations}
as can be seen in {\tt EOM01::ls\_accel()} and
{\tt CRRC\_AirplaneSim\_MCopter01::aero()}.
Therefore,
\begin{equation}
\texttt{yaw.damp1} = b \, \frac{I\vi{xx}\,I\vi{zz} - I\vi{xz}^2}{I\vi{xx}}
\end{equation}
which results in {\tt yaw.damp1=0.00341, yaw.damp2=0}.
Although I found $b$=0 for nick and roll, {\tt roll.damp1=0.0009}, {\tt roll.damp2=0}
because the simulation likes at least some damping.
I have not thought about something to measure {\tt speed.damp}, so this
is done by try and error.
\section{Controllers}
Well, we're not through yet. Physics are defined now, but the control
loop of the copter is not\dots
Looking at the source, any controllers output means how much voltage is
applied in the sense of equation~\eqref{f:U} with
\begin{equation}
u\vi{ControllerX} = \textrm{URel} \cdot U\vi{Rel} = \textrm{URel} \cdot U\vi{Battery0} \cdot 0.7
\end{equation}
So if the controller output is one, the voltage $u\vi{ControllerX}$ that
will be applied is 0.7 times the voltage of the fully charged battery.
The controllers action will be independent of battery voltage as
long as it is at least 0.7 times the full charge voltage and the
controller output is smaller than one.
\subsection{Controller type "Omega"}
It gives rate controlled behaviour. Because it does not know about the
scaling with $U\vi{Battery0} \cdot 0.7$, its parameters depend on this
value. Using variable names for roll axis, with $p\vi{sp}$ being the
setpoint and $p\vi{pv}$ being the process value, its output is
\begin{subequations}
\begin{eqnarray}
p\vi{d} &=& p\vi{sp} - p\vi{pv}\\
u\vi{ControllerX} &=& U\vi{Battery0} \cdot 0.7 \left( K\vi{P} \, p\vi{d} + K\vi{D} \, \frac{d\,p\vi{pv}}{dt} + K\vi{I} \, \int p\vi{d} \right)
\end{eqnarray}
\end{subequations}
Compared to the settings of my real copter I had to halve $K\vi{D}$,
otherwise the simulation got unstable.
To the controller, maximum stick input is 0.5 (just like every other
signed stick input in CRRCSim) and $p\vi{sp} = {\tt stick} \cdot ${\tt
scale}. If {\tt scale\_roll\_pitch.exp} $>$ 1, a special scaling is used for
roll and nick to allow flips and loopings:
\begin{equation}
p\vi{sp} = \texttt{scale} \left( \texttt{a} \cdot \texttt{stick}
+ \texttt{b} \cdot \texttt{stick}^\texttt{exp}
\right)
\end{equation}
Here {\tt a}, {\tt b} and {\tt exp} are from the {\tt
scale\_roll\_pitch} section of the input file.
\clearpage
\begin{thebibliography}{99}
\bibitem{l:C_FILE}
CRRCSim fixed wing file format description,
CRRCSim installation: {\tt documentation/file\_format/index.html}
\bibitem{l:C_POWER}
CRRCSim power and propulsion system description,
CRRCSim installation: {\tt documentation/power\_propulsion/power\_propulsion.html}
\end{thebibliography}
\end{document}
|