~ubuntu-branches/debian/sid/flightgear/sid

« back to all changes in this revision

Viewing changes to src/FDM/JSBSim/input_output/FGScript.cpp

  • Committer: Package Import Robot
  • Author(s): Markus Wanner, Markus Wanner, Rebecca Palmer
  • Date: 2014-01-21 22:31:02 UTC
  • mfrom: (1.3.1) (15.1.2 experimental)
  • Revision ID: package-import@ubuntu.com-20140121223102-cjw7g9le25acd119
Tags: 3.0.0~git20140204+c99ea4-1
[ Markus Wanner ]
* Upload to unstable.
* Adjust B-D to allow building on kfreebsd-*. Closes: #724686.
* Add a lintian-overrides on autotools; we use cmake.
* Upstream corrected the fgfs manpage. Closes: #556362.
* Drop unnecessary man page for gl-info. Closes: #698308.
* Drop README.Linux: it's outdated to the point of uselessness.
  Closes: #574173.
* Add an upper limit of libsimgear-dev versions that flightgear can be
  built with. Closes: #738436.
* Drop the libsvn-dev dependency, neither flightgear nor simgear depend
  on libsvn, anymore. Closes: #682947.
* List icons in debian/install rather than copying around from rules.
* Update menu entry for flightgear, add one for fgcom; add .xpm icons.
  Closes: #713924.
* flightgear.desktop: add German translation
* Bump Standards-Version to 3.9.5; no changes needed.

[ Rebecca Palmer ]
* New upstream release.
* Install the icons (based on code by Saikrishna Arcot).  (Not a
  complete fix for LP908153 as it only sets the menu/Dash icon, not the
  running window's icon, but better than nothing).
* Disable screensaver while running. Closes: LP#793599. Add required
  libdbus-1-dev dependency.
* Remove outdated README.Debian.
* Terrasync now works after just ticking the box. Closes: #252899.
* Always set Terrasync directory.

Show diffs side-by-side

added added

removed removed

Lines of Context:
47
47
 
48
48
#include "FGScript.h"
49
49
#include "input_output/FGXMLElement.h"
50
 
#include "input_output/FGXMLParse.h"
 
50
#include "input_output/FGXMLFileRead.h"
51
51
#include "initialization/FGTrim.h"
52
52
#include "models/FGInput.h"
53
53
 
55
55
 
56
56
namespace JSBSim {
57
57
 
58
 
static const char *IdSrc = "$Id: FGScript.cpp,v 1.49 2011/11/10 12:06:14 jberndt Exp $";
 
58
static const char *IdSrc = "$Id: FGScript.cpp,v 1.53 2013/11/24 11:40:55 bcoconni Exp $";
59
59
static const char *IdHdr = ID_FGSCRIPT;
60
60
 
61
61
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
99
99
 
100
100
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101
101
 
102
 
bool FGScript::LoadScript(string script, double deltaT)
 
102
bool FGScript::LoadScript(string script, double deltaT, const string initfile)
103
103
{
104
104
  string aircraft="", initialize="", comparison = "", prop_name="";
105
105
  string notifyPropertyName="";
114
114
  struct event *newEvent;
115
115
  FGCondition *newCondition;
116
116
 
117
 
  document = LoadXMLDocument(script);
 
117
  FGXMLFileRead XMLFileRead;
 
118
  Element* document = XMLFileRead.LoadXMLDocument(script);
118
119
 
119
120
  if (!document) {
120
121
    cerr << "File: " << script << " could not be loaded." << endl;
174
175
    }
175
176
 
176
177
    initialize = element->GetAttributeValue("initialize");
 
178
    if (initfile.empty()) {
177
179
    if (initialize.empty()) {
178
180
      cerr << "Initialization file must be specified in use element." << endl;
179
181
      return false;
 
182
      }
 
183
    } else {
 
184
      cout << endl << "The initialization file specified in the script file (" << initialize
 
185
                   << ") has been overridden with a specified file (" << initfile << ")." << endl;
 
186
      initialize = initfile;
180
187
    }
181
188
 
182
189
  } else {
269
276
 
270
277
    // Notify about when this event is triggered?
271
278
    if ((notify_element = event_element->FindElement("notify")) != 0) {
 
279
      if (notify_element->HasAttribute("format")) {
 
280
        if (notify_element->GetAttributeValue("format") == "kml") newEvent->NotifyKML = true;
 
281
      }
272
282
      newEvent->Notify = true;
273
283
      // Check here for new <description> tag that gets echoed
274
284
      string notify_description = notify_element->FindElementValue("description");
278
288
      notify_property_element = notify_element->FindElement("property");
279
289
      while (notify_property_element) {
280
290
        notifyPropertyName = notify_property_element->GetDataLine();
281
 
        if (PropertyManager->GetNode(notifyPropertyName)) {
282
 
          newEvent->NotifyProperties.push_back( PropertyManager->GetNode(notifyPropertyName) );
 
291
 
 
292
        newEvent->NotifyPropertyNames.push_back(notifyPropertyName);
 
293
        newEvent->NotifyProperties.push_back(0);
283
294
          string caption_attribute = notify_property_element->GetAttributeValue("caption");
284
295
          if (caption_attribute.empty()) {
285
296
            newEvent->DisplayString.push_back(notifyPropertyName);
286
297
          } else {
287
298
            newEvent->DisplayString.push_back(caption_attribute);
288
299
          }
289
 
        } else {
290
 
          cout << endl << fgred << "  Could not find the property named "
291
 
               << notifyPropertyName << " in script" << endl << "  \""
292
 
               << ScriptName << "\". Execution is aborted. Please recheck "
293
 
               << "your input files and scripts." << reset << endl;
294
 
          delete newEvent->Condition;
295
 
          delete newEvent;
296
 
          return false;
297
 
        }
 
300
 
298
301
        notify_property_element = notify_element->FindNextElement("property");
299
302
      }
300
303
    }
303
306
    set_element = event_element->FindElement("set");
304
307
    while (set_element) {
305
308
      prop_name = set_element->GetAttributeValue("name");
 
309
      if (PropertyManager->HasNode(prop_name)) {
306
310
      newEvent->SetParam.push_back( PropertyManager->GetNode(prop_name) );
 
311
      } else {
 
312
        newEvent->SetParam.push_back( 0L );
 
313
      }
 
314
      newEvent->SetParamName.push_back( prop_name );
 
315
 
307
316
      //Todo - should probably do some safety checking here to make sure one or the other
308
317
      //of value or function is specified.
309
318
      if (!set_element->GetAttributeValue("value").empty()) {
368
377
 
369
378
  // Iterate over all events.
370
379
  for (unsigned int ev_ctr=0; ev_ctr < Events.size(); ev_ctr++) {
 
380
 
 
381
    struct event &thisEvent = Events[ev_ctr];
 
382
 
371
383
    // Determine whether the set of conditional tests for this condition equate
372
384
    // to true and should cause the event to execute. If the conditions evaluate 
373
385
    // to true, then the event is triggered. If the event is not persistent,
374
386
    // then this trigger will remain set true. If the event is persistent,
375
387
    // the trigger will reset to false when the condition evaluates to false.
376
 
    if (Events[ev_ctr].Condition->Evaluate()) {
377
 
      if (!Events[ev_ctr].Triggered) {
 
388
    if (thisEvent.Condition->Evaluate()) {
 
389
      if (!thisEvent.Triggered) {
378
390
 
379
391
        // The conditions are true, do the setting of the desired Event parameters
380
 
        for (i=0; i<Events[ev_ctr].SetValue.size(); i++) {
381
 
          Events[ev_ctr].OriginalValue[i] = Events[ev_ctr].SetParam[i]->getDoubleValue();
382
 
          if (Events[ev_ctr].Functions[i] != 0) { // Parameter should be set to a function value
 
392
        for (i=0; i<thisEvent.SetValue.size(); i++) {
 
393
          if (thisEvent.SetParam[i] == 0L) { // Late bind property if necessary
 
394
            if (PropertyManager->HasNode(thisEvent.SetParamName[i])) {
 
395
              thisEvent.SetParam[i] = PropertyManager->GetNode(thisEvent.SetParamName[i]);
 
396
            } else {
 
397
              throw("No property, \""+thisEvent.SetParamName[i]+"\" is defined.");
 
398
            }
 
399
          }
 
400
          thisEvent.OriginalValue[i] = thisEvent.SetParam[i]->getDoubleValue();
 
401
          if (thisEvent.Functions[i] != 0) { // Parameter should be set to a function value
383
402
            try {
384
 
              Events[ev_ctr].SetValue[i] = Events[ev_ctr].Functions[i]->GetValue();
 
403
              thisEvent.SetValue[i] = thisEvent.Functions[i]->GetValue();
385
404
            } catch (string msg) {
386
405
              std::cerr << std::endl << "A problem occurred in the execution of the script. " << msg << endl;
387
406
              throw;
388
407
            }
389
408
          }
390
 
          switch (Events[ev_ctr].Type[i]) {
 
409
          switch (thisEvent.Type[i]) {
391
410
          case FG_VALUE:
392
411
          case FG_BOOL:
393
 
            Events[ev_ctr].newValue[i] = Events[ev_ctr].SetValue[i];
 
412
            thisEvent.newValue[i] = thisEvent.SetValue[i];
394
413
            break;
395
414
          case FG_DELTA:
396
 
            Events[ev_ctr].newValue[i] = Events[ev_ctr].OriginalValue[i] + Events[ev_ctr].SetValue[i];
 
415
            thisEvent.newValue[i] = thisEvent.OriginalValue[i] + thisEvent.SetValue[i];
397
416
            break;
398
417
          default:
399
418
            cerr << "Invalid Type specified" << endl;
400
419
            break;
401
420
          }
402
 
          Events[ev_ctr].StartTime = currentTime + Events[ev_ctr].Delay;
403
 
          Events[ev_ctr].ValueSpan[i] = Events[ev_ctr].newValue[i] - Events[ev_ctr].OriginalValue[i];
404
 
          Events[ev_ctr].Transiting[i] = true;
 
421
          thisEvent.StartTime = currentTime + thisEvent.Delay;
 
422
          thisEvent.ValueSpan[i] = thisEvent.newValue[i] - thisEvent.OriginalValue[i];
 
423
          thisEvent.Transiting[i] = true;
405
424
        }
406
425
      }
407
 
      Events[ev_ctr].Triggered = true;
 
426
      thisEvent.Triggered = true;
408
427
 
409
 
    } else if (Events[ev_ctr].Persistent) { // If the event is persistent, reset the trigger.
410
 
      Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events
411
 
      Events[ev_ctr].Notified = false;  // Also reset the notification flag
412
 
    } else if (Events[ev_ctr].Continuous) { // If the event is continuous, reset the trigger.
413
 
      Events[ev_ctr].Triggered = false; // Reset the trigger for persistent events
414
 
      Events[ev_ctr].Notified = false;  // Also reset the notification flag
 
428
    } else if (thisEvent.Persistent) { // If the event is persistent, reset the trigger.
 
429
      thisEvent.Triggered = false; // Reset the trigger for persistent events
 
430
      thisEvent.Notified = false;  // Also reset the notification flag
 
431
    } else if (thisEvent.Continuous) { // If the event is continuous, reset the trigger.
 
432
      thisEvent.Triggered = false; // Reset the trigger for persistent events
 
433
      thisEvent.Notified = false;  // Also reset the notification flag
415
434
    }
416
435
 
417
 
    if ((currentTime >= Events[ev_ctr].StartTime) && Events[ev_ctr].Triggered) {
 
436
    if ((currentTime >= thisEvent.StartTime) && thisEvent.Triggered) {
418
437
 
419
 
      for (i=0; i<Events[ev_ctr].SetValue.size(); i++) {
420
 
        if (Events[ev_ctr].Transiting[i]) {
421
 
          Events[ev_ctr].TimeSpan = currentTime - Events[ev_ctr].StartTime;
422
 
          switch (Events[ev_ctr].Action[i]) {
 
438
      for (i=0; i<thisEvent.SetValue.size(); i++) {
 
439
        if (thisEvent.Transiting[i]) {
 
440
          thisEvent.TimeSpan = currentTime - thisEvent.StartTime;
 
441
          switch (thisEvent.Action[i]) {
423
442
          case FG_RAMP:
424
 
            if (Events[ev_ctr].TimeSpan <= Events[ev_ctr].TC[i]) {
425
 
              newSetValue = Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i];
 
443
            if (thisEvent.TimeSpan <= thisEvent.TC[i]) {
 
444
              newSetValue = thisEvent.TimeSpan/thisEvent.TC[i] * thisEvent.ValueSpan[i] + thisEvent.OriginalValue[i];
426
445
            } else {
427
 
              newSetValue = Events[ev_ctr].newValue[i];
428
 
              if (Events[ev_ctr].Continuous != true) Events[ev_ctr].Transiting[i] = false;
 
446
              newSetValue = thisEvent.newValue[i];
 
447
              if (thisEvent.Continuous != true) thisEvent.Transiting[i] = false;
429
448
            }
430
449
            break;
431
450
          case FG_STEP:
432
 
            newSetValue = Events[ev_ctr].newValue[i];
 
451
            newSetValue = thisEvent.newValue[i];
433
452
 
434
453
            // If this is not a continuous event, reset the transiting flag.
435
454
            // Otherwise, it is known that the event is a continuous event.
436
455
            // Furthermore, if the event is to be determined by a function,
437
456
            // then the function will be continuously calculated.
438
 
            if (Events[ev_ctr].Continuous != true)
439
 
              Events[ev_ctr].Transiting[i] = false;
440
 
            else if (Events[ev_ctr].Functions[i] != 0)
441
 
              newSetValue = Events[ev_ctr].Functions[i]->GetValue();
 
457
            if (thisEvent.Continuous != true)
 
458
              thisEvent.Transiting[i] = false;
 
459
            else if (thisEvent.Functions[i] != 0)
 
460
              newSetValue = thisEvent.Functions[i]->GetValue();
442
461
 
443
462
            break;
444
463
          case FG_EXP:
445
 
            newSetValue = (1 - exp( -Events[ev_ctr].TimeSpan/Events[ev_ctr].TC[i] )) * Events[ev_ctr].ValueSpan[i] + Events[ev_ctr].OriginalValue[i];
 
464
            newSetValue = (1 - exp( -thisEvent.TimeSpan/thisEvent.TC[i] )) * thisEvent.ValueSpan[i] + thisEvent.OriginalValue[i];
446
465
            break;
447
466
          default:
448
467
            cerr << "Invalid Action specified" << endl;
449
468
            break;
450
469
          }
451
 
          Events[ev_ctr].SetParam[i]->setDoubleValue(newSetValue);
 
470
          thisEvent.SetParam[i]->setDoubleValue(newSetValue);
452
471
        }
453
472
      }
454
473
 
455
474
      // Print notification values after setting them
456
 
      if (Events[ev_ctr].Notify && !Events[ev_ctr].Notified) {
457
 
        cout << endl << "  Event " << event_ctr << " (" << Events[ev_ctr].Name << ")"
458
 
             << " executed at time: " << currentTime << endl;
459
 
        if (!Events[ev_ctr].Description.empty()) {
460
 
          cout << "    " << Events[ev_ctr].Description << endl;
461
 
        }
462
 
        for (j=0; j<Events[ev_ctr].NotifyProperties.size();j++) {
463
 
//          cout << "    " << Events[ev_ctr].NotifyProperties[j]->GetRelativeName()
464
 
          cout << "    " << Events[ev_ctr].DisplayString[j]
465
 
               << " = " << Events[ev_ctr].NotifyProperties[j]->getDoubleValue() << endl;
 
475
      if (thisEvent.Notify && !thisEvent.Notified) {
 
476
        if (thisEvent.NotifyKML) {
 
477
          cout << endl << "<Placemark>" << endl;
 
478
          cout << "  <name> " << currentTime << " seconds" << " </name>" << endl;
 
479
          cout << "  <description>" << endl;
 
480
          cout << "  <![CDATA[" << endl;
 
481
          cout << "  <b>" << thisEvent.Name << " (Event " << event_ctr << ")" << " executed at time: " << currentTime << "</b><br/>" << endl;
 
482
        } else  {
 
483
          cout << endl << underon
 
484
               << highint << thisEvent.Name << normint << underoff
 
485
               << " (Event " << event_ctr << ")" 
 
486
               << " executed at time: " << highint << currentTime << normint << endl;
 
487
        }
 
488
        if (!thisEvent.Description.empty()) {
 
489
          cout << "    " << thisEvent.Description << endl;
 
490
        }
 
491
        for (j=0; j<thisEvent.NotifyProperties.size();j++) {
 
492
          if (thisEvent.NotifyProperties[j] == 0) {
 
493
            if (PropertyManager->HasNode(thisEvent.NotifyPropertyNames[j])) {
 
494
              thisEvent.NotifyProperties[j] = PropertyManager->GetNode(thisEvent.NotifyPropertyNames[j]);
 
495
            } else {
 
496
              throw("Could not find property named "+thisEvent.NotifyPropertyNames[j]+" in script.");
 
497
            }
 
498
          }
 
499
          cout << "    " << thisEvent.DisplayString[j] << " = " << thisEvent.NotifyProperties[j]->getDoubleValue();
 
500
          if (thisEvent.NotifyKML) cout << " <br/>";
 
501
          cout << endl;
 
502
        }
 
503
        if (thisEvent.NotifyKML) {
 
504
          cout << "  ]]>" << endl;
 
505
          cout << "  </description>" << endl;
 
506
          cout << "  <Point>" << endl;
 
507
          cout << "    <altitudeMode> absolute </altitudeMode>" << endl;
 
508
          cout << "    <extrude> 1 </extrude>" << endl;
 
509
          cout << "    <coordinates>" << FDMExec->GetPropagate()->GetLongitudeDeg()
 
510
            << "," << FDMExec->GetPropagate()->GetGeodLatitudeDeg()
 
511
            << "," << FDMExec->GetPropagate()->GetAltitudeASLmeters() << "</coordinates>" << endl;
 
512
          cout << "  </Point>" << endl;
 
513
          cout << "</Placemark>" << endl;
466
514
        }
467
515
        cout << endl;
468
 
        Events[ev_ctr].Notified = true;
 
516
        thisEvent.Notified = true;
469
517
      }
470
518
 
471
519
    }
538
586
        for (unsigned j=0; j<Events[i].SetValue.size(); j++) {
539
587
          if (Events[i].SetValue[j] == 0.0 && Events[i].Functions[j] != 0L) {
540
588
            if (Events[i].SetParam[j] == 0) {
 
589
              if (Events[i].SetParamName[j].size() == 0) {
541
590
              cerr << fgred << highint << endl
542
591
                   << "  An attempt has been made to access a non-existent property" << endl
543
592
                   << "  in this event. Please check the property names used, spelling, etc."
544
593
                   << reset << endl;
545
594
              exit(-1);
 
595
              } else {
 
596
                cout << endl << "      set " << Events[i].SetParamName[j]
 
597
                     << " to function value (Late Bound)";
546
598
            }
 
599
            } else {
547
600
            cout << endl << "      set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
548
601
                 << " to function value";
 
602
            }
549
603
          } else {
550
604
            if (Events[i].SetParam[j] == 0) {
 
605
              if (Events[i].SetParamName[j].size() == 0) {
551
606
              cerr << fgred << highint << endl
552
607
                   << "  An attempt has been made to access a non-existent property" << endl
553
608
                   << "  in this event. Please check the property names used, spelling, etc."
554
609
                   << reset << endl;
555
610
              exit(-1);
 
611
              } else {
 
612
                cout << endl << "      set " << Events[i].SetParamName[j]
 
613
                     << " to function value (Late Bound)";
556
614
            }
 
615
            } else {
557
616
            cout << endl << "      set " << Events[i].SetParam[j]->GetRelativeName("/fdm/jsbsim/")
558
617
                 << " to " << Events[i].SetValue[j];
559
618
          }
 
619
          }
560
620
 
561
621
          switch (Events[i].Type[j]) {
562
622
          case FG_VALUE:
592
652
        // Print notifications
593
653
        if (Events[i].Notify) {
594
654
          if (Events[i].NotifyProperties.size() > 0) {
595
 
            cout << "  Notifications" << ":" << endl << "    {" << endl;
596
 
            for (unsigned j=0; j<Events[i].NotifyProperties.size();j++) {
 
655
            if (Events[i].NotifyKML) {
 
656
              cout << "  Notifications (KML Format):" << endl << "    {" << endl;
 
657
            } else {
 
658
              cout << "  Notifications:" << endl << "    {" << endl;
 
659
            }
 
660
            for (unsigned j=0; j<Events[i].NotifyPropertyNames.size();j++) {
597
661
              cout << "      "
598
 
                   << Events[i].NotifyProperties[j]->GetRelativeName("/fdm/jsbsim/")
 
662
                   << Events[i].NotifyPropertyNames[j]
599
663
                   << endl;
600
664
            }
601
665
            cout << "    }" << endl;