Fixed-Wing UAV Attitude Control
Hello, thank you very much for your team's contributions to the UAV reinforcement learning community! I am currently using PyFlyt, developed by your team, for research on fixed-wing UAV path following.
As is well known, the inner-loop control (attitude control) of fixed-wing UAVs has a significant impact on outer-loop path following. I have spent a considerable amount of time studying PyFlyt, but perhaps due to my limited abilities, I still haven't fully understood how PyFlyt handles the inner-loop control of fixed-wing UAVs. Could you kindly assist me in understanding the inner-loop control aspects of fixed-wing UAVs in PyFlyt? This includes the main functions, inputs, outputs, and other relevant details related to inner-loop control.
I am eagerly looking forward to your reply and sincerely appreciate your help!
Hi, at the present moment, the fixedwing UAV has no inner loop control, the commands are sent as raw actuator commands to the following components:
These components are modelled as second order ODEs (mimicking having mass). Math here and here.
If you would like to implement inner/outer loop control, kindly refer to this tutorial.
Got it, thank you for your prompt and helpful reply !
Hello! I've encountered some issues while implementing the inner-loop control, and I hope you could assist me. During testing of the fixed-wing drone's control surfaces using the following program, I found that the rudder (setpoint[2]) was ineffective (I understand that the four elements of setpoint correspond to ailerons, elevator, rudder, and propeller motor commands, respectively.) :
import matplotlib.pyplot as plt
import numpy as np
import sys
sys.path.append(r"E:\RL-plane\PyFlyt")
from PyFlyt.core import Aviary
log = np.zeros((1000, 3), dtype=np.float32)
start_pos = np.array([[0.0, 0.0, 10.0]])
start_orn = np.array([[0.0, 0.0, 0.0]])
env = Aviary(start_pos=start_pos, start_orn=start_orn, render=True, drone_type="fixedwing")
env.set_mode(0)
setpoint = np.array([-0.0165, -0.1, 0.0, 0.75])
env.set_setpoint(0, setpoint)
for i in range(500):
env.step()
# record the linear position state
log[i] = env.state(0)[-1]
plt.plot(np.arange(1000), log[:, 0], color='r', label='x')
plt.plot(np.arange(1000), log[:, 1], color='g', label='y')
plt.plot(np.arange(1000), log[:, 2], color='b', label='z')
plt.legend()
plt.show()
Then I saw these three lines of code in PyFlyt/PyFlyt/core/drones/fixedwing.py:
self.surface_assist_ids = np.array([0, 0, 1, 1, 2, 3])
self.surface_assist_signs = np.array([1.0, -1.0, 1.0, -1.0, 0.0, 1.0])
......
self.cmd = (
self.setpoint[self.surface_assist_ids] * self.surface_assist_signs
)
These three lines of code seem to zero out the rudder deflection in self.cmd (since the fifth element of self.surface_assist_signs is zero). But the code comment says: "mapping for RPYT -> LeftAil, RightAil, HorStab, VertStab, MainWing, Motor". The fifth element (zero) corresponds to the main wing (no flaps). I'm confused and need your help understanding the physical meaning of each element in setpoint = np.array([-0.0165, -0.1, 0.0, 0.75]) and how to control rudder deflection.
Looking forward to your reply. Thank you!
Wishing you happiness every day!
You are right, that seems like a mistake. Good catch and thanks for pointing this out.
I believe the last two elements of surface_asaiat_signs should be flipped. Would you be open to making this change and testing it, the opening a PR for this?
Hello! I've found that swapping the last two elements of surface_assist_signs doesn't resolve the issue.
I hope the PyFlyt team coulde help me. First, I think you should check the physical meaning of the plane setpoints (env.set_setpoint(0, setpoint)) when the fixed-wing drone is in mode 0 (self.mode==0).
Looking forward to your reply. Thank you!
Wishing you happiness every day!
I am currently on vacation, and will be back next Tuesday. So I will probably look at this then, when I have my PC available. This should be resolved by then.
That said, I do recall that the rudder controls are very weak. Given that PyFlyt is deterministic under a fixed seed, could you check that there is indeed no change in yaw rate when rudder is used in a run with rudder input and without? If this is too complicated, I'm afraid this ticket will have to wait several days.
I'm truly sorry to disrupt your vacation!
Have a splendid time !
@ZF113120 Could you test out the branch at #85 and let me know if it works? I've tested it locally and the yaw seems to work, but the aircraft experiences a significant amount of adverse yaw.
@jjshoots :
Hi! I've tested the new branch PyFlyt-fix_fixedwing_yaw you uploaded on GitHub.
The yaw channel mapping in the new branch is correct, but there's an issue with the pitch channel mapping (it inputs the expected value into the main wing). I think the fifth element of self.surface_assist_signs in fixedwing.py should be 0 (i.e., self.surface_assist_signs = np.array([1.0, -1.0, 1.0, -1.0, 0, 1.0])).
Also, the model does have an inverse yaw problem. I've noticed that with low thrust, the inverse yaw problem is minimal, but it becomes severe as thrust increases. This indicates a modeling issue with the aircraft, which greatly hinders researchers using the model. I'm not familiar with the fixed-wing UAV modeling in this project, so I can't help. I'm looking forward to you solving this.
Wish you joy every day!
Thanks for testing this out! Yes, the pitch is now mapped into the main wing. This (is supposed to) have zero effect on the default fixed wing model, since the main wing on that model has zero deflection limit. This should only take effect on the acrowing model, where the main wing has some level of deflection on the main wing control surface, resulting in faster pitching motions.
Yes, the inverse yaw problem likely arises from the rudder producing more rolling motion than yawing motion. As a result, the dipped wing produces much more drag, causing an adverse yaw motion. For this issue, I would encourage a custom fixedwing model. One way is to just copy out the files of the default model, and perhaps play around with the parameters to produce a better result. One way I can imagine is simply moving the vertical stabilizer lower.
Does this help with your issue?
@jjshoots You mentioned that "the inverse yaw problem likely arises from the rudder producing more rolling motion than yawing motion". I conducted a test where I only input thrust to the aircraft, with all control surfaces set to zero deflection and set the simulation step to 1. I then printed out the forces generated by each wing surface:
3
[-0.24141466 0. 1.12053137]
4
[-0.24141633 0. 1.12123313]
1
[-0.30625591 -0. -0.14564751]
2
[-1.52861397e-01 5.11784485e-05 0.00000000e+00]
5
[-1.63171836 0. 17.53523051]
The output showed that wing 2 (the vertical tail) generated a lateral force of 5.11784485e-05**, while none of the other wings produced any lateral force. I am very curious about why this happens. Therefore, I would greatly appreciate it if you could find the time to review your modeling process to check if there are any issues with the model.
Additionally, you suggested copying the files of the default model to use a custom fixed-wing model. Could you please specify which files need to be replaced?
Lastly, regarding your suggestion to "simply moving the vertical stabilizer lower", how should this be implemented in the program?
I am looking forward to your reply and hope you can help me resolve these three questions. Thank you very much!
Have a good time!