From b55eb11a6f517b34ccc881acc1db910e81e9dbc5 Mon Sep 17 00:00:00 2001 From: Craig Earls Date: Sun, 28 Dec 2014 11:45:54 -0800 Subject: [PATCH] Compute fillet cross section and mass. --- .../sf/openrocket/rocketcomponent/FinSet.java | 60 ++++++++++++++++++- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java index 4bd623577..dfa6c64b0 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FinSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FinSet.java @@ -125,6 +125,7 @@ public abstract class FinSet extends ExternalComponent { protected Material filletMaterial = null; protected double filletRadius = 0; + protected double filletCenterY = 0; // Cached fin area & CG. Validity of both must be checked using finArea! // Fin area does not include fin tabs, CG does. @@ -410,29 +411,82 @@ public abstract class FinSet extends ExternalComponent { } + @Override + public double getComponentMass() { + return getFilletMass() + getFinMass(); + } + + public double getFinMass() { + return getComponentVolume() * material.getDensity(); + } + + public double getFilletMass() { + return getFilletVolume() * filletMaterial.getDensity(); + } + @Override public double getComponentVolume() { + // this is for the fins alone, fillets are taken care of separately. return fins * (getFinArea() + tabHeight * tabLength) * thickness * crossSection.getRelativeVolume(); } + @Override public Coordinate getComponentCG() { if (finArea < 0) calculateAreaCG(); - double mass = getComponentMass(); // safe + double mass = getFinMass(); + double filletMass = getFilletMass(); + double filletCenter = length / 2; + + double newCGx = (filletCenter * filletMass + finCGx * mass) / (filletMass + mass); + + // FilletRadius/5 is a good estimate for where the vertical centroid of the fillet + // is. Finding the actual position is very involved and won't make a huge difference. + double newCGy = (filletRadius / 5 * filletMass + finCGy * mass) / (filletMass + mass); if (fins == 1) { return baseRotation.transform( - new Coordinate(finCGx, finCGy + getBodyRadius(), 0, mass)); + new Coordinate(finCGx, finCGy + getBodyRadius(), 0, (filletMass + mass))); } else { - return new Coordinate(finCGx, 0, 0, mass); + return new Coordinate(finCGx, 0, 0, (filletMass + mass)); } } + public double getFilletVolume() { + /* + * Here is how the volume of the fillet is found. It assumes a circular concave + * fillet tangent to the fin and the body tube. + * + * 1. Form a triangle with vertices at the BT center, the tangent point between + * the fillet and the fin, and the center of the fillet radius. + * 2. The line between the center of the BT and the center of the fillet radius + * will pass through the tangent point between the fillet and the BT. + * 3. Find the area of the triangle, then subtract the portion of the BT and + * fillet that is in that triangle. (angle/2PI * pi*r^2= angle/2 * r^2) + * 4. Multiply the remaining area by the length. + * 5. Return twice that since there is a fillet on each side of the fin. + * + */ + double btRadius = 1000.0; // assume a really big body tube if we can't get the radius, + RocketComponent c = this.getParent(); + if (BodyTube.class.isInstance(c)) { + btRadius = ((BodyTube) c).getOuterRadius(); + } + double totalRad = filletRadius + btRadius; + double innerAngle = Math.asin(filletRadius / totalRad); + double outerAngle = Math.acos(filletRadius / totalRad); + + double outerArea = Math.tan(outerAngle) * filletRadius * filletRadius / 2; + double filletVolume = length * (outerArea + - outerAngle * filletRadius * filletRadius / 2 + - innerAngle * btRadius * btRadius / 2); + return 2 * filletVolume; + } private void calculateAreaCG() { Coordinate[] points = this.getFinPoints();