JSBSim-Team / jsbsim

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

Propeller, engine improvements to support quadcopters etc. #333

Open seanmcleod opened 3 years ago

seanmcleod commented 3 years ago

I've been looking to model small quadcopters along the lines of the DJI Phantom plus hybrid models like the Wingcopter and the Alti.

I did a bit of JSBSim work for VTOL Technologies a couple of years ago and Marta Marimon mentioned that:

We used the external forces and moments to model the rotors.

Basically, our main limitation was the thrust-vectoring. As far as I remember, at that point in time, it was not possible to change the direction of the thrust vector (engine tilt) using the built-in model. This was our main reason for making use of the external forces and moments.

The second reason was that we had our own tool to compute the rotors thrust. Due to thrust-vectoring and the A/C flight envelope, the rotor(s) thrust was not only function of RPM/Power, but also the vehicle TAS and the tilt angle of the rotor(s). Therefore, the built-in model was not compatible since was not initially conceived for this type of propulsion.

As mentioned in the video you shared with me, the limitation of the built-in thrust/torque model was not a limitation at the end. Thanks to the flexibility of the external forces and moments capability and the way the configuration files are created, enabling different means to input data (equations, 3D tables, etc.), our ‘problem’ could be solved. Such flexibility is one of the advantages of JSBSim I believe. However, in the future it could be interesting to expand the built-in thrust/torque model and add a capability for drone propulsion, as more and more companies within the drone development use JSBSim.

Another thing I vaguely remember was that we had to slightly modify the workflow of the execution of the different JSBSim modules, since, for us, the external forces and moments had the dependency of AOA, BETA…

I came across a presentation by Matt Vacanti (@mvacanti) and Jesse Hoskins - Open Source Workflow for Advanced Vehicle Dynamics Simulation which included the following slide:

image

So I asked Matt Vacanti to elaborate on what the core assumptions are that break down when dealing with small UAS models in JSBSim.

A key point of clarification is that the issue is most pronounced when using the propeller / engine combination in a vertical lift scenario.

I ran into several problems and will dig up my old models to grab the gritty details but the problem is linked primarily to two issues:

  1. JSBSim overrides the user entered moment of inertia for the propeller if it is less than 0.001 SLUG*FT2 so that it is always 0.001. This can be orders of magnitude too large for small propellers.

  2. When using a jsbsim electric engine model, power is assumed to be linear to throttle input and torque is derived.

The combination of the two factors results in thrust and torque generation that significantly lags input commands (and also real world performance). This makes a small multicopter vehicle (vertical lift) completely unstable.

I settled on the lookup table solution as I felt the likely use case for someone interested matching real-world performance would be to measure actual system performance and apply coefficients as appropriate. There is a great wealth of small propeller data here: https://www.apcprop.com/technical-information/ which is where I extracted data for some of the models. The models I made publicly available are intentionally simple to make it easier for those picking it up to understand what is happening.

If I were to create a new function for small vertical lift motors / props I think it would need to have several considerations:

  1. Battery Voltage / Current Capacity (and therefore a battery model)
  2. User defined Motor Power and Torque Curves

Taking an initial glance at the source code for FGPropeller I noticed in addition to the issue with propeller inertia being limited to a minimum of 0.001 SLUG*FT2 that Matt mentioned:

https://github.com/JSBSim-Team/jsbsim/blob/4fe1aa72cd4234824f686b9495194f2ef5556774/src/models/propulsion/FGPropeller.cpp#L78

I also noticed the following:

https://github.com/JSBSim-Team/jsbsim/blob/4fe1aa72cd4234824f686b9495194f2ef5556774/src/models/propulsion/FGPropeller.cpp#L53-L56

So the x-axis assumption is going to be an issue:

https://github.com/JSBSim-Team/jsbsim/blob/4fe1aa72cd4234824f686b9495194f2ef5556774/src/models/propulsion/FGPropeller.cpp#L270

https://github.com/JSBSim-Team/jsbsim/blob/4fe1aa72cd4234824f686b9495194f2ef5556774/src/models/propulsion/FGPropeller.cpp#L357

https://github.com/JSBSim-Team/jsbsim/blob/4fe1aa72cd4234824f686b9495194f2ef5556774/src/models/propulsion/FGPropeller.cpp#L211

pbecchi commented 2 years ago

@bcoconni Thanks again for your help! I have been able to modify the @mvacanti FGBldc.cpp, to compile and build and to run some of @mvacanti motor benchmark.

Results are good enought : static performances are very similar but for same throttle input resulting RPM is lower as it was expected since a % of the input power is taken by internal losses. Transition from one state to next one result in a small peak in torque given by the prop RPM accelerations: image

The changes to FGBldc are quite simple : it is only necessary to input 2 new properties: coilresistance 0.08 noloadcurrent 1.8 The values can by easily found on motor specs or available motor data base (ecalcl.ch).

Now i would like to test the new FGBldc code on a multirotor example .... how I should proceed? There is an existing multicopter model I can test with?

rega0051 commented 2 years ago

@pbecchi for an existing multicopter model you should look at the DJI F450 that I was using earlier. DJI F450 Airframe DJI E305 Motor DJI 9450 Prop

Note that in F450.xml you can change: to in order to remove the loop closure I made around the ESC and motors to get a desired frequency cutoff.

It's good to see that you're using internal resistance and no load current. I had elected to go with just a cut-off frequency because I believe the motor model is otherwise a too stiff ODE and the actual response of a real physical system doesn't have response out nearly high enough to cause issues running JSBSim with a typical dt. Any kind of damping and high-frequency cutoff would help that situation, hopefully the physical motor parameters will be sufficient to mitigate the stiffness without warranting the outer-loop closure method that I ended up using. Both internal resistance and no load current are pretty easy to measure even if the spec sheets don't always list them.

pbecchi commented 2 years ago

@rega0051 I am trying to run the F450 quadcopter script, but ,since I am new to JSBSIM, I have problems to fully undestrand and modify effector_closedloop.xml. It look like propeller RPM are computed there while they should be computed by FGBldc code that expect as an input ThrottlePos[] . But it do not appear to be defined anywhere. I guess that all caculations of propeller properties should be commented out and in.ThrottlePos[EngineNumber] definition should be added...... but how? Can you help me?

bcoconni commented 2 years ago

I have been able to modify the @mvacanti FGBldc.cpp, to compile and build and to run some of @mvacanti motor benchmark.

Great ! Thanks.

Results are good enought : static performances are very similar but for same throttle input resulting RPM is lower as it was expected since a % of the input power is taken by internal losses. Transition from one state to next one result in a small peak in torque given by the prop RPM accelerations: image

The motor output power /fdm/jsbsim/propulsion/engine/power-hp seems to be oscillating after t=45s. Is that the expected behaviour ?

pbecchi commented 2 years ago

Hi guys I am slowly improving in my learning curve: I find the solutions for my previous message questions and I succeed on running some simulations. I had to increase throttle to avoid retouching the ground and now it perform all the simulation without unexpected events. This what I get: image I have nothing to compare with and I am unable to judge if BLDC motor perform as it should.....

I will appreciate your comments! ........and thanks for your help and encouragement!

bcoconni commented 2 years ago

@pbecchi, unless I'm mistaken you have not brought an answer to my question: why is the motor power output oscillating in the previous chart you've shown ? Given the simple model you told you're using, this is quite unexpected.

In addition, I don't see any fork of JSBSim under your GitHub user name so it's quite difficult to provide you with further comments if we can't review your code.

pbecchi commented 2 years ago

@bcoconni , you are right! Sorry I was busy with the F450 tests.... Anyhow this oscillation is due to a numerical instability of the code in these lines:

TorqueAvailable = MaxTorque - TorqueRequired;
DeltaTorque = (((DeltaRPM/60)*(2.0 * M_PI))/(max(0.00001, in.TotalDeltaT))) * ((FGPropeller*)Thruster)->GetIxx();
TorqueAvailable = MaxTorque - TorqueRequired;
if (DeltaRPM >= 0) {
   TargetTorque = min(DeltaTorque, TorqueAvailable) + TorqueRequired;
} else {
   TargetTorque = min(abs(DeltaTorque), TorqueRequired) * -1;
}
EnginePower = ((2 * M_PI) * max(RPM, 0.0001) * TargetTorque) / 60;

Since i am a beginner and i have not any knowledge of JSBSim, I have decided to use the existing code of FGBLdc.cpp written by @mvacanti with minimal modifications. I have worked using his fork and i have run his test scripts. The FGBldc code his here FGBldc.txt All my modification are commented. As you can see the lines that create the instability are an @mvacanti eritage. I really dont see any need for these lines of code but.....since they where in, i decided to keep it. Now I will make a fork of your repo, I will add the code that I have modified from @mvacanti fork and all test scripts . This way the fork will be alligned to your commits and this will give you the possibility to access and review. Anyhow ..... thanks for your comments.

pbecchi commented 2 years ago

@bcoconni I have corrected the code of FGBLdc.cpp and run some tests. Everything is available on my fork: https://github.com/pbecchi/jsbsim . Basically I have revised the lines of my previuos message to better control deceleration phase. The torque in acceleration is given by the propeller aerodynamic torque + the propeller acceleration * prop inertia and is limited by max available motor torque. During deceleration the can be set on the Electronic Speed Controller and vary from zero braking to maximum braking (the motor generated current is absorbed by internal resistance). @mvacanti was assuming to simply change the direction of max torque applying a huge braking force . This was the reason of the torque (power) fluctuations. I have now changed the code assuming that when you reduce the speed the applied torque drop to the reduced torque necessary for the new prop speed, this means no braking. As you can see the resulting curves are much smoother: image The braking take few seconds. To adjust breaking time it may be necessary to add a external parameter to be added to motor properties. I have also rerun the scripts for testing quadrotor F450 and results seams very good (for what i can judge!): image

@bcoconni @rega0051 I will appreciate your comments! Then I will finish and cleanup the code.

bcoconni commented 2 years ago

Thanks for the updates @pbecchi. This looks very good.

I was a bit surprised that the motor accelerates much faster than it decelerates so I had a look to your code and found the following statement:

if (DeltaRPM >= 0) {
  TargetTorque = min(DeltaTorque, TorqueAvailable) + TorqueRequired;
}
else {
  TargetTorque = TorqueRequired  - abs(DeltaTorque)*abs(DeltaRPM)/max(RPM,0.001);
  TargetTorque =  TorqueRequired*(CommandedRPM / max(RPM,0.01))* (CommandedRPM / max(RPM, 0.01));
}

The different treatment based on the sign of DeltaRPM is unexpected. You may have given the explanation about that result but I'm not sure about what you meant since a word seems to be missing in one of your statement:

During deceleration the ??? can be set on the Electronic Speed Controller

pbecchi commented 2 years ago

Thaks for your comment @bcoconni , in general acceleration and deceleration of a BLDC motor are not comparabele. But in the case of the above plot your comment is correct: in this case min deceleration is applied equivalent to no braking torque (see the orange line).
Since in most cases a more reactive motor control is desired, as anticipated in previous post, I have modified the statement TargetTorque = TorqueRequired*(CommandedRPM / max(RPM,0.01))* (CommandedRPM / max(RPM, 0.01)); with a new one TargetTorque = TorqueRequired - min(abs(DeltaTorque)/(max(deceleration_time,0.01)*30),RPM*TorqueConstant/VelocityConstant/VelocityConstant/coilResistance);

where you can set the desired deceleration time as you normally do programming the ESC (??? word is "time"). A value of about 1 second will lead to a much shorter sweep and will mantain a stable behaviour, Regarding acceleration i think that the code is correct and give the maximum acceleration that it is phisically achievable with the motor. This acceleration tested on the F450 copter give result that I consider in line with normal performances of a similar UAV #253. I will cleanup the code and update shortly the fork on github.com/pbecchi. Meanwhile i am trying to add the Dj F450 on PX4 sitl and to simulate a fly , it look possible but .............challenging!

pbecchi commented 2 years ago

@rega0051 , @bcoconni @Jaeyoung-Lim dji f450 model now run on PX4_sitl. The f450 model use BLDC motors. If you are interested you can check .ulg logs at: https://review.px4.io/plot_app?log=fe9c6b64-52a5-4c05-be95-5e30470608e8 Consider only times between 0:55 to 1:40 minutes controlled with joystick in "altitude mode". Afterword there is a lot of noise due to "return to land " that do not work. I had some difficulty to find documentation on how to interface jsbsim with the PX4_sitl controller, but after several trial i succeeded. I would also like to know if is possible to get an output log from jsbsim were I could check propeller thrusts and RPMs. In jsbsim output is specified in the launch script, but here ,as far as i understand, there is no launch script.......

Jaeyoung-Lim commented 2 years ago

@pbecchi Would you be interested in making a PR to https://github.com/Auterion/px4-jsbsim-bridge ?

Regarding logging, we can try to add those in the jsbsim bridge

pbecchi commented 2 years ago

@Jaeyoung-Lim Yes I can do it..... but keep in mind that I use my fork of jsbsim: in github.com/pbecchi/jsbsim. There I have added the code for the new BLDC electric motor. So or you use my fork or I should make a PR also for JSBSim-Team/jsbsim.

seanmcleod commented 2 years ago

In jsbsim output is specified in the launch script, but here ,as far as i understand, there is no launch script......

Output can also be specified in the aircraft file as well, e.g.

https://github.com/JSBSim-Team/jsbsim/blob/d9df84593b40a5bddb67a94f51d57cd1e514c313/aircraft/c172x/c172x.xml#L1207-L1226

bcoconni commented 2 years ago

So or you use my fork or I should make a PR also for JSBSim-Team/jsbsim.

@pbecchi, your branch seems to be quite stable, so it could be time to pull your changes. We'd be glad to review your PR 😃.

bcoconni commented 2 years ago

The PR #560 has just been merged to the masterbranch. Thanks @pbecchi 👍

bcoconni commented 2 years ago

There are a few topics that remain open for discussion however:

Why is DeltaRPM rounded to the nearest integer ?

https://github.com/JSBSim-Team/jsbsim/blob/d3536e95a9d4e68dcc9325696e6fc024558d574c/src/models/propulsion/FGBrushLessDCMotor.cpp#L152 I'd expect that to be a destabilizing factor, numerically speaking since the engine power will increase (resp. decrease) discretely rather than increasing (resp. decreasing) continuously.

Why is EnginePower prevented from going to zero ?

https://github.com/JSBSim-Team/jsbsim/blob/d3536e95a9d4e68dcc9325696e6fc024558d574c/src/models/propulsion/FGBrushLessDCMotor.cpp#L172 There is this max(RPM, 0.0001) factor. What's wrong with having EnginePower == 0.0 ?

Joule heating is limited to the motor deceleration ?

There is this strange expression RPM*TorqueConstant/VelocityConstant/VelocityConstant/CoilResistance: https://github.com/JSBSim-Team/jsbsim/blob/d3536e95a9d4e68dcc9325696e6fc024558d574c/src/models/propulsion/FGBrushLessDCMotor.cpp#L165-L170 and I have this gut feeling that it is linked to the Joule heating. What else could dissipate energy during deceleration in an electric motor ?

However, would RPM*TorqueConstant/VelocityConstant/VelocityConstant/CoilResistance be characterizing the Joule heating then it should apply to the acceleration as well but it doesn't. So what is this factor ?

And I'm looking forward to your next PR @pbecchi that will include example usage of the new brushless DC motor in order to carry out some experiments with your code 😉

pbecchi commented 2 years ago

Thanks for merging the PR. You are right rounding of RPM is unnecessary , it is still an heritage from @mvacanti version as well as max(RPM,0.001) The effect will be to stop oscillation when deltaRPM is < 1 , I dont think this will impact numerical stability...... RPM*TorqueConstant/VelocityConstant/VelocityConstant/CoilResistance identify the torque that is necessary to drive the propeller at resulting RPM like in the graph of my 20th december post. This is the condition there is no braking The torque show no negative pics and deceleration is due to propeller resistance, therefore is considered the minimum deceleration that is possible to apply. My plan now are to concentrate of the FDM of my VTOL but I will spend some time on preparation of a PR with a quadcopter example: after taking out any reference to @rega0051 original ,I plan to use the DJI F450 model I have used for the PX4_sitl so that I can make a similar PR on Auterion depo.

I am a little concerned on the number of corrections this PR will originate: this my first JSBSIM FDM and I have to derive it from an existing model without full understanding of all inputs. From another perspective ......I have a good opportunity to learn :-)

pbecchi commented 2 years ago

Let discuss a little more on example PR: The quadcopter FDM will be quite simple from a geometry , landing pads, mass and propulsion viewpoint. It will anyhow require an attitude stabilisation flight control to fly without crashing. There is 2 way to solve this: or to use the FlightControl.xlm prepared by @rega0051 or to use the FDM with PX4_sitl. Since I have no competence and time to modify existing FlightControl.xlm i wonder if it will be possible to use it as it is, with the agreement of @rega0051 . Another doubt is about F450-set.xml. Is the file necessary for JSBSim tests? I think is there only for virtual reality inputs (e.g. Flightgear) and will be difficult (for me😒 ) and time consuming to get the informations needed. Do you want me to open a new issue to discuss about all this?

seanmcleod commented 2 years ago

@pbecchi yep, I created this initial discussion in Oct 2020 to discuss propeller and engine improvements for quadcopters etc. and it's a pretty long discussion by now. So rather create a new discussion for the sample quadcopter FDM. I'd suggest we continue discussing any outstanding questions/issues with your BLDC implementation here though.

pbecchi commented 2 years ago

@bcoconni Good evening, during the test for the new PR with the quadcopter example, I have discovered that ,unfortunately, I made a copy/paste error during one of the several modifications i did on FGBrushLessDCMotor.cpp. This error generate performances that are unrealistic and need to be corrected ASAP. I have created on my branch a new commit that correct this error and eliminate unnecessary operations according to your previous comments. What shall I do? A new PR with the new commit or the are other way to implement the corrections? Immediately after I should be ready with the PR of the DJI F450 quadrotor example.

seanmcleod commented 2 years ago

Submit a PR with a commit just for the changes to FGBrushLessDCMotor.cpp, i.e. don't include other changes accidently e.g. changes you're busying making to the DJI F450 aircraft model etc.

66Ton99 commented 3 months ago

Any progress in this direction?

pbecchi commented 3 months ago

Yes .....it is working