Skip to content

Instantly share code, notes, and snippets.

@olexs
Created November 21, 2015 21:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save olexs/d4c4dabacbb5050ad5bb to your computer and use it in GitHub Desktop.
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
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
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