Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Control surface deflection sign convention #193

ngoiz opened this issue Apr 29, 2022 · 2 comments

Control surface deflection sign convention #193

ngoiz opened this issue Apr 29, 2022 · 2 comments


Copy link

ngoiz commented Apr 29, 2022

Hi all,

This is related to #192 but really is a topic that needs addressing on its own as it is something that we may want to change, although, if we do, will imply backwards changes to all models with symmetric control surfaces.


Control surfaces deflections are not well defined according to a sign convention, which may pose problems in the future for antisymmetric control surfaces (ailerons) and may suppose now a difference in the linear versus nonlinear implementation of the control surfaces. We either change behaviour or continue as is, knowing how it works (a bug becomes a feature if you leave it long enough).


Control surfaces are implemented in the file as part of the grid assembly process.

The UVLM grid is assembled in "strips", where a strip is a chord wise section. These strips are concatenated in a span wise manner resulting in surfaces.

A strip is generated here:

def generate_strip(node_info, airfoil_db, aligned_grid, orientation_in=np.array([1, 0, 0]), calculate_zeta_dot = False):

The whole surface is generated here:

def generate_zeta_timestep_info(self, structure_tstep, aero_tstep, beam, aero_settings, it=None, dt=None):

In the process of generating the strip, control surfaces are done first, in the local B frame by rotating the relevant chord wise section about xb = [1, 0, 0]. Then, the section is rotated according to any desired twist or sweep.

Current process

These strips are concatenated sequentially in increasing node order. However, any rotation on the strip to assemble the surface is performed AFTER the control surface is implemented. Therefore, the control surface is rotated about an axis different from the material frame.

Take, for example the following configuration, where the arrow indicates the local xb, which is aligned with the beam and positive in the increasing node number direction

4 -<- 3 -<- 0 ->- 1 ->- 2 

The grid strips are generated sequentially for each element. Since the control surfaces are implemented always rotating about the local [1, 0, 0] and these are appended, the resulting rotation axis of each CS upon assembly looks like:

4 ->- 3 ->- 0 ->- 1 -> 2

which is NOT coincident with xb.

Current behaviour

The current implementation is that, for symmetric control surfaces with a single control surface input (i.e. same control_surface_id, control surfaces are deflected in the same direction on both wings, as if they were elevators. Most, if not all, work done in SHARPy has been focused on longitudinal problems so I understand that this is simple as a single input is needed to define an elevator.


  • The sign convention is not well defined.
  • This is not easily implemented in the linear solver, where no strips are generated, and a more clear convention is required.


  1. Leave as is. Backwards compatible and as long as the user is informed on how this works for the nonlinear problem it should be ok. A different convention will be required in the linear solver which may need control surfaces to be defined separately (different control_surface_id) as there the convention will be the local xb. How would antisymmetric control surfaces (ailerons) be implemented with the current implementation and a single input is yet to be determined.
  2. Change the behaviour, this can be done by moving where the control surface is implemented in
    def generate_strip(node_info, airfoil_db, aligned_grid, orientation_in=np.array([1, 0, 0]), calculate_zeta_dot = False):

    moving the #control surface implementation after #transformation to beam and beam prime. The result is
    If this is done, this will affect all previous models as effectively all previously implemented control surfaces will deflect anti-symmetrically. The current behaviour (i.e. elevator-like) could be retained by modifying the models xb as
3 ->- 4 ->- 0 ->- 1 -> 2

The advantage of this being that the sign convention is clearly defined, and that the same approach is retained in the linear solver.
3. A final option would be to leave as is, introducing some kind of "linkage" between control surfaces. This could mean a -1 gain from one to another to simulate ailerons in the current nonlinear implementation.

Please comment :)

A bit of a longwinded explanation but I think that should be tackled as the code goes forward. Probably the easiest short term option is 1) (and I'll see what to do for the linear solver in relation to #192) but we may want to look towards option 2) for future releases.

Copy link

ACea15 commented May 2, 2022

Brilliant explanation. A few thoughts after quick look to the code:

  1. The part of the code that makes the trick for the symmetric behaviour of the control surface on right and left wings is the definition of this rot_angle

    rot_angle = algebra.angle_between_vectors_sign(orientation_in, Cab[:, 1], Cab[:, 2])

    this is also what makes definition of twist consistent.
    I would add another index to the variable control_surface_type, -1 for example, for antisymmetric behaviour of ailerons, and depending on that apply the Crot before or after the control surface rotation. Thus maintaining backwards compatibility but having this added feature in the future (a table in the docs with the options would suffice for establishing a convention for users). I would not change xb vectors which are well defined towards increasing node-index and are sort of lower level. For the linear, we will need to have a chat.

  2. We would need to check whether this Crot applies to complex configurations with structural sweep, dihedral, etc. It is part of a bigger discussion regarding the symmetric modelling of the aircraft since some issues are appearing when inputting fully populated stiffness and mass matrices on these models. It might be worth opening a github project for this, I will arrange something when freer.

  3. Before doing this we need to merge Arturo's last commit where he put the option to apply sweep before twist...

  4. @kccwing, this is a very relevant discussion for your project regarding the semi-aeroelastic hinge modelling. When you sort out the multibody part, the next challenge is to have an aero surface that is continuous for the different directions of the hinge... it could entail some additions to this

Copy link
Collaborator Author

ngoiz commented May 3, 2022

Yep, the thing is that control surfaces are applied currently before the definition of rot_angle, thus they are applied using rotation_3dx in which the x axis used for the rotation is not necessarily xb. I wouldn't go into changing xb, but only moving where the CS is applied.

Practically, most applications benefit from the symmetric CS behaviour as is, therefore maybe the best option is to add the extra input to tell the code whether the CS deflects anti-symmetrically.

Agree on 2). I had experience with symmetric modelling with non-diagonal stiffness matrices and it was tricky.

Also agree on 3). Although the control surface behaviour is not affected by it

sduess added a commit that referenced this issue Oct 12, 2022
- useful if free flying aircraft has to be trimmed and linearized due to issue #193
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet

No branches or pull requests

5 participants