1
0
Fork 0

Merge branch 'next' of git://gitorious.org/fg/flightgear into next

This commit is contained in:
Erik Hofman 2010-11-30 13:35:18 +01:00
commit 2a674c76fa
12 changed files with 691 additions and 284 deletions

View file

@ -133,6 +133,30 @@ window, camera, or gui tags.
This specifies an orthographic view. The parameters are the sames as This specifies an orthographic view. The parameters are the sames as
the frustum node's. the frustum node's.
texture
This tag indicates that the camera renders to a texture instead of the
framebuffer. For now the following tags are supported, but obviously
different texture formats should be specified too.
name - string
The name of the texture. This can be referred to by other cameras.
width, height - double
The dimensions of the texture
panoramic-distortion
This tag cause the camera to create distortion geometry that
corrects for projection onto a spherical screen. It is equivalent to
the --panoramic-sd option to osgviewer.
texture - string
The name of a texture, created by another camera, that will be
rendered on the distortion correction geometry.
radius - double
Radius of string
collar - double
size of screen collar.
gui gui
This is a special camera node that displays the 2D GUI. This is a special camera node that displays the 2D GUI.
@ -313,3 +337,61 @@ accounted for.
</rendering> </rendering>
</sim> </sim>
</PropertyList> </PropertyList>
This example renders the scene for projection onto a spherical screen.
<PropertyList>
<sim>
<rendering>
<camera-group>
<camera>
<window>
<name type="string">main</name>
<host-name type="string"></host-name>
<display>0</display>
<screen>0</screen>
<!-- <fullscreen type = "bool">true</fullscreen>-->
<width>1024</width>
<height>768</height>
</window>
<view>
<heading-deg type = "double">0</heading-deg>
</view>
<frustum>
<top>0.133</top>
<bottom>-0.133</bottom>
<left>-.1668</left>
<right>.1668</right>
<near>0.4</near>
<far>120000.0</far>
</frustum>
<texture>
<name>mainview</name>
<width>1024</width>
<height>768</height>
</texture>
</camera>
<camera>
<window><name>main</name></window>
<ortho>
<top>768</top>
<bottom>0</bottom>
<left>0</left>
<right>1024</right>
<near>-1.0</near>
<far>1.0</far>
</ortho>
<panoramic-spherical>
<texture>mainview</texture>
</panoramic-spherical>
</camera>
<gui>
<window>
<name type="string">main</name>
</window>
</gui>
</camera-group>
</rendering>
</sim>
</PropertyList>

View file

@ -152,11 +152,11 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
props->setStringValue("contents/path", _contents_path.c_str()); props->setStringValue("contents/path", _contents_path.c_str());
} }
if(_parent != ""){ //if(_parent != ""){
setParentNode(); // setParentNode();
} //}
setParentNodes(_selected_ac); //setParentNodes(_selected_ac);
//props->setStringValue("vector/path", _vector_path.c_str()); //props->setStringValue("vector/path", _vector_path.c_str());
@ -168,7 +168,11 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
Transform(); Transform();
//cout << _name << " speed init: " << speed << endl; if(_parent != ""){
setParentNode();
}
setParentNodes(_selected_ac);
return true; return true;
} }

View file

@ -215,13 +215,14 @@ bool FGAIWingman::init(bool search_in_AI_path) {
roll = _rotation; roll = _rotation;
_ht_agl_ft = 1e10; _ht_agl_ft = 1e10;
props->setStringValue("submodels/path", _path.c_str());
if(_parent != ""){ if(_parent != ""){
setParentNode(); setParentNode();
} }
setParentNodes(_selected_ac); setParentNodes(_selected_ac);
props->setStringValue("submodels/path", _path.c_str());
user_WoW_node = fgGetNode("gear/gear[1]/wow", true);
return true; return true;
} }
@ -277,7 +278,7 @@ double FGAIWingman::calcAngle(double range, SGGeod pos1, SGGeod pos2){
void FGAIWingman::formateToAC(double dt){ void FGAIWingman::formateToAC(double dt){
double p_hdg, p_pch, p_rll, p_agl, p_ht = 0; double p_hdg, p_pch, p_rll, p_agl, p_ht, p_wow = 0;
setTgtOffsets(dt, 25); setTgtOffsets(dt, 25);
@ -312,8 +313,9 @@ void FGAIWingman::formateToAC(double dt){
double h_feet = 3 * factor; double h_feet = 3 * factor;
p_agl = manager->get_user_agl(); p_agl = manager->get_user_agl();
p_wow = user_WoW_node->getDoubleValue();
if(p_agl <= 10) { if(p_agl <= 10 || p_wow == 1) {
_height = p_ht; _height = p_ht;
//cout << "ht case1 " ; //cout << "ht case1 " ;
} else if (p_agl > 10 && p_agl <= 150 ) { } else if (p_agl > 10 && p_agl <= 150 ) {
@ -332,7 +334,8 @@ void FGAIWingman::formateToAC(double dt){
pos.setLongitudeDeg(_offsetpos.getLongitudeDeg()); pos.setLongitudeDeg(_offsetpos.getLongitudeDeg());
// these calculations are unreliable at slow speeds // these calculations are unreliable at slow speeds
if(speed >= 10) { // and we don't want random movement on the ground
if(speed >= 10 && p_wow != 1) {
setHdg(p_hdg + h_angle, dt, 0.9); setHdg(p_hdg + h_angle, dt, 0.9);
setPch(p_pch + p_angle + _pitch_offset, dt, 0.9); setPch(p_pch + p_angle + _pitch_offset, dt, 0.9);

View file

@ -67,7 +67,7 @@ private:
double _coeff_bnk; //dimensionless coefficient double _coeff_bnk; //dimensionless coefficient
double _coeff_spd; //dimensionless coefficient double _coeff_spd; //dimensionless coefficient
SGPropertyNode_ptr user_WoW_node;
inline void setFormate(bool f); inline void setFormate(bool f);
inline void setTgtHdg(double hdg); inline void setTgtHdg(double hdg);

View file

@ -7,6 +7,7 @@
// This file is in the Public Domain and comes with no warranty. // This file is in the Public Domain and comes with no warranty.
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/sg_inlines.h>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <sstream> #include <sstream>
@ -54,15 +55,26 @@ HeadingIndicatorDG::init ()
branch = "/instrumentation/" + name; branch = "/instrumentation/" + name;
_heading_in_node = fgGetNode("/orientation/heading-deg", true); _heading_in_node = fgGetNode("/orientation/heading-deg", true);
_yaw_rate_node = fgGetNode("/orientation/yaw-rate-degps", true);
_g_node = fgGetNode("/accelerations/pilot-g", true);
SGPropertyNode *node = fgGetNode(branch.c_str(), num, true ); SGPropertyNode *node = fgGetNode(branch.c_str(), num, true );
_offset_node = node->getChild("offset-deg", 0, true); _offset_node = node->getChild("offset-deg", 0, true);
_serviceable_node = node->getChild("serviceable", 0, true); _serviceable_node = node->getChild("serviceable", 0, true);
_error_node = node->getChild("heading-bug-error-deg", 0, true); _heading_bug_error_node = node->getChild("heading-bug-error-deg", 0, true);
_error_node = node->getChild("error-deg", 0, true);
_nav1_error_node = node->getChild("nav1-course-error-deg", 0, true); _nav1_error_node = node->getChild("nav1-course-error-deg", 0, true);
_heading_out_node = node->getChild("indicated-heading-deg", 0, true); _heading_out_node = node->getChild("indicated-heading-deg", 0, true);
_last_heading_deg = (_heading_in_node->getDoubleValue() + _align_node = node->getChild("align-deg", 0, true);
_offset_node->getDoubleValue());
_electrical_node = fgGetNode("/systems/electrical/outputs/DG", true); _electrical_node = fgGetNode("/systems/electrical/outputs/DG", true);
_align_node->setDoubleValue(0);
_error_node->setDoubleValue(0);
_last_heading_deg = (_heading_in_node->getDoubleValue() +
_offset_node->getDoubleValue() + _align_node->getDoubleValue());
} }
void void
@ -100,11 +112,30 @@ HeadingIndicatorDG::update (double dt)
_gyro.update(dt); _gyro.update(dt);
double spin = _gyro.get_spin_norm(); double spin = _gyro.get_spin_norm();
// No time-based precession for a flux gate compass // Next, calculate time-based precession
// No magvar double offset = _offset_node->getDoubleValue();
double offset = 0; offset -= dt * (0.25 / 60.0); // 360deg/day
SG_NORMALIZE_RANGE(offset, -360.0, 360.0);
_offset_node->setDoubleValue(offset);
// TODO: movement-induced error // No magvar - set the alignment manually
double align = _align_node->getDoubleValue();
// Movement-induced error
double yaw_rate = _yaw_rate_node->getDoubleValue();
double error = _error_node->getDoubleValue();
double g = _g_node->getDoubleValue();
int sign = 0;
if ( fabs ( yaw_rate ) > 5 ) {
error += 0.033 * -yaw_rate * dt ;
}
if ( g > 1.5 || g < -0.5){
error += 0.033 * g * dt;
}
_error_node->setDoubleValue(error);
// Next, calculate the indicated heading, // Next, calculate the indicated heading,
// introducing errors. // introducing errors.
@ -122,11 +153,8 @@ HeadingIndicatorDG::update (double dt)
heading = fgGetLowPass(_last_heading_deg, heading, dt * factor); heading = fgGetLowPass(_last_heading_deg, heading, dt * factor);
_last_heading_deg = heading; _last_heading_deg = heading;
heading += offset; heading += offset + align + error;
while (heading < 0) SG_NORMALIZE_RANGE(heading, 0.0, 360.0);
heading += 360;
while (heading > 360)
heading -= 360;
_heading_out_node->setDoubleValue(heading); _heading_out_node->setDoubleValue(heading);
@ -138,7 +166,7 @@ HeadingIndicatorDG::update (double dt)
double diff = bnode->getDoubleValue() - heading; double diff = bnode->getDoubleValue() - heading;
if ( diff < -180.0 ) { diff += 360.0; } if ( diff < -180.0 ) { diff += 360.0; }
if ( diff > 180.0 ) { diff -= 360.0; } if ( diff > 180.0 ) { diff -= 360.0; }
_error_node->setDoubleValue( diff ); _heading_bug_error_node->setDoubleValue( diff );
} }
// calculate the difference between the indicated heading // calculate the difference between the indicated heading
// and the selected nav1 radial for use with an autopilot // and the selected nav1 radial for use with an autopilot
@ -152,4 +180,4 @@ HeadingIndicatorDG::update (double dt)
} }
} }
// end of heading_indicator_fg.cxx // end of heading_indicator_dg.cxx

View file

@ -10,6 +10,7 @@
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/structure/subsystem_mgr.hxx> #include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/math/sg_random.h>
#include "gyro.hxx" #include "gyro.hxx"
@ -59,6 +60,10 @@ private:
SGPropertyNode_ptr _electrical_node; SGPropertyNode_ptr _electrical_node;
SGPropertyNode_ptr _error_node; SGPropertyNode_ptr _error_node;
SGPropertyNode_ptr _nav1_error_node; SGPropertyNode_ptr _nav1_error_node;
SGPropertyNode_ptr _align_node;
SGPropertyNode_ptr _yaw_rate_node;
SGPropertyNode_ptr _heading_bug_error_node;
SGPropertyNode_ptr _g_node;
}; };
#endif // __INSTRUMENTS_HEADING_INDICATOR_ELEC_HXX #endif // __INSTRUMENTS_HEADING_INDICATOR_ELEC_HXX

View file

@ -20,10 +20,11 @@
#include "mrg.hxx" #include "mrg.hxx"
const double MasterReferenceGyro::gravity = -32.1740485564;
MasterReferenceGyro::MasterReferenceGyro ( SGPropertyNode *node ) : MasterReferenceGyro::MasterReferenceGyro ( SGPropertyNode *node ) :
_name(node->getStringValue("name", "master-reference-gyro")), _name(node->getStringValue("name", "master-reference-gyro")),
_num(node->getIntValue("number", 0)) _num(node->getIntValue("number", 0))
{ {
} }
@ -34,237 +35,252 @@ MasterReferenceGyro::~MasterReferenceGyro ()
void void
MasterReferenceGyro::init () MasterReferenceGyro::init ()
{ {
_last_hdg = 0; _last_hdg = 0;
_last_roll = 0; _last_roll = 0;
_last_pitch = 0; _last_pitch = 0;
_indicated_hdg = 0; _indicated_hdg = 0;
_indicated_roll = 0; _indicated_roll = 0;
_indicated_pitch = 0; _indicated_pitch = 0;
_indicated_hdg_rate = 0; _indicated_hdg_rate = 0;
_indicated_roll_rate = 0; _indicated_roll_rate = 0;
_indicated_pitch_rate = 0; _indicated_pitch_rate = 0;
_erect_time = 0; _erect_time = 180;
_last_g = 1;
_g_error = 10;
string branch; string branch;
branch = "/instrumentation/" + _name; branch = "/instrumentation/" + _name;
_pitch_in_node = fgGetNode("/orientation/pitch-deg", true); _pitch_in_node = fgGetNode("/orientation/pitch-deg", true);
_roll_in_node = fgGetNode("/orientation/roll-deg", true); _roll_in_node = fgGetNode("/orientation/roll-deg", true);
_hdg_in_node = fgGetNode("/orientation/heading-deg", true); _hdg_in_node = fgGetNode("/orientation/heading-deg", true);
_hdg_mag_in_node = fgGetNode("/orientation/heading-magnetic-deg", true); _hdg_mag_in_node = fgGetNode("/orientation/heading-magnetic-deg", true);
_pitch_rate_node = fgGetNode("/orientation/pitch-rate-degps", true); _pitch_rate_node = fgGetNode("/orientation/pitch-rate-degps", true);
_roll_rate_node = fgGetNode("/orientation/roll-rate-degps", true); _roll_rate_node = fgGetNode("/orientation/roll-rate-degps", true);
_yaw_rate_node = fgGetNode("/orientation/yaw-rate-degps", true); _yaw_rate_node = fgGetNode("/orientation/yaw-rate-degps", true);
_g_in_node = fgGetNode("/accelerations/pilot-g", true); //_g_in_node = fgGetNode("/accelerations/pilot/z-accel-fps_sec", true);
_electrical_node = fgGetNode("/systems/electrical/outputs/MRG", true); _g_in_node = fgGetNode("/accelerations/pilot-g", true);
_hdg_mag_in_node = fgGetNode("/orientation/heading-magnetic-deg", true); _electrical_node = fgGetNode("/systems/electrical/outputs/MRG", true);
_hdg_mag_in_node = fgGetNode("/orientation/heading-magnetic-deg", true);
SGPropertyNode *node = fgGetNode(branch.c_str(), _num, true ); SGPropertyNode *node = fgGetNode(branch.c_str(), _num, true );
_off_node = node->getChild("off-flag", 0, true); _off_node = node->getChild("off-flag", 0, true);
_pitch_out_node = node->getChild("indicated-pitch-deg", 0, true); _pitch_out_node = node->getChild("indicated-pitch-deg", 0, true);
_roll_out_node = node->getChild("indicated-roll-deg", 0, true); _roll_out_node = node->getChild("indicated-roll-deg", 0, true);
_hdg_out_node = node->getChild("indicated-hdg-deg", 0, true); _hdg_out_node = node->getChild("indicated-hdg-deg", 0, true);
_hdg_mag_out_node = node->getChild("indicated-mag-hdg-deg", 0, true); _hdg_mag_out_node = node->getChild("indicated-mag-hdg-deg", 0, true);
_pitch_rate_out_node = node->getChild("indicated-pitch-rate-degps", 0, true); _pitch_rate_out_node = node->getChild("indicated-pitch-rate-degps", 0, true);
_roll_rate_out_node = node->getChild("indicated-roll-rate-degps", 0, true); _roll_rate_out_node = node->getChild("indicated-roll-rate-degps", 0, true);
_hdg_rate_out_node = node->getChild("indicated-hdg-rate-degps", 0, true); _hdg_rate_out_node = node->getChild("indicated-hdg-rate-degps", 0, true);
_responsiveness_node = node->getChild("responsiveness", 0, true); _responsiveness_node = node->getChild("responsiveness", 0, true);
_error_out_node = node->getChild("heading-bug-error-deg", 0, true); _error_out_node = node->getChild("heading-bug-error-deg", 0, true);
_hdg_input_source_node = node->getChild("heading-source", 0, true); _hdg_input_source_node = node->getChild("heading-source", 0, true);
_fast_erect_node = node->getChild("fast-erect", 0, true); _fast_erect_node = node->getChild("fast-erect", 0, true);
_electrical_node->setDoubleValue(0); _electrical_node->setDoubleValue(0);
_responsiveness_node->setDoubleValue(0.75); _responsiveness_node->setDoubleValue(0.75);
_off_node->setBoolValue(false); _off_node->setBoolValue(false);
_hdg_input_source_node->setBoolValue(false); _hdg_input_source_node->setBoolValue(false);
_fast_erect_node->setBoolValue(false); _fast_erect_node->setBoolValue(false);
_g_in_node->setDoubleValue(1);
} }
void void
MasterReferenceGyro::bind () MasterReferenceGyro::bind ()
{ {
std::ostringstream temp; std::ostringstream temp;
string branch; string branch;
temp << _num; temp << _num;
branch = "/instrumentation/" + _name + "[" + temp.str() + "]"; branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
fgTie((branch + "/serviceable").c_str(), fgTie((branch + "/serviceable").c_str(),
&_gyro, &Gyro::is_serviceable, &Gyro::set_serviceable); &_gyro, &Gyro::is_serviceable, &Gyro::set_serviceable);
fgTie((branch + "/spin").c_str(), fgTie((branch + "/spin").c_str(),
&_gyro, &Gyro::get_spin_norm, &Gyro::set_spin_norm); &_gyro, &Gyro::get_spin_norm, &Gyro::set_spin_norm);
} }
void void
MasterReferenceGyro::unbind () MasterReferenceGyro::unbind ()
{ {
std::ostringstream temp; std::ostringstream temp;
string branch; string branch;
temp << _num; temp << _num;
branch = "/instrumentation/" + _name + "[" + temp.str() + "]"; branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
fgUntie((branch + "/serviceable").c_str()); fgUntie((branch + "/serviceable").c_str());
fgUntie((branch + "/spin").c_str()); fgUntie((branch + "/spin").c_str());
} }
void void
MasterReferenceGyro::update (double dt) MasterReferenceGyro::update (double dt)
{ {
double indicated_roll = 0; //sanity check
double indicated_pitch = 0; if (!fgGetBool("/sim/fdm-initialized", false)) {
double indicated_hdg = 0;
double indicated_roll_rate = 0;
double indicated_pitch_rate = 0;
double indicated_hdg_rate = 0;
// Get the spin from the gyro
_gyro.set_power_norm( _electrical_node->getDoubleValue()/24 );
_gyro.update(dt);
double spin = _gyro.get_spin_norm();
// set the "off-flag"
if ( _electrical_node->getDoubleValue() > 0 && spin >= 0.25) {
_off_node->setBoolValue(false);
} else {
_off_node->setBoolValue(true);
return; return;
} }
// Get the input values double indicated_roll = 0;
double hdg = _hdg_mag_in_node->getDoubleValue(); double indicated_pitch = 0;
double indicated_hdg = 0;
double indicated_roll_rate = 0;
double indicated_pitch_rate = 0;
double indicated_hdg_rate = 0;
double hdg = 0;
double erect_time_factor = 1;
if(_hdg_input_source_node->getBoolValue()) const double erect_time = 180;
hdg = _hdg_in_node->getDoubleValue(); const double max_g_error = 10.0;
double roll = _roll_in_node->getDoubleValue(); //Get the spin from the gyro
double pitch = _pitch_in_node->getDoubleValue(); _gyro.set_power_norm( _electrical_node->getDoubleValue()/24 );
_gyro.update(dt);
double spin = _gyro.get_spin_norm();
double roll_rate = _yaw_rate_node->getDoubleValue(); // set the "off-flag"
double pitch_rate = _yaw_rate_node->getDoubleValue(); if ( _electrical_node->getDoubleValue() > 0 && spin >= 0.25) {
double yaw_rate = _yaw_rate_node->getDoubleValue(); _off_node->setBoolValue(false);
double g = _g_in_node->getDoubleValue(); } else {
_off_node->setBoolValue(true);
return;
}
//modulate the input by the spin rate // Get the input values
double responsiveness = spin * spin * spin * spin * spin * spin; if(_hdg_input_source_node->getBoolValue()){
roll = fgGetLowPass( _last_roll, roll, responsiveness ); hdg = _hdg_in_node->getDoubleValue();
pitch = fgGetLowPass( _last_pitch , pitch, responsiveness ); } else {
hdg = _hdg_mag_in_node->getDoubleValue();
}
if ((hdg - _last_hdg) > 180) double roll = _roll_in_node->getDoubleValue();
_last_hdg += 360; double pitch = _pitch_in_node->getDoubleValue();
if ((hdg - _last_hdg) < -180) double g = _g_in_node->getDoubleValue()/* / gravity*/;
_last_hdg -= 360;
hdg = fgGetLowPass( _last_hdg , hdg, responsiveness ); double roll_rate = _yaw_rate_node->getDoubleValue();
double pitch_rate = _pitch_rate_node->getDoubleValue();
double yaw_rate = _yaw_rate_node->getDoubleValue();
//but we need to filter the hdg and yaw_rate as well - yuk! //modulate the input by the spin rate
responsiveness = 0.1 / (spin * spin * spin * spin * spin * spin); double responsiveness = spin * spin * spin * spin * spin * spin;
yaw_rate = fgGetLowPass( _last_yaw_rate , yaw_rate, responsiveness ); roll = fgGetLowPass( _last_roll, roll, responsiveness );
g = fgGetLowPass( _last_g , g, 0.015 ); pitch = fgGetLowPass( _last_pitch , pitch, responsiveness );
if ((hdg - _last_hdg) > 180)
_last_hdg += 360;
if ((hdg - _last_hdg) < -180)
_last_hdg -= 360;
hdg = fgGetLowPass( _last_hdg , hdg, responsiveness );
//but we need to filter the hdg and yaw_rate as well - yuk!
responsiveness = 0.1 / (spin * spin * spin * spin * spin * spin);
yaw_rate = fgGetLowPass( _last_yaw_rate , yaw_rate, responsiveness );
g = fgGetLowPass( _last_g , g, 1.5);
// store the new values // store the new values
_last_roll = roll; _last_roll = roll;
_last_pitch = pitch; _last_pitch = pitch;
_last_hdg = hdg; _last_hdg = hdg;
_last_roll_rate = roll_rate; _last_roll_rate = roll_rate;
_last_pitch_rate = pitch_rate; _last_pitch_rate = pitch_rate;
_last_yaw_rate = yaw_rate; _last_yaw_rate = yaw_rate;
_last_g = g; _last_g = g;
if (_erect_time > 0){ //the gyro only erects inside limits
if ( fabs ( yaw_rate ) <= 5
&& g <= 1.5 && g >= -0.5){
if ( !_fast_erect_node->getBoolValue() ) if ( !_fast_erect_node->getBoolValue() ){
_erect_time -= dt; erect_time_factor = 1;
else } else {
_erect_time -= 2 * dt; erect_time_factor = 2;
}
_g_error -= (max_g_error/(erect_time * 0.33)) * dt * erect_time_factor;
} else {
_g_error += (max_g_error /(erect_time * 0.33)) * dt * 2;
//SG_LOG(SG_GENERAL, SG_ALERT,_num <<
// " g input " << _g_in_node->getDoubleValue() * gravity
// <<" _erect_time " << _erect_time
// << " yaw " << yaw_rate
// << " pitch " << _pitch_rate_node->getDoubleValue()
// << " roll " << _roll_rate_node->getDoubleValue());
} }
//SG_LOG(SG_GENERAL, SG_ALERT, //cout << "_g_error "<< _g_error << endl;
// "g input " << g <<" _erect_time " << _erect_time << " spin " << spin); _g_error = SGMiscd::clip(_g_error, 0, 10);
// cout << "_g_error clip "<< _g_error << endl;
indicated_roll = _last_roll + _g_error;
indicated_pitch = _last_pitch + _g_error;
indicated_hdg = _last_hdg + _g_error;
indicated_roll_rate = _last_roll_rate;
indicated_pitch_rate = _last_pitch_rate;
indicated_hdg_rate = _last_yaw_rate;
// calculate the difference between the indicated heading
// and the selected heading for use with an autopilot
static SGPropertyNode *bnode
= fgGetNode( "/autopilot/settings/heading-bug-deg", false );
//the gyro only erects inside limits if ( bnode ) {
if ( fabs ( yaw_rate ) <= 5 double diff = bnode->getDoubleValue() - indicated_hdg;
&& ( g <= 1.5 || g >= -0.5) if ( diff < -180.0 ) { diff += 360.0; }
&& _erect_time <=0 ) { if ( diff > 180.0 ) { diff -= 360.0; }
indicated_roll = _last_roll; _error_out_node->setDoubleValue( diff );
indicated_pitch = _last_pitch; //SG_LOG(SG_GENERAL, SG_ALERT,
indicated_hdg = _last_hdg; //"autopilot input " << bnode->getDoubleValue()
indicated_roll_rate = _last_roll_rate; //<< " output " << _error_out_node->getDoubleValue()<<);
indicated_pitch_rate = _last_pitch_rate; }
indicated_hdg_rate = _last_yaw_rate;
} else {
indicated_roll_rate = 0;
indicated_pitch_rate = 0;
indicated_hdg_rate = 0;
if (_erect_time <= 0 ) //smooth the output
_erect_time = 34; double factor = _responsiveness_node->getDoubleValue() * dt;
} indicated_roll = fgGetLowPass( _indicated_roll, indicated_roll, factor );
indicated_pitch = fgGetLowPass( _indicated_pitch , indicated_pitch, factor );
//indicated_hdg = fgGetLowPass( _indicated_hdg , indicated_hdg, factor );
// calculate the difference between the indicated heading indicated_roll_rate = fgGetLowPass( _indicated_roll_rate, indicated_roll_rate, factor );
// and the selected heading for use with an autopilot indicated_pitch_rate = fgGetLowPass( _indicated_pitch_rate , indicated_pitch_rate, factor );
static SGPropertyNode *bnode indicated_hdg_rate = fgGetLowPass( _indicated_hdg_rate , indicated_hdg_rate, factor );
= fgGetNode( "/autopilot/settings/heading-bug-deg", false );
if ( bnode ) { // store the new values
double diff = bnode->getDoubleValue() - indicated_hdg; _indicated_roll = indicated_roll;
if ( diff < -180.0 ) { diff += 360.0; } _indicated_pitch = indicated_pitch;
if ( diff > 180.0 ) { diff -= 360.0; } _indicated_hdg = indicated_hdg;
_error_out_node->setDoubleValue( diff );
//SG_LOG(SG_GENERAL, SG_ALERT,
//"autopilot input " << bnode->getDoubleValue()
//<< " output " << _error_out_node->getDoubleValue()<<);
}
//smooth the output _indicated_roll_rate = indicated_roll_rate;
double factor = _responsiveness_node->getDoubleValue() * dt; _indicated_pitch_rate = indicated_pitch_rate;
_indicated_hdg_rate = indicated_hdg_rate;
indicated_roll = fgGetLowPass( _indicated_roll, indicated_roll, factor ); // add in a gyro underspin "error" if gyro is spinning too slowly
indicated_pitch = fgGetLowPass( _indicated_pitch , indicated_pitch, factor ); const double spin_thresh = 0.8;
//indicated_hdg = fgGetLowPass( _indicated_hdg , indicated_hdg, factor ); const double max_roll_error = 40.0;
const double max_pitch_error = 12.0;
const double max_hdg_error = 140.0;
double roll_error;
double pitch_error;
double hdg_error;
indicated_roll_rate = fgGetLowPass( _indicated_roll_rate, indicated_roll_rate, factor ); if ( spin <= spin_thresh ) {
indicated_pitch_rate = fgGetLowPass( _indicated_pitch_rate , indicated_pitch_rate, factor ); double roll_error_factor = ( spin_thresh - spin ) / spin_thresh;
indicated_hdg_rate = fgGetLowPass( _indicated_hdg_rate , indicated_hdg_rate, factor ); double pitch_error_factor = ( spin_thresh - spin ) / spin_thresh;
double hdg_error_factor = ( spin_thresh - spin ) / spin_thresh;
roll_error = roll_error_factor * roll_error_factor * max_roll_error;
pitch_error = pitch_error_factor * pitch_error_factor * max_pitch_error;
hdg_error = hdg_error_factor * hdg_error_factor * max_hdg_error;
} else {
roll_error = 0.0;
pitch_error = 0.0;
hdg_error = 0.0;
}
// store the new values _roll_out_node->setDoubleValue( _indicated_roll + roll_error );
_indicated_roll = indicated_roll; _pitch_out_node->setDoubleValue( _indicated_pitch + pitch_error );
_indicated_pitch = indicated_pitch; _hdg_out_node->setDoubleValue( _indicated_hdg + hdg_error );
_indicated_hdg = indicated_hdg; _pitch_rate_out_node ->setDoubleValue( _indicated_pitch_rate );
_roll_rate_out_node ->setDoubleValue( _indicated_roll_rate );
_indicated_roll_rate = indicated_roll_rate; _hdg_rate_out_node ->setDoubleValue( _indicated_hdg_rate );
_indicated_pitch_rate = indicated_pitch_rate;
_indicated_hdg_rate = indicated_hdg_rate;
// add in a gyro underspin "error" if gyro is spinning too slowly
const double spin_thresh = 0.8;
const double max_roll_error = 40.0;
const double max_pitch_error = 12.0;
const double max_hdg_error = 140.0;
double roll_error;
double pitch_error;
double hdg_error;
if ( spin <= spin_thresh ) {
double roll_error_factor = ( spin_thresh - spin ) / spin_thresh;
double pitch_error_factor = ( spin_thresh - spin ) / spin_thresh;
double hdg_error_factor = ( spin_thresh - spin ) / spin_thresh;
roll_error = roll_error_factor * roll_error_factor * max_roll_error;
pitch_error = pitch_error_factor * pitch_error_factor * max_pitch_error;
hdg_error = hdg_error_factor * hdg_error_factor * max_hdg_error;
} else {
roll_error = 0.0;
pitch_error = 0.0;
hdg_error = 0.0;
}
_roll_out_node->setDoubleValue( _indicated_roll + roll_error );
_pitch_out_node->setDoubleValue( _indicated_pitch + pitch_error );
_hdg_out_node->setDoubleValue( _indicated_hdg + hdg_error );
_pitch_rate_out_node ->setDoubleValue( _indicated_pitch_rate );
_roll_rate_out_node ->setDoubleValue( _indicated_roll_rate );
_hdg_rate_out_node ->setDoubleValue( _indicated_hdg_rate );
} }
// end of mrg.cxx // end of mrg.cxx

View file

@ -49,6 +49,8 @@ public:
private: private:
static const double gravity; //conversion factor
string _name; string _name;
int _num; int _num;
@ -66,6 +68,7 @@ private:
double _last_yaw_rate; double _last_yaw_rate;
double _last_g; double _last_g;
double _erect_time; double _erect_time;
double _g_error;
Gyro _gyro; Gyro _gyro;

View file

@ -35,10 +35,15 @@
#include <string> #include <string>
#include <osg/Camera> #include <osg/Camera>
#include <osg/Geometry>
#include <osg/GraphicsContext> #include <osg/GraphicsContext>
#include <osg/io_utils>
#include <osg/Math> #include <osg/Math>
#include <osg/Matrix> #include <osg/Matrix>
#include <osg/Notify>
#include <osg/Program>
#include <osg/Quat> #include <osg/Quat>
#include <osg/TexMat>
#include <osg/Vec3d> #include <osg/Vec3d>
#include <osg/Viewport> #include <osg/Viewport>
@ -148,7 +153,18 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera,
// resized; if the the viewport isn't copied here, it gets updated // resized; if the the viewport isn't copied here, it gets updated
// twice and ends up with the wrong value. // twice and ends up with the wrong value.
farCamera->setViewport(simgear::clone(camera->getViewport())); farCamera->setViewport(simgear::clone(camera->getViewport()));
_viewer->addSlave(farCamera, view, projection, useMasterSceneData); farCamera->setDrawBuffer(camera->getDrawBuffer());
farCamera->setReadBuffer(camera->getReadBuffer());
farCamera->setRenderTargetImplementation(
camera->getRenderTargetImplementation());
const Camera::BufferAttachmentMap& bufferMap
= camera->getBufferAttachmentMap();
if (bufferMap.count(Camera::COLOR_BUFFER) != 0) {
farCamera->attach(
Camera::COLOR_BUFFER,
bufferMap.find(Camera::COLOR_BUFFER)->second._texture);
}
_viewer->addSlave(farCamera, projection, view, useMasterSceneData);
installCullVisitor(farCamera); installCullVisitor(farCamera);
info->farCamera = farCamera; info->farCamera = farCamera;
info->farSlaveIndex = _viewer->getNumSlaves() - 1; info->farSlaveIndex = _viewer->getNumSlaves() - 1;
@ -156,7 +172,7 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera,
camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT); camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT);
camera->setClearMask(GL_DEPTH_BUFFER_BIT); camera->setClearMask(GL_DEPTH_BUFFER_BIT);
} }
_viewer->addSlave(camera, view, projection, useMasterSceneData); _viewer->addSlave(camera, projection, view, useMasterSceneData);
installCullVisitor(camera); installCullVisitor(camera);
info->camera = camera; info->camera = camera;
info->slaveIndex = _viewer->getNumSlaves() - 1; info->slaveIndex = _viewer->getNumSlaves() - 1;
@ -297,6 +313,199 @@ void buildViewport(flightgear::CameraInfo* info, SGPropertyNode* viewportNode,
namespace flightgear namespace flightgear
{ {
// Mostly copied from osg's osgViewer/View.cpp
static osg::Geometry* createParoramicSphericalDisplayDistortionMesh(
const Vec3& origin, const Vec3& widthVector, const Vec3& heightVector,
double sphere_radius, double collar_radius,
Image* intensityMap = 0, const Matrix& projectorMatrix = Matrix())
{
osg::Vec3d center(0.0,0.0,0.0);
osg::Vec3d eye(0.0,0.0,0.0);
double distance = sqrt(sphere_radius*sphere_radius - collar_radius*collar_radius);
bool flip = false;
bool texcoord_flip = false;
osg::Vec3d projector = eye - osg::Vec3d(0.0,0.0, distance);
#if 0
OSG_INFO<<"createParoramicSphericalDisplayDistortionMesh : Projector position = "<<projector<<std::endl;
OSG_INFO<<"createParoramicSphericalDisplayDistortionMesh : distance = "<<distance<<std::endl;
#endif
// create the quad to visualize.
osg::Geometry* geometry = new osg::Geometry();
geometry->setSupportsDisplayList(false);
osg::Vec3 xAxis(widthVector);
float width = widthVector.length();
xAxis /= width;
osg::Vec3 yAxis(heightVector);
float height = heightVector.length();
yAxis /= height;
int noSteps = 160;
osg::Vec3Array* vertices = new osg::Vec3Array;
osg::Vec2Array* texcoords0 = new osg::Vec2Array;
osg::Vec2Array* texcoords1 = intensityMap==0 ? new osg::Vec2Array : 0;
osg::Vec4Array* colors = new osg::Vec4Array;
osg::Vec3 bottom = origin;
osg::Vec3 dx = xAxis*(width/((float)(noSteps-2)));
osg::Vec3 dy = yAxis*(height/((float)(noSteps-1)));
osg::Vec3 top = origin + yAxis*height;
osg::Vec3 screenCenter = origin + widthVector*0.5f + heightVector*0.5f;
float screenRadius = heightVector.length() * 0.5f;
geometry->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
for(int i=0;i<noSteps;++i)
{
osg::Vec3 cursor = bottom+dy*(float)i;
for(int j=0;j<noSteps;++j)
{
osg::Vec2 texcoord(double(i)/double(noSteps-1), double(j)/double(noSteps-1));
double theta = texcoord.x() * 2.0 * osg::PI;
double phi = (1.0-texcoord.y()) * osg::PI;
if (texcoord_flip) texcoord.y() = 1.0f - texcoord.y();
osg::Vec3 pos(sin(phi)*sin(theta), sin(phi)*cos(theta), cos(phi));
pos = pos*projectorMatrix;
double alpha = atan2(pos.x(), pos.y());
if (alpha<0.0) alpha += 2.0*osg::PI;
double beta = atan2(sqrt(pos.x()*pos.x() + pos.y()*pos.y()), pos.z());
if (beta<0.0) beta += 2.0*osg::PI;
double gamma = atan2(sqrt(double(pos.x()*pos.x() + pos.y()*pos.y())), double(pos.z()+distance));
if (gamma<0.0) gamma += 2.0*osg::PI;
osg::Vec3 v = screenCenter + osg::Vec3(sin(alpha)*gamma*2.0/osg::PI, -cos(alpha)*gamma*2.0/osg::PI, 0.0f)*screenRadius;
if (flip)
vertices->push_back(osg::Vec3(v.x(), top.y()-(v.y()-origin.y()),v.z()));
else
vertices->push_back(v);
texcoords0->push_back( texcoord );
osg::Vec2 texcoord1(alpha/(2.0*osg::PI), 1.0f - beta/osg::PI);
if (intensityMap)
{
colors->push_back(intensityMap->getColor(texcoord1));
}
else
{
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
if (texcoords1) texcoords1->push_back( texcoord1 );
}
}
}
// pass the created vertex array to the points geometry object.
geometry->setVertexArray(vertices);
geometry->setColorArray(colors);
geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
geometry->setTexCoordArray(0,texcoords0);
if (texcoords1) geometry->setTexCoordArray(1,texcoords1);
osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES);
geometry->addPrimitiveSet(elements);
for(int i=0;i<noSteps-1;++i)
{
for(int j=0;j<noSteps-1;++j)
{
int i1 = j+(i+1)*noSteps;
int i2 = j+(i)*noSteps;
int i3 = j+1+(i)*noSteps;
int i4 = j+1+(i+1)*noSteps;
osg::Vec3& v1 = (*vertices)[i1];
osg::Vec3& v2 = (*vertices)[i2];
osg::Vec3& v3 = (*vertices)[i3];
osg::Vec3& v4 = (*vertices)[i4];
if ((v1-screenCenter).length()>screenRadius) continue;
if ((v2-screenCenter).length()>screenRadius) continue;
if ((v3-screenCenter).length()>screenRadius) continue;
if ((v4-screenCenter).length()>screenRadius) continue;
elements->push_back(i1);
elements->push_back(i2);
elements->push_back(i3);
elements->push_back(i1);
elements->push_back(i3);
elements->push_back(i4);
}
}
return geometry;
}
void CameraGroup::buildDistortionCamera(const SGPropertyNode* psNode,
Camera* camera)
{
const SGPropertyNode* texNode = psNode->getNode("texture");
if (!texNode) {
// error
return;
}
string texName = texNode->getStringValue();
TextureMap::iterator itr = _textureTargets.find(texName);
if (itr == _textureTargets.end()) {
// error
return;
}
Viewport* viewport = camera->getViewport();
float width = viewport->width();
float height = viewport->height();
TextureRectangle* texRect = itr->second.get();
double radius = psNode->getDoubleValue("radius", 1.0);
double collar = psNode->getDoubleValue("collar", 0.45);
Geode* geode = new Geode();
geode->addDrawable(createParoramicSphericalDisplayDistortionMesh(
Vec3(0.0f,0.0f,0.0f), Vec3(width,0.0f,0.0f),
Vec3(0.0f,height,0.0f), radius, collar));
// new we need to add the texture to the mesh, we do so by creating a
// StateSet to contain the Texture StateAttribute.
StateSet* stateset = geode->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(0, texRect, StateAttribute::ON);
stateset->setMode(GL_LIGHTING, StateAttribute::OFF);
TexMat* texmat = new TexMat;
texmat->setScaleByTextureRectangleSize(true);
stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON);
#if 0
if (!applyIntensityMapAsColours && intensityMap)
{
stateset->setTextureAttributeAndModes(1, new osg::Texture2D(intensityMap), osg::StateAttribute::ON);
}
#endif
// add subgraph to render
camera->addChild(geode);
camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
camera->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
camera->setCullingMode(osg::CullSettings::NO_CULLING);
camera->setName("DistortionCorrectionCamera");
}
CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode) CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode)
{ {
WindowBuilder *wBuild = WindowBuilder::getWindowBuilder(); WindowBuilder *wBuild = WindowBuilder::getWindowBuilder();
@ -390,13 +599,43 @@ CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode)
double sheary = cameraNode->getDoubleValue("shear-y", 0); double sheary = cameraNode->getDoubleValue("shear-y", 0);
pOff.makeTranslate(-shearx, -sheary, 0); pOff.makeTranslate(-shearx, -sheary, 0);
} }
CameraInfo* info = addCamera(cameraFlags, camera, pOff, vOff); const SGPropertyNode* textureNode = cameraNode->getNode("texture");
if (textureNode) {
string texName = textureNode->getStringValue("name");
int tex_width = textureNode->getIntValue("width");
int tex_height = textureNode->getIntValue("height");
TextureRectangle* texture = new TextureRectangle;
texture->setTextureSize(tex_width, tex_height);
texture->setInternalFormat(GL_RGB);
texture->setFilter(Texture::MIN_FILTER, Texture::LINEAR);
texture->setFilter(Texture::MAG_FILTER, Texture::LINEAR);
texture->setWrap(Texture::WRAP_S, Texture::CLAMP_TO_EDGE);
texture->setWrap(Texture::WRAP_T, Texture::CLAMP_TO_EDGE);
camera->setDrawBuffer(GL_FRONT);
camera->setReadBuffer(GL_FRONT);
camera->setRenderTargetImplementation(Camera::FRAME_BUFFER_OBJECT);
camera->attach(Camera::COLOR_BUFFER, texture);
_textureTargets[texName] = texture;
} else {
camera->setDrawBuffer(GL_BACK);
camera->setReadBuffer(GL_BACK);
}
const SGPropertyNode* psNode = cameraNode->getNode("panoramic-spherical");
bool useMasterSceneGraph = !psNode;
CameraInfo* info = addCamera(cameraFlags, camera, vOff, pOff,
useMasterSceneGraph);
// If a viewport isn't set on the camera, then it's hard to dig it // If a viewport isn't set on the camera, then it's hard to dig it
// out of the SceneView objects in the viewer, and the coordinates // out of the SceneView objects in the viewer, and the coordinates
// of mouse events are somewhat bizzare. // of mouse events are somewhat bizzare.
SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true); SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true);
buildViewport(info, viewportNode, window->gc->getTraits()); buildViewport(info, viewportNode, window->gc->getTraits());
updateCameras(info); updateCameras(info);
// Distortion camera needs the viewport which is created by addCamera().
if (psNode) {
info->flags = info->flags | VIEW_ABSOLUTE;
buildDistortionCamera(psNode, camera);
}
return info; return info;
} }

View file

@ -17,6 +17,7 @@
#ifndef CAMERAGROUP_HXX #ifndef CAMERAGROUP_HXX
#define CAMERAGROUP_HXX 1 #define CAMERAGROUP_HXX 1
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
@ -24,6 +25,7 @@
#include <osg/ref_ptr> #include <osg/ref_ptr>
#include <osg/Referenced> #include <osg/Referenced>
#include <osg/Node> #include <osg/Node>
#include <osg/TextureRectangle>
// For osgUtil::LineSegmentIntersector::Intersections, which is a typedef. // For osgUtil::LineSegmentIntersector::Intersections, which is a typedef.
#include <osgUtil/LineSegmentIntersector> #include <osgUtil/LineSegmentIntersector>
@ -178,6 +180,9 @@ public:
/** Update camera properties after a resize event. /** Update camera properties after a resize event.
*/ */
void resized(); void resized();
void buildDistortionCamera(const SGPropertyNode* psNode,
osg::Camera* camera);
protected: protected:
CameraList _cameras; CameraList _cameras;
osg::ref_ptr<osgViewer::Viewer> _viewer; osg::ref_ptr<osgViewer::Viewer> _viewer;
@ -186,6 +191,8 @@ protected:
float _zNear; float _zNear;
float _zFar; float _zFar;
float _nearField; float _nearField;
typedef std::map<std::string, osg::ref_ptr<osg::TextureRectangle> > TextureMap;
TextureMap _textureTargets;
}; };
} }

View file

@ -601,6 +601,9 @@ public:
SGPropertyNode *n = _cache->getNode("fg-root", true); SGPropertyNode *n = _cache->getNode("fg-root", true);
n->setStringValue(globals->get_fg_root().c_str()); n->setStringValue(globals->get_fg_root().c_str());
n->setAttribute(SGPropertyNode::USERARCHIVE, true); n->setAttribute(SGPropertyNode::USERARCHIVE, true);
n = _cache->getNode("fg-aircraft", true);
n->setStringValue(getAircraftPaths().c_str());
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
_cache->removeChildren("aircraft"); _cache->removeChildren("aircraft");
fgFindAircraft(this, &FindAndCacheAircraft::checkAircraft); fgFindAircraft(this, &FindAndCacheAircraft::checkAircraft);
@ -629,12 +632,30 @@ public:
} }
private: private:
SGPath getAircraftPaths() {
string_list pathList = globals->get_aircraft_paths();
SGPath aircraftPaths;
string_list::const_iterator it = pathList.begin();
if (it != pathList.end()) {
aircraftPaths.set(*it);
it++;
}
for (; it != pathList.end(); ++it) {
aircraftPaths.add(*it);
}
return aircraftPaths;
}
bool checkCache() bool checkCache()
{ {
if (globals->get_fg_root() != _cache->getStringValue("fg-root", "")) { if (globals->get_fg_root() != _cache->getStringValue("fg-root", "")) {
return false; // cache mismatch return false; // cache mismatch
} }
if (getAircraftPaths().str() != _cache->getStringValue("fg-aircraft", "")) {
return false; // cache mismatch
}
vector<SGPropertyNode_ptr> cache = _cache->getChildren("aircraft"); vector<SGPropertyNode_ptr> cache = _cache->getChildren("aircraft");
for (unsigned int i = 0; i < cache.size(); i++) { for (unsigned int i = 0; i < cache.size(); i++) {
const char *name = cache[i]->getStringValue("file", ""); const char *name = cache[i]->getStringValue("file", "");

View file

@ -33,7 +33,6 @@ SceneryPager::SceneryPager()
{ {
_pagerRequests.reserve(48); _pagerRequests.reserve(48);
_deleteRequests.reserve(16); _deleteRequests.reserve(16);
setExpiryDelay(120.0);
} }
SceneryPager::SceneryPager(const SceneryPager& rhs) : SceneryPager::SceneryPager(const SceneryPager& rhs) :