Implementing VNAV support in FlightGear: Difference between revisions

Jump to navigation Jump to search
m
Line 213: Line 213:


It is foreseeable that we may need to modify and extend JSBSim, i.e. to add new components - unfortunately, the "Extending JSBSim" chapter in the JSBSim reference manual is still just a placeholder without any content, so here are some stubs to help lower the barrier to entry when extending JSBSim.
It is foreseeable that we may need to modify and extend JSBSim, i.e. to add new components - unfortunately, the "Extending JSBSim" chapter in the JSBSim reference manual is still just a placeholder without any content, so here are some stubs to help lower the barrier to entry when extending JSBSim.
=== FGWaypoint ===
There are some basic building blocks for supporting waypoints via the [https://en.wikipedia.org/wiki/Haversine_formula Haversine formula] in $JSBSIM_SRC/model/flight_controls/FGWaypoint.cpp, currently these are:
* waypoint_heading (computes the heading to the waypoint)
* waypoint_distance (computes the distance between to waypoints)
The '''FGWaypoint''' class would need to be extended to help with the calculation of other types of waypoints related to VNAV. To add a stub for a new waypoint named '''waypoint_custom''', these would be the required changes (lacking any implementation in FGWaypoint::Run() ):
<syntaxhighlight lang="diff">
diff --git a/src/models/FGFCS.cpp b/src/models/FGFCS.cpp
index 5457632..fc921cb 100644
--- a/src/models/FGFCS.cpp
+++ b/src/models/FGFCS.cpp
@@ -636,7 +636,8 @@ bool FGFCS::Load(Element* el, SystemType systype)
        } else if (component_element->GetName() == string("gyro")) {
          newChannel->Add(new FGGyro(this, component_element));
        } else if ((component_element->GetName() == string("waypoint_heading")) ||
-                  (component_element->GetName() == string("waypoint_distance")))
+                  (component_element->GetName() == string("waypoint_distance")) ||
+       (component_element->GetName() == string("waypoint_custom")) )
        {
          newChannel->Add(new FGWaypoint(this, component_element));
        } else if (component_element->GetName() == string("angle")) {
diff --git a/src/models/flight_control/FGFCSComponent.cpp b/src/models/flight_control/FGFCSComponent.cpp
index 630f5cb..29ebbdc 100644
--- a/src/models/flight_control/FGFCSComponent.cpp
+++ b/src/models/flight_control/FGFCSComponent.cpp
@@ -110,6 +110,8 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
    Type = "WAYPOINT_HEADING";
  } else if (element->GetName() == string("waypoint_distance")) {
    Type = "WAYPOINT_DISTANCE";
+  } else if (element->GetName() == string("waypoint_custom")) {
+    Type = "WAYPOINT_CUSTOM";
  } else if (element->GetName() == string("angle")) {
    Type = "ANGLE";
  } else if (element->GetName() == string("distributor")) {
diff --git a/src/models/flight_control/FGWaypoint.cpp b/src/models/flight_control/FGWaypoint.cpp
index 0df8d07..4c5b707 100644
--- a/src/models/flight_control/FGWaypoint.cpp
+++ b/src/models/flight_control/FGWaypoint.cpp
@@ -58,6 +58,9 @@ FGWaypoint::FGWaypoint(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme
{
  if      (Type == "WAYPOINT_HEADING")  WaypointType = eHeading;
  else if (Type == "WAYPOINT_DISTANCE") WaypointType = eDistance;
+  else if (Type == "WAYPOINT_CUSTOM") WaypointType = eCustom;
+
+
  target_latitude_unit = 1.0;
  target_longitude_unit = 1.0;
@@ -123,7 +126,7 @@ FGWaypoint::FGWaypoint(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme
  } else {
      eUnit = eRad; // Default is radians if unspecified
    }
-  } else {
+  } else if (WaypointType == eDistance) {
    if (!unit.empty()) {
    if      (unit == "FT") eUnit = eFeet;
    else if (unit == "M")  eUnit = eMeters;
@@ -131,7 +134,10 @@ FGWaypoint::FGWaypoint(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme
    } else {
      eUnit = eFeet; // Default is feet if unspecified
    }
-  }
+  }
+    else if (WaypointType ==eCustom) {
+    }
+
  FGFCSComponent::bind();
  Debug(0);
diff --git a/src/models/flight_control/FGWaypoint.h b/src/models/flight_control/FGWaypoint.h
index 4444671..0aac0db 100644
--- a/src/models/flight_control/FGWaypoint.h
+++ b/src/models/flight_control/FGWaypoint.h
@@ -123,7 +123,7 @@ private:
  double radius;
  std::string unit;
  enum {eNone=0, eDeg, eRad, eFeet, eMeters} eUnit;
-  enum {eNoType=0, eHeading, eDistance} WaypointType;
+  enum {eNoType=0, eHeading, eDistance, eCustom} WaypointType;
  void Debug(int from);
};
</syntaxhighlight>


=== Adding new Functions ===
=== Adding new Functions ===
Line 480: Line 394:
+} // of namespace JSBSim
+} // of namespace JSBSim
+#endif
+#endif
</syntaxhighlight>
=== FGWaypoint ===
There are some basic building blocks for supporting waypoints via the [https://en.wikipedia.org/wiki/Haversine_formula Haversine formula] in $JSBSIM_SRC/model/flight_controls/FGWaypoint.cpp, currently these are:
* waypoint_heading (computes the heading to the waypoint)
* waypoint_distance (computes the distance between to waypoints)
The '''FGWaypoint''' class would need to be extended to help with the calculation of other types of waypoints related to VNAV. To add a stub for a new waypoint named '''waypoint_custom''', these would be the required changes (lacking any implementation in FGWaypoint::Run() ):
<syntaxhighlight lang="diff">
diff --git a/src/models/FGFCS.cpp b/src/models/FGFCS.cpp
index 5457632..fc921cb 100644
--- a/src/models/FGFCS.cpp
+++ b/src/models/FGFCS.cpp
@@ -636,7 +636,8 @@ bool FGFCS::Load(Element* el, SystemType systype)
        } else if (component_element->GetName() == string("gyro")) {
          newChannel->Add(new FGGyro(this, component_element));
        } else if ((component_element->GetName() == string("waypoint_heading")) ||
-                  (component_element->GetName() == string("waypoint_distance")))
+                  (component_element->GetName() == string("waypoint_distance")) ||
+       (component_element->GetName() == string("waypoint_custom")) )
        {
          newChannel->Add(new FGWaypoint(this, component_element));
        } else if (component_element->GetName() == string("angle")) {
diff --git a/src/models/flight_control/FGFCSComponent.cpp b/src/models/flight_control/FGFCSComponent.cpp
index 630f5cb..29ebbdc 100644
--- a/src/models/flight_control/FGFCSComponent.cpp
+++ b/src/models/flight_control/FGFCSComponent.cpp
@@ -110,6 +110,8 @@ FGFCSComponent::FGFCSComponent(FGFCS* _fcs, Element* element) : fcs(_fcs)
    Type = "WAYPOINT_HEADING";
  } else if (element->GetName() == string("waypoint_distance")) {
    Type = "WAYPOINT_DISTANCE";
+  } else if (element->GetName() == string("waypoint_custom")) {
+    Type = "WAYPOINT_CUSTOM";
  } else if (element->GetName() == string("angle")) {
    Type = "ANGLE";
  } else if (element->GetName() == string("distributor")) {
diff --git a/src/models/flight_control/FGWaypoint.cpp b/src/models/flight_control/FGWaypoint.cpp
index 0df8d07..4c5b707 100644
--- a/src/models/flight_control/FGWaypoint.cpp
+++ b/src/models/flight_control/FGWaypoint.cpp
@@ -58,6 +58,9 @@ FGWaypoint::FGWaypoint(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme
{
  if      (Type == "WAYPOINT_HEADING")  WaypointType = eHeading;
  else if (Type == "WAYPOINT_DISTANCE") WaypointType = eDistance;
+  else if (Type == "WAYPOINT_CUSTOM") WaypointType = eCustom;
+
+
  target_latitude_unit = 1.0;
  target_longitude_unit = 1.0;
@@ -123,7 +126,7 @@ FGWaypoint::FGWaypoint(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme
  } else {
      eUnit = eRad; // Default is radians if unspecified
    }
-  } else {
+  } else if (WaypointType == eDistance) {
    if (!unit.empty()) {
    if      (unit == "FT") eUnit = eFeet;
    else if (unit == "M")  eUnit = eMeters;
@@ -131,7 +134,10 @@ FGWaypoint::FGWaypoint(FGFCS* fcs, Element* element) : FGFCSComponent(fcs, eleme
    } else {
      eUnit = eFeet; // Default is feet if unspecified
    }
-  }
+  }
+    else if (WaypointType ==eCustom) {
+    }
+
  FGFCSComponent::bind();
  Debug(0);
diff --git a/src/models/flight_control/FGWaypoint.h b/src/models/flight_control/FGWaypoint.h
index 4444671..0aac0db 100644
--- a/src/models/flight_control/FGWaypoint.h
+++ b/src/models/flight_control/FGWaypoint.h
@@ -123,7 +123,7 @@ private:
  double radius;
  std::string unit;
  enum {eNone=0, eDeg, eRad, eFeet, eMeters} eUnit;
-  enum {eNoType=0, eHeading, eDistance} WaypointType;
+  enum {eNoType=0, eHeading, eDistance, eCustom} WaypointType;
  void Debug(int from);
};


</syntaxhighlight>
</syntaxhighlight>
Line 487: Line 488:
The whole VNAV effort would be greatly simplified if we could directly run and query the FDM for some future point in time. This isn't directly supported by JSBSim. However, as a workaround, we could run a "simulation inside the simulation" by instantiating the JSBSim FDM recursively:
The whole VNAV effort would be greatly simplified if we could directly run and query the FDM for some future point in time. This isn't directly supported by JSBSim. However, as a workaround, we could run a "simulation inside the simulation" by instantiating the JSBSim FDM recursively:


As in, run an independent instance of the FDM as part of the FCS, to solve for certain VNAV constraints (altitude, speed, time) via specific pitch/thrust settings.
Instantiating a JSBSim FDM instance is straightforward, thanks to the FGFDMExec class, which manages a single JSBSim instance:
Instantiating a JSBSim FDM instance is straightforward, thanks to the FGFDMExec class, which manages a single JSBSim instance:
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
Line 494: Line 496:
</syntaxhighlight>
</syntaxhighlight>


As in, run an independent instance of the FDM as part of the FCS, to solve for certain VNAV constraints (altitude, speed, time) via specific pitch/thrust settings.  
And as it turns out, this is another long-standing idea/feature request, i.e. supporting recursion in JSBSim FDMs and having multiple instances per process (single-threaded):
 
{{cquote|One feature in JSBSim that I began and have not yet finished (pending other things) is a parent/child capability. You can (for instance) load a Mk82 on
an F-16 and the physical effects of the Mk82 will affect the F-16. The position is based on the position of the parent, and so is the orientation.
However, the Mk82 position is not integrated, it always has a position based on the parent, UNTIL it is released. Then, the EOM begins integrating and
the flyout is physics based.
 
The child objects are each their own individual JSBSim objects in their own right, and each could be loaded and flown by itself. The JSBSim executive is
sort of recursive in this way. Each would be addressable in a way that I think Tony set up with Properties, but I can't recall what it is.
 
Technically, it is also possible for each droppable piece to have its own propulsion and flight control system, too. The possiblities there are quite
broad.<ref>{{cite web |url=http://www.mail-archive.com/flightgear-devel@flightgear.org/msg21162.html |title=Eye Candy  |author=Jon S. Berndt |date= Sat, 14 Feb 2004 13:43:55 -0800}}</ref>|Jon S. Berndt}}
 
{{cquote|Of course we would like a parent/child FDM system, and from all these postings is seems as if we nearly have. In the order of things, I don't think it is very high on the todo list.<ref>{{cite web |url=http://www.mail-archive.com/flightgear-devel@flightgear.org/msg21164.html |title=Eye Candy  |author=Vivian Meazza |date= Sat, 14 Feb 2004 13:43:55 -0800}}</ref>|Vivian Meazza}}
 
 
{{cquote|One thing I've been playing around with (OK, _played_ around with - about a year ago) in JSBSim was the ability to add "child" objects to the main aircraft. Each child would be a separate instance of a JSBSim FDM. The idea would be to provide a way to model an aircraft with attached stores. Each store would transmit forces and moments to the parent aircraft (for example a Mirage) until it was released, at which time the FDM for that child object (for example a Mk-82 or AIM-9) would start integrating and do its own flyout - the parent aircraft now free of the effects of the store. Additionally, each store would have its own config file - and its own flight control system/autopilot/guidance. In theory, the possibilities are limitless for game playing, where one might <PC> set up a food drop tank to be released from an aircraft and make a mid-air "connection" to another aircraft, mid-flight</PC>, or <PC> a water delivery tank could be guided by homing device to a precision landing extremely close to a hostile anti-aircraft battery or needy family (in some cases these are coincident)</PC>. I've been threatening to complete this for a long time, but one day we'll allwake up and I'll announce that it is finished. <ref>{{cite web |url=http://www.mail-archive.com/flightgear-devel@flightgear.org/msg18114.html |title=Multiplayer Server RFC  |author=Jon S. Berndt |date=Wed, 05 Nov 2003 13:01:44 -0800}}</ref>|Jon S. Berndt}}
 
 
 
<references/>


And as it turns out, this is another long-standing idea/feature request, i.e. supporting recursion in JSBSim FDMs and having multiple instances per process (single-threaded).


Meanwhile, since around ~2009, this has been partially implemented in JSBSim, which now contains support for a slaved '''<child>''' FDM element that is mated/coupled to the main FDM. The feature is still considered experimental and unsupported by JSBSim developers, it is also currently disabled by default - especially in FlightGear, where it's causing problems/segfaults.  
Meanwhile, since around ~2009, this has been partially implemented in JSBSim, which now contains support for a slaved '''<child>''' FDM element that is mated/coupled to the main FDM. The feature is still considered experimental and unsupported by JSBSim developers, it is also currently disabled by default - especially in FlightGear, where it's causing problems/segfaults.  
Line 554: Line 575:
</syntaxhighlight>
</syntaxhighlight>


{{cquote|One feature in JSBSim that I began and have not yet finished (pending other things) is a parent/child capability. You can (for instance) load a Mk82 on
an F-16 and the physical effects of the Mk82 will affect the F-16. The position is based on the position of the parent, and so is the orientation.
However, the Mk82 position is not integrated, it always has a position based on the parent, UNTIL it is released. Then, the EOM begins integrating and
the flyout is physics based.
The child objects are each their own individual JSBSim objects in their own right, and each could be loaded and flown by itself. The JSBSim executive is
sort of recursive in this way. Each would be addressable in a way that I think Tony set up with Properties, but I can't recall what it is.
Technically, it is also possible for each droppable piece to have its own propulsion and flight control system, too. The possiblities there are quite
broad.<ref>{{cite web |url=http://www.mail-archive.com/flightgear-devel@flightgear.org/msg21162.html |title=Eye Candy  |author=Jon S. Berndt |date= Sat, 14 Feb 2004 13:43:55 -0800}}</ref>|Jon S. Berndt}}
{{cquote|Of course we would like a parent/child FDM system, and from all these postings is seems as if we nearly have. In the order of things, I don't think it is very high on the todo list.<ref>{{cite web |url=http://www.mail-archive.com/flightgear-devel@flightgear.org/msg21164.html |title=Eye Candy  |author=Vivian Meazza |date= Sat, 14 Feb 2004 13:43:55 -0800}}</ref>|Vivian Meazza}}
{{cquote|One thing I've been playing around with (OK, _played_ around with - about a year ago) in JSBSim was the ability to add "child" objects to the main aircraft. Each child would be a separate instance of a JSBSim FDM. The idea would be to provide a way to model an aircraft with attached stores. Each store would transmit forces and moments to the parent aircraft (for example a Mirage) until it was released, at which time the FDM for that child object (for example a Mk-82 or AIM-9) would start integrating and do its own flyout - the parent aircraft now free of the effects of the store. Additionally, each store would have its own config file - and its own flight control system/autopilot/guidance. In theory, the possibilities are limitless for game playing, where one might <PC> set up a food drop tank to be released from an aircraft and make a mid-air "connection" to another aircraft, mid-flight</PC>, or <PC> a water delivery tank could be guided by homing device to a precision landing extremely close to a hostile anti-aircraft battery or needy family (in some cases these are coincident)</PC>. I've been threatening to complete this for a long time, but one day we'll allwake up and I'll announce that it is finished. <ref>{{cite web |url=http://www.mail-archive.com/flightgear-devel@flightgear.org/msg18114.html |title=Multiplayer Server RFC  |author=Jon S. Berndt |date=Wed, 05 Nov 2003 13:01:44 -0800}}</ref>|Jon S. Berndt}}
<references/>


=== Open Questions ===
=== Open Questions ===

Navigation menu