Trad Heli Attitude controller requirements - Help Requested

So my implementation used pretty much the same test criteria that was used for landing detection but unlike landing detecting if any were not true, it flagged take off state. There is a parameter called H_LAND_COL_MIN which was described in the wiki as minimum collective while landed or landing. I thought this was the perfect candidate for the collective position that would indicate the pilot was taking off. I can’t remember what this particular parameter was used for. But it adds another parameter that users need to have set properly to make the takeoff detection work properly.

Ok, lets work through a theoretical process with a focus on defining what heli require from the Attitude Controllers. Bear with me as I am brain dumping here.

For first time initialisation of the attitude controller and times where you have just finished the servo travel test we need a complete reset of the attitude controllers and rate controllers. We have this in copter here:
https://github.com/ArduPilot/ardupilot/blob/master/libraries/AC_AttitudeControl/AC_AttitudeControl.cpp#L110

This sets the ghost to the current attitude and sets all the targets equal to the measurements. It also resets the I terms. This ensures a smooth startup of the attitude controllers with any input. This should be done immediately after arming.

For stabilize we need to keep the I terms zero until the last moment we are guaranteed to be on the ground. Ideally the IMAX would increase slowly from this point but the leaky I term will be hard to let go of. Other than this the attitude controller runs normally.
Is this correct?

So I guess there are four decision points:

  • When the ghost is set to the current attitude and I terms zeroed.
  • When to stop playing with the ghost (probably immediately)
  • When to let the I terms go

Am I missing something here?

ACRO is where all the interesting bits are. We need to keep the ghost on the current attitude without touching the rate loops so a separate function is needed doing basicly this:

_attitude_target_quat.from_rotation_matrix(_ahrs.get_rotation_body_to_ned());

While on the ground we also need to reset the roll and pitch I terms. (not Yaw I assume)

get_rate_roll_pid().reset_I();

get_rate_pitch_pid().reset_I();

This should mean you are operating on a basic rate controller with feedforward. This should mean that the aircraft is controllable in this mode but it will drift around a bit. If tuned properly this should be very similar to a flybarless heli, or early ones anyway.

The pilot should observe all the stabilizing reactions to attitude change but the swash should return to zero after the aircraft is made stationary, even if the aircraft isn’t level.

At some decision point you need to let the ghost go. Like the I term this could be after take off but given the wide range of tuning and the lack of a clear tuning methodology there is probably a strong desire to have this happen while still on the ground. I am not familiar enough with the start up procedures and the wiki needs more work than the code does!!! But from what we have discussed here there are some reasonable points to do this.

Now my personal opinion is that anybody stirring the sticks after this point and unable to read the swash and TPP to know the aircraft will take off correctly is probably safer crashing there and then. But lets talk about how this could be made easier for the pilot who is doing all the right things.

First up I think the slow convergence of the ghost over the current attitude is a nice and elegant solution. If the time constant is of the order of 2 to 5 seconds it won’t let the aircraft drift much if it happens to stay active for a short period after lift off. Too fast and it will cause the aircraft to obviously drift, too slow and it will take too long to level the swash. This could also be done as a constant ramp rate towards zero in a degrees per second style but this will feel less flybar heli like.

Bill has got pretty close with his code but we would need to rotate the lift vector with a single quaternion rotation rather than two euler style rotations. We would also need to ensure the functions used to do this were fool proof and setup for this purpose. We would also need to minimise the impact to the thrust_heading_rotation_angles function to keep it as easy to understand as possible (it is already a bit of a dog and I need to go over it all again to see if I can make it clearer).

I think after that we just need to decide when the I term is let go and when all ghost games are stopped completely. Again, not being familiar with the start up and take off procedure it is hard for me to help there.

So I guess there are four decision points:

  • When the ghost is locked to the current attitude and I terms zeroed.
  • When you let the ghost go with a decay (not important but nice)
  • When to stop playing with the ghost at all
  • When to let the I terms go

Ok, it is late and I still have a bunch of work to do.

The startup procedure is not really all that difficult. Helicopters can be powered with electric or combustion engine, which is one major difference from multi’s, however. So for startup and getting off the ground here’s my procedure in a nutshell as far as the software is concerned

Combustion engine:

  1. Arm the flight controller. Turn on the servo power. Observe the servo test cycle (H_SV_TEST). It is necessary to arm before starting the engine because there is a param, H_RSC_IDLE, that is set for the engine’s governor to let it idle and warm up without the clutch engaged so the main rotor is not spinning. H_RSC_IDLE does not become effective until the FC is in the armed state.
  2. While the engine is warming up I’m by the helicopter putting the starter back in the box, and I have the RC radio there. So I do the correlation checks on the swash and rudder at that point.

Electric power:

  1. Power the heli up (ESC and FC power). Turn on the servo power. Observe the servo test cycle.
  2. Do the swash and rudder correlation checks.

With both, retreat to a safe distance, since with ICE the engine is already running and FC armed, no need to do that. With electric arm the FC.

  1. Set collective lever (throttle stick on a multi) to zero collective pitch. Unlike a multi, this is not with the stick at the bottom. It can be anywhere from near bottom to about 40% depending on how you have your collective curve set up (IM_STAB_COL_x params).

  2. Turn on the governor signal (Channel 8). This performs a smooth, timed spool-up of the head, set with the H_RSC_RAMP_TIME and H_RSC_RUNUP_TIME params.

I think we’re now at the point where the rest has been covered fairly well. The takeoff conditions dictate what the pilot is going to do with the collective and cyclic before liftoff. If it’s really windy the pilot may use some negative collective pitch to keep the heli “planted” if the helicopter does not demonstrate ground resonance issues (some do so can’t use negative collective on the ground). As collective is raised into the postive range where the main rotor starts making lift, the pilot may have to “fly it on the ground” if it’s windy to keep it from tipping over. If the helicopter is on a slanted surface, may have to compensate for that. The main rotor develops a huge amount of torque on the frame and may have to compensate for that with yaw input.

The main difference from multi’s in runup and takeoff is that smooth is the name of the game in flying UAV helicopters after takeoff. They are much heavier with higher disc loading than most multi’s, and have way more power. Experienced pilots do not do the “ICBM Power Launch” with a big, heavy, UAV helicopter that you will see FBL or 3D pilots doing with lightly-loaded 3D machines. So it is imperative that the flight controller not do anything during the takeoff and initial stages of flight that the pilot does not command the helicopter to do.

I hope that helps to get a better understanding of powered down to flight with a heli.

Oh my goodness, I’m not sure I’m going to be able to keep up with this thread. Just picking away at it when I can. Sorry for disjointed answers.

So, obvious ones are, scale factor errors with PIDs. Very easy to do. Especially with D-term. There’s a really big difference between a D-term of 0.0001 and 0.001. Or 0.01. This is why I wish we had grossly rescaled the PID values when this was all reworked. These small decimals are not at all friendly for humans. But that’s done now. Moving on.

So, this can be easily caught.

Then, special case, is things like actually doing development work on the PID controllers. I developed the attitude controller while looking at the swashplate reaction on the bench. For example, the angular acceleration damper. First stage was on the bench with a heli. Then initial flights with a multirotor. Then finally when I was sure it was right, in flight with a helicopter.

I tend to think that people shouldn’t be taking off with really unlevel ground. But that’s just me. I guess eventually I will be wanting to take off from the deck of a rolling ship… [quote=“Leonardthall, post:25, topic:18281”]
I am mindful the angle error x stabP x FF + RATE PID may cause a flip over or boom strike during spool up even if the I term is kept zero. Maybe flybar heads move further that flybarless and need some angle error limitations during take off for example. I am just looking for what I don’t appreciate or understand.

I assume that heli pilots go further out of their way to limit the angle of the take off pad relative to what I may expect from a multirotor and all these effects are not significant. If so, cool.
[/quote]

It might be the case that taking off from extreme angles, or rolling decks, just isn’t possible until and unless the system has direct knowledge of being on the ground. There’s only so much the system can guess at.

I’m thinking about the case of a manned helicopter taking off from a rolling deck. There is no issue. There’s a thing called “following rate” which is the rate at which the rotor disk will follow the swashplate. It’s fast enough that on a rolling deck, if the swashplate is just left neutral, so that it follows the angle of the deck, the rotor disk does likewise, and there is no risk of a blade strike. The pilot simply leaves his hands off the cyclic stick, and all it find. He does not give input, until he knows he’s off the deck.

The autopilot needs to do the same.

Yes, I think we disagree with the resetting of the I-term. I prefer the leak, as it still shows some I-term action, but it doesn’t simply saturate.

All of this being said… and this is a bombshell… But more and more I believe the current StabP->RatePID+FF controller structure is just not right. At all. Needs a total tear up.

I’ve long observed that, the most sharply tuned Ardupilot heli, is not as sharp as a hobby FBL controller. It’s good enough to get the job done for UAV use for sure. But it’s not nearly as performant as an FBL. This is very apparent in yaw. For a long time, I was thinking maybe it was just because of how I was building UAV’s. They are usually overweight, underpowered, etc. But the yaw control has always seemed really off to me. But I was never sure, not having a lot of experience with FBL controllers.

However, lately I have been playing with the RealFlight/FlightAxis simulator. And I can fly the same heli back to back with a “hobby FBL” and Ardupilot. The same underperformance is visible. Again, particularly in yaw. The Ardupilot control is so, so soft. Even when tuned to the point of oscillation.

Maybe Bill’s notch filter is the key. I don’t know. I need to sit down and look at the data closely.

What makes the problem stupid obvious though, is the massive overshoot on yaw stopping. It always overshoots the target, and bounces back. Why?

It’s also apparent looking at the data I presented here 2 months ago. I’ve got my Acro heli, doing a high speed manoever, and it had over a 30 degree pitch or roll error, but the roll/pitch output was only about 10% of the saturation limit. It just wasn’t even trying to fix the angle error. But it’s tuned within an inch of it’s oscillation limit.

Something is not right.

Again, it’s plenty good for UAV use. But I wonder how much better they would be with better control.

I’m wondering if what is needed, is to structure the controller more similarly to a flybar. With a flybar, what you have is Rate Feedforward directly to the rotor head. But then the flybar also accumulates rate error. The rate error accumulation outputs Rate P to the rotor head.

In the past, we used to not have Acro on a heli. We only had Stabilize. It was simply Angle Error PID → Output. We didn’t have Acro, as we didn’t understand how to do rate control when we were only looking at live angle error.

But we have developed methods over the years which would make this possible. When I created the angle error tracking and accumulation method, it would be have been interesting to circle back and revisit the old angle error PID controller.

I would like to try this now. But the Attitude Controller code is so complex now it would be hard for me to do.

Actually, the autopilot sort of can know where the disk is. The disk is usually very closely controlled by the swash plate.

The rotor disk of a typical RC heli could be modeled as if the disk was attached to the shaft by springs. Aerodynamically, the disk wants to follow the swash angle. But, when the swash tips relative the shaft, the disk wants to follow the swash angle, but it resisted by the spring rate. The more the angle of the swash, the more the springs are deflecting, resulting in more torque on the shaft. But also, the disk finds an angle that is a balance of forces between the springs and the aerodynamic forces. There are often different dampers available for helis, resulting in different spring rates. But many modern RC helis have very stiff heads with plastic dampers. Ideally for UAV use, we want soft dampers. Softer dampers result in less cyclic vibration forces.

Similarly in flight, aerodynamics forces such as the Flap-Back force on the rotor in FastForwardFlight, physically tips the disk away from the swash plate angle.

Then you can throw in some Delta-3 angle, and things get really fun. Delta-3 effectively results in mechanical PD between the swash angle and the rotor disk. No RC helis have this available. Most likely because RC heli designers don’t actually know much about helicopters. (shocking but true)

Anyway… The autopilot can guess that the disk is fairly closely following the swash angle, until things get to extremes.

Yes. Remember, the helicopter rotor can be thought of as an “air screw”. Rotor disk angle does not result in runaway rate acceleration like on a multirotors. A small angle will only ever result in a small rate.[quote=“Leonardthall, post:28, topic:18281”]
Yes, this is specifically in the disarmed or pre take off state. So I term build up and saturation should be included. So would it be fair to say that we let I term build up in both unarmed and armed state but reset the I term at the point of arming and deal start dealing with the additional ground and in flight then if needed?
[/quote]

Reseting the I-term and Acro target angle on arming, does make a lot of sense. The problem is dealing with I-term build up after arming, when the heli is on the ground, if a novice pilot has moved the cyclic controls and doesn’t know enough to level out the rotor disk as the rotor comes up to speed.

So… IMO, your goal, while laudable, might be sacrificing too much in search of that goal, which has a very limited use case.

If the solution to this problem makes the code so complicated, that nearly nobody can understand it. And makes the operation for 99.99% of use-cases less than optimal, or overly complicated… why pursue it? What is the use-case for taking off from a hook?

I would say that what heli pilots want, can fit into two boxes:

  1. Take off in Stabilize mode (or Loiter, Auto, etc.) from an landing pad with any angle which does not result in a ground strike. This is probably around 10 degrees. Depends on the helicopter.

  2. Take off from the deck of a rolling ship. Rolling up to 30 degrees. It must be clear that this is different from the case above,because the “ground” is actually moving. The expectation is that the autopilot will allow the fuselage, and thus the swashplate, and thus the rotor disk will roll with the deck, as long as the weight is on the landing gear. Essentially, the rate controller does nothing. Once the weight is off the gear, the heli must climb at whatever angle it has, until it has cleared the deck to such a height that there is no chance of blade strike.

This is obviously a stretch goal, that is perhaps beyond the scope of this discussion. But I think it presents a clear and plausible use-case. Taking off from ships in rough seas.

Landing is an even bigger problem. Here’s a great video of the problem. This will probably only be possible with a companion computer and sophisticated vision system. Timing plays a large part of it.

That’s correct - that’s a landing collective parameter. The reason I suggested using H_COL_MID is because that is the zero pitch position and no lift available. H_COL_MID would be your normal runup collective pitch (or should be). As pitch increases above H_COL_MID the rotor is now making lift. If the runup timer has expired it means two things are now true:

  • the helicopter’s engine or motor is at full takeoff power and the headspeed is normal
  • the main rotor is making lift

At this point the pilot had better be on the cyclic because even if the helicopter doesn’t lift off because hover collective hasn’t been achieved yet, all it takes is a wind gust and its airborne or gets blown over. So it seems to me to be the logical choice of conditions that must be met to get to that last moment before flight commences.

The argument that some people may set H_COL_MID to hover collective pitch doesn’t really hold water. That is not the proper way to set up the helicopter, and the software can’t be designed for people who refuse to follow instructions on how to set it up.

So the attitude controller always running after APM startup, even in the unarmed state, for the trad heli. The whole time in the unarmed state, the I term is reset and if in acro, the target is reset to the actual. So why does the attitude controller need to be initialized when its armed?

So what do you mean by the leaky I term will be hard to let go of?

I don’t see why you wouldn’t alway treat yaw the same as pitch and roll when in acro mode. So yaw I term is always reset while aircraft is UNARMED regardless of stabilize or acro since yaw is always treated as rate command, attitude hold.

Careful. Except for in the case of asymmetric rotor blades that could be making lift at COL_MID. Unlikely to be flying, but you never know…

Hit the reply by accident.

*When the ghost is locked to the current attitude and I terms zeroed.
In Acro, all the time in the unarmed state.
In Stabilize, I think only the I term is reset. Again all of the time in the unarmed state.

*When you let the ghost go with a decay
In Acro, once the aircraft is armed

*When to stop playing with the ghost at all
in Acro, at liftoff (if you can determine it reliably enough) It could be linked to the collective stick but maybe just base it on the movement of the aircraft (accels and descent rate).

*When to let the I terms go.
In Acro or Stabilize mode, at liftoff. use same criteria as letting go of the ghost.

I think we need to add letting I terms go with a decay. That would follow the same criteria as letting go of the ghost with a decay.

And once landing is detected then both the I term and ghost (acro only) should be decayed.

I have asymmetric fiberglass blades on my 700. They don’t fly at zero AoA any better than an airplane wing does. They still take about 4 degrees for liftoff.

What is interesting AFCS implementation in manned aircraft either completely disable the AFCS with weight on wheels or at a minimum disable attitude stabilization. Don’t want the AFCS trying to keep the aircraft at an attitude while the aircraft is on deck with the ship pitching and rolling. And believe me, the pilots are flying the aircraft in the transition phase (ground to air).

@timbaconheli and I have been working this offline. We reached the limit of what we could do with notching the error signal. So I transitioned the firmware from a notch filter on the error to the gyro signal. From what he has reported so far, the results are much better than filtering the error. The instability is still appearing again at higher P gains but at a different frequency. Certainly an attitude command aircraft can be controlled with lower P gains but to have an aircraft that you can easily transition from attitude to rate command will require suffiicient P gain to offer the necessary damping in a rate command. I think I might look at zeroing the ANG_XXX_P parameters once we get the notch filter figured out to see the impact on handling qualities.

Thanks for your feedback Rob!


Yes I agree “saturate” suggests it is simpler than it is, when I say saturate I mean where the rate error integration rate equals the leak.


Cool, I am glad you are open to a redesign especially given the amount of work you have put into it.


This is strange. I have assumed yaw is all good. This is probably the closest to multi roll/pitch. I might have to do some work characterising the response at some stage. See if I can work out what is going on. Nonlinearities can really destroy the pid performance though. One of the reasons I can get aircraft flying well that have been impossible to tune is because I understand how to linearise the thrust response. There has been a few occasions now where I had a copter with terrible performance and couldn’t tune it. After throwing the linearisation settings and characterising it myself, boom, easytune. With the heli tail it is a little more complicated because it is collective pitch driven. There may also be different linearization factors for the FF and PID that need to be considered.


Yes, this does seem like the tricky bit. What is the last moment we can reset the I term. From our conversations so far it seems to be the end of the spool up timer. We should ensure there is still basic control before this of course, just in case the pilot pulls up the collective early.


You give me a too much credit here. My goal was to limit the scope of the problem, not expand it. My interpretation was that the autopilot will be able to move to a level attitude without getting a ground strike. It simplifies things a lot. I am happy to leave boat take off and landing to another day :slight_smile: So I think we are on the same page here.


I must be misunderstanding something. We have a FF term that takes the rate request and feeds it directly to the swash. Then we have a PID that handles the error, it can accumulate with the I term. Sorry, could you go over this idea again?

I just had a bit of a thought, we may have an issue like Yaw on multirotor where the response is a combination of two effects. One of them causes high frequency gain that prevents tuning of the first. Just a thought that might spark ideas. I am thinking about the interplay between the flex and rate response on roll and pitch in Heli.

Yeh, I am a strong believer that it is fair to expect people to set their aircraft and flight controller up correctly. There is always room to add functionality to keep the stupid and lazy safe but it shouldn’t be at the expense of the average user. We also need to consider all reasonable cases, something that is stupid in one context may be sensible in another. Rob’s asymmetrical blade example.
So yeh, I agree.

So H_COL_MID would be the highest we would chose and H_LAND_COL_MIN would be a conservative value that may kick us off too early. Often you can choose the less conservative value H_COL_MID then ensure there are loud and clear instructions in the wiki with a equally clear warning about what happens if you mess that parameter up.

You are correct. In copter we do this after arming but in heli it would be just on initialisation if we are holding the I terms zero and keeping the ghost set to the current attitude in ACRO.

I meant to replace it with other techniques that may give us better control and transition behaviour. I am happy to be wrong here, I am also happy to find that the leaky I term is the best option.

True, I haven’t really been thinking about yaw much in this discussion. But it is obvious now that I think about it that the yaw collective would be set to zero thrust and zero output and therefore the I term should be held to zero there as well.


Why not keep it locked until lift off?

The beauty of both of these parameters is they both decay naturally when the limit is removed. Where you need the decay is when you start to constrain them. I think this is why the leaki I worked well, not at launch when you could simply keep the I terms zero, but at landing where you want to smoothly zero the I terms. The ghost is the same, letting it go will be smooth, constraining it on landing needs a decay or you simply need to not touch the sticks (complexities need to be explored for landing).

Ok. I see what you mean. I think I had used the leak to because it was a little easier to implement through takeoff and landing. We just have to get the takeoff determination right. I don’t think it should be when the collective stick comes off of the stop. Maybe use H_COL_MID or maybe just look at the descent rate and accels.
Thanks for working through this with us.

My pleasure!!

Post must be 20 characters long…

On this point, you might consider that you don’t need to build a 100% reliable threshold. You can have the threshold and a bunch of test that will trigger early for safety like a change in altitude, acceleration, attitude change, time out ect ect.

I have been wondering about this.
Doesn’t the gyro made to measure rate of rotation?

Does this, in mathematical term, mean “integral of error”?

ähm … overshooting/back bouncing is the normal behavior of a heading-hold PID controller, unless proper counter measures are taken: OlliW's Bastelseiten » Das GA250 Gyro Firmware Projekt : http://www.olliw.eu/uploads/Instructions-GA250-OW-v016-v120607.pdf, chapter 6.3

strange that this basic knowledge hasn’t found it’s way to AP

a heli tail is usually much faster than a multirotor “tail”, and is not very comparable when it comes to crisp behavior

some work on characterizing a heli tail can be found here: https://www.rcgroups.com/forums/showthread.php?1538273-The-Heli-Gyro-as-a-Controller-Theory-and-Experiment, OlliW's Bastelseiten » Der Heli-Gyro als Regler: Theorie und Experiment (I’ve never completed the write up, but at least it’s something)

1 Like

Yeah, that’s not a mystery here. I have been experimenting with a DDFP tail on my Trex 500 and I have it working very well now. It is much smoother tail action than a conventional VP servo-operated tail. It may not be suitable for 3D, aerobatics or autorotations** but I am very happy with it on a UAV helicopter and it is using the same PID controller that drives the tail servo on a normal tail (with a few tweaks). So I think the mechanical setup on a normal tail has a lot to do with it too.

**The DDFP tail can be autorotated fine - the helicopter just flies in a gentle left hand turn (clockwise main rotor) during autorotation.

Yeah… but I’ve had helicopter not able to descend when using Asymmetric blades with -2° collective pitch, when hovering a wind (Translational Lift).