mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-05-02 05:04:08 +08:00
The flight graph is stored as a series of delta elements at 1m resolution and a list of nodes. Both lists share the same buffer. Each delta element takes up 2 bytes or sometimes 6 bytes if the delta is large. The path can consist of multiple disconnected segments, in which case the gaps are stored as delta elements with a jump-bit set. Once in a while or when required the graph is consolidated, which means: - Points that lie roughly in a line are replaced by a single line - Points that lie close to previously recorded lines are pruned - For lines that pass close to each other a node element is created Furthermore: - The graph is recorded at a higher precision closer to home - If the graph becomes full, the overall precision is reduced and the whole graph is re-consolidated - If the graph becomes full once more, all data is removed except for the shortest path home at that moment. One of these actions is repeated at each subsequent fill-up. Path finding information is generated/refreshed on demand and stored in the nodes. During return-to-home, the best direction to home is continuously evaluated by using the information stored in the nodes. The graph recording and path finding is implemented in navigator/tracker.cpp. The graph based return-to-home is implemented in navigator/smart_rtl.cpp.
242 lines
5.8 KiB
Bash
Executable File
242 lines
5.8 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# Script to draw 2D flight paths. The z-component is always 0.
|
|
# The purpose is to test the flight graph tracker by handing it a predesigned path.
|
|
#
|
|
# Usage: draw_path.sh [file]
|
|
# If the file already exists, new points are appended.
|
|
# arrow keys: move cursor
|
|
# spacebar: add current cursor position to path
|
|
# q: quit
|
|
|
|
|
|
|
|
# Shows a status message at the end of the screen
|
|
function show_status() {
|
|
tput cup $(expr $SCREEN_WIDTH-1) 0
|
|
echo $1
|
|
move_cursor
|
|
STATUS_CLEAR="no"
|
|
}
|
|
|
|
# Clears the status message
|
|
function clear_status() {
|
|
[ "$STATUS_CLEAR" = "no" ] || return 0
|
|
tput cup 0 0
|
|
tput el && tput el1
|
|
move_cursor
|
|
STATUS_CLEAR="yes"
|
|
}
|
|
|
|
# Terminates the script
|
|
function quit() {
|
|
tput rmcup
|
|
stty echo
|
|
exit 0
|
|
}
|
|
|
|
# Moves the terminal cursor to position ($CURSOR_X, $CURSOR_Y)
|
|
function move_cursor() {
|
|
#echo "\033[$CURSOR_Y;$CURSOR_X"'f'
|
|
#echo -e "\033[$CURSOR_Y;3f"
|
|
tput cup $CURSOR_Y $CURSOR_X
|
|
}
|
|
|
|
# Draws a line from the last point to the current cursor position
|
|
function go_here() {
|
|
draw_line $LAST_POINT_X $LAST_POINT_Y $CURSOR_X $CURSOR_Y
|
|
echo "o"
|
|
move_cursor
|
|
LAST_POINT_X=$CURSOR_X
|
|
LAST_POINT_Y=$CURSOR_Y
|
|
}
|
|
|
|
# Adds the current cursor position to the file $FILE
|
|
function store_point() {
|
|
echo "$CURSOR_X,$CURSOR_Y,0," >> $FILE
|
|
}
|
|
|
|
# Loads all points from the file $FILE
|
|
# Each line stores a point in the format "x,y,z".
|
|
# Empty lines and lines starting with "/" are ignored.
|
|
function load_file() {
|
|
while IFS='' read -r line || [[ -n "$line" ]]; do
|
|
CURSOR_X=$(echo "$line" | awk -F, "/^[^\/]/{print \$1}")
|
|
CURSOR_Y=$(echo "$line" | awk -F, "/^[^\/]/{print \$2}")
|
|
#echo "X=$CURSOR_X Y=$CURSOR_Y"
|
|
[ "$CURSOR_X" = "" ] || [ "$CURSOR_Y" = "" ] || go_here
|
|
done < "$FILE"
|
|
}
|
|
|
|
# Draws a line using the Bresenham algorithm
|
|
# usage: draw_line x1 y1 x2 y2
|
|
# The point (x1, y1) is not filled.
|
|
# The point (x2, y2) is filled and the cursor is placed there.
|
|
function draw_line() {
|
|
X1=$1
|
|
Y1=$2
|
|
X2=$3
|
|
Y2=$4
|
|
LINE_CHAR="\\"
|
|
|
|
# The algorithm requires that delta-y is smaller than delta-x
|
|
SWAP_XY=$(echo "define delta(a, b) {if (a>b) return a-b; return b-a;}; delta($X1,$X2) < delta($Y1,$Y2)" | bc)
|
|
[ "$SWAP_XY" = "1" ] && {
|
|
TEMP=$X1; X1=$Y1; Y1=$TEMP
|
|
TEMP=$X2; X2=$Y2; Y2=$TEMP
|
|
}
|
|
|
|
# Delta-x must be positive
|
|
REVERSE_DIR=$(echo "$X1 > $X2" | bc)
|
|
[ "$REVERSE_DIR" = "1" ] && {
|
|
TEMP=$X1; X1=$X2; X2=$TEMP
|
|
TEMP=$Y1; Y1=$Y2; Y2=$TEMP
|
|
}
|
|
|
|
# Now the slope is in [-45°, +45], in positive x-direction. The update update differs for positive and negative slopes.
|
|
POS_SLOPE=$(echo "$Y2 > $Y1" | bc)
|
|
|
|
DELTA_X=$(($X2-$X1))
|
|
DELTA_Y=$(($Y2-$Y1))
|
|
|
|
# init update criterion
|
|
if [ "$POS_SLOPE" = "1" ]; then
|
|
D=$(echo "$DELTA_Y * ($X1+1) - $DELTA_X * ($Y1+0.5) + $X2 * $Y1 - $X1 * $Y2" | bc)
|
|
else
|
|
D=$(echo "$DELTA_Y * ($X1+1) - $DELTA_X * ($Y1-0.5) + $X2 * $Y1 - $X1 * $Y2" | bc)
|
|
fi
|
|
|
|
XP=$X1
|
|
YP=$Y1
|
|
|
|
while [ $XP -lt $X2 ]; do
|
|
[ "$SWAP_XY" = "0" ] && LINE_CHAR="-" || LINE_CHAR="|"
|
|
|
|
# Move to next pixel, according to update criterion
|
|
XP=$(($XP+1))
|
|
if [ "$POS_SLOPE" = "1" ]; then
|
|
[ $(echo "$D > 0" | bc) = "1" ] && {
|
|
YP=$(($YP+1))
|
|
D=$(echo "$D - $DELTA_X" | bc)
|
|
LINE_CHAR="\\"
|
|
}
|
|
D=$(echo "$D + $DELTA_Y" | bc)
|
|
else
|
|
[ $(echo "$D < 0" | bc) = "1" ] && {
|
|
YP=$(($YP-1))
|
|
D=$(echo "$D + $DELTA_X" | bc)
|
|
LINE_CHAR="/"
|
|
}
|
|
D=$(echo "$D + $DELTA_Y" | bc)
|
|
fi
|
|
|
|
# Draw pixel
|
|
[ "$SWAP_XY" = "0" ] && { CURSOR_X=$XP; CURSOR_Y=$YP; } || { CURSOR_X=$YP; CURSOR_Y=$XP; }
|
|
move_cursor;
|
|
|
|
([ "$REVERSE_DIR" = "1" ] && [ "$XP" = "$X2" ]) || echo "$LINE_CHAR"
|
|
done
|
|
|
|
[ "$REVERSE_DIR" = "1" ] && { [ "$SWAP_XY" = "0" ] && { CURSOR_X=$X1; CURSOR_Y=$Y1; } || { CURSOR_X=$Y1; CURSOR_Y=$X1; } }
|
|
move_cursor;
|
|
}
|
|
|
|
# Moves the cursor up if possible
|
|
function up() {
|
|
[ $CURSOR_Y -gt 0 ] && let CURSOR_Y=$CURSOR_Y-1
|
|
move_cursor
|
|
}
|
|
|
|
# Moves the cursor down if possible
|
|
function down() {
|
|
let CURSOR_Y=$CURSOR_Y+1
|
|
[ $CURSOR_Y -lt $SCREEN_HEIGHT ] || let CURSOR_Y=$SCREEN_HEIGHT-1
|
|
move_cursor
|
|
}
|
|
|
|
# Moves the cursor left if possible
|
|
function left() {
|
|
[ $CURSOR_X -gt 0 ] && let CURSOR_X=$CURSOR_X-1
|
|
move_cursor
|
|
}
|
|
|
|
# Moves the cursor right if possible
|
|
function right() {
|
|
let CURSOR_X=$CURSOR_X+1
|
|
[ $CURSOR_X -lt $SCREEN_WIDTH ] || let CURSOR_X=$SCREEN_WIDTH-1
|
|
move_cursor
|
|
}
|
|
|
|
|
|
|
|
|
|
# Set up globals
|
|
SCREEN_WIDTH=$(tput cols)
|
|
SCREEN_HEIGHT=$(tput lines)
|
|
let CURSOR_X=$SCREEN_WIDTH/2
|
|
let CURSOR_Y=$SCREEN_HEIGHT/2
|
|
LAST_POINT_X=$CURSOR_X
|
|
LAST_POINT_Y=$CURSOR_Y
|
|
KEY_SEQUENCE=""
|
|
FILE=$1
|
|
|
|
touch $FILE 2>/dev/null || { echo "could not open file $FILE"; exit 1; }
|
|
|
|
# Switch to alternate screen
|
|
tput smcup
|
|
#x=$(tput lines)
|
|
#while [ $x -gt 0 ]; do echo ""; let x=$x-1; done;
|
|
tput clear
|
|
stty -echo
|
|
move_cursor
|
|
|
|
load_file
|
|
|
|
|
|
# draws two crosses
|
|
#draw_line 20 3 50 15
|
|
#draw_line 20 15 50 3
|
|
#draw_line 5 5 20 30
|
|
#draw_line 20 5 5 30
|
|
|
|
# draws the same two crosses (with swapped start end end points)
|
|
#draw_line 50 15 20 3
|
|
#draw_line 50 3 20 15
|
|
#draw_line 20 30 5 5
|
|
#draw_line 5 30 20 5
|
|
|
|
|
|
while true; do
|
|
IFS=""
|
|
read -r -n 1 CHAR
|
|
|
|
KEY_SEQUENCE=$KEY_SEQUENCE$CHAR
|
|
CARRY_SEQUENCE=""
|
|
|
|
clear_status
|
|
|
|
case $KEY_SEQUENCE in
|
|
$'\033'|$'\033[')
|
|
# incomplete escape sequence - read another char
|
|
CARRY_SEQUENCE=$KEY_SEQUENCE
|
|
#show_status "press q to exit"
|
|
;;
|
|
|
|
'q') quit ;;
|
|
|
|
$'\033[A') up ;;
|
|
$'\033[B') down ;;
|
|
$'\033[C') right ;;
|
|
$'\033[D') left ;;
|
|
|
|
$" ") go_here; store_point ;;
|
|
|
|
*)
|
|
show_status "unknown key"
|
|
;;
|
|
esac
|
|
|
|
KEY_SEQUENCE=$CARRY_SEQUENCE
|
|
done
|
|
|