Sample Python Code for Quadcopter Arm Design

This is a sample Python code to calculate the maximum bending stress and total mass of the beam or quadcopter arm that you design.

There are several model parameters that you can modify. You need to provide your design of the beam as follows.

  • Thickness or height of beam
  • Width of beam
  • Formula for the cross-sectional area
  • Formula for the second moment of area

The above are given as functions of the position $x$ along the length of the beam. Your task is to give an optimal design of the beam through variations of the cross sectional shape (width, thickness and other parameters where needed) along its length.

You will also need to give the formulae for the cross-sectional area and second moment of area of the beam along its length. These can be given as functions of width and thickness, which varies along the length. Otherwise, you may also give explicit formula for the cross-sectional area and second moment of area in terms of $x$.

For example, you may choose a rectangular cross-section with a linear taper in thickness and constant width.

$$ h(x) = 0.015 - 0.005(L-x) $$$$ w(x) = 0.015 $$

The cross-sectional area and second moment of area of the beam at any location will be given as follows.

$$ A(x) = h(x) \ w(x) $$$$ I(x) = \frac{w(x) \ h(x)^3}{12} $$

With these inputs, the script will calculate the maximum bending stress in the beam and also its weight. You should check that the design meets the criterion in terms of strength, which is a factor of safety of 2. Plots of the bending moment and bending stress are also generated.

You can try designs with different cross-sections, such as circular shape and hollow section. You will need to derive or find the formulae for the area and second moment of area of the cross-section that you choose.

See if you can come up with a lighter beam than your classmates without compromising its strength!

In [1]:
import numpy as np
import matplotlib.pyplot as plt
% matplotlib inline

# Define the height, width and second moment of area 
# as a function of distance x from clamped end.

# Do not change the names of these four functions.
# You can change the expressions within each function.

def height(x):
    # Give expression of height in m
    # Sample code for a tapered thickness
    return 0.015 - 0.005*(L-x)

def width(x):
    # Give your expression of width in m
    # Sample code for a constant width
    return 0.015

def area(x):
    # Give the expression for your design here
    # Sample code: This is for rectangular cross-section
    return width(x) * height(x)

def area_moment(x):
    # Give the expression for your design here
    # Sample code: This is for rectangular cross-section
    return (width(x) * height(x)**3)/12

## You do not need to change the code below this
## But you are encouraged to look through and understand how the code works!

# Model parameters

T = 10            # Thrust at each arm in N
rho = 1000        # Density in kg/m^3
L = 0.5           # Length of arm in m
stress_y = 30e6   # Yield strength in Pa

N = 201                   # Number of segments to divide the arm for calculation
x = np.linspace(0,L,N)    # Generate N evenly-spaced data points from 0 to L
dx = x[1]                 # Spacing between each x-location

moment = np.zeros(N)      # Allocate space to store the moment at each location along the length        
stress = np.zeros(N)      # Allocate space to store the bending stress at each location along the length
mass = 0                  # We will accumulate the mass to this variable as we go along the beam

# We use a for loop to run through all the locations of x or all the small segments with width dx
# Calculate moment and stress for each point and also sum up the mass
for i in range(N):
    # The moment take on a linear variation due to point force at the end (See notes)
    moment[i] = T*(L - x[i])    
    # With the moment and 2nd moment of area, get the bending stress
    stress[i] = - moment[i]*(height(x[i])/2)/area_moment(x[i])
    # Calculate the small segment of mass (dx) and accumulate into the mass variable
    mass += rho*dx*area(x[i])

# Done with the loop!

# We can now look for the largest bending stress along the length of the beam
stress_max = max(abs(stress))  # Maximum of the absolute stress values calculated above

print 'Mass = {:.3f} kg'.format(mass)  
print 'Maximum stress = {:.2f}  MPa'.format(stress_max/1e6)

# Check factor of safety
safety = stress_y/stress_max
print 'Factor of safety = {:.3f} '.format(safety)
if (safety < 2):
    print 'Your factor of safety is less than 2! Redesign and try again.'
else:
    print 'Good! Your factor of safety is greater or equal to 2.'

# Plot data
plt.figure(1)
plt.plot(x,moment)
plt.ylabel('moment (Nm)')
plt.xlabel('position x (m)')
plt.title('Moment along the arm')

plt.figure(2)
plt.plot(x,stress/1e6)
plt.ylabel('stress (MPa)')
plt.xlabel('position x (m)')
plt.title('Bending stress along the arm')
Mass = 0.104 kg
Maximum stress = 12.80  MPa
Factor of safety = 2.344 
Good! Your factor of safety is greater or equal to 2.
Out[1]:
<matplotlib.text.Text at 0x7f6fad711990>