package VehicleGeometryAndCoordinateFrames {
private import TrigFunctions::*;
private import ISQ::*;
private import SI::*;
private import Time::*;
private import ShapeItems::*;
private import SpatialItems::*;
private import MeasurementReferences::CoordinateFrame;
private import MeasurementReferences::TranslationRotationSequence;
private import MeasurementReferences::Translation;
private import MeasurementReferences::Rotation;
private import Collections::Array;
private import ScalarValues::Boolean;
private import ScalarValues::Real;
private import ScalarValues::Natural;
private import ControlFunctions::forAll;
part def Vehicle :> SpatialItem;
part def Chassis :> SpatialItem {
item :>> shape = new Box(4800 [mm], 1840 [mm], 1350 [mm]);
}
part def Wheel :> SpatialItem {
doc
/*
* Generic wheel with lugbolts
*
* The radius is estimated for a 22 inch hub plus 110 mm tire height.
* The wheel width is equal to the cylinder height.
* The wheel has 5 lugbolts that are evenly distributed along a circle centered at the wheel's center.
*/
item :>> shape : Cylinder {
:>> radius = 22/2*25.4 + 110 [mm];
:>> height = 220 [mm];
}
attribute <wcf> wheelCoordinateFrame : CoordinateFrame;
attribute numberOfBolts : Natural = 5;
part lugBolts : LugBolt[1..numberOfBolts] :> subSpatialParts;
/*
* As an example of a more involved placement of composite parts, constrain the positions of the coordinate frame origins
* of the lugbolts to a circle with radius lbpr distributed evenly over 360°.
*/
attribute <lbpr> lugBoltPlacementRadius :>> radius default 60 [mm];
private attribute lugBoltDistributionAngle :>> planeAngle = 360/numberOfBolts ['°'];
private attribute lbda : Real = lugBoltDistributionAngle.num * (pi/180); // lugBoltDistributionAngle in radian
assert constraint {
(1..numberOfBolts)->forAll {
in i : Natural;
private attribute lbcf = lugBolts#(i).coordinateFrame;
private attribute trs : TranslationRotationSequence {
:>> source = wcf;
:>> target = lbcf;
:>> elements = new Translation((lbpr*cos((i-1)*lbda), lbpr*sin((i-1)*lbda), -8)[wcf]);
}
lbcf.transformation == trs
}
}
}
part def LugBolt :> SpatialItem {
item :>> shape : Cylinder {
:>> radius = 14 [mm];
:>> height = 40 [mm];
}
}
part vehicle : Vehicle, SpatialItem {
/*
* Vehicle frame origin at center of bottom plate of chassis
* with +Z upwards and +X in the forward (front) direction
*/
attribute datum :>> coordinateFrame {
:>> mRefs = (mm, mm, mm);
}
part chassis : Chassis[1] :> componentParts {
attribute :>> coordinateFrame {
attribute :>> transformation : TranslationRotationSequence {
attribute :>> source = datum;
attribute :>> elements = new Translation((-(shape as Box).length/2, -(shape as Box).width/2, 0)[datum]);
}
}
}
private attribute plusXAxis : Array { :>> dimensions = 3; :>> elements : Real[3] = (1, 0, 0); }
private attribute frontWheelXShift : Real = 1670;
private attribute rearWheelXShift : Real = -1820;
private attribute wheelYShift : Real = 720;
part leftFrontWheel : Wheel[1] :> componentParts {
attribute :>> coordinateFrame {
attribute :>> transformation : TranslationRotationSequence {
attribute :>> source = datum;
attribute :>> elements = (new Translation((frontWheelXShift, wheelYShift, 80)[datum]), new Rotation(plusXAxis[datum], -90['°']));
}
}
}
part rightFrontWheel : Wheel[1] :> componentParts {
attribute :>> coordinateFrame {
attribute :>> transformation : TranslationRotationSequence {
attribute :>> source = datum;
attribute :>> elements = (new Translation((frontWheelXShift, -wheelYShift, 80)[datum]), new Rotation((1, 0, 0)[datum], 90['°']));
}
}
}
part leftRearWheel : Wheel[1] :> componentParts {
attribute :>> coordinateFrame {
attribute :>> transformation : TranslationRotationSequence {
attribute :>> source = datum;
attribute :>> elements = (new Translation((rearWheelXShift, wheelYShift, 80)[datum]), new Rotation((1, 0, 0)[datum], 90['°']));
}
}
}
part rightRearWheel : Wheel[1] :> componentParts {
attribute :>> coordinateFrame {
attribute :>> transformation : TranslationRotationSequence {
attribute :>> source = datum;
attribute :>> elements = (new Translation((rearWheelXShift, -wheelYShift, 80)[datum]), new Rotation((-1, 0, 0)[datum], 90['°']));
}
}
}
}
}