1
0
Fork 0

Vivian Meazza:

This is a sub-system which can be added to any carrier.

These files add a functioning Fresnel Lens Optical Landing System (FLOLS).
The orange/red 'source' lights are illuminated according to the position of
the pilot's eye above/below the 3.5 deg glide slope. The apparent position
of the source light relative to the fixed green datum lights allow the pilot
to 'fly the meatball'. The green 'cut' lights flash when the pilot's eye is
below the coverage of the lowest (red) source light.

TODO - add rules for the operation of the wave-off lights.
This commit is contained in:
ehofman 2004-11-30 12:34:11 +00:00
parent fee003e8cc
commit 8ba9f4e3a4
5 changed files with 252 additions and 14 deletions

View file

@ -73,7 +73,9 @@ typedef struct {
list<string> wire_objects; // List of wire object names
list<string> catapult_objects; // List of catapult object names
double radius; // used by ship ojects, in feet
double x_offset; // used by ship ojects, in meters
double y_offset; // used by ship ojects, in meters
double z_offset; // used by ship ojects, in meters
} FGAIModelEntity;
@ -102,6 +104,10 @@ public:
void setLongitude( double longitude );
void setBank( double bank );
void setRadius ( double radius );
void setXoffset( double x_offset );
void setYoffset( double y_offset );
void setZoffset( double z_offset );
void* getID();
void setDie( bool die );
@ -122,6 +128,12 @@ protected:
double vs; // vertical speed, feet per minute
double turn_radius_ft; // turn radius ft at 15 kts rudder angle 15 degrees
// these describe the flols
Point3D flolspos; // WGS84 lat & lon in degrees, elev above sea-level in meters
double flols_x_offset; // longitudinal distance, in meters
double flols_y_offset; // lateral distance, in meters
double flols_z_offset; // height, in meters
double ft_per_deg_lon;
double ft_per_deg_lat;
@ -223,6 +235,17 @@ inline void FGAIBase::setRadius( double radius ) {
turn_radius_ft = radius;
}
inline void FGAIBase::setXoffset( double x_offset ) {
flols_x_offset = x_offset;
}
inline void FGAIBase::setYoffset( double y_offset ) {
flols_y_offset = y_offset;
}
inline void FGAIBase::setZoffset( double z_offset ) {
flols_z_offset = z_offset;
}
inline void FGAIBase::setHeading( double heading ) {
hdg = tgt_heading = heading;
}
@ -251,5 +274,7 @@ inline FGAIBase::object_type FGAIBase::getType() { return _otype; }
inline void* FGAIBase::getID() { return this; }
#endif // _FG_AIBASE_HXX

View file

@ -24,6 +24,12 @@
#include <string>
#include <vector>
#include <simgear/math/point3d.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <math.h>
#include <Main/util.hxx>
#include <Main/viewer.hxx>
#include "AICarrier.hxx"
@ -50,6 +56,7 @@ void FGAICarrier::getVelocityWrtEarth(sgVec3 v) {
}
void FGAICarrier::update(double dt) {
UpdateFlols(dt);
FGAIShip::update(dt);
// Update the velocity information stored in those nodes.
@ -89,7 +96,23 @@ bool FGAICarrier::init() {
return true;
}
void FGAICarrier::bind() {
FGAIBase::bind();
props->tie("controls/flols/source-lights",
SGRawValuePointer<int>(&source));
props->tie("controls/flols/distance-m",
SGRawValuePointer<double>(&dist));
props->setBoolValue("controls/flols/cut-lights", false);
props->setBoolValue("controls/flols/wave-off-lights", false);
props->setBoolValue("controls/flols/cond-datum-lights", true);
}
void FGAICarrier::unbind() {
FGAIBase::unbind();
props->untie("controls/flols/source-lights");
}
void FGAICarrier::mark_nohot(ssgEntity* e) {
if (e->isAKindOf(ssgTypeBranch())) {
ssgBranch* br = (ssgBranch*)e;
@ -183,7 +206,7 @@ bool FGAICarrier::mark_cat(ssgEntity* e, const list<string>& cat_objects) {
SG_LOG(SG_GENERAL, SG_ALERT,
"AICarrier: Found a cat not modelled with exactly one line!");
}
// Now some special code to make shure the cat points in the right
// Now some special code to make sure the cat points in the right
// direction. The 0 index must be the backward end, the 1 index
// the forward end.
// Forward is positive x-direction in our 3D model, also the model
@ -208,4 +231,163 @@ bool FGAICarrier::mark_cat(ssgEntity* e, const list<string>& cat_objects) {
return found;
}
void FGAICarrier::UpdateFlols( double dt) {
/* cout << "x_offset " << flols_x_offset
<< " y_offset " << flols_y_offset
<< " z_offset " << flols_z_offset << endl;
cout << "roll " << roll
<< " heading " << hdg
<< " pitch " << pitch << endl;
cout << "carrier lon " << pos[0]
<< " lat " << pos[1]
<< " alt " << pos[2] << endl;*/
// set the Flols intitial position to the carrier position
flolspos = pos;
/* cout << "flols lon " << flolspos[0]
<< " lat " << flolspos[1]
<< " alt " << flolspos[2] << endl;*/
// set the offsets in metres
/* cout << "flols_x_offset " << flols_x_offset << endl
<< "flols_y_offset " << flols_y_offset << endl
<< "flols_z_offset " << flols_z_offset << endl;*/
in[0] = flols_x_offset;
in[1] = flols_y_offset;
in[2] = flols_z_offset;
// pre-process the trig functions
cosRx = cos(roll * SG_DEGREES_TO_RADIANS);
sinRx = sin(roll * SG_DEGREES_TO_RADIANS);
cosRy = cos(pitch * SG_DEGREES_TO_RADIANS);
sinRy = sin(pitch * SG_DEGREES_TO_RADIANS);
cosRz = cos(hdg * SG_DEGREES_TO_RADIANS);
sinRz = sin(hdg * SG_DEGREES_TO_RADIANS);
// set up the transform matrix
trans[0][0] = cosRy * cosRz;
trans[0][1] = -1 * cosRx * sinRz + sinRx * sinRy * cosRz ;
trans[0][2] = sinRx * sinRz + cosRx * sinRy * cosRz;
trans[1][0] = cosRy * sinRz;
trans[1][1] = cosRx * cosRz + sinRx * sinRy * sinRz;
trans[1][2] = -1 * sinRx * cosRx + cosRx * sinRy * sinRz;
trans[2][0] = -1 * sinRy;
trans[2][1] = sinRx * cosRy;
trans[2][2] = cosRx * cosRy;
// multiply the input and transform matrices
out[0] = in[0] * trans[0][0] + in[1] * trans[0][1] + in[2] * trans[0][2];
out[1] = in[0] * trans[1][0] + in[1] * trans[1][1] + in[2] * trans[1][2];
out[2] = in[0] * trans[2][0] + in[1] * trans[2][1] + in[2] * trans[2][2];
// convert meters to ft to degrees of latitude
out[0] = (out[0] * 3.28083989501) /(366468.96 - 3717.12 * cos(flolspos[0] * SG_DEGREES_TO_RADIANS));
// convert meters to ft to degrees of longitude
out[1] = (out[1] * 3.28083989501)/(365228.16 * cos(flolspos[1] * SG_DEGREES_TO_RADIANS));
//print out the result
/* cout << "lat adjust deg" << out[0]
<< " lon adjust deg " << out[1]
<< " alt adjust m " << out[2] << endl;*/
// adjust Flols position
flolspos[0] += out[0];
flolspos[1] += out[1];
flolspos[2] += out[2];
// convert flols position to cartesian co-ordinates
sgGeodToCart(flolspos[1] * SG_DEGREES_TO_RADIANS,
flolspos[0] * SG_DEGREES_TO_RADIANS,
flolspos[2] , flolsXYZ );
/* cout << "flols X " << flolsXYZ[0]
<< " Y " << flolsXYZ[1]
<< " Z " << flolsXYZ[2] << endl;
// check the conversion
sgCartToGeod(flolsXYZ, &lat, &lon, &alt);
cout << "flols check lon " << lon
<< " lat " << lat
<< " alt " << alt << endl; */
//get the current position of the pilot's eyepoint (cartesian cordinates)
sgdCopyVec3( eyeXYZ, globals->get_current_view()->get_absolute_view_pos() );
/* cout << "Eye_X " << eyeXYZ[0]
<< " Eye_Y " << eyeXYZ[1]
<< " Eye_Z " << eyeXYZ[2] << endl; */
sgCartToGeod(eyeXYZ, &lat, &lon, &alt);
eyepos[0] = lon * SG_RADIANS_TO_DEGREES;
eyepos[1] = lat * SG_RADIANS_TO_DEGREES;
eyepos[2] = alt;
/* cout << "eye lon " << eyepos[0]
<< " eye lat " << eyepos[1]
<< " eye alt " << eyepos[2] << endl; */
//calculate the ditance from eye to flols
dist = sgdDistanceVec3( flolsXYZ, eyeXYZ );
//cout << "distance " << dist << endl;
if ( dist < 5000 ) {
// calculate height above FLOLS
double y = eyepos[2] - flolspos[2];
// calculate the angle from the flols to eye
// above the horizontal
double angle;
if ( dist != 0 ) {
angle = asin( y / dist );
} else {
angle = 0.0;
}
angle *= SG_RADIANS_TO_DEGREES;
// cout << " height " << y << " angle " << angle ;
// set the value of source
if ( angle <= 4.35 && angle > 4.01 )
{ source = 1; }
else if ( angle <= 4.01 && angle > 3.670 )
{ source = 2; }
else if ( angle <= 3.670 && angle > 3.330 )
{ source = 3; }
else if ( angle <= 3.330 && angle > 2.990 )
{ source = 4; }
else if ( angle <= 2.990 && angle > 2.650 )
{ source = 5; }
else if ( angle <= 2.650 )
{ source = 6; }
else
{ source = 0; }
// cout << " source " << source << endl;
}
} // end updateflols
int FGAICarrierHardware::unique_id = 1;

View file

@ -80,6 +80,9 @@ public:
void setCatapultObjects(const list<string>& catapult_objects);
void getVelocityWrtEarth(sgVec3 v);
virtual void bind();
virtual void unbind();
void UpdateFlols ( double dt );
bool init();
@ -97,6 +100,25 @@ private:
// Velocity wrt earth.
sgVec3 vel_wrt_earth;
float trans[3][3];
float in[3];
float out[3];
double Rx, Ry, Rz;
double Sx, Sy, Sz;
double Tx, Ty, Tz;
float cosRx, sinRx;
float cosRy, sinRy;
float cosRz, sinRz;
double flolsXYZ[3], eyeXYZ[3];
double lat, lon, alt;
double dist;
int source;
Point3D eyepos;
Point3D flolspos;
};
#endif // _FG_AICARRIER_HXX

View file

@ -176,7 +176,7 @@ FGAIManager::createAircraft( FGAIModelEntity *entity, FGAISchedule *ref) {
void*
FGAIManager::createShip( FGAIModelEntity *entity ) {
//cout << "creating ship" << endl;
// cout << "creating ship" << endl;
FGAIShip* ai_ship = new FGAIShip(this);
ai_list.push_back(ai_ship);
@ -202,7 +202,7 @@ FGAIManager::createShip( FGAIModelEntity *entity ) {
void*
FGAIManager::createCarrier( FGAIModelEntity *entity ) {
//cout << "creating carrier" << endl;
// cout << "creating carrier" << endl;
FGAICarrier* ai_carrier = new FGAICarrier(this);
ai_list.push_back(ai_carrier);
@ -219,6 +219,9 @@ FGAIManager::createCarrier( FGAIModelEntity *entity ) {
ai_carrier->setWireObjects(entity->wire_objects);
ai_carrier->setCatapultObjects(entity->catapult_objects);
ai_carrier->setRadius(entity->radius);
ai_carrier->setXoffset(entity->x_offset);
ai_carrier->setYoffset(entity->y_offset);
ai_carrier->setZoffset(entity->z_offset);
if ( entity->fp ) {
ai_carrier->setFlightPlan(entity->fp);

View file

@ -40,24 +40,32 @@ FGAIScenario::FGAIScenario(string &filename)
{
int i;
SGPath path( globals->get_fg_root() );
//cout << "/Data/AI/" << filename << endl;
cout << "/Data/AI/" << filename << endl;
path.append( ("/Data/AI/" + filename + ".xml").c_str() );
SGPropertyNode root;
readProperties(path.str(), &root);
//cout <<"path " << path.str() << endl;
cout <<"path " << path.str() << endl;
try {
readProperties(path.str(), &root);
} catch (const sg_exception &e) {
SG_LOG(SG_GENERAL, SG_ALERT,
"Incorrect path specified for AI scenario: ");
//cout << path.str() << endl;
cout << path.str() << endl;
return;
}
entries.clear();
SGPropertyNode * node = root.getNode("scenario");
for (i = 0; i < node->nChildren(); i++) {
//cout << "Reading entity data entry " << i << endl;
cout << "Reading entity data entry " << i << endl;
SGPropertyNode * entry_node = node->getChild(i);
FGAIModelEntity* en = new FGAIModelEntity;
@ -88,12 +96,10 @@ FGAIScenario::FGAIScenario(string &filename)
en->cd = entry_node->getDoubleValue("cd", 0.029);
en->mass = entry_node->getDoubleValue("mass", 0.007);
en->radius = entry_node->getDoubleValue("turn-radius-ft", 2000);
/* en->name = entry_node->getStringValue("name", "");
en->x_pivot = entry_node->getDoubleValue("x-pivot", 0.0);
en->y_pivot = entry_node->getDoubleValue("y-pivot", 0.0);
en->z_pivot = entry_node->getDoubleValue("z-pivot", 0.0); */
en->x_offset = entry_node->getDoubleValue("x-offset-m", 5.5);
en->y_offset = entry_node->getDoubleValue("y-offset-m", 1.0);
en->z_offset = entry_node->getDoubleValue("z-offset-m", 1.0);
/* en->name = entry_node->getStringValue("name", "");*/
en->wire_objects = getAllNodeVals("wire", entry_node);
en->catapult_objects = getAllNodeVals("catapult", entry_node);
en->solid_objects = getAllNodeVals("solid", entry_node);