JSBSim-Team / jsbsim

An open source flight dynamics & control software library
GNU Lesser General Public License v2.1
1.22k stars 420 forks source link

Adding capability to aim external forces in inertial frame; added exa… #962

Closed jonsberndt closed 7 months ago

jonsberndt commented 7 months ago

Added support for simple orbital phasing. This included adding a new frame in FGForce (tInertialBody). I added a new IC file to model an ISS orbit. I added a new script to run the example.

codecov[bot] commented 7 months ago

Codecov Report

Merging #962 (0e5f579) into master (c9b12c4) will decrease coverage by 0.01%. The diff coverage is 0.00%.

@@            Coverage Diff             @@
##           master     #962      +/-   ##
==========================================
- Coverage   24.90%   24.89%   -0.01%     
==========================================
  Files         168      168              
  Lines       18890    18897       +7     
==========================================
  Hits         4704     4704              
- Misses      14186    14193       +7     
Files Changed Coverage Δ
src/models/FGExternalForce.cpp 0.00% <0.00%> (ø)
src/models/FGExternalForce.h 0.00% <ø> (ø)
src/models/propulsion/FGForce.cpp 0.00% <0.00%> (ø)
src/models/propulsion/FGForce.h 0.00% <ø> (ø)
seanmcleod commented 7 months ago

Simply commit the changes to your current local branch, and then push your local branch. They will then automatically show up here on the pull request with the additional commits you've made.

jonsberndt commented 7 months ago

I've added the changes (I think) that were suggested above, and added additional orbital maneuvers. Note that these are for demonstrative purposes only and don't represent any actual vehicle.

With that said ... :-)

I also created a script in Octave that post-processes the data for plotting/verification and makes a plot. The plot assumes that:

A JSBSim run is first made with the "thrust" set to zero in the script, ball_orbit_phase.xml. That would be implemented by setting the "value" to zero in lines that look like this in each of the three "burn" events currently in the script:

      <set name="propulsion/rocket_thrust" value="2000" action="FG_RAMP" tc="1.0"/>

Above, the thrust is already set to 2000 (lbs).

Then, rename the BallOut.csv file that results from this run to BallOut_noburn.csv.

Following that, run the script again WITH the thrust values that are currently there in order to change the orbit. After that run is complete, rename the BallOut.csv file to BallOut_burn.csv, and you are ready for the octave script. I haven't added this to the repo - I'm not sure if that's appropriate and not sure where I would put it, so just going to share the octave script here:

% Read the burn and no-burn data files
% The "burn" trajectory represents a capsule that begins moving away from the space station.
% The "no-burn" trajectory represents an unperturned space station trajectory.

burn = csvread('BallOut_burn.csv');
noburn = csvread('BallOut_noburn.csv');

% Move the vector difference in inertial position into new variables

vecx = burn(:,121) - noburn(:,121);
vecy = burn(:,122) - noburn(:,122);
vecz = burn(:,123) - noburn(:,123);
vecdist=[vecx vecy vecz];

% Calculate the magnitudes of the vector distances between the non-perturbed 
% and perturbed trajectories

vecdist_mag = sqrt(vecdist(:,1).^2 + vecdist(:,2).^2 + vecdist(:,3).^2);
radialdist_mag = burn(:,132) - noburn(:,132);

% Need to calculate the horizontal distance properly which requires a look at
% the relative longitudinal differenes

long_diff = noburn(:,120) - burn(:,120);
for idx=1:length(long_diff)
  if abs(long_diff(idx)) > 180
    if (long_diff(idx) > 0) 
      long_diff(idx) = long_diff(idx) - 360;
    else
      long_diff(idx) = long_diff(idx) + 360;
    end
  end
end

% The sign of the difference indicates which vehicle is ahead and which trails in orbit

mysign = sign(long_diff);

trackdist_mag = mysign.*sqrt(vecdist_mag.*vecdist_mag - radialdist_mag.*radialdist_mag);

% Plot vertical (radial) separation versus horizontal tracking distance as vehicles separate

plot(trackdist_mag/5280, radialdist_mag/5280);

This pair of runs shows a spacecraft undocking from a space station from a forward facing port, such that in undocking the speed increases and subsequently orbital altitude does as well. As altitude increases, velocity decreases and the capsule flies above and behind the station. At the new apogee another burn is made (slowing the capsule) and it drops down behind the station and in a lower orbit. Half an orbit later, anothern bur is made to circularize the orbit.

jonsberndt commented 7 months ago

It also looks like some of the changes I made have introduced some failures. Not sure what happened ... works on my end.

Edit: After further review it looks like the external reactions test is failing. Is this because the script used for the test now produces different results than it previously did - ostensibly because I changed the mass of the ball?

seanmcleod commented 7 months ago

works on my end

Yep, was going to ask if you had run https://github.com/JSBSim-Team/jsbsim/blob/master/tests/TestExternalReactions.py

So when I run it locally using JSBSim master it passes with the following output.

(base) C:\source\jsbsim\tests>python .\TestExternalReactions.py
test_body_frame (__main__.TestExternalReactions) ... GEAR_CONTACT: 0 seconds: NOSE_LG 1
GEAR_CONTACT: 0 seconds: LEFT_MLG 1
GEAR_CONTACT: 0 seconds: RIGHT_MLG 1
ok
test_moment (__main__.TestExternalReactions) ...
  The aerodynamic moment axis system has been set by default to the bodyXYZ system.

Reef 1 (Event 0) executed at time: 30.3821
    simulation/sim-time-sec = 30.3821

Reef 2 (Event 1) executed at time: 31.8654
    simulation/sim-time-sec = 31.8654

Reef Final (Event 2) executed at time: 34.5903
    simulation/sim-time-sec = 34.5903

GEAR_CONTACT: 37.0985 seconds: CONTACT 1

Terminate (Event 3) executed at time: 37.1068
    simulation/sim-time-sec = 37.1068

*CRASH DETECTED* 37.1068 seconds: CONTACTok
test_wind_frame (__main__.TestExternalReactions) ...
  The aerodynamic moment axis system has been set by default to the bodyXYZ system.

Reef 1 (Event 0) executed at time: 30.3821
    simulation/sim-time-sec = 30.3821

Reef 2 (Event 1) executed at time: 31.8654
    simulation/sim-time-sec = 31.8654

Reef Final (Event 2) executed at time: 34.5903
    simulation/sim-time-sec = 34.5903

GEAR_CONTACT: 37.0985 seconds: CONTACT 1

Terminate (Event 3) executed at time: 37.1068
    simulation/sim-time-sec = 37.1068

ok

----------------------------------------------------------------------
Ran 3 tests in 1.573s

OK
(base) C:\source\jsbsim\tests>

If you look at the error log during the automated build test I noticed this difference.

No direction element specified in force object. Default is (0,0,0).
Start 30: TestExternalReactions
 6/71 Test #30: TestExternalReactions ............***Failed    1.62 sec
test_body_frame (__main__.TestExternalReactions) ... GEAR_CONTACT: 0 seconds: NOSE_LG 1
GEAR_CONTACT: 0 seconds: LEFT_MLG 1
GEAR_CONTACT: 0 seconds: RIGHT_MLG 1
ok
test_moment (__main__.TestExternalReactions) ... 
In file ./aircraft/ball/ball.xml: line 124
No direction element specified in force object. Default is (0,0,0).

  The aerodynamic moment axis system has been set by default to the bodyXYZ system.

Reef 1 (Event 0) executed at time: 30.3821
    simulation/sim-time-sec = 30.3821

FAIL
test_wind_frame (__main__.TestExternalReactions) ... 
In file ./../../../aircraft/ball/ball.xml: line 134
No direction element specified in force object. Default is (0,0,0).

  The aerodynamic moment axis system has been set by default to the bodyXYZ system.

Reef 1 (Event 0) executed at time: 30.3821
    simulation/sim-time-sec = 30.3821

FAIL

======================================================================
FAIL: test_moment (__main__.TestExternalReactions)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/work/jsbsim/jsbsim/tests/TestExternalReactions.py", line 236, in test_moment
    self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0, 0])
AssertionError: 7688.1197741397 != 15.376239455482793 within 7 places (7672.743488 difference)
jonsberndt commented 7 months ago

I'm not exactly sure what the specific cause of the failure is, after looking at this. Will have to revisit it later. Do you have any suggestions?

seanmcleod commented 7 months ago

Okay I think I've spotted the issue.

So note the parachute area of 20 which is used to calculate the force.

https://github.com/JSBSim-Team/jsbsim/blob/c9b12c4794046ae1406e1a66941937a64417bfd5/aircraft/ball/ball.xml#L104-L112

And then note that the force is calculated in TestExternalReactions.py on line 57, in which the parachute area of 20 is hard-coded in the test script.

https://github.com/JSBSim-Team/jsbsim/blob/c9b12c4794046ae1406e1a66941937a64417bfd5/tests/TestExternalReactions.py#L57-L59

Now in your commit, after @bcoconni's suggestion, you've increased the area of the parachute in ball.xml but the test script is still using the old parachute area when calculating and comparing the force during the test run.

jonsberndt commented 7 months ago

Well, I thought I fixed it, but it appears there is still a failure and I can't see what's wrong - not familiar with this python testing setup.

jonsberndt commented 7 months ago

Looking at the test that I believe failed, test_moment, that test uses the ball_chute script - not the new ball_orbit_phase.xml script.

The parachute is reefed in three stages as a percentage of its total surface area. This would result in stages where the drag force and moment are entirely different than what was there previously. Since this is done in the ball.xml vehicle file, not sure we can maintain backwards compatibility with previous results. If this test involves comparing with the previous results, it will fail and I don't think there's any way to fix that. If it is desirable to maintain backwards compatibility with the previous test I could dispense with this use of the ball example and make a new one, such as capsule or something.

seanmcleod commented 7 months ago

not sure we can maintain backwards compatibility with previous results. If this test involves comparing with the previous results

Yep, but this particular test doesn't do a comparison with a previously stored set of results.

The issue is that there are two places in this test script where the parachute area is used in the python calculation and you only updated the one location 😉

https://github.com/JSBSim-Team/jsbsim/blob/c9b12c4794046ae1406e1a66941937a64417bfd5/tests/TestExternalReactions.py#L57

And

https://github.com/JSBSim-Team/jsbsim/blob/c9b12c4794046ae1406e1a66941937a64417bfd5/tests/TestExternalReactions.py#L234

Ideally we wouldn't have this hard-coded parachute area in the python code, rather it would be specified as a property which the python code then could query when needing to use it in it's force calculation.

bcoconni commented 7 months ago

Ideally we wouldn't have this hard-coded parachute area in the python code, rather it would be specified as a property which the python code then could query when needing to use it in it's force calculation.

I'm in total agreement with this statement so I took the liberty to modify the code of this PR and replace the hardcoded values of the parachute area in TestExternalReactions.py by a value that is extracted from the XML definition file of ball.

bcoconni commented 7 months ago

The tests have just succeeded so let me know if you are happy with the changes I made to TestExternalReactions.py (the rest of the PR code is pristine as per @jonsberndt submission).