Skip to content

Instantly share code, notes, and snippets.

@kubark42
Last active January 6, 2021 19:54
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 kubark42/53b0ccd7ec310fcf0136b47c166cbdbb to your computer and use it in GitHub Desktop.
Save kubark42/53b0ccd7ec310fcf0136b47c166cbdbb to your computer and use it in GitHub Desktop.
AC5M eRussia.ipynb
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"source": [
"using Plots\n",
"using DataFrames\n",
"using LinearAlgebra"
],
"outputs": [],
"execution_count": 20,
"metadata": {
"collapsed": true,
"outputExpanded": false,
"jupyter": {
"source_hidden": false,
"outputs_hidden": false
},
"nteract": {
"transient": {
"deleting": false
}
},
"execution": {
"iopub.status.busy": "2021-01-06T19:54:03.481Z",
"iopub.execute_input": "2021-01-06T19:54:03.493Z",
"iopub.status.idle": "2021-01-06T19:54:03.507Z"
}
}
},
{
"cell_type": "markdown",
"source": [
"# Mass and CG of existing system\n",
"\n",
"## From flight manual\n",
"\n",
" - Basic empty weight: **175kg**\n",
" - The C.G. position of an empty motorglider (airframe + engine):\n",
" - with the engine in: **550mm**\n",
" - with the engine out: **605mm**\n",
" - Diameter of the propeller is **1180mm**.\n",
" \n",
" We must guess at where the engine pylon is located. We do this from the profile view in the manual, and arrive at 5300/375*93 = ~**1300mm** from the datum (i.e. the leading edge)"
],
"metadata": {
"nteract": {
"transient": {
"deleting": false
}
}
}
},
{
"cell_type": "code",
"source": [
"emptyMass = 175\n",
"emptyCg_engineIn = .550\n",
"emptyCg_engineOut = .605\n",
"\n",
"deltaCg = emptyCg_engineOut - emptyCg_engineIn\n",
"\n",
"propellerEngineOffset = .1\n",
"\n",
"# Assume that the pylon length is the propeller radius, minus the a bit because the engine is lower than the propeller\n",
"pylonLength = 1.180/2 - propellerEngineOffset \n",
"\n",
"# CG + deltaCG = sum(Moments + deltaEngineMoment)/sum(Masses) --> deltaEngineMoment = deltaCG * Mass\n",
"deltaEngineMoment = deltaCg * emptyMass\n",
"\n",
"# deltaEngineMoment = engineMass * arm_out - engineMass * arm_in = motorMass * (arm_out - arm_in) = engineMass * ((arm_in + pylonLength) - arm_in) = engineMass*(pylonLength) --> engineMass = deltaEngineMoment / pylonLength\n",
"engineMass = round(deltaEngineMoment / pylonLength, digits=2)\n"
],
"outputs": [
{
"output_type": "execute_result",
"execution_count": 15,
"data": {
"text/plain": "19.64"
},
"metadata": {}
}
],
"execution_count": 15,
"metadata": {
"collapsed": true,
"outputExpanded": false,
"jupyter": {
"source_hidden": false,
"outputs_hidden": false
},
"nteract": {
"transient": {
"deleting": false
}
},
"execution": {
"iopub.status.busy": "2021-01-06T19:53:21.899Z",
"iopub.execute_input": "2021-01-06T19:53:25.549Z",
"iopub.status.idle": "2021-01-06T19:53:25.741Z"
}
}
},
{
"cell_type": "markdown",
"source": [
"# Mass and CG of new system\n"
],
"metadata": {
"nteract": {
"transient": {
"deleting": false
}
}
}
},
{
"cell_type": "code",
"source": [
"# All weight in kg\n",
"# All distances in m\n",
"\n",
"w_empty = 175\n",
"L_empty = .550\n",
"\n",
"w_pilot = 85\n",
"L_pilot = -.380\n",
"\n",
"w_engine = -engineMass\n",
"L_engineOut = 1.300\n",
"L_engineIn = 1.300 - pylonLength\n",
"\n",
"# Assume the propeller hub, blades, and spinner are part of the same package\n",
"w_woodPropeller = -1.6\n",
"L_woodPropellerIn = L_engineIn\n",
"L_woodPropellerOut = L_engineOut + .1 # This allows the propeller to be shifted a few cm behind the motor. Note that this value is only applicable when the engine is extended\n",
"\n",
"w_fuelTank = -(1 + 3) # 1kg for the tank, and 3kg of fuel\n",
"L_fuelTank = 0 # It's basically right above the CG\n",
"\n",
"# Assume using the REG 30 from Rotex\n",
"w_motor = 4.1\n",
"L_motorIn = L_engineIn + propellerEngineOffset\n",
"L_motorOut = L_engineOut - .05 # This allows the motor to be shifted a few cm away from the pylon. Note that this value is only applicable when the engine is extended\n",
"\n",
"w_motorMount = 0.3 # Guesstimate about firewall weight, with hardware\n",
"L_motorMountIn = L_motorIn\n",
"L_motorMountOut = L_motorOut\n",
"\n",
"# Assume the propeller hub, blades, and spinner are part of the same package\n",
"w_CfPropeller = 0.8\n",
"L_CfPropellerIn = L_motorIn\n",
"L_CfPropellerOut = L_motorOut + .1 # This allows the propeller to be shifted a few cm behind the motor. Note that this value is only applicable when the engine is extended\n",
"\n",
"# Guessing a screen + throttle lever will weigh around 250g\n",
"w_controlPanel = 0.25\n",
"L_controlPanel = -0.890\n",
"\n",
"# Removing the SLA \n",
"w_controlPanel = 6\n",
"L_controlPanel = -0.890\n",
"\n",
"# Assume the battery pack will be ~30cm long, and that it can't be coser than a few inches from the rear bulkhead\n",
"w_battery = 13\n",
"L_battery = (L_engineOut - .3/2 - 0.30)\n",
"\n",
"# Guessing a quality ESC with big heat sinks will weigh 1.5kg\n",
"w_ESC = 1.5 * 2.2\n",
"L_ESC = L_battery + .10\n",
"\n",
"# Assume 4AWG aluminum wire (C.f. http://www.interfacebus.com/Aluminum_Wire_AWG_Size.html) and allow for 50% insulation weight\n",
"cableWeightPerFoot_lbs = 39.2/1000*1.5\n",
"cableResistancePerFoot = 0.408/1000\n",
"\n",
"L_cables = (L_motorIn - L_battery)/2 # assume that the cable's CG is at the midway point\n",
"w_cables = 2* (L_cables*2/.0254)/12 * cableWeightPerFoot_lbs /2.2 # Don't forget to multiply by 2 for both (+) and (-) cables and by 2 for doubling the length from the CG\n",
"\n",
"# Create an empty dataframe\n",
"df = DataFrame(Name = String[], Weight_kg = Float64[],\n",
" MomentArm_In = Float64[], MomentArm_Out = Float64[])\n",
"\n",
"# Populate it\n",
"push!(df, [\"empty airframe\", w_empty, L_empty, L_empty] )\n",
"push!(df, [\"removed engine\", w_engine, L_engineIn, L_engineIn] )\n",
"push!(df, [\"removed wood propeller\", w_woodPropeller, L_woodPropellerIn, L_woodPropellerIn] )\n",
"push!(df, [\"pilot + parachute\", w_pilot, L_pilot, L_pilot] )\n",
"push!(df, [\"battery\", w_battery, L_battery, L_battery] )\n",
"push!(df, [\"cables\", w_cables, L_cables, L_cables] )\n",
"push!(df, [\"motor mount\", w_motorMount, L_motorMountIn, L_motorMountOut] )\n",
"push!(df, [\"control panel\", w_controlPanel, L_controlPanel, L_controlPanel] )\n",
"push!(df, [\"motor\", w_motor, L_motorIn, L_motorOut] )\n",
"push!(df, [\"CF propeller\", w_CfPropeller, L_CfPropellerIn, L_CfPropellerOut] )\n",
"push!(df, [\"ESC\", w_ESC, L_ESC, L_ESC] )\n",
"\n",
"display(df)\n",
"println()\n",
"\n",
"# Calculate the CG\n",
"weights = df[!,:Weight_kg]\n",
"momentArmsIn = df[!,:MomentArm_In]\n",
"momentArmsOut = df[!,:MomentArm_Out]\n",
"\n",
"netMomentIn = weights' * momentArmsIn\n",
"cgIn = netMomentIn / sum(weights)\n",
"cgIn_stationPercentage = ((cgIn - 0.127)/(0.267 - 0.127)) * 100\n",
"\n",
"netMomentOut = weights' * momentArmsOut\n",
"cgOut = netMomentOut / sum(weights)\n",
"cgOut_stationPercentage = ((cgOut - 0.127)/(0.267 - 0.127)) * 100\n",
"\n",
"println(\"Weight: \", round(sum(weights), digits=1), \"kg, \", round(sum(weights)/300 * 100), \"% of MTOW (300kg)\")\n",
"println(\"min CG: 127mm, max CG: 267mm\")\n",
"\n",
"println(\"CG motor retracted: \", round(cgIn*1000), \"mm, \", round(cgIn_stationPercentage), \"%\")\n",
"\n",
"println(\"CG motor deployed: \", round(cgOut*1000), \"mm, \", round(cgOut_stationPercentage), \"%\")"
],
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "11×4 DataFrame\n│ Row │ Name │ Weight_kg │ MomentArm_In │ MomentArm_Out │\n│ │ \u001b[90mString\u001b[39m │ \u001b[90mFloat64\u001b[39m │ \u001b[90mFloat64\u001b[39m │ \u001b[90mFloat64\u001b[39m │\n├─────┼────────────────────────┼───────────┼──────────────┼───────────────┤\n│ 1 │ empty airframe │ 175.0 │ 0.55 │ 0.55 │\n│ 2 │ removed engine │ -19.64 │ 0.81 │ 0.81 │\n│ 3 │ removed wood propeller │ -1.6 │ 0.81 │ 0.81 │\n│ 4 │ pilot + parachute │ 85.0 │ -0.38 │ -0.38 │\n│ 5 │ battery │ 13.0 │ 0.85 │ 0.85 │\n│ 6 │ cables │ 0.0105225 │ 0.03 │ 0.03 │\n│ 7 │ motor mount │ 0.3 │ 0.91 │ 1.25 │\n│ 8 │ control panel │ 6.0 │ -0.89 │ -0.89 │\n│ 9 │ motor │ 4.1 │ 0.91 │ 1.25 │\n│ 10 │ CF propeller │ 0.8 │ 0.91 │ 1.35 │\n│ 11 │ ESC │ 3.3 │ 0.95 │ 0.95 │",
"text/html": "<table class=\"data-frame\"><thead><tr><th></th><th>Name</th><th>Weight_kg</th><th>MomentArm_In</th><th>MomentArm_Out</th></tr><tr><th></th><th>String</th><th>Float64</th><th>Float64</th><th>Float64</th></tr></thead><tbody><p>11 rows × 4 columns</p><tr><th>1</th><td>empty airframe</td><td>175.0</td><td>0.55</td><td>0.55</td></tr><tr><th>2</th><td>removed engine</td><td>-19.64</td><td>0.81</td><td>0.81</td></tr><tr><th>3</th><td>removed wood propeller</td><td>-1.6</td><td>0.81</td><td>0.81</td></tr><tr><th>4</th><td>pilot + parachute</td><td>85.0</td><td>-0.38</td><td>-0.38</td></tr><tr><th>5</th><td>battery</td><td>13.0</td><td>0.85</td><td>0.85</td></tr><tr><th>6</th><td>cables</td><td>0.0105225</td><td>0.03</td><td>0.03</td></tr><tr><th>7</th><td>motor mount</td><td>0.3</td><td>0.91</td><td>1.25</td></tr><tr><th>8</th><td>control panel</td><td>6.0</td><td>-0.89</td><td>-0.89</td></tr><tr><th>9</th><td>motor</td><td>4.1</td><td>0.91</td><td>1.25</td></tr><tr><th>10</th><td>CF propeller</td><td>0.8</td><td>0.91</td><td>1.35</td></tr><tr><th>11</th><td>ESC</td><td>3.3</td><td>0.95</td><td>0.95</td></tr></tbody></table>",
"text/latex": "\\begin{tabular}{r|cccc}\n\t& Name & Weight\\_kg & MomentArm\\_In & MomentArm\\_Out\\\\\n\t\\hline\n\t& String & Float64 & Float64 & Float64\\\\\n\t\\hline\n\t1 & empty airframe & 175.0 & 0.55 & 0.55 \\\\\n\t2 & removed engine & -19.64 & 0.81 & 0.81 \\\\\n\t3 & removed wood propeller & -1.6 & 0.81 & 0.81 \\\\\n\t4 & pilot + parachute & 85.0 & -0.38 & -0.38 \\\\\n\t5 & battery & 13.0 & 0.85 & 0.85 \\\\\n\t6 & cables & 0.0105225 & 0.03 & 0.03 \\\\\n\t7 & motor mount & 0.3 & 0.91 & 1.25 \\\\\n\t8 & control panel & 6.0 & -0.89 & -0.89 \\\\\n\t9 & motor & 4.1 & 0.91 & 1.25 \\\\\n\t10 & CF propeller & 0.8 & 0.91 & 1.35 \\\\\n\t11 & ESC & 3.3 & 0.95 & 0.95 \\\\\n\\end{tabular}\n"
},
"metadata": {}
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"\n",
"Weight: 266.3kg, 89.0% of MTOW (300kg)\n",
"min CG: 127mm, max CG: 267mm\n",
"CG motor retracted: 227.0mm, 71.0%\n",
"CG motor deployed: 233.0mm, 76.0%\n"
]
}
],
"execution_count": 16,
"metadata": {
"collapsed": true,
"outputExpanded": false,
"jupyter": {
"source_hidden": false,
"outputs_hidden": false
},
"nteract": {
"transient": {
"deleting": false
}
},
"execution": {
"iopub.status.busy": "2021-01-06T19:53:25.756Z",
"iopub.execute_input": "2021-01-06T19:53:25.766Z",
"iopub.status.idle": "2021-01-06T19:53:32.255Z"
}
}
},
{
"cell_type": "markdown",
"source": [
"# Additional mass savings and advantages\n",
"\n",
" - Gas springs for lowering the engine are now too strong?\n",
" - The motor is now easier to raise from the cockpit, no longer requiring as much muscle.\n",
" - The ESC can stop the motor in the appropriate position, or have a very slow \"cogging mode\" which advances the motor until the propeller reaches the stop.\n",
" - Reduced prop breakage because the stop pin no longer accidentally pierces the prop?"
],
"metadata": {
"nteract": {
"transient": {
"deleting": false
}
}
}
},
{
"cell_type": "markdown",
"source": [
"# Airframe power requirements"
],
"metadata": {
"nteract": {
"transient": {
"deleting": false
}
}
}
},
{
"cell_type": "code",
"source": [
"MTOW = 300 # Maximum takeoff weight, in [kg]. \n",
"ld_deployed = 18 # L/D when engine is deployed\n",
"sinkRate_best = 0.82 * 1.1# in [m/s], downrated ~10% from published figures\n",
"\n",
"v_ld = 53 *.511 # in [m/s]\n",
"v_sr = 48 *.511 # in [m/s]. This is a guesstimate from the stall at 36kts and the best LD at 53kts.\n",
"\n",
"# Desired climb rate, in [m/s]\n",
"vz_desired = 2.5\n",
"\n",
"# Calculate thrust required for level flight\n",
"F_cruise = MTOW*9.81/ld_deployed\n",
"\n",
"# Calculate cruise and climb mechanical power\n",
"P_cruise = F_cruise*v_ld\n",
"P_climb = F_cruise*v_sr + MTOW*9.81 * vz_desired\n",
"\n",
"F_climb = P_climb/v_sr\n",
"\n",
"println(round.([F_cruise F_climb P_cruise P_climb], digits = 1))"
],
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"[163.5 463.5 4428.1 11367.8]\n"
]
}
],
"execution_count": 17,
"metadata": {
"collapsed": true,
"outputExpanded": false,
"jupyter": {
"source_hidden": false,
"outputs_hidden": false
},
"nteract": {
"transient": {
"deleting": false
}
},
"execution": {
"iopub.status.busy": "2021-01-06T19:53:32.270Z",
"iopub.execute_input": "2021-01-06T19:53:32.279Z",
"iopub.status.idle": "2021-01-06T19:53:32.301Z"
}
}
},
{
"cell_type": "markdown",
"source": [
"## Powerplant description"
],
"metadata": {
"nteract": {
"transient": {
"deleting": false
}
}
}
},
{
"cell_type": "code",
"source": [
"# Propeller max efficiency, in %/100\n",
"eta_prop_climb = .7\n",
"eta_prop_cruise = .75\n",
"\n",
"# Transmission effiency, in %/100\n",
"eta_transmission = .98\n",
"\n",
"# Calculate shaft power\n",
"P_shaft_cruise = P_cruise / (eta_prop_cruise * eta_transmission)\n",
"P_shaft_max = P_climb / (eta_prop_climb * eta_transmission)\n",
"\n",
"# Motor efficiency, in %/100\n",
"eta_motor_cruisePower = .93\n",
"eta_motor_maxPower = .90\n",
"\n",
"# Calculate motor power\n",
"P_motor_cruise = P_shaft_cruise / eta_motor_cruisePower\n",
"P_motor_max = P_shaft_max / eta_motor_maxPower\n",
"\n",
"# Calculate motor power loss\n",
"P_motorLosses_cruise = P_motor_cruise * (1-eta_motor_cruisePower)\n",
"P_motorLosses_max = P_motor_max * (1-eta_motor_maxPower)\n",
"\n",
"println(\"Shaft power out: \", round.([P_shaft_cruise P_shaft_max], digits = 1))\n",
"\n",
"println(\"Motor power in: \", round.([P_motor_cruise P_motor_max P_motorLosses_max P_motorLosses_cruise], digits = 1))"
],
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Shaft power out: [6024.6 16571.2]\n",
"Motor power in: [6478.0 18412.4 1841.2 453.5]\n"
]
}
],
"execution_count": 18,
"metadata": {
"collapsed": true,
"outputExpanded": false,
"jupyter": {
"source_hidden": false,
"outputs_hidden": false
},
"nteract": {
"transient": {
"deleting": false
}
},
"execution": {
"iopub.status.busy": "2021-01-06T19:53:32.314Z",
"iopub.execute_input": "2021-01-06T19:53:32.324Z",
"iopub.status.idle": "2021-01-06T19:53:32.345Z"
}
}
},
{
"cell_type": "markdown",
"source": [
"# Costs"
],
"metadata": {
"nteract": {
"transient": {
"deleting": false
}
}
}
},
{
"cell_type": "code",
"source": [
"euro2dollar = 1.09\n",
"\n",
"# Create an empty dataframe\n",
"df = DataFrame(Item = String[], Price = Float64[])\n",
"\n",
"# Prices in $, not including shipping, taxes, or duties\n",
"p_motor = 1400 * euro2dollar\n",
"p_propeller = 300 * euro2dollar\n",
"p_battery = (420*6) * .9 # Represents the 10% discount for bulk orders\n",
"p_ESC = 979 * euro2dollar\n",
"p_cables = 40\n",
"p_hardware = 100\n",
"p_controlPanel = 200\n",
"p_Charger = 270\n",
"\n",
"\n",
"# Populate it\n",
"push!(df, [\"battery\", p_battery] )\n",
"push!(df, [\"cables\", p_cables] )\n",
"push!(df, [\"hardware\", p_hardware] )\n",
"push!(df, [\"control panel\", p_controlPanel] )\n",
"push!(df, [\"motor\", p_motor] )\n",
"push!(df, [\"propeller\", p_propeller] )\n",
"push!(df, [\"ESC\", p_ESC] )\n",
"push!(df, [\"charger\", p_Charger] )\n",
"\n",
"display(df)\n",
"println()\n",
"\n",
"costs = df[!,:Price]\n",
"\n",
"subTotal = sum(costs)\n",
"\n",
"# Add in 15% for shipping and other costs\n",
"totalPrice = subTotal * 1.15\n",
"\n",
"println(round.([subTotal totalPrice]))"
],
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "8×2 DataFrame\n│ Row │ Item │ Price │\n│ │ \u001b[90mString\u001b[39m │ \u001b[90mFloat64\u001b[39m │\n├─────┼───────────────┼─────────┤\n│ 1 │ battery │ 2268.0 │\n│ 2 │ cables │ 40.0 │\n│ 3 │ hardware │ 100.0 │\n│ 4 │ control panel │ 200.0 │\n│ 5 │ motor │ 1526.0 │\n│ 6 │ propeller │ 327.0 │\n│ 7 │ ESC │ 1067.11 │\n│ 8 │ charger │ 270.0 │",
"text/html": "<table class=\"data-frame\"><thead><tr><th></th><th>Item</th><th>Price</th></tr><tr><th></th><th>String</th><th>Float64</th></tr></thead><tbody><p>8 rows × 2 columns</p><tr><th>1</th><td>battery</td><td>2268.0</td></tr><tr><th>2</th><td>cables</td><td>40.0</td></tr><tr><th>3</th><td>hardware</td><td>100.0</td></tr><tr><th>4</th><td>control panel</td><td>200.0</td></tr><tr><th>5</th><td>motor</td><td>1526.0</td></tr><tr><th>6</th><td>propeller</td><td>327.0</td></tr><tr><th>7</th><td>ESC</td><td>1067.11</td></tr><tr><th>8</th><td>charger</td><td>270.0</td></tr></tbody></table>",
"text/latex": "\\begin{tabular}{r|cc}\n\t& Item & Price\\\\\n\t\\hline\n\t& String & Float64\\\\\n\t\\hline\n\t1 & battery & 2268.0 \\\\\n\t2 & cables & 40.0 \\\\\n\t3 & hardware & 100.0 \\\\\n\t4 & control panel & 200.0 \\\\\n\t5 & motor & 1526.0 \\\\\n\t6 & propeller & 327.0 \\\\\n\t7 & ESC & 1067.11 \\\\\n\t8 & charger & 270.0 \\\\\n\\end{tabular}\n"
},
"metadata": {}
},
{
"output_type": "stream",
"name": "stdout",
"text": [
"\n",
"[5798.0 6668.0]\n"
]
}
],
"execution_count": 19,
"metadata": {
"collapsed": true,
"outputExpanded": false,
"jupyter": {
"source_hidden": false,
"outputs_hidden": false
},
"nteract": {
"transient": {
"deleting": false
}
},
"execution": {
"iopub.status.busy": "2021-01-06T19:53:32.356Z",
"iopub.execute_input": "2021-01-06T19:53:32.365Z",
"iopub.status.idle": "2021-01-06T19:53:32.474Z"
}
}
},
{
"cell_type": "code",
"source": [],
"outputs": [],
"execution_count": null,
"metadata": {
"collapsed": true,
"outputExpanded": false,
"jupyter": {
"source_hidden": false,
"outputs_hidden": false
},
"nteract": {
"transient": {
"deleting": false
}
}
}
},
{
"cell_type": "code",
"source": [],
"outputs": [],
"execution_count": null,
"metadata": {
"collapsed": true,
"jupyter": {
"source_hidden": false,
"outputs_hidden": false
},
"nteract": {
"transient": {
"deleting": false
}
}
}
}
],
"metadata": {
"kernel_info": {
"name": "julia-1.5"
},
"language_info": {
"file_extension": ".jl",
"name": "julia",
"mimetype": "application/julia",
"version": "1.5.2"
},
"kernelspec": {
"argv": [
"/Applications/Julia-1.5.app/Contents/Resources/julia/bin/julia",
"-i",
"--startup-file=yes",
"--color=yes",
"--project=@.",
"/Users/kenz/.julia/packages/IJulia/yLI42/src/kernel.jl",
"{connection_file}"
],
"display_name": "Julia 1.5.2",
"env": {},
"interrupt_mode": "signal",
"language": "julia",
"name": "julia-1.5"
},
"gist_id": "53b0ccd7ec310fcf0136b47c166cbdbb",
"nteract": {
"version": "0.27.0"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment