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
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
This is a special camera node that displays the 2D GUI.
@ -313,3 +337,61 @@ accounted for.
</rendering>
</sim>
</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());
}
if(_parent != ""){
setParentNode();
}
//if(_parent != ""){
// setParentNode();
//}
setParentNodes(_selected_ac);
//setParentNodes(_selected_ac);
//props->setStringValue("vector/path", _vector_path.c_str());
@ -168,7 +168,11 @@ bool FGAIBallistic::init(bool search_in_AI_path) {
Transform();
//cout << _name << " speed init: " << speed << endl;
if(_parent != ""){
setParentNode();
}
setParentNodes(_selected_ac);
return true;
}

View file

@ -215,13 +215,14 @@ bool FGAIWingman::init(bool search_in_AI_path) {
roll = _rotation;
_ht_agl_ft = 1e10;
props->setStringValue("submodels/path", _path.c_str());
if(_parent != ""){
setParentNode();
}
setParentNodes(_selected_ac);
props->setStringValue("submodels/path", _path.c_str());
user_WoW_node = fgGetNode("gear/gear[1]/wow", true);
return true;
}
@ -277,7 +278,7 @@ double FGAIWingman::calcAngle(double range, SGGeod pos1, SGGeod pos2){
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);
@ -312,8 +313,9 @@ void FGAIWingman::formateToAC(double dt){
double h_feet = 3 * factor;
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;
//cout << "ht case1 " ;
} else if (p_agl > 10 && p_agl <= 150 ) {
@ -332,7 +334,8 @@ void FGAIWingman::formateToAC(double dt){
pos.setLongitudeDeg(_offsetpos.getLongitudeDeg());
// 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);
setPch(p_pch + p_angle + _pitch_offset, dt, 0.9);

View file

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

View file

@ -7,6 +7,7 @@
// This file is in the Public Domain and comes with no warranty.
#include <simgear/compiler.h>
#include <simgear/sg_inlines.h>
#include <iostream>
#include <string>
#include <sstream>
@ -54,15 +55,26 @@ HeadingIndicatorDG::init ()
branch = "/instrumentation/" + name;
_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 );
_offset_node = node->getChild("offset-deg", 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);
_heading_out_node = node->getChild("indicated-heading-deg", 0, true);
_last_heading_deg = (_heading_in_node->getDoubleValue() +
_offset_node->getDoubleValue());
_align_node = node->getChild("align-deg", 0, 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
@ -100,11 +112,30 @@ HeadingIndicatorDG::update (double dt)
_gyro.update(dt);
double spin = _gyro.get_spin_norm();
// No time-based precession for a flux gate compass
// No magvar
double offset = 0;
// Next, calculate time-based precession
double offset = _offset_node->getDoubleValue();
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,
// introducing errors.
@ -122,11 +153,8 @@ HeadingIndicatorDG::update (double dt)
heading = fgGetLowPass(_last_heading_deg, heading, dt * factor);
_last_heading_deg = heading;
heading += offset;
while (heading < 0)
heading += 360;
while (heading > 360)
heading -= 360;
heading += offset + align + error;
SG_NORMALIZE_RANGE(heading, 0.0, 360.0);
_heading_out_node->setDoubleValue(heading);
@ -138,7 +166,7 @@ HeadingIndicatorDG::update (double dt)
double diff = bnode->getDoubleValue() - heading;
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
// 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/structure/subsystem_mgr.hxx>
#include <simgear/math/sg_random.h>
#include "gyro.hxx"
@ -59,6 +60,10 @@ private:
SGPropertyNode_ptr _electrical_node;
SGPropertyNode_ptr _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

View file

@ -20,10 +20,11 @@
#include "mrg.hxx"
const double MasterReferenceGyro::gravity = -32.1740485564;
MasterReferenceGyro::MasterReferenceGyro ( SGPropertyNode *node ) :
_name(node->getStringValue("name", "master-reference-gyro")),
_num(node->getIntValue("number", 0))
_name(node->getStringValue("name", "master-reference-gyro")),
_num(node->getIntValue("number", 0))
{
}
@ -34,237 +35,252 @@ MasterReferenceGyro::~MasterReferenceGyro ()
void
MasterReferenceGyro::init ()
{
_last_hdg = 0;
_last_roll = 0;
_last_pitch = 0;
_indicated_hdg = 0;
_indicated_roll = 0;
_indicated_pitch = 0;
_indicated_hdg_rate = 0;
_indicated_roll_rate = 0;
_indicated_pitch_rate = 0;
_erect_time = 0;
_last_hdg = 0;
_last_roll = 0;
_last_pitch = 0;
_indicated_hdg = 0;
_indicated_roll = 0;
_indicated_pitch = 0;
_indicated_hdg_rate = 0;
_indicated_roll_rate = 0;
_indicated_pitch_rate = 0;
_erect_time = 180;
_last_g = 1;
_g_error = 10;
string branch;
branch = "/instrumentation/" + _name;
string branch;
branch = "/instrumentation/" + _name;
_pitch_in_node = fgGetNode("/orientation/pitch-deg", true);
_roll_in_node = fgGetNode("/orientation/roll-deg", true);
_hdg_in_node = fgGetNode("/orientation/heading-deg", true);
_hdg_mag_in_node = fgGetNode("/orientation/heading-magnetic-deg", true);
_pitch_rate_node = fgGetNode("/orientation/pitch-rate-degps", true);
_roll_rate_node = fgGetNode("/orientation/roll-rate-degps", true);
_yaw_rate_node = fgGetNode("/orientation/yaw-rate-degps", true);
_g_in_node = fgGetNode("/accelerations/pilot-g", true);
_electrical_node = fgGetNode("/systems/electrical/outputs/MRG", true);
_hdg_mag_in_node = fgGetNode("/orientation/heading-magnetic-deg", true);
_pitch_in_node = fgGetNode("/orientation/pitch-deg", true);
_roll_in_node = fgGetNode("/orientation/roll-deg", true);
_hdg_in_node = fgGetNode("/orientation/heading-deg", true);
_hdg_mag_in_node = fgGetNode("/orientation/heading-magnetic-deg", true);
_pitch_rate_node = fgGetNode("/orientation/pitch-rate-degps", true);
_roll_rate_node = fgGetNode("/orientation/roll-rate-degps", true);
_yaw_rate_node = fgGetNode("/orientation/yaw-rate-degps", true);
//_g_in_node = fgGetNode("/accelerations/pilot/z-accel-fps_sec", true);
_g_in_node = fgGetNode("/accelerations/pilot-g", 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 );
_off_node = node->getChild("off-flag", 0, true);
_pitch_out_node = node->getChild("indicated-pitch-deg", 0, true);
_roll_out_node = node->getChild("indicated-roll-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);
_pitch_rate_out_node = node->getChild("indicated-pitch-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);
_responsiveness_node = node->getChild("responsiveness", 0, true);
_error_out_node = node->getChild("heading-bug-error-deg", 0, true);
_hdg_input_source_node = node->getChild("heading-source", 0, true);
_fast_erect_node = node->getChild("fast-erect", 0, true);
SGPropertyNode *node = fgGetNode(branch.c_str(), _num, true );
_off_node = node->getChild("off-flag", 0, true);
_pitch_out_node = node->getChild("indicated-pitch-deg", 0, true);
_roll_out_node = node->getChild("indicated-roll-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);
_pitch_rate_out_node = node->getChild("indicated-pitch-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);
_responsiveness_node = node->getChild("responsiveness", 0, true);
_error_out_node = node->getChild("heading-bug-error-deg", 0, true);
_hdg_input_source_node = node->getChild("heading-source", 0, true);
_fast_erect_node = node->getChild("fast-erect", 0, true);
_electrical_node->setDoubleValue(0);
_responsiveness_node->setDoubleValue(0.75);
_off_node->setBoolValue(false);
_hdg_input_source_node->setBoolValue(false);
_fast_erect_node->setBoolValue(false);
_electrical_node->setDoubleValue(0);
_responsiveness_node->setDoubleValue(0.75);
_off_node->setBoolValue(false);
_hdg_input_source_node->setBoolValue(false);
_fast_erect_node->setBoolValue(false);
_g_in_node->setDoubleValue(1);
}
void
MasterReferenceGyro::bind ()
{
std::ostringstream temp;
string branch;
temp << _num;
branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
std::ostringstream temp;
string branch;
temp << _num;
branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
fgTie((branch + "/serviceable").c_str(),
&_gyro, &Gyro::is_serviceable, &Gyro::set_serviceable);
fgTie((branch + "/spin").c_str(),
&_gyro, &Gyro::get_spin_norm, &Gyro::set_spin_norm);
fgTie((branch + "/serviceable").c_str(),
&_gyro, &Gyro::is_serviceable, &Gyro::set_serviceable);
fgTie((branch + "/spin").c_str(),
&_gyro, &Gyro::get_spin_norm, &Gyro::set_spin_norm);
}
void
MasterReferenceGyro::unbind ()
{
std::ostringstream temp;
string branch;
temp << _num;
branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
std::ostringstream temp;
string branch;
temp << _num;
branch = "/instrumentation/" + _name + "[" + temp.str() + "]";
fgUntie((branch + "/serviceable").c_str());
fgUntie((branch + "/spin").c_str());
fgUntie((branch + "/serviceable").c_str());
fgUntie((branch + "/spin").c_str());
}
void
MasterReferenceGyro::update (double dt)
{
double indicated_roll = 0;
double indicated_pitch = 0;
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);
//sanity check
if (!fgGetBool("/sim/fdm-initialized", false)) {
return;
}
}
// Get the input values
double hdg = _hdg_mag_in_node->getDoubleValue();
double indicated_roll = 0;
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())
hdg = _hdg_in_node->getDoubleValue();
const double erect_time = 180;
const double max_g_error = 10.0;
double roll = _roll_in_node->getDoubleValue();
double pitch = _pitch_in_node->getDoubleValue();
//Get the spin from the gyro
_gyro.set_power_norm( _electrical_node->getDoubleValue()/24 );
_gyro.update(dt);
double spin = _gyro.get_spin_norm();
double roll_rate = _yaw_rate_node->getDoubleValue();
double pitch_rate = _yaw_rate_node->getDoubleValue();
double yaw_rate = _yaw_rate_node->getDoubleValue();
double g = _g_in_node->getDoubleValue();
// set the "off-flag"
if ( _electrical_node->getDoubleValue() > 0 && spin >= 0.25) {
_off_node->setBoolValue(false);
} else {
_off_node->setBoolValue(true);
return;
}
//modulate the input by the spin rate
double responsiveness = spin * spin * spin * spin * spin * spin;
roll = fgGetLowPass( _last_roll, roll, responsiveness );
pitch = fgGetLowPass( _last_pitch , pitch, responsiveness );
// Get the input values
if(_hdg_input_source_node->getBoolValue()){
hdg = _hdg_in_node->getDoubleValue();
} else {
hdg = _hdg_mag_in_node->getDoubleValue();
}
if ((hdg - _last_hdg) > 180)
_last_hdg += 360;
if ((hdg - _last_hdg) < -180)
_last_hdg -= 360;
double roll = _roll_in_node->getDoubleValue();
double pitch = _pitch_in_node->getDoubleValue();
double g = _g_in_node->getDoubleValue()/* / gravity*/;
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!
responsiveness = 0.1 / (spin * spin * spin * spin * spin * spin);
yaw_rate = fgGetLowPass( _last_yaw_rate , yaw_rate, responsiveness );
g = fgGetLowPass( _last_g , g, 0.015 );
//modulate the input by the spin rate
double responsiveness = spin * spin * spin * spin * spin * spin;
roll = fgGetLowPass( _last_roll, roll, responsiveness );
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
_last_roll = roll;
_last_pitch = pitch;
_last_hdg = hdg;
_last_roll_rate = roll_rate;
_last_pitch_rate = pitch_rate;
_last_yaw_rate = yaw_rate;
_last_g = g;
// store the new values
_last_roll = roll;
_last_pitch = pitch;
_last_hdg = hdg;
_last_roll_rate = roll_rate;
_last_pitch_rate = pitch_rate;
_last_yaw_rate = yaw_rate;
_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() )
_erect_time -= dt;
else
_erect_time -= 2 * dt;
if ( !_fast_erect_node->getBoolValue() ){
erect_time_factor = 1;
} else {
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,
// "g input " << g <<" _erect_time " << _erect_time << " spin " << spin);
//cout << "_g_error "<< _g_error << endl;
_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 ( fabs ( yaw_rate ) <= 5
&& ( g <= 1.5 || g >= -0.5)
&& _erect_time <=0 ) {
indicated_roll = _last_roll;
indicated_pitch = _last_pitch;
indicated_hdg = _last_hdg;
indicated_roll_rate = _last_roll_rate;
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 ( bnode ) {
double diff = bnode->getDoubleValue() - indicated_hdg;
if ( diff < -180.0 ) { diff += 360.0; }
if ( diff > 180.0 ) { diff -= 360.0; }
_error_out_node->setDoubleValue( diff );
//SG_LOG(SG_GENERAL, SG_ALERT,
//"autopilot input " << bnode->getDoubleValue()
//<< " output " << _error_out_node->getDoubleValue()<<);
}
if (_erect_time <= 0 )
_erect_time = 34;
//smooth the output
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
// and the selected heading for use with an autopilot
static SGPropertyNode *bnode
= fgGetNode( "/autopilot/settings/heading-bug-deg", false );
indicated_roll_rate = fgGetLowPass( _indicated_roll_rate, indicated_roll_rate, factor );
indicated_pitch_rate = fgGetLowPass( _indicated_pitch_rate , indicated_pitch_rate, factor );
indicated_hdg_rate = fgGetLowPass( _indicated_hdg_rate , indicated_hdg_rate, factor );
if ( bnode ) {
double diff = bnode->getDoubleValue() - indicated_hdg;
if ( diff < -180.0 ) { diff += 360.0; }
if ( diff > 180.0 ) { diff -= 360.0; }
_error_out_node->setDoubleValue( diff );
//SG_LOG(SG_GENERAL, SG_ALERT,
//"autopilot input " << bnode->getDoubleValue()
//<< " output " << _error_out_node->getDoubleValue()<<);
}
// store the new values
_indicated_roll = indicated_roll;
_indicated_pitch = indicated_pitch;
_indicated_hdg = indicated_hdg;
//smooth the output
double factor = _responsiveness_node->getDoubleValue() * dt;
_indicated_roll_rate = indicated_roll_rate;
_indicated_pitch_rate = indicated_pitch_rate;
_indicated_hdg_rate = indicated_hdg_rate;
indicated_roll = fgGetLowPass( _indicated_roll, indicated_roll, factor );
indicated_pitch = fgGetLowPass( _indicated_pitch , indicated_pitch, factor );
//indicated_hdg = fgGetLowPass( _indicated_hdg , indicated_hdg, factor );
// 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;
indicated_roll_rate = fgGetLowPass( _indicated_roll_rate, indicated_roll_rate, factor );
indicated_pitch_rate = fgGetLowPass( _indicated_pitch_rate , indicated_pitch_rate, factor );
indicated_hdg_rate = fgGetLowPass( _indicated_hdg_rate , indicated_hdg_rate, factor );
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;
}
// store the new values
_indicated_roll = indicated_roll;
_indicated_pitch = indicated_pitch;
_indicated_hdg = indicated_hdg;
_indicated_roll_rate = indicated_roll_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 );
_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

View file

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

View file

@ -35,10 +35,15 @@
#include <string>
#include <osg/Camera>
#include <osg/Geometry>
#include <osg/GraphicsContext>
#include <osg/io_utils>
#include <osg/Math>
#include <osg/Matrix>
#include <osg/Notify>
#include <osg/Program>
#include <osg/Quat>
#include <osg/TexMat>
#include <osg/Vec3d>
#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
// twice and ends up with the wrong value.
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);
info->farCamera = farCamera;
info->farSlaveIndex = _viewer->getNumSlaves() - 1;
@ -156,7 +172,7 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera,
camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT);
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
}
_viewer->addSlave(camera, view, projection, useMasterSceneData);
_viewer->addSlave(camera, projection, view, useMasterSceneData);
installCullVisitor(camera);
info->camera = camera;
info->slaveIndex = _viewer->getNumSlaves() - 1;
@ -297,6 +313,199 @@ void buildViewport(flightgear::CameraInfo* info, SGPropertyNode* viewportNode,
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)
{
WindowBuilder *wBuild = WindowBuilder::getWindowBuilder();
@ -390,13 +599,43 @@ CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode)
double sheary = cameraNode->getDoubleValue("shear-y", 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
// out of the SceneView objects in the viewer, and the coordinates
// of mouse events are somewhat bizzare.
SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true);
buildViewport(info, viewportNode, window->gc->getTraits());
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;
}

View file

@ -17,6 +17,7 @@
#ifndef CAMERAGROUP_HXX
#define CAMERAGROUP_HXX 1
#include <map>
#include <string>
#include <vector>
@ -24,6 +25,7 @@
#include <osg/ref_ptr>
#include <osg/Referenced>
#include <osg/Node>
#include <osg/TextureRectangle>
// For osgUtil::LineSegmentIntersector::Intersections, which is a typedef.
#include <osgUtil/LineSegmentIntersector>
@ -178,6 +180,9 @@ public:
/** Update camera properties after a resize event.
*/
void resized();
void buildDistortionCamera(const SGPropertyNode* psNode,
osg::Camera* camera);
protected:
CameraList _cameras;
osg::ref_ptr<osgViewer::Viewer> _viewer;
@ -186,6 +191,8 @@ protected:
float _zNear;
float _zFar;
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);
n->setStringValue(globals->get_fg_root().c_str());
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
n = _cache->getNode("fg-aircraft", true);
n->setStringValue(getAircraftPaths().c_str());
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
_cache->removeChildren("aircraft");
fgFindAircraft(this, &FindAndCacheAircraft::checkAircraft);
@ -629,12 +632,30 @@ public:
}
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()
{
if (globals->get_fg_root() != _cache->getStringValue("fg-root", "")) {
return false; // cache mismatch
}
if (getAircraftPaths().str() != _cache->getStringValue("fg-aircraft", "")) {
return false; // cache mismatch
}
vector<SGPropertyNode_ptr> cache = _cache->getChildren("aircraft");
for (unsigned int i = 0; i < cache.size(); i++) {
const char *name = cache[i]->getStringValue("file", "");

View file

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