311 const string& Prefix)
320 temp +=
p->GetValue();
326 string operation = element->
GetName();
329 if (operation ==
"property" || operation ==
"p") {
332 if (var && simgear::strutils::strip(property_name) ==
"#")
335 if (property_name.find(
"#") != string::npos) {
337 property_name =
replace(property_name,
"#",Prefix);
341 <<
fgred <<
"Illegal use of the special character '#'"
343 throw(
"Fatal Error.");
356 << function_str <<
" has been defined. This property will "
357 <<
"not be logged. You should check your configuration file."
365 }
else if (operation ==
"value" || operation ==
"v") {
367 }
else if (operation ==
"pi") {
369 }
else if (operation ==
"table" || operation ==
"t") {
372 }
else if (operation ==
"product") {
377 temp *=
p->GetValue();
382 }
else if (operation ==
"sum") {
384 }
else if (operation ==
"avg") {
385 auto avg = [&](
const decltype(
Parameters)&
p)->
double {
386 return sum(
p) /
p.size();
389 }
else if (operation ==
"difference") {
394 temp -= (*p)->GetValue();
399 }
else if (operation ==
"min") {
401 double _min = HUGE_VAL;
404 double x =
p->GetValue();
412 }
else if (operation ==
"max") {
414 double _max = -HUGE_VAL;
417 double x =
p->GetValue();
425 }
else if (operation ==
"and") {
426 string ctxMsg = element->
ReadFrom();
435 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix,
437 }
else if (operation ==
"or") {
438 string ctxMsg = element->
ReadFrom();
447 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix,
449 }
else if (operation ==
"quotient") {
450 auto f = [](
const decltype(
Parameters)&
p)->
double {
451 double y =
p[1]->GetValue();
452 return y != 0.0 ?
p[0]->GetValue()/y : HUGE_VAL;
454 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix, var));
455 }
else if (operation ==
"pow") {
456 auto f = [](
const decltype(
Parameters)&
p)->
double {
459 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix, var));
460 }
else if (operation ==
"toradians") {
461 auto f = [](
const decltype(
Parameters)&
p)->
double {
462 return p[0]->GetValue()*
M_PI/180.;
464 Parameters.push_back(
new aFunc<
decltype(f), 1>(f, fdmex, element, Prefix, var));
465 }
else if (operation ==
"todegrees") {
466 auto f = [](
const decltype(
Parameters)&
p)->
double {
467 return p[0]->GetValue()*180./
M_PI;
469 Parameters.push_back(
new aFunc<
decltype(f), 1>(f, fdmex, element, Prefix, var));
470 }
else if (operation ==
"sqrt") {
471 auto f = [](
const decltype(
Parameters)&
p)->
double {
472 double x =
p[0]->GetValue();
473 return x >= 0.0 ? sqrt(x) : -HUGE_VAL;
475 Parameters.push_back(
new aFunc<
decltype(f), 1>(f, fdmex, element, Prefix, var));
476 }
else if (operation ==
"log2") {
477 auto f = [](
const decltype(
Parameters)&
p)->
double {
478 double x =
p[0]->GetValue();
479 return x > 0.0 ? log10(x)*
invlog2val : -HUGE_VAL;
481 Parameters.push_back(
new aFunc<
decltype(f), 1>(f, fdmex, element, Prefix, var));
482 }
else if (operation ==
"ln") {
483 auto f = [](
const decltype(
Parameters)&
p)->
double {
484 double x =
p[0]->GetValue();
485 return x > 0.0 ? log(x) : -HUGE_VAL;
487 Parameters.push_back(
new aFunc<
decltype(f), 1>(f, fdmex, element, Prefix, var));
488 }
else if (operation ==
"log10") {
489 auto f = [](
const decltype(
Parameters)&
p)->
double {
490 double x =
p[0]->GetValue();
491 return x > 0.0 ? log10(x) : -HUGE_VAL;
493 Parameters.push_back(
new aFunc<
decltype(f), 1>(f, fdmex, element, Prefix, var));
494 }
else if (operation ==
"sign") {
495 auto f = [](
const decltype(
Parameters)&
p)->
double {
496 return p[0]->GetValue() < 0.0 ? -1 : 1;
498 Parameters.push_back(
new aFunc<
decltype(f), 1>(f, fdmex, element, Prefix, var));
499 }
else if (operation ==
"exp") {
501 }
else if (operation ==
"abs") {
503 }
else if (operation ==
"sin") {
505 }
else if (operation ==
"cos") {
507 }
else if (operation ==
"tan") {
509 }
else if (operation ==
"asin") {
511 }
else if (operation ==
"acos") {
513 }
else if (operation ==
"atan") {
515 }
else if (operation ==
"floor") {
517 }
else if (operation ==
"ceil") {
519 }
else if (operation ==
"fmod") {
520 auto f = [](
const decltype(
Parameters)&
p)->
double {
521 double y =
p[1]->GetValue();
522 return y != 0.0 ? fmod(
p[0]->
GetValue(), y) : HUGE_VAL;
524 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix, var));
525 }
else if (operation ==
"atan2") {
526 auto f = [](
const decltype(
Parameters)&
p)->
double {
529 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix, var));
530 }
else if (operation ==
"mod") {
531 auto f = [](
const decltype(
Parameters)&
p)->
double {
532 return static_cast<int>(
p[0]->GetValue()) %
static_cast<int>(
p[1]->GetValue());
534 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix, var));
535 }
else if (operation ==
"fraction") {
536 auto f = [](
const decltype(
Parameters)&
p)->
double {
540 Parameters.push_back(
new aFunc<
decltype(f), 1>(f, fdmex, element, Prefix, var));
541 }
else if (operation ==
"integer") {
542 auto f = [](
const decltype(
Parameters)&
p)->
double {
547 Parameters.push_back(
new aFunc<
decltype(f), 1>(f, fdmex, element, Prefix, var));
548 }
else if (operation ==
"lt") {
549 auto f = [](
const decltype(
Parameters)&
p)->
double {
550 return p[0]->GetValue() <
p[1]->GetValue() ? 1.0 : 0.0;
552 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix, var));
553 }
else if (operation ==
"le") {
554 auto f = [](
const decltype(
Parameters)&
p)->
double {
555 return p[0]->GetValue() <=
p[1]->GetValue() ? 1.0 : 0.0;
557 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix, var));
558 }
else if (operation ==
"gt") {
559 auto f = [](
const decltype(
Parameters)&
p)->
double {
560 return p[0]->GetValue() >
p[1]->GetValue() ? 1.0 : 0.0;
562 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix, var));
563 }
else if (operation ==
"ge") {
564 auto f = [](
const decltype(
Parameters)&
p)->
double {
565 return p[0]->GetValue() >=
p[1]->GetValue() ? 1.0 : 0.0;
567 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix, var));
568 }
else if (operation ==
"eq") {
569 auto f = [](
const decltype(
Parameters)&
p)->
double {
570 return p[0]->GetValue() ==
p[1]->GetValue() ? 1.0 : 0.0;
572 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix, var));
573 }
else if (operation ==
"nq") {
574 auto f = [](
const decltype(
Parameters)&
p)->
double {
575 return p[0]->GetValue() !=
p[1]->GetValue() ? 1.0 : 0.0;
577 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix, var));
578 }
else if (operation ==
"not") {
579 string ctxMsg = element->
ReadFrom();
580 auto f = [ctxMsg](
const decltype(
Parameters)&
p)->
double {
583 Parameters.push_back(
new aFunc<
decltype(f), 1>(f, fdmex, element, Prefix, var));
584 }
else if (operation ==
"ifthen") {
585 string ctxMsg = element->
ReadFrom();
586 auto f = [ctxMsg](
const decltype(
Parameters)&
p)->
double {
588 return p[1]->GetValue();
590 return p[2]->GetValue();
592 Parameters.push_back(
new aFunc<
decltype(f), 3>(f, fdmex, element, Prefix, var));
593 }
else if (operation ==
"random") {
598 if (!mean_attr.empty())
599 mean =
atof(mean_attr.c_str());
600 if (!stddev_attr.empty())
601 stddev =
atof(stddev_attr.c_str());
602 auto distribution = make_shared<normal_distribution<double>>(mean, stddev);
604 auto f = [generator, distribution]()->
double {
605 return (*distribution.get())(*generator);
609 }
else if (operation ==
"urandom") {
614 if (!lower_attr.empty())
615 lower =
atof(lower_attr.c_str());
616 if (!upper_attr.empty())
617 upper =
atof(upper_attr.c_str());
618 auto distribution = make_shared<uniform_real_distribution<double>>(lower, upper);
620 auto f = [generator, distribution]()->
double {
621 return (*distribution.get())(*generator);
625 }
else if (operation ==
"switch") {
626 string ctxMsg = element->
ReadFrom();
627 auto f = [ctxMsg](
const decltype(
Parameters)&
p)->
double {
628 double temp =
p[0]->GetValue();
631 <<
"The switch function index (" << temp
632 <<
") is negative." <<
reset << endl;
633 throw(
"Fatal error");
635 size_t n =
p.size()-1;
636 size_t i =
static_cast<size_t>(temp+0.5);
639 return p[
i+1]->GetValue();
642 <<
"The switch function index (" << temp
643 <<
") selected a value above the range of supplied values"
644 <<
"[0:" << n-1 <<
"]"
645 <<
" - not enough values were supplied." <<
reset << endl;
646 throw(
"Fatal error");
649 Parameters.push_back(
new aFunc<
decltype(f), 2>(f, fdmex, element, Prefix,
651 }
else if (operation ==
"interpolate1d") {
652 auto f = [](
const decltype(
Parameters)&
p)->
double {
656 double x =
p[0]->GetValue();
657 double xmin =
p[1]->GetValue();
658 double ymin =
p[2]->GetValue();
659 if (x <= xmin)
return ymin;
661 double xmax =
p[n-2]->GetValue();
662 double ymax =
p[n-1]->GetValue();
663 if (x >= xmax)
return ymax;
666 size_t nmax = (n-3)/2;
667 while (nmax-nmin > 1) {
668 size_t m = (nmax-nmin)/2+nmin;
669 double xm =
p[2*m+1]->GetValue();
670 double ym =
p[2*m+2]->GetValue();
684 return ymin + (x-xmin)*(ymax-ymin)/(xmax-xmin);
686 Parameters.push_back(
new aFunc<
decltype(f), 5>(f, fdmex, element, Prefix,
688 }
else if (operation ==
"rotation_alpha_local") {
692 auto f = [](
const decltype(
Parameters)&
p)->
double {
693 double alpha =
p[0]->GetValue()*
degtorad;
696 double theta =
p[4]->GetValue()*
degtorad;
700 double cos_beta = cos(beta);
702 sin(alpha)*cos_beta);
705 if (fabs(fabs(wind_local(
eY)) - 1.0) < 1E-9)
710 Parameters.push_back(
new aFunc<
decltype(f), 6>(f, fdmex, element, Prefix, var));
711 }
else if (operation ==
"rotation_beta_local") {
715 auto f = [](
const decltype(
Parameters)&
p)->
double {
716 double alpha =
p[0]->GetValue()*
degtorad;
719 double theta =
p[4]->GetValue()*
degtorad;
722 double cos_beta = cos(beta);
724 sin(alpha)*cos_beta);
727 if (fabs(fabs(wind_local(
eY)) - 1.0) < 1E-9)
728 return wind_local(
eY) > 0.0 ? 0.5*
M_PI : -0.5*
M_PI;
730 double alpha_local = atan2(wind_local(
eZ), wind_local(
eX));
731 double cosa = cos(alpha_local);
732 double sina = sin(alpha_local);
735 if (fabs(cosa) > fabs(sina))
736 cosb = wind_local(
eX) / cosa;
738 cosb = wind_local(
eZ) / sina;
742 Parameters.push_back(
new aFunc<
decltype(f), 6>(f, fdmex, element, Prefix, var));
743 }
else if (operation ==
"rotation_gamma_local") {
747 auto f = [](
const decltype(
Parameters)&
p)->
double {
748 double alpha =
p[0]->GetValue()*
degtorad;
750 double gamma =
p[2]->GetValue()*
degtorad;
752 double theta =
p[4]->GetValue()*
degtorad;
754 double cos_alpha = cos(alpha), sin_alpha = sin(alpha);
755 double cos_beta = cos(beta), sin_beta = sin(beta);
756 double cos_gamma = cos(gamma), sin_gamma = sin(gamma);
760 FGColumnVector3 wind_body_Y(-sin_alpha*sin_gamma-sin_beta*cos_alpha*cos_gamma,
762 -sin_alpha*sin_beta*cos_gamma+sin_gamma*cos_alpha);
765 double cosacosb = wind_local_X(
eX);
766 double sinb = wind_local_X(
eY);
767 double sinacosb = wind_local_X(
eZ);
770 if (fabs(sinb) < 1E-9) {
771 cosc = wind_local_Y(
eY);
773 if (fabs(cosacosb) > fabs(sinacosb))
774 sinc = wind_local_Y(
eZ) / cosacosb;
776 sinc = -wind_local_Y(
eX) / sinacosb;
778 else if (fabs(fabs(sinb)-1.0) < 1E-9) {
779 sinc = wind_local_Y(
eZ);
780 cosc = -wind_local_Y(
eX);
783 sinc = cosacosb*wind_local_Y(
eZ)-sinacosb*wind_local_Y(
eX);
784 cosc = (-sinacosb*wind_local_Y(
eZ)-cosacosb*wind_local_Y(
eX))/sinb;
789 Parameters.push_back(
new aFunc<
decltype(f), 6>(f, fdmex, element, Prefix, var));
790 }
else if (operation ==
"rotation_bf_to_wf") {
793 string ctxMsg = element->
ReadFrom();
794 auto f = [ctxMsg](
const decltype(
Parameters)&
p)->
double {
795 double rx =
p[0]->GetValue();
796 double ry =
p[1]->GetValue();
797 double rz =
p[2]->GetValue();
798 double alpha =
p[3]->GetValue()*
degtorad;
800 double gamma =
p[5]->GetValue()*
degtorad;
801 int idx =
static_cast<int>(
p[6]->GetValue());
803 if ((idx < 1) || (idx > 3)) {
805 <<
"The index must be one of the integer value 1, 2 or 3."
807 throw(
"Fatal error");
817 Parameters.push_back(
new aFunc<
decltype(f), 7>(f, fdmex, element, Prefix, var));
818 }
else if (operation ==
"rotation_wf_to_bf") {
821 string ctxMsg = element->
ReadFrom();
822 auto f = [ctxMsg](
const decltype(
Parameters)&
p)->
double {
823 double rx =
p[0]->GetValue();
824 double ry =
p[1]->GetValue();
825 double rz =
p[2]->GetValue();
826 double alpha =
p[3]->GetValue()*
degtorad;
828 double gamma =
p[5]->GetValue()*
degtorad;
829 int idx =
static_cast<int>(
p[6]->GetValue());
831 if ((idx < 1) || (idx > 3)) {
833 <<
"The index must be one of the integer value 1, 2 or 3."
835 throw(
"Fatal error");
846 Parameters.push_back(
new aFunc<
decltype(f), 7>(f, fdmex, element, Prefix, var));
847 }
else if (operation !=
"description") {
849 <<
"Bad operation <" << operation
850 <<
"> detected in configuration file" <<
reset << endl;
858 if (
p &&
p->IsConstant()) {
859 double constant =
p->GetValue();
861 string pName =
p->GetName();
867 <<
"<" << operation <<
"> is applied on constant parameters."
868 << endl <<
"It will be replaced by its result ("
872 node->setDoubleValue(constant);
873 node->setAttribute(SGPropertyNode::WRITE,
false);
875 cout <<
" and the property " << pName
876 <<
" will be unbound and made read only.";
878 cout <<
reset << endl << endl;