Skip to content

Instantly share code, notes, and snippets.

@caudamus
Last active November 28, 2018 23:13
Show Gist options
  • Save caudamus/79b6e4d1bb9f266b462047f0913617cf to your computer and use it in GitHub Desktop.
Save caudamus/79b6e4d1bb9f266b462047f0913617cf to your computer and use it in GitHub Desktop.
Tensegrity Design Analysis
#!/usr/bin/env python
import numpy as np
from collections import OrderedDict
from scipy.optimize import LinearConstraint, minimize, BFGS
def normlen(v):
''' length of norm of a vector '''
return np.sqrt(np.sum(np.square(v)))
# FREE PARAMETERS
L = 20 # Length of upper triangle side
H = 9 # Height of structure
G = 12 # Length of lower triangle side
T = 0 # Angle (degrees) of top triangle (should probably be 0)
U = 200 # Angle (degrees) of bottom triangle (should probably be 200)
# GEOMETRY CALCULATION
X, Y, Z = np.eye(3) # Unit vectors
J = L * np.sqrt(3) / 3 # Radius of upper triangle
K = G * np.sqrt(3) / 3 # Radius of lower triangle
# Top triangle points
a, b, c = [np.deg2rad(T + x) for x in range(0, 360, 120)] # Angles in radians
A, B, C = [np.array([np.sin(x) * J, np.cos(x) * J, H]) for x in (a, b, c)]
# Bottom triangle points
d, e, f = [np.deg2rad(U + x) for x in range(0, 360, 120)] # Angles in radians
D, E, F = [np.array([np.sin(x) * K, np.cos(x) * K, 0]) for x in (d, e, f)]
def normvec(v):
''' return a normalized vector '''
return np.array(v) / normlen(v)
# structural force vectors
structure = OrderedDict([
('rod AD', normvec(A - D)),
('rope AB', normvec(B - A)),
('rope AC', normvec(C - A)),
('rope AE', normvec(E - A)),
])
SV = np.array(list(structure.values())).transpose()
# hammock force vectors
hammocks = OrderedDict([
('hammock AB', normvec(B - A - Z * L / 2)),
('hammock AC', normvec(C - A - Z * L / 2)),
])
HV = np.array(list(hammocks.values())).transpose()
def error(hf, sf):
''' Calculate error in total forces '''
return normlen(np.dot(SV, sf) + np.dot(HV, hf))
def solve_sf(hf):
''' Solve for structural forces (sf) given hammock forces (hf) '''
# Convert to array
hf = np.array(hf)
# Total forces at corner must equal zero
# SV * sf + HV * hf = 0, therefore: -HV * hf <= SV * sf <= -HV * hf
equality_constraint = LinearConstraint(SV, -np.dot(HV, hf), -np.dot(HV, hf))
# Also forces must all be nonnegative
n = len(structure)
positive_constraint = LinearConstraint(np.eye(n), np.zeros(n), np.ones(n) * np.inf)
# We will use both constraints for optimization
constraints = [equality_constraint, positive_constraint]
# Calculate structure forces as minimum total forces which satisfy constraints
sf = minimize(np.sum, # function to minimize -- want the smallest sum of total forces
np.zeros(n), # initial guess
method='trust-constr', # For when we have LinearConstraint's
constraints=constraints, # Constraints on our solution space
# These two are defaults, but need to be included because of a bug.
jac='2-point', hess=BFGS()) # https://github.com/scipy/scipy/issues/8867
return sf.x
def main():
# Check geometry
print('Top triangle sides', normlen(A - B), normlen(B - C), normlen(C - A))
print('Bottom triangle sides', normlen(D - E), normlen(E - F), normlen(F - D))
print('Rod lengths', normlen(A - D), normlen(B - E), normlen(C - F))
# Print out structure forces for different hammock loads
for hf in [[200, 200], [200, 0], [0, 200]]:
sf = solve_sf(hf)
print('hammock forces:', list(zip(hammocks.keys(), hf)))
print('error', error(hf, sf))
print('structure forces:')
for name, force in zip(structure.keys(), sf):
print(f' {name} {force:.2f}')
if __name__ == '__main__':
main()
#!/usr/bin/env python
import numpy as np
'''
Notes:
- Tensile strength of 7x19 1/4" galvanized steel wire rope ~ 7000 lbs
'''
# TUNABLE PARAMETERS
# Length
L = 20 * 12 # Length in inches
K = 1.0 # Column effective length factor -- taken to be 1.0 for pinned at both ends
def buckling(D, W, E):
'''
Calculate the euler critical buckling load of a round tube column
- D - outer diameter (in)
- W - wall thickness (in)
- E - Modulus of elasticity (ksi)
'''
# Inner diameter (in)
d = D - 2 * W
# Moment of Inertia (in^4)
inertia = np.pi * ((D ** 4) - (d ** 4)) / 64
# Euler Critical Buckling Load (lbf)
return 1000 * (np.pi ** 2) * E * inertia / ((K * L) ** 2)
for E in (10000, 30000): # Modulus of elasticity for [aluminum, steel]
for D in [3, 3.5, 4, 5]: # Outer diameter
for W in [.063, .083, .095, 0.1, 0.12, .125, .18, .187, .25]: # Wall thickness
buckle = buckling(D, W, E)
if buckle >= 16000:
mat = {10000: '6061', 30000: 'A500'}[E]
print(f'D {D:0.2f} W {W:0.3f} mat {mat} buckling {buckle:.0f}')
break
# D 5.00 W 0.250 mat 6061 buckling 18078
# D 3.50 W 0.250 mat A500 buckling 17427
# D 4.00 W 0.180 mat A500 buckling 20299
# D 5.00 W 0.083 mat A500 buckling 19923

Tensegrity Geometry and Force Analysis

I've been working on a tensegrity structure that can support 3 hammocks for burning man.

This script is a simple analysis of static loads at a corner.

Geometry:

  • Top triangle is 12 feet side length
  • Structure height is 5 feet
  • Bottom triangle is ~8.78 feet side length
  • Rods are 13 feet long

Force Analysis:

  • Assuming a 200lb person in a hammock
  • Max static load on the rod is ~500 lb
  • Max static load on the ropes (not including hammock rigging) is ~150lb

Given a safety factor of 5 we want:

  • rods with buckling load > 2500lb
  • ropes with breaking strength > 3000lb (want failure point to be rods)

Rods

Specs:

  • Material: 6061 Aluminum -- won't rust in the desert, light to pack/carry
  • Shape: Round Tube
  • Size: 2.5" OD x 0.125" wall thickness x 2.25" ID

Calculations:

(Based on calculations used for aluminum tensegrity project for burning man in 2015)

P = pi^2 * E * I / (K * L)^2
  • P = Euler Buckling Load (~ 2670 lbf)
  • E = Modulus of Elasticity of 6061 (~ 10000 ksi)
  • I = Moment of Inertia of cross-section (~ 0.659 in^4)
  • K = Effective length factor (taken to be 1.0 here)
  • L = Length (13 feet = 156 in)

Moment of Inertia of pipe section

I = pi^2 * (D^4 - d^4) / 64
  • I = Moment of Inertia (~ 0.659 in^4)
  • D = Outer diameter (2.5 in)
  • d = Inner diameter (2.25 in)

Rope

Specs:

  • Braid: 12-strand -- Easy to splice
  • Material: Dyneema -- Strong, lightweight, low radius
  • Size: 3/16" diameter -- Tensile strength 6000 lbs (depends on manufacturer)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment