Created
November 21, 2015 21:53
-
-
Save olexs/d4c4dabacbb5050ad5bb to your computer and use it in GitHub Desktop.
Script for generating a Lipo table and TWR vs. flight time scatter graph
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import division | |
import numpy as np | |
import matplotlib.pyplot as plt | |
from matplotlib.ticker import MultipleLocator, FormatStrFormatter | |
# http://godsnotwheregodsnot.blogspot.ru/2013/11/kmeans-color-quantization-seeding.html | |
Colormap = ["#FFFF00", "#1CE6FF", "#FF34FF", "#FF4A46", "#008941", "#006FA6", "#A30059", | |
"#FFDBE5", "#7A4900", "#0000A6", "#63FFAC", "#B79762", "#004D43", "#8FB0FF", "#997D87", | |
"#5A0007", "#809693", "#FEFFE6", "#1B4400", "#4FC601", "#3B5DFF", "#4A3B53", "#FF2F80", | |
"#61615A", "#BA0900", "#6B7900", "#00C2A0", "#FFAA92", "#FF90C9", "#B903AA", "#D16100", | |
"#DDEFFF", "#000035", "#7B4F4B", "#A1C299", "#300018", "#0AA6D8", "#013349", "#00846F", | |
"#372101", "#FFB500", "#C2FFED", "#A079BF", "#CC0744", "#C0B9B2", "#C2FF99", "#001E09", | |
"#00489C", "#6F0062", "#0CBD66", "#EEC3FF", "#456D75", "#B77B68", "#7A87A1", "#788D66", | |
"#885578", "#FAD09F", "#FF8A9A", "#D157A0", "#BEC459", "#456648", "#0086ED", "#886F4C"] | |
PrintBBCode = True | |
#FigureToFile = False | |
FigureToFile = "F:\Dropbox\Quadcopter\QR400\Rechner\plot.png" | |
NumberOfRotors = 4 | |
CopterWeight = 830 | |
FigureTitle = "QR400" | |
FigureSubtitle = "Flyduino X2212-1000kv, 9x4.5SF (%dg w/o battery)" % CopterWeight | |
MotorPropThrust = np.array([0, 337, 533, 698, 849, 1087]) | |
MotorPropAmps = np.array([0.4, 2.8, 6, 8.5, 11.7, 17.5]) | |
Lipos = [ | |
dict(Name = "Hacker 4S 5000 20C", | |
AmpHours = 5, | |
CRating = 20, | |
Mass = 503), | |
dict(Name = "Multistar 4S 5200 10C", | |
AmpHours = 5.2, | |
CRating = 10, | |
Mass = 433), | |
dict(Name = "Multistar Race 4S 1400 40C", | |
AmpHours = 1.4, | |
CRating = 40, | |
Mass = 153), | |
dict(Name = "Multistar 4S 16000 10C", | |
AmpHours = 16, | |
CRating = 10, | |
Mass = 1290), | |
# dict(Name = "Mylipo 4S 15000 15C", | |
# AmpHours = 15, | |
# CRating = 15, | |
# Mass = 1310), | |
dict(Name = "Multistar 4S 8000 10C", | |
AmpHours = 8, | |
CRating = 10, | |
Mass = 643), | |
dict(Name = "Multistar 4S 10000 10C", | |
AmpHours = 10, | |
CRating = 10, | |
Mass = 804), | |
dict(Name = "Tattu 4S 1800 45C", | |
AmpHours = 1.8, | |
CRating = 45, | |
Mass = 200), | |
# dict(Name = "Nanotech 4S 1800 65C", | |
# AmpHours = 1.8, | |
# CRating = 65, | |
# Mass = 203), | |
dict(Name = "SLS APL Magnum 4S 1800 45C", | |
AmpHours = 1.8, | |
CRating = 45, | |
Mass = 225), | |
dict(Name = "SLS XTRON 4S 4000 20C", | |
AmpHours = 4, | |
CRating = 20, | |
Mass = 427), | |
dict(Name = "SLS XTRON 4S 3000 30C", | |
AmpHours = 3, | |
CRating = 30, | |
Mass = 339), | |
dict(Name = "SLS XTRON 4S 3200 20C", | |
AmpHours = 3.2, | |
CRating = 20, | |
Mass = 345), | |
dict(Name = "SLS XTRON 4S 2600 30C", | |
AmpHours = 2.6, | |
CRating = 30, | |
Mass = 284), | |
dict(Name = "Tattu 4S 6750 25C", | |
AmpHours = 7, | |
CRating = 25, | |
Mass = 605), | |
# dict(Name = "SLS XTRON 4S 3600 30C", | |
# AmpHours = 3.6, | |
# CRating = 30, | |
# Mass = 417) | |
] | |
Lipos = sorted(Lipos, key=lambda k: k["AmpHours"]) | |
# Step 1: interpolate motor thrust-amps function | |
Coefficients = np.polyfit(MotorPropThrust, MotorPropAmps, 2) | |
InvCoefficients = np.polyfit(MotorPropAmps, MotorPropThrust, 2) | |
# Step 2: calculate and print tabular data for all lipos | |
TotalMotorPropMaxAmps = MotorPropAmps.max() * NumberOfRotors | |
ColumnLabels = ( | |
"Lipo name", | |
"Weight", | |
"AUW", | |
"Hover amps", | |
"Hover time", | |
"TWR" | |
) | |
if PrintBBCode: | |
print '[table="align: left"]' | |
print '[tr][td] [/td]' | |
for label in ColumnLabels: | |
print '[td][b]%s[/b][/td]' % label | |
print '[/tr]' | |
else: | |
print "%26s: %5d g" % ("Copter weight without lipo", CopterWeight) | |
print "%26s: %5d" % ("Number of motors", NumberOfRotors) | |
print "%-26s %6s %13s %12s %12s %10s" % ColumnLabels | |
print "-----------------------------------------------------------------------------" | |
LipoTWRs = np.array([]) | |
LipoTimes = np.array([]) | |
i = -1 | |
for Lipo in Lipos: | |
i = i + 1 | |
# hover thrust, amps, flight time | |
TotalMass = CopterWeight + Lipo["Mass"] | |
HoverThrustPerMotor = TotalMass / NumberOfRotors | |
HoverAmpsPerMotor = Coefficients[0] * HoverThrustPerMotor * HoverThrustPerMotor + Coefficients[1] * HoverThrustPerMotor + Coefficients[2] | |
TotalHoverAmps = HoverAmpsPerMotor * NumberOfRotors | |
FlightTimeMinutes = Lipo["AmpHours"] / TotalHoverAmps * 60 | |
# thrust to weight | |
NominalThrustToWeight = MotorPropThrust.max() * NumberOfRotors / TotalMass | |
# thrust limit by C-rating | |
MaxAmps = Lipo["AmpHours"] * Lipo["CRating"] | |
if MaxAmps < TotalMotorPropMaxAmps: | |
MaxAmpsPerMotor = MaxAmps / NumberOfRotors | |
MotorPropMaxThrust = InvCoefficients[0] * MaxAmpsPerMotor * MaxAmpsPerMotor + InvCoefficients[1] * MaxAmpsPerMotor + InvCoefficients[2] | |
RealThrustToWeight = MotorPropMaxThrust * NumberOfRotors / TotalMass | |
else: | |
RealThrustToWeight = NominalThrustToWeight | |
# print line | |
if PrintBBCode: | |
print '[tr]' | |
print '[td][COLOR="%s"][b]*[/b][/COLOR][/td]' % Colormap[i] | |
print '[td]%s[/td]' % Lipo["Name"] | |
print '[td]%d g[/td]' % Lipo["Mass"] | |
print '[td]%d g[/td]' % TotalMass | |
print '[td]%.1f A[/td]' % TotalHoverAmps | |
print '[td]%.2f min[/td]' % FlightTimeMinutes | |
print '[td]%.1f : 1%s[/td]' % (RealThrustToWeight, "*" if RealThrustToWeight < NominalThrustToWeight else "") | |
print '[/tr]' | |
else: | |
print "%-26s %d g %11d g %10.1f A %8.2f min %6.1f : 1%s" % ( | |
Lipo["Name"], | |
Lipo["Mass"], | |
TotalMass, | |
TotalHoverAmps, | |
FlightTimeMinutes, | |
RealThrustToWeight, | |
"*" if RealThrustToWeight < NominalThrustToWeight else "" | |
) | |
if RealThrustToWeight < NominalThrustToWeight: | |
Lipo["Name"] = Lipo["Name"] + " *" | |
# save data for plots | |
LipoTWRs = np.append(LipoTWRs, RealThrustToWeight) | |
LipoTimes = np.append(LipoTimes, FlightTimeMinutes) | |
Lipo["TWR"] = RealThrustToWeight | |
Lipo["Time"] = FlightTimeMinutes | |
if PrintBBCode: | |
print '[/table]' | |
else: | |
print "-----------------------------------------------------------------------------" | |
print "(*) Maximum thrust and TWR limited by lipo C-rating" | |
# Step 3: Plot scatter graph of TWR vs. flight time | |
fig, ax = plt.subplots(figsize=(7,6)) | |
plt.scatter(LipoTimes, LipoTWRs, c=Colormap, s=50) | |
for Lipo in Lipos: | |
plt.annotate( | |
Lipo["Name"], | |
xy = (Lipo["Time"], Lipo["TWR"]), | |
xytext = (5, 0), | |
fontsize = 9, | |
textcoords = 'offset points', ha = 'left', va = 'center') | |
plt.grid() | |
fig.suptitle(FigureTitle, fontsize=14, fontweight='bold') | |
ax.set_title(FigureSubtitle) | |
plt.ylabel('Thrust-to-weight ratio') | |
plt.xlabel('Hover time (100% capacity)') | |
plt.ylim((2, 4.5)) | |
plt.xlim((10, 45)) | |
ax.yaxis.set_major_formatter(FormatStrFormatter('%3.1f : 1')) | |
ax.xaxis.set_major_formatter(FormatStrFormatter('%d min')) | |
if FigureToFile: | |
plt.savefig(FigureToFile) | |
else: | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment