Skip to content

Instantly share code, notes, and snippets.

Created March 26, 2017 04:33
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 anonymous/4c4e2a10ddcc90ecf5ef0f0d7d0713e8 to your computer and use it in GitHub Desktop.
Save anonymous/4c4e2a10ddcc90ecf5ef0f0d7d0713e8 to your computer and use it in GitHub Desktop.
import java.lang.Math;
public class SpokedWheelCalculator {
private static double f (Wheel.Side s, double dd, double da) {
return s.calculateEffectiveSpokeLength(dd, da) - s.calculateEffectiveSpokeLength(dd, 0);
}
public static void main (String[] args) {
final Wheel wheel = new Wheel(new Rim(600), new Hub(60, 20, 16), SpokeType.GENERIC_SWAGED_JBEND_SPOKE, 3);
final double angleDelta = wheel.getLeftSide().calculateFlangeTwistUnderTorque(2000, 200); // 0.3x Bugatti Veyron peak engine torque
System.out.format("Angle delta = %f rad%n", angleDelta);
final double
lengthDelta1 = f(wheel.getLeftSide(), -3, angleDelta),
lengthDelta2 = f(wheel.getLeftSide(), 3, angleDelta);
System.out.format("dl-3mm = %f%ndl+3mm = %f%n", lengthDelta1, lengthDelta2);
}
}
enum SpokeType {
GENERIC_SWAGED_JBEND_SPOKE(200000, 1.8);
private final double
materialYoungsModulus, // N/mm^2
mainSectionDiameter;
private SpokeType (double materialYoungsModulus, double mainSectionDiameter) {
this.materialYoungsModulus = materialYoungsModulus;
this.mainSectionDiameter = mainSectionDiameter;
}
public double calculateHookesLengthChange (double force, double length) {
return force * length / (materialYoungsModulus * Math.PI * Math.pow(mainSectionDiameter / 2, 2));
}
}
class Rim {
private final double effectiveRadius;
public Rim (double erd) {
effectiveRadius = erd / 2d;
}
public double getEffectiveRadius () { return effectiveRadius; }
}
class Hub {
public static class Flange {
private final double
radius,
distanceFromCenter; // distance from plane containing centers of rim holes on this side of the wheel
private final int numberOfSpokes;
public Flange (double radius, double distanceFromCenter, int numberOfSpokes) {
this.radius = radius;
this.distanceFromCenter = distanceFromCenter;
this.numberOfSpokes = numberOfSpokes;
}
public double getRadius () { return radius; }
public double getDistanceFromCenter () { return distanceFromCenter; }
public int getNumberOfSpokes () { return numberOfSpokes; }
}
private final Flange leftFlange;
public Hub (double leftFlangePcd, double leftFlangeDistanceFromCenter, int nLeftFlangeHoles) {
leftFlange = new Flange(leftFlangePcd / 2d, leftFlangeDistanceFromCenter, nLeftFlangeHoles);
}
public Flange getLeftFlange () { return leftFlange; }
}
class Wheel {
// www.compilejava.net doesn't allow inner classes
public static class Side {
private final Wheel wheel;
private final Hub.Flange flange;
//private final double offsetDistanceToRim; for asymmetric wheels
private final SpokeType spokeType;
private final int nCrosses;
public Side (Wheel wheel, Hub.Flange flange, SpokeType spokeType, int nCrosses) {
this.wheel = wheel;
this.flange = flange;
this.spokeType = spokeType;
this.nCrosses = nCrosses;
}
public double getFlangeHoleAngle () {
return (2 * Math.PI * nCrosses) / flange.getNumberOfSpokes();
}
public double calculateEffectiveSpokeLength (double flangeDistanceOffset, double angleDelta) {
final double
R = wheel.rim.getEffectiveRadius(),
r = flange.getRadius();
return Math.sqrt(
Math.pow(R, 2) +
Math.pow(r, 2) +
Math.pow(flange.getDistanceFromCenter() + flangeDistanceOffset, 2) -
2 * R * r * Math.cos(getFlangeHoleAngle() + angleDelta)
);
// - spokeHoleRadius and account for spoke stretch for material spoke length calculation (a different method)
}
// for now, assume hub shell has zero torsional stiffness
//
public double calculateFlangeTwistUnderTorque (double force, double armLength) {
final double
torquePerSpoke = force * armLength / flange.getNumberOfSpokes(),
forcePerSpoke = torquePerSpoke / calculateSpokeTorqueArmLength(),
spokeLengthChange = spokeType.calculateHookesLengthChange(forcePerSpoke, calculateEffectiveSpokeLength(0, 0));
return 2 * Math.asin(spokeLengthChange / (2 * flange.getRadius())); // angle from chord length
}
private double calculateSpokeTorqueArmLength () {
final double
r = flange.getRadius(),
alpha = getFlangeHoleAngle(),
flatWheelTangentialSpokeLength = calculateEffectiveSpokeLength(-flange.getDistanceFromCenter(), 0),
flatWheelRadialSpokeLength = calculateEffectiveSpokeLength(-flange.getDistanceFromCenter(), -alpha);
return (flatWheelRadialSpokeLength + r) * r * Math.sin(alpha) / flatWheelTangentialSpokeLength;
}
}
private final Rim rim;
private final Hub hub;
private final Side leftSide;
public Wheel (Rim rim, Hub hub, SpokeType spokeTypeLeftSide, int nCrossesLeftSide) {
this.rim = rim;
this.hub = hub;
leftSide = new Side(this, hub.getLeftFlange(), spokeTypeLeftSide, nCrossesLeftSide);
}
public Side getLeftSide() { return leftSide; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment