]> git.mxchange.org Git - flightgear.git/blobdiff - src/Systems/electrical.cxx
Boris Koenig:
[flightgear.git] / src / Systems / electrical.cxx
index 2559874cace44b644658ab9f3e962a829e44c01f..72dcf3917aeba31d489307cabc3c69fdf6d69812 100644 (file)
@@ -21,7 +21,7 @@
 // $Id$
 
 
-#include <simgear/misc/exception.hxx>
+#include <simgear/structure/exception.hxx>
 #include <simgear/misc/sg_path.hxx>
 
 #include <Main/fg_props.hxx>
@@ -33,7 +33,8 @@
 FGElectricalComponent::FGElectricalComponent() :
     kind(-1),
     name(""),
-    value(0.0)
+    volts(0.0),
+    load_amps(0.0)
 {
 }
 
@@ -56,12 +57,13 @@ FGElectricalSupplier::FGElectricalSupplier ( SGPropertyNode *node ) {
     }
     volts = node->getDoubleValue("volts");
     amps = node->getDoubleValue("amps");
+    rpm_src = node->getStringValue("rpm-source");
 
     int i;
     for ( i = 0; i < node->nChildren(); ++i ) {
         SGPropertyNode *child = node->getChild(i);
         // cout << " scanning: " << child->getName() << endl;
-        if ( (string)child->getName() == "prop" ) {
+        if ( !strcmp(child->getName(), "prop") ) {
             string prop = child->getStringValue();
             // cout << "  Adding prop = " << prop << endl;
             add_prop( prop );
@@ -69,7 +71,7 @@ FGElectricalSupplier::FGElectricalSupplier ( SGPropertyNode *node ) {
         }
     }
 
-    _rpm_node = fgGetNode("/engines/engine[0]/rpm", true);
+    _rpm_node = fgGetNode( rpm_src.c_str(), true);
 }  
 
 
@@ -106,7 +108,7 @@ FGElectricalBus::FGElectricalBus ( SGPropertyNode *node ) {
     int i;
     for ( i = 0; i < node->nChildren(); ++i ) {
         SGPropertyNode *child = node->getChild(i);
-        if ( (string)child->getName() == "prop" ) {
+        if ( !strcmp(child->getName(), "prop") ) {
             string prop = child->getStringValue();
             add_prop( prop );
         }
@@ -116,12 +118,19 @@ FGElectricalBus::FGElectricalBus ( SGPropertyNode *node ) {
 
 FGElectricalOutput::FGElectricalOutput ( SGPropertyNode *node ) {
     kind = FG_OUTPUT;
+    output_amps = 0.1;          // arbitrary default value
 
     name = node->getStringValue("name");
+    SGPropertyNode *draw = node->getNode("rated-draw");
+    if ( draw != NULL ) {
+        output_amps = draw->getDoubleValue();
+    }
+    // cout << "rated draw = " << output_amps << endl;
+
     int i;
     for ( i = 0; i < node->nChildren(); ++i ) {
         SGPropertyNode *child = node->getChild(i);
-        if ( (string)child->getName() == "prop" ) {
+        if ( !strcmp(child->getName(), "prop") ) {
             string prop = child->getStringValue();
             add_prop( prop );
         }
@@ -129,6 +138,37 @@ FGElectricalOutput::FGElectricalOutput ( SGPropertyNode *node ) {
 }  
 
 
+FGElectricalSwitch::FGElectricalSwitch( SGPropertyNode *node ) :
+    switch_node( NULL ),
+    rating_amps( 0.0f ),
+    circuit_breaker( false )
+{
+    bool initial_state = true;
+    int i;
+    for ( i = 0; i < node->nChildren(); ++i ) {
+        SGPropertyNode *child = node->getChild(i);
+        string cname = child->getName();
+        string cval = child->getStringValue();
+        if ( cname == "prop" ) {
+            switch_node = fgGetNode( cval.c_str(), true );
+            // cout << "switch node = " << cval << endl;
+        } else if ( cname == "initial-state" ) {
+            if ( cval == "off" || cval == "false" ) {
+                initial_state = false;
+            }
+            // cout << "initial state = " << initial_state << endl;
+        } else if ( cname == "rating-amps" ) {
+            rating_amps = atof( cval.c_str() );
+            circuit_breaker = true;
+            // cout << "initial state = " << initial_state << endl;
+        }            
+    }
+
+    switch_node->setBoolValue( initial_state );
+    // cout << "  value = " << switch_node->getBoolValue() << endl;
+}
+
+
 FGElectricalConnector::FGElectricalConnector ( SGPropertyNode *node,
                                                FGElectricalSystem *es ) {
     kind = FG_CONNECTOR;
@@ -174,25 +214,9 @@ FGElectricalConnector::FGElectricalConnector ( SGPropertyNode *node,
                         << child->getStringValue() );
             }
         } else if ( cname == "switch" ) {
-            // set default value of switch to true
-            // cout << "Switch = " << child->getStringValue() << endl;
-            fgSetBool( child->getStringValue(), true );
-            add_switch( fgGetNode( child->getStringValue(), true ) );
-        }
-    }
-
-    // do a 2nd pass to pick up starting switch value if specified
-    for ( i = 0; i < node->nChildren(); ++i ) {
-        SGPropertyNode *child = node->getChild(i);
-        string cname = child->getName();
-        string cval = child->getStringValue();
-        // cout << "  " << cname << " = " << cval << endl;
-        if ( cname == "initial-state" ) {
-            if ( cval == "off" ) {
-                set_switches( false );
-            } else {
-                set_switches( true );
-            }
+             // cout << "Switch = " << child->getStringValue() << endl;
+            FGElectricalSwitch s( child );
+            add_switch( s );
         }
     }
 }  
@@ -200,9 +224,9 @@ FGElectricalConnector::FGElectricalConnector ( SGPropertyNode *node,
 
 // set all switches to the specified state
 void FGElectricalConnector::set_switches( bool state ) {
-    cout << "setting switch state to " << state << endl;
+    // cout << "setting switch state to " << state << endl;
     for ( unsigned int i = 0; i < switches.size(); ++i ) {
-        switches[i]->setBoolValue( state );
+        switches[i].set_state( state );
     }
 }
 
@@ -213,7 +237,7 @@ void FGElectricalConnector::set_switches( bool state ) {
 bool FGElectricalConnector::get_state() {
     unsigned int i;
     for ( i = 0; i < switches.size(); ++i ) {
-        if ( ! switches[i]->getBoolValue() ) {
+        if ( ! switches[i].get_state() ) {
             return false;
         }
     }
@@ -236,12 +260,14 @@ void FGElectricalSystem::init () {
     config_props = new SGPropertyNode;
 
     SGPropertyNode *path_n = fgGetNode("/sim/systems/electrical/path");
+    _volts_out = fgGetNode( "/systems/electrical/volts", true );
+    _amps_out = fgGetNode( "/systems/electrical/amps", true );
 
     if (path_n) {
         SGPath config( globals->get_fg_root() );
         config.append( path_n->getStringValue() );
 
-        SG_LOG( SG_ALL, SG_ALERT, "Reading electrical system model from "
+        SG_LOG( SG_ALL, SG_INFO, "Reading electrical system model from "
                 << config.str() );
         try {
             readProperties( config.str(), config_props );
@@ -262,9 +288,10 @@ void FGElectricalSystem::init () {
                     << config.str() );
         }
 
-    } else
-        SG_LOG( SG_ALL, SG_ALERT,
+    } else {
+        SG_LOG( SG_ALL, SG_WARN,
                 "No electrical model specified for this model!");
+    }
 
     delete config_props;
 }
@@ -280,6 +307,7 @@ void FGElectricalSystem::unbind () {
 
 void FGElectricalSystem::update (double dt) {
     if ( !enabled ) {
+        _amps_out->setDoubleValue(0);
         return;
     }
 
@@ -289,24 +317,76 @@ void FGElectricalSystem::update (double dt) {
 
     // zero everything out before we start
     for ( i = 0; i < suppliers.size(); ++i ) {
-        suppliers[i]->set_value( 0.0 );
+        suppliers[i]->set_volts( 0.0 );
+        suppliers[i]->set_load_amps( 0.0 );
     }
     for ( i = 0; i < buses.size(); ++i ) {
-        buses[i]->set_value( 0.0 );
+        buses[i]->set_volts( 0.0 );
+        buses[i]->set_load_amps( 0.0 );
     }
     for ( i = 0; i < outputs.size(); ++i ) {
-        outputs[i]->set_value( 0.0 );
+        outputs[i]->set_volts( 0.0 );
+        outputs[i]->set_load_amps( 0.0 );
     }
     for ( i = 0; i < connectors.size(); ++i ) {
-        connectors[i]->set_value( 0.0 );
+        connectors[i]->set_volts( 0.0 );
+        connectors[i]->set_load_amps( 0.0 );
     }
 
-    // for each supplier, propogate the electrical current
+    // for each supplier, propagate the electrical current
     for ( i = 0; i < suppliers.size(); ++i ) {
         // cout << " Updating: " << suppliers[i]->get_name() << endl;
-        propogate( suppliers[i], 0.0, " " );
+        propagate( suppliers[i], 0.0, " " );
     }
 
+    double alt_norm
+        = fgGetDouble("/systems/electrical/suppliers/alternator") / 60.0;
+
+    // impliment an extremely simplistic voltage model (assumes
+    // certain naming conventions in electrical system config)
+    // FIXME: we probably want to be able to feed power from all
+    // engines if they are running and the master-alt is switched on
+    double volts = 0.0;
+    if ( fgGetBool("/controls/engines/engine[0]/master-bat") ) {
+        volts = 24.0;
+    }
+    if ( fgGetBool("/controls/engines/engine[0]/master-alt") ) {
+        if ( fgGetDouble("/engines/engine[0]/rpm") > 800 ) {
+            double alt_contrib = 28.0;
+            if ( alt_contrib > volts ) {
+                volts = alt_contrib;
+            }
+        } else if ( fgGetDouble("/engines/engine[0]/rpm") > 200 ) {
+            double alt_contrib = 20.0;
+            if ( alt_contrib > volts ) {
+                volts = alt_contrib;
+            }
+        }
+    }
+    _volts_out->setDoubleValue( volts );
+
+    // impliment an extremely simplistic amps model (assumes certain
+    // naming conventions in the electrical system config) ... FIXME:
+    // make this more generic
+    double amps = 0.0;
+    if ( fgGetBool("/controls/engines/engine[0]/master-bat") ) {
+        if ( fgGetBool("/controls/engines/engine[0]/master-alt") &&
+             fgGetDouble("/engines/engine[0]/rpm") > 800 )
+        {
+            amps += 40.0 * alt_norm;
+        }
+        amps -= 15.0;            // normal load
+        if ( fgGetBool("/controls/switches/flashing-beacon") ) {
+            amps -= 7.5;
+        }
+        if ( fgGetBool("/controls/switches/nav-lights") ) {
+            amps -= 7.5;
+        }
+        if ( amps > 7.0 ) {
+            amps = 7.0;
+        }
+    }
+    _amps_out->setDoubleValue( amps );
 }
 
 
@@ -346,52 +426,68 @@ bool FGElectricalSystem::build () {
 }
 
 
-// propogate the electrical current through the network
-void FGElectricalSystem::propogate( FGElectricalComponent *node, double val,
+// propagate the electrical current through the network, returns the
+// total current drawn by the children of this node.
+float FGElectricalSystem::propagate( FGElectricalComponent *node, double val,
                                     string s ) {
     s += " ";
+    
+    float current_amps = 0.0;
 
     // determine the current to carry forward
-    double current = 0.0;
+    double volts = 0.0;
     if ( !fgGetBool("/systems/electrical/serviceable") ) {
-        current = 0;
+        volts = 0;
     } else if ( node->get_kind() == FG_SUPPLIER ) {
         // cout << s << " is a supplier" << endl;
-        current = ((FGElectricalSupplier *)node)->get_output();
+        volts = ((FGElectricalSupplier *)node)->get_output();
     } else if ( node->get_kind() == FG_BUS ) {
         // cout << s << " is a bus" << endl;
-        current = val;
+        volts = val;
     } else if ( node->get_kind() == FG_OUTPUT ) {
         // cout << s << " is an output" << endl;
-        current = val;
+        volts = val;
+        if ( volts > 1.0 ) {
+            // draw current if we have voltage
+            current_amps = ((FGElectricalOutput *)node)->get_output_amps();
+        }
     } else if ( node->get_kind() == FG_CONNECTOR ) {
         // cout << s << " is a connector" << endl;
         if ( ((FGElectricalConnector *)node)->get_state() ) {
-            current = val;
+            volts = val;
         } else {
-            current = 0.0;
+            volts = 0.0;
         }
-        // cout << s << "  val = " << current << endl;
+        // cout << s << "  val = " << volts << endl;
     } else {
         SG_LOG( SG_ALL, SG_ALERT, "unkown node type" );
     }
 
-    if ( current > node->get_value() ) {
-        node->set_value( current );
+    if ( volts > node->get_volts() ) {
+        node->set_volts( volts );
     }
 
     int i;
 
     // publish values to specified properties
     for ( i = 0; i < node->get_num_props(); ++i ) {
-        fgSetDouble( node->get_prop(i).c_str(), node->get_value() );
+        fgSetDouble( node->get_prop(i).c_str(), node->get_volts() );
     }
     // cout << s << node->get_name() << " -> " << node->get_value() << endl;
 
-    // propogate to all children
+    // propagate to all children
     for ( i = 0; i < node->get_num_outputs(); ++i ) {
-        propogate( node->get_output(i), current, s );
+        current_amps += propagate( node->get_output(i), volts, s );
     }
+
+    // if not an output node, register the downstream current draw
+    // with this node.  If volts are zero, current draw should be zero.
+    if ( node->get_kind() != FG_OUTPUT ) {
+        node->set_load_amps( current_amps );
+    }
+    // cout << s << node->get_name() << " -> " << current_amps << endl;
+
+    return current_amps;
 }