global: fix MD007 unordered list indentation in markdown files Normalize unordered list indentation to use 2-space multiples: - Top-level list items start at column 0 - Nested list items use 2 additional spaces per level Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> global: fix MD009 trailing whitespace in markdown files Remove trailing whitespace from all affected markdown files. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> global: fix MD010 hard tabs in markdown files Replace hard tab characters with 4 spaces. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> global: fix MD012 multiple consecutive blank lines in markdown Collapse multiple consecutive blank lines to single blank lines across all markdown files (excluding vendored code). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> global: fix MD007 list indentation base level in markdown Shift list indentation left by 2 spaces so top-level list items start at column 0 instead of column 2. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD022 blank lines around headings in markdown Ensure headings are surrounded by blank lines as required by markdownlint MD022 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD032 blank lines around lists in markdown Ensure lists are surrounded by blank lines as required by markdownlint MD032 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD031 blank lines around code blocks in markdown Ensure fenced code blocks are surrounded by blank lines as required by markdownlint MD031 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD047 files should end with single newline Ensure all markdown files end with exactly one newline character as required by markdownlint MD047 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD023 headings must start at beginning of line Remove leading whitespace from heading lines as required by markdownlint MD023 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD007 remaining list indentation in markdown Fix unordered list indentation to use correct spacing as required by markdownlint MD007 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD030 spaces after list markers in markdown Reduce multiple spaces after list markers to single space as required by markdownlint MD030 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD022 blank lines around setext headings Ensure setext-style headings (underlined with === or ---) are surrounded by blank lines as required by markdownlint MD022 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD018 missing space after hash in headings Add space after hash marks in atx-style headings as required by markdownlint MD018 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD019 multiple spaces after hash in headings Reduce multiple spaces after hash marks to single space in atx-style headings as required by markdownlint MD019 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD012 multiple consecutive blank lines in markdown Remove multiple consecutive blank lines and ensure files end with exactly one newline as required by markdownlint MD012 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD023 headings with leading whitespace Remove leading whitespace from setext-style heading text lines as required by markdownlint MD023 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD022 blank line after heading in markdown Add missing blank line after heading as required by markdownlint MD022 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD009 trailing non-breaking space in markdown Remove trailing non-breaking space (U+00A0) as required by markdownlint MD009 rule. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Tools/scripts: fix MD012 remaining multiple blank lines in markdown Remove leading blank lines and whitespace-only lines that create multiple consecutive blank lines. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
8.1 KiB
Drone Ping-Pong Code
This script makes the drone go forward and backward a defined distance and number of times.
Stages
- 0: Change to Guided mode
- 1: Takeoff to the height defined by
takeoff_alt - 2: Wait until reaching the takeoff altitude
- 3: Go forward to the defined distance
- 4: Go back to the initial position
- 5: Change to Land mode
Variables:
takeoff_alt: Takeoff height (m)copter_guided_mode_num: Guided mode numbercopter_land_mode_num: Land mode numberstage: current stagecount: Number of times the drone has gone forwardmax_count: Maximum number of times the drone should go forwardping_pong_distance: Distance up to which the drone should go forward (m)vel: Drone velocity (m/s)
Understand the code:
First, there is a comment explaining what the code is about and how it works. Then, the local variables that will be used are declared.
The copter_guided_mode_num and copter_land_mode_num are standard numbers, defined by ArduPilot, for the Guided and Land flight modes, respectively. The other variables are user-defined settings according to the desired behavior, as indicated in the comments in front of each one.
-- This script makes the drone go forward and backward at a defined distance and number of times.
-- The stages are:
-- 0) Change to Guided mode
-- 1) Takeoff to the height defined by takeoff_alt
-- 2) Wait until reaching the takeoff altitude
-- 3) Go forward to the defined distance
-- 4) Go back to the initial position
-- 5) Change to Land mode
local takeoff_alt = 3 -- Takeoff height
local copter_guided_mode_num = 4
local copter_land_mode_num = 9
local stage = 0
local count = 0 -- Number of times the drone has gone forward
local max_count = 2 -- Maximum number of times the drone should go forward
local ping_pong_distance = 10 -- Distance up to which the drone should go forward (m)
local vel = 1
Next, there's the main function of the code, the update() function, which will be called once the code is started (since it wasn't indicated a waiting time at the last line of the code) and its return indicates that this same fucntion will be called again 100ms after finishing its executuion.
function update()
-- [Code]
return update(), 100
end
return update()
In the presented if, the code is waiting for the drone to be armed to change to the next stage. The is_armed() function from the arming library is used to check if the drone is armed or not. The send_text() function from the gcs library is used to send a message ("Arming") with severity 6 (information) to the GCS (Ground Control Station). Thus, while the drone is not armed, it remains in stage 0 of the code.
if not arming:is_armed() then
stage = 0
gcs:send_text(6, "Arming")
If the drone is armed, it moves to the else section, which presents a behavior for each stage.
In stage 0, the drone flight mode is changed to GUIDED MODE. To do this, it's used the function set_mode() of vehicle library, which receives the desired flight mode number(copter_guided_mode_num, defined in the local variables). When it verifies the drone has switched to the desired flight mode, it moves to the next stage.
else
if stage == 0 then
if vehicle:set_mode(copter_guided_mode_num) then
stage = stage + 1
end
in stage 1, it's used the start_takeoff() function from the vehicle library for the drone to take off to a height defined by the variable takeoff_alt.
elseif stage == 1 then
gcs:send_text(6, "Taking off")
if vehicle:start_takeoff(takeoff_alt) then
stage = stage + 1
end
In stage 2, it's used the ahrs:get_home() function to get the drone's takeoff location, and the ahrs:get_position() function to get the drone's current position. In line 4, it checks that the obtained values are not null. Then, the home:get_distance_NED() function stores in vec_from_home a 3D vector, starting from curr_loc and ending at home. In line 7, the code sends to the GCS the value contained in the z-coordinate of vec_from_home, i.e., the current altitude of the drone (multiplied by -1 since the vector points towards home, which is at a lower altitude than the current position).
When the difference between takeoff_alt and vec_from_home:z() is less than 1, indicating that the drone has reached the takeoff altitude, it moves to the next stage (math.abs() is used to get the absolute value, and we performed an addition instead of subtraction because the z component is negative).
elseif stage == 2 then
local home = ahrs:get_home()
local curr_loc = ahrs:get_position()
if home and curr_loc then
local vec_from_home = home:get_distance_NED(curr_loc)
gcs:send_text(6, "Altitude above home: " .. tostring(math.floor(-vec_from_home:z())))
if math.abs(takeoff_alt + vec_from_home:z()) < 1 then
stage = stage + 1
end
end
In stage3, first, the drone checks if it has already performed all the requested loops specified in max_count. If so, it switches to stage5. If not, it executes the commands of stage3.
First, it creates a 3D vector target_vel to store the desired velocity. Then, it sets the value of each of the components of this created vector (0 for y and z, and vel for x).
Then, it uses the vehicle:set_target_velocity_NED(target_vel) function to set the drone's velocity as that of target_vel. If it encounters any issues, it sends a warning message.
elseif (stage == 3) then -- Stage 3: Moving Forward
-- If the maximum number of times is exceeded, move to stage 5
if (count >= max_count) then
stage = stage + 2
end
-- Calculate velocity vector
local target_vel = Vector3f()
target_vel:x(vel)
target_vel:y(0)
target_vel:z(0)
-- Send velocity request
if not (vehicle:set_target_velocity_NED(target_vel)) then
gcs:send_text(6, "Failed to execute velocity command")
end
After that, it uses the same strategy as shown before to calculate the distance vector from the takeoff location to verify the distance x traveled. When the difference between the distance x that the drone traveled and the ping_pong_distance is less than 1, it increments the count and moves to the next stage.
-- checking if reached stop point
local home = ahrs:get_home()
local curr_loc = ahrs:get_position()
if home and curr_loc then
local vec_from_home = home:get_distance_NED(curr_loc)
gcs:send_text(6, "Distance from home: " .. tostring(math.floor(vec_from_home:x())))
if(math.abs(ping_pong_distance - vec_from_home:x()) < 1) then
count = count + 1
stage = stage + 1
end
end
end
In Stage4, the velocity in x is multiplied by -1 for the drone to fly in the opposite direction, returning to the takeoff position. When the difference between the drone's position x and the takeoff position's x is less than 1, it goes back to Stage3 to start the forward movement again (or not, if the count has reached max_count).
elseif (stage == 4) then -- Stage 4: Moving Back
-- calculate velocity vector
local target_vel = Vector3f()
target_vel:x(-vel)
target_vel:y(0)
target_vel:z(0)
-- send velocity request
if not (vehicle:set_target_velocity_NED(target_vel)) then
gcs:send_text(6, "Failed to execute velocity command")
end
-- checking if reached stop point
local home = ahrs:get_home()
local curr_loc = ahrs:get_position()
if home and curr_loc then
local vec_from_home = home:get_distance_NED(curr_loc)
gcs:send_text(6, "Distance from home: " .. tostring(math.floor(vec_from_home:x())))
if(math.abs(vec_from_home:x()) < 1) then
stage = stage - 1
end
end
end
In stage5, the drone simply changes to the Land flight mode and lands, indicating the completion of the code through a message.
elseif (stage == 5) then -- Stage 5: Change to LAND mode
vehicle:set_mode(copter_rtl_mode_num)
stage = stage + 1
gcs:send_text(6, "Finished pingpong, switching to LAND")
end