Skip to content

Commit

Permalink
Feature/pid tuning (#9)
Browse files Browse the repository at this point in the history
* Initial commit

* Initial commit

* Added environment setup instructions

* Added necessary docstring/reference

* Fixed list numbering

* Added Docstrings

* Added basic manual-mode drone control

* Added various missing type annotations and reformatted docstrings

* Started working on class docstring

* Removed wrongly committed file

* Added proper type annotations and docstrings. Minor reformatting.

* Initial commit

* Added environment setup instructions

* Added necessary docstring/reference

* Fixed list numbering

* Added Docstrings

* Added basic manual-mode drone control

* Added various missing type annotations and reformatted docstrings

* Started working on class docstring

* Added proper type annotations and docstrings. Minor reformatting.

* Fixed behind tests branch

* Fix typos

* Fix improper formatting

* Added missing type annotation

* Added missing type annotation

* Initial commit

* Added some docstrings

* Initial commit

* Pre-commit whitespace fixes

* Added files needed for pre-commit

* Reformat README

* Updated package management, reformat README, docstring additions

* Update .pre-commit-config.yaml

* Fix unsupported character

* Completed docstrings and type annotations

* Started PID loop integration

* Implemented throttle PID

* Implemented gps velocity tracking for more sensible calculations

* Implement basic PID tuning (that works)

* Tuned pitch and roll PID loops

* PID Tuning

* Completed PID Tuning, added comments

* Complete pre-commit

* Added variable pitch target

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Fix mega mondo missing type hints

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
Pyrallux and pre-commit-ci[bot] authored Mar 22, 2024
1 parent 37517d5 commit 594011b
Show file tree
Hide file tree
Showing 5 changed files with 699 additions and 52 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ The programs associated with the development of drone racing powered my Microsof

- `git clone https://github.com/MissouriMRR/ai-racing.git`

4. Future steps require Python to be installed (The download can be found online, multirotor uses python 3.10). Navigate the the home directory of the git repository you just cloned. Open the command line and run the following command to install dependencies.

4. Future steps require Python 3.10 to be installed (the download can be found [here](https://www.python.org/downloads/release/python-31011/)). Navigate to the home directory of the git repository you just cloned. Open the command line and run the following command to install dependencies.
- `pip install -r requirements.txt`

Python scripts can now be run interfacing with the drone using the airsimdroneracinglab API package.
Expand Down
18 changes: 9 additions & 9 deletions tests/manual_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@ class ReproduceResetRaceCondition:
Attributes
----------
airsim_client : airsimdroneracinglab.client.MultirotorCleint
airsim_client : airsimdroneracinglab.client.MultirotorClient
Default airsim client for interacting with the environment
airsim_client_2 : airsimdroneracinglab.client.MultirotorCleint
airsim_client_2 : airsimdroneracinglab.client.MultirotorClient
Second alternative airsim client for interacting with the environment
airsim_client_3 : airsimdroneracinglab.client.MultirotorCleint
airsim_client_3 : airsimdroneracinglab.client.MultirotorClient
Third alternative airsim client for interacting with the environment
drone_name : string
Name of user controlled drone.
is_thread_active : boolean
Boolean used to see if current thread is active or not
thread_reset : threading.Thread
Thread used to reset airsim cleint.
Thread used to reset airsim client.
thread_reset_race : threading.Thread
Thread used to reset current race
thread_reset_and_reset_race : threading.Thread
Expand All @@ -38,7 +38,7 @@ class ReproduceResetRaceCondition:
Methods
-------
repeat_timer(callback, period: float)
repeat_timer(callback : Callable[[], None], period: float)
Simple sleep timer
load_level(level_name: str, sleep_sec: float = 2.0)
Loads given simulator level
Expand All @@ -47,7 +47,7 @@ class ReproduceResetRaceCondition:
reset_race()
Resets current race
reset_and_reset_race()
Resets airsim cleint and current race
Resets airsim client and current race
start_race(tier: int = 1)
Starts race against a baseline drone using moveonspline
initialize_drone()
Expand Down Expand Up @@ -104,7 +104,7 @@ def repeat_timer(self, callback: Callable[[], None], period: float) -> None:
Parameters
----------
callback : function
callback : Callable[[], None]
Function to call
period : float
Repeat interval in seconds
Expand Down Expand Up @@ -132,7 +132,7 @@ def load_level(self, level_name: str, sleep_sec: float = 2.0) -> None:
time.sleep(sleep_sec) # let the environment load completely

def reset(self) -> None:
"""Resets Airsim cleint."""
"""Resets Airsim client."""
print(time.time(), "called reset")
self.airsim_client.reset()

Expand All @@ -142,7 +142,7 @@ def reset_race(self) -> None:
self.airsim_client_2.simResetRace()

def reset_and_reset_race(self) -> None:
"""Resets airsim cleint and current race"""
"""Resets airsim client and current race"""
print(time.time(), "called reset, followed by simResetRace")
self.airsim_client_3.reset()
self.airsim_client_3.simResetRace()
Expand Down
61 changes: 29 additions & 32 deletions tests/pathing.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ class ReproduceResetRaceCondition:
Attributes
----------
airsim_client : airsimdroneracinglab.client.MultirotorCleint
airsim_client : airsimdroneracinglab.client.MultirotorClient
Default airsim client for interacting with the environment
airsim_client_2 : airsimdroneracinglab.client.MultirotorCleint
airsim_client_2 : airsimdroneracinglab.client.MultirotorClient
Second alternative airsim client for interacting with the environment
airsim_client_3 : airsimdroneracinglab.client.MultirotorCleint
airsim_client_3 : airsimdroneracinglab.client.MultirotorClient
Third alternative airsim client for interacting with the environment
drone_name : string
Name of user controlled drone.
is_thread_active : boolean
Boolean used to see if current thread is active or not
thread_reset : threading.Thread
Thread used to reset airsim cleint.
Thread used to reset airsim client.
thread_reset_race : threading.Thread
Thread used to reset current race
thread_reset_and_reset_race : threading.Thread
Expand All @@ -42,7 +42,7 @@ class ReproduceResetRaceCondition:
Methods
-------
repeat_timer(callback, period: float)
repeat_timer(callback : Callable[[], None], period: float)
Simple sleep timer
load_level(level_name: str, sleep_sec: float = 2.0)
Loads given simulator level
Expand All @@ -51,7 +51,7 @@ class ReproduceResetRaceCondition:
reset_race()
Resets current race
reset_and_reset_race()
Resets airsim cleint and current race
Resets airsim client and current race
start_race(tier: int = 1)
Starts race against a baseline drone using moveonspline
initialize_drone()
Expand All @@ -64,10 +64,11 @@ class ReproduceResetRaceCondition:
takeoff()
Built-in ADRL async takeoff function.
Sends moveonspline commands to drone in order to take off.
give_control_stick_inputs(self, roll, pitch, yaw, z, duration)
Reads various control stick inputs from command-line interface
and passes them to the drone for a given amount of time.
get_gate_pose(gate_index)
give_control_stick_inputs(
self, roll: float, pitch: float, yaw: float, z: float, duration: float
)
Passes various inputs to the drone for a given amount of time.
get_gate_pose(gate_index: int)
Gets a list of gates from the airsim client,
then returns the pose of the gate requested in the form of an object.
get_drone_pose()
Expand Down Expand Up @@ -117,7 +118,7 @@ def repeat_timer(self, callback: Callable[[], None], period: float) -> None:
Parameters
----------
callback : function
callback : Callable[[], None]
Function to call
period : float
Repeat interval in seconds
Expand Down Expand Up @@ -145,7 +146,7 @@ def load_level(self, level_name: str, sleep_sec: float = 2.0) -> None:
time.sleep(sleep_sec) # let the environment load completely

def reset(self) -> None:
"""Resets Airsim cleint."""
"""Resets Airsim client."""
print(time.time(), "called reset")
self.airsim_client.reset()

Expand All @@ -155,7 +156,7 @@ def reset_race(self) -> None:
self.airsim_client_2.simResetRace()

def reset_and_reset_race(self) -> None:
"""Resets airsim cleint and current race"""
"""Resets airsim client and current race"""
print(time.time(), "called reset, followed by simResetRace")
self.airsim_client_3.reset()
self.airsim_client_3.simResetRace()
Expand Down Expand Up @@ -308,9 +309,8 @@ def get_drone_y_velocity(self) -> float:
Drone's current y velocity (perpendicular left-right velocity) in relation to frame
"""
interval: float = 0.01
velocity_deadzone: float = (
0.15 # Adjusting this value may result in better/worse performance
)
# Increasing gives more accurate output but can lead to overcorrection for small velocities
velocity_deadzone: float = 0.15

# Gets drone's positon "interval" number of seconds apart
old_position: airsimdroneracinglab.Pose = self.get_drone_pose()
Expand Down Expand Up @@ -360,7 +360,7 @@ def get_num_gates(self) -> int:
The number of gates present on the active level
"""
gate_list: list[str] = self.airsim_client.simListSceneObjects("Gate.*")
num_gates = len(gate_list)
num_gates: int = len(gate_list)
return num_gates


Expand Down Expand Up @@ -462,15 +462,14 @@ def calc_roll_angle(y_velocity: float) -> float:

if __name__ == "__main__":
# Sets up race, initializes drone, loads level, and takes off
reproducer = ReproduceResetRaceCondition("drone_1")
reproducer: ReproduceResetRaceCondition = ReproduceResetRaceCondition("drone_1")
reproducer.load_level("Soccer_Field_Easy") # Level name can be changed - see load_level() args
NUM_GATES = 12 # There are 12 gates on the default level "Soccer_Field_Easy"
reproducer.initialize_drone()
reproducer.start_race(1)
reproducer.takeoff()

# Gets the number of gates in the active level
NUM_GATES = reproducer.get_num_gates()
NUM_GATES: int = reproducer.get_num_gates()
print("There are ", NUM_GATES, " gates present.")

# Iterates through each gate in the level
Expand All @@ -480,27 +479,25 @@ def calc_roll_angle(y_velocity: float) -> float:
0.02 # Currently a constant, should be calculated with a PID loop
)

# Gets next gate position and orientation
gate_pose = reproducer.get_gate_pose(next_gate)
gate_orientation = airsimdroneracinglab.utils.to_eularian_angles(gate_pose.orientation)
# Gets next gate position
gate_pose: airsimdroneracinglab.Pose = reproducer.get_gate_pose(next_gate)

# Gives the drone inputs to move it towards the next gate until it arrives
distance_to_gate: float = 10000
while distance_to_gate > 1:
# Gets the drone's current position and orientation
drone_pose = reproducer.get_drone_pose()
drone_orientation = airsimdroneracinglab.utils.to_eularian_angles(
drone_pose.orientation
)
print("Drone Orientation:", drone_orientation)
# Gets the drone's current position
drone_pose: airsimdroneracinglab.Pose = reproducer.get_drone_pose()

# Generates vector to next gate, then verifies that the vector is a number
vector_to_gate = generate_vector(drone_pose.position, gate_pose.position)
vector_to_gate: tuple[float, float, float] = generate_vector(
drone_pose.position, gate_pose.position
)
if math.isnan(vector_to_gate[0]):
time.sleep(INPUT_DURATION)
continue
# Calculates various angles needed to point the drone at the next gate
target_yaw_angle = generate_yaw_angle(vector_to_gate)
drone_y_velocity = reproducer.get_drone_y_velocity()
target_yaw_angle: float = generate_yaw_angle(vector_to_gate)
drone_y_velocity: float = reproducer.get_drone_y_velocity()
drone_roll_angle: float = calc_roll_angle(drone_y_velocity)
# Sends inputs to the drone
reproducer.give_control_stick_inputs(
Expand Down
Loading

0 comments on commit 594011b

Please sign in to comment.