openpilot0/tools/op.sh

392 lines
12 KiB
Bash
Executable File

#!/usr/bin/env bash
if [[ ! "${BASH_SOURCE[0]}" = "${0}" ]]; then
echo "Invalid invocation! This script must not be sourced."
echo "Run 'op.sh' directly or check your .bashrc for a valid alias"
return 0
fi
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
UNDERLINE='\033[4m'
BOLD='\033[1m'
NC='\033[0m'
SHELL_NAME="$(basename ${SHELL})"
RC_FILE="${HOME}/.$(basename ${SHELL})rc"
if [ "$(uname)" == "Darwin" ] && [ $SHELL == "/bin/bash" ]; then
RC_FILE="$HOME/.bash_profile"
fi
function op_install() {
echo "Installing op system-wide..."
CMD="\nalias op='"$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )/op.sh" \"\$@\"'\n"
grep "alias op=" "$RC_FILE" &> /dev/null || printf "$CMD" >> $RC_FILE
echo -e " ↳ [${GREEN}${NC}] op installed successfully. Open a new shell to use it."
}
function loge() {
if [[ -f "$LOG_FILE" ]]; then
# error type
echo "$1" >> $LOG_FILE
# error log
echo "$2" >> $LOG_FILE
fi
}
function op_run_command() {
CMD="$@"
echo -e "${BOLD}Running command →${NC} $CMD"
for ((i=0; i<$((19 + ${#CMD})); i++)); do
echo -n "─"
done
echo -e "┘\n"
if [[ -z "$DRY" ]]; then
eval "$CMD"
fi
}
# be default, assume openpilot dir is in current directory
OPENPILOT_ROOT=$(pwd)
function op_get_openpilot_dir() {
while [[ "$OPENPILOT_ROOT" != '/' ]];
do
if find "$OPENPILOT_ROOT/launch_openpilot.sh" -maxdepth 1 -mindepth 1 &> /dev/null; then
return 0
fi
OPENPILOT_ROOT="$(readlink -f "$OPENPILOT_ROOT/"..)"
done
}
function op_install_post_commit() {
op_get_openpilot_dir
if [[ ! -d $OPENPILOT_ROOT/.git/hooks/post-commit.d ]]; then
mkdir $OPENPILOT_ROOT/.git/hooks/post-commit.d
mv $OPENPILOT_ROOT/.git/hooks/post-commit $OPENPILOT_ROOT/.git/hooks/post-commit.d 2>/dev/null || true
fi
cd $OPENPILOT_ROOT/.git/hooks
ln -sf ../../scripts/post-commit post-commit
}
function op_check_openpilot_dir() {
echo "Checking for openpilot directory..."
if [[ -f "$OPENPILOT_ROOT/launch_openpilot.sh" ]]; then
echo -e " ↳ [${GREEN}${NC}] openpilot found."
return 0
fi
echo -e " ↳ [${RED}${NC}] openpilot directory not found! Make sure that you are"
echo " inside the openpilot directory or specify one with the"
echo " --dir option!"
return 1
}
function op_check_git() {
echo "Checking for git..."
if ! command -v "git" > /dev/null 2>&1; then
echo -e " ↳ [${RED}${NC}] git not found on your system!"
return 1
else
echo -e " ↳ [${GREEN}${NC}] git found."
fi
echo "Checking for git lfs files..."
if [[ $(file -b $OPENPILOT_ROOT/selfdrive/modeld/models/supercombo.onnx) == "data" ]]; then
echo -e " ↳ [${GREEN}${NC}] git lfs files found."
else
echo -e " ↳ [${RED}${NC}] git lfs files not found! Run 'git lfs pull'"
return 1
fi
echo "Checking for git submodules..."
for name in $(git config --file .gitmodules --get-regexp path | awk '{ print $2 }' | tr '\n' ' '); do
if [[ -z $(ls $OPENPILOT_ROOT/$name) ]]; then
echo -e " ↳ [${RED}${NC}] git submodule $name not found! Run 'git submodule update --init --recursive'"
return 1
fi
done
echo -e " ↳ [${GREEN}${NC}] git submodules found."
}
function op_check_os() {
echo "Checking for compatible os version..."
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
if [ -f "/etc/os-release" ]; then
source /etc/os-release
case "$VERSION_CODENAME" in
"jammy" | "kinetic" | "noble" | "focal")
echo -e " ↳ [${GREEN}${NC}] Ubuntu $VERSION_CODENAME detected."
;;
* )
echo -e " ↳ [${RED}${NC}] Incompatible Ubuntu version $VERSION_CODENAME detected!"
loge "ERROR_INCOMPATIBLE_UBUNTU" "$VERSION_CODENAME"
return 1
;;
esac
else
echo -e " ↳ [${RED}${NC}] No /etc/os-release on your system. Make sure you're running on Ubuntu, or similar!"
loge "ERROR_UNKNOWN_UBUNTU"
return 1
fi
elif [[ "$OSTYPE" == "darwin"* ]]; then
echo -e " ↳ [${GREEN}${NC}] macOS detected."
else
echo -e " ↳ [${RED}${NC}] OS type $OSTYPE not supported!"
loge "ERROR_UNKNOWN_OS" "$OSTYPE"
return 1
fi
}
function op_check_python() {
echo "Checking for compatible python version..."
REQUIRED_PYTHON_VERSION=$(grep "requires-python" $OPENPILOT_ROOT/pyproject.toml)
INSTALLED_PYTHON_VERSION=$(python3 --version 2> /dev/null || true)
if [[ -z $INSTALLED_PYTHON_VERSION ]]; then
echo -e " ↳ [${RED}${NC}] python3 not found on your system. You need python version at least $(echo $REQUIRED_PYTHON_VERSION | tr -d -c '[0-9.]') to continue!"
loge "ERROR_PYTHON_NOT_FOUND"
return 1
elif [[ $(echo $INSTALLED_PYTHON_VERSION | grep -o '[0-9]\+\.[0-9]\+' | tr -d -c '[0-9]') -ge $(echo $REQUIRED_PYTHON_VERSION | tr -d -c '[0-9]') ]]; then
echo -e " ↳ [${GREEN}${NC}] $INSTALLED_PYTHON_VERSION detected."
else
echo -e " ↳ [${RED}${NC}] You need python version at least $(echo $REQUIRED_PYTHON_VERSION | tr -d -c '[0-9.]') to continue!"
loge "ERROR_PYTHON_VERSION" "$INSTALLED_PYTHON_VERSION"
return 1
fi
}
function op_check_venv() {
echo "Checking for venv..."
if [[ -f $OPENPILOT_ROOT/.venv/bin/activate ]]; then
echo -e " ↳ [${GREEN}${NC}] venv detected."
else
echo -e " ↳ [${RED}${NC}] Can't activate venv in $OPENPILOT_ROOT. Assuming global env!"
fi
}
function op_before_cmd() {
if [[ ! -z "$NO_VERIFY" ]]; then
return 0
fi
op_get_openpilot_dir
cd $OPENPILOT_ROOT
result="$((op_check_openpilot_dir ) 2>&1)" || (echo -e "$result" && return 1)
result="${result}\n$(( op_check_git ) 2>&1)" || (echo -e "$result" && return 1)
result="${result}\n$(( op_check_os ) 2>&1)" || (echo -e "$result" && return 1)
result="${result}\n$(( op_check_venv ) 2>&1)" || (echo -e "$result" && return 1)
op_activate_venv
result="${result}\n$(( op_check_python ) 2>&1)" || (echo -e "$result" && return 1)
if [[ -z $VERBOSE ]]; then
echo -e "${BOLD}Checking system →${NC} [${GREEN}${NC}]"
else
echo -e "$result"
fi
}
function op_setup() {
op_get_openpilot_dir
cd $OPENPILOT_ROOT
op_check_openpilot_dir
op_check_os
echo "Installing dependencies..."
st="$(date +%s)"
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
SETUP_SCRIPT="tools/ubuntu_setup.sh"
elif [[ "$OSTYPE" == "darwin"* ]]; then
SETUP_SCRIPT="tools/mac_setup.sh"
fi
if ! $OPENPILOT_ROOT/$SETUP_SCRIPT; then
echo -e "[${RED}${NC}] Dependencies installation failed!"
loge "ERROR_DEPENDENCIES_INSTALLATION"
return 1
fi
et="$(date +%s)"
echo -e "[${GREEN}${NC}] Dependencies installed successfully in $((et - st)) seconds."
echo "Getting git submodules..."
st="$(date +%s)"
if ! git submodule update --filter=blob:none --jobs 4 --init --recursive; then
echo -e "[${RED}${NC}] Getting git submodules failed!"
loge "ERROR_GIT_SUBMODULES"
return 1
fi
et="$(date +%s)"
echo -e "[${GREEN}${NC}] Submodules installed successfully in $((et - st)) seconds."
echo "Pulling git lfs files..."
st="$(date +%s)"
if ! git lfs pull; then
echo -e "[${RED}${NC}] Pulling git lfs files failed!"
loge "ERROR_GIT_LFS"
return 1
fi
et="$(date +%s)"
echo -e "[${GREEN}${NC}] Files pulled successfully in $((et - st)) seconds."
op_check
}
function op_activate_venv() {
# bash 3.2 can't handle this without the 'set +e'
set +e
source $OPENPILOT_ROOT/.venv/bin/activate &> /dev/null || true
set -e
}
function op_venv() {
op_before_cmd
if [[ ! -f $OPENPILOT_ROOT/.venv/bin/activate ]]; then
echo -e "No venv found in $OPENPILOT_ROOT"
return 1
fi
case $SHELL_NAME in
"zsh")
ZSHRC_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t 'tmp_zsh')
echo "source $RC_FILE; source $OPENPILOT_ROOT/.venv/bin/activate" >> $ZSHRC_DIR/.zshrc
ZDOTDIR=$ZSHRC_DIR zsh ;;
*)
bash --rcfile <(echo "source $RC_FILE; source $OPENPILOT_ROOT/.venv/bin/activate") ;;
esac
}
function op_check() {
VERBOSE=1
op_before_cmd
unset VERBOSE
}
function op_build() {
CDIR=$(pwd)
op_before_cmd
cd "$CDIR"
op_run_command scons $@
}
function op_juggle() {
op_before_cmd
op_run_command tools/plotjuggler/juggle.py $@
}
function op_lint() {
op_before_cmd
op_run_command scripts/lint/lint.sh $@
}
function op_test() {
op_before_cmd
op_run_command pytest $@
}
function op_replay() {
op_before_cmd
op_run_command tools/replay/replay $@
}
function op_cabana() {
op_before_cmd
op_run_command tools/cabana/cabana $@
}
function op_sim() {
op_before_cmd
op_run_command exec tools/sim/run_bridge.py &
op_run_command exec tools/sim/launch_openpilot.sh
}
function op_default() {
echo "An openpilot helper"
echo ""
echo -e "${BOLD}${UNDERLINE}Description:${NC}"
echo " op is your entry point for all things related to openpilot development."
echo " op is only a wrapper for existing scripts, tools, and commands."
echo " op will always show you what it will run on your system."
echo ""
echo " op will try to find your openpilot directory in the following order:"
echo " 1: use the directory specified with the --dir option"
echo " 2: use the current working directory"
echo " 3: go up the file tree non-recursively"
echo ""
echo -e "${BOLD}${UNDERLINE}Usage:${NC} op [OPTIONS] <COMMAND>"
echo ""
echo -e "${BOLD}${UNDERLINE}Commands [System]:${NC}"
echo -e " ${BOLD}check${NC} Check the development environment (git, os, python) to start using openpilot"
echo -e " ${BOLD}venv${NC} Activate the python virtual environment"
echo -e " ${BOLD}setup${NC} Install openpilot dependencies"
echo -e " ${BOLD}build${NC} Run the openpilot build system in the current working directory"
echo -e " ${BOLD}install${NC} Install the 'op' tool system wide"
echo ""
echo -e "${BOLD}${UNDERLINE}Commands [Tooling]:${NC}"
echo -e " ${BOLD}juggle${NC} Run PlotJuggler"
echo -e " ${BOLD}replay${NC} Run Replay"
echo -e " ${BOLD}cabana${NC} Run Cabana"
echo ""
echo -e "${BOLD}${UNDERLINE}Commands [Testing]:${NC}"
echo -e " ${BOLD}sim${NC} Run openpilot in a simulator"
echo -e " ${BOLD}lint${NC} Run the linter"
echo -e " ${BOLD}post-commit${NC} Install the linter as a post-commit hook"
echo -e " ${BOLD}test${NC} Run all unit tests from pytest"
echo ""
echo -e "${BOLD}${UNDERLINE}Options:${NC}"
echo -e " ${BOLD}-d, --dir${NC}"
echo " Specify the openpilot directory you want to use"
echo -e " ${BOLD}--dry${NC}"
echo " Don't actually run anything, just print what would be run"
echo -e " ${BOLD}-n, --no-verify${NC}"
echo " Skip environment check before running commands"
echo ""
echo -e "${BOLD}${UNDERLINE}Examples:${NC}"
echo " op setup"
echo " Run the setup script to install"
echo " openpilot's dependencies."
echo ""
echo " op build -j4"
echo " Compile openpilot using 4 cores"
echo ""
echo " op juggle --demo"
echo " Run PlotJuggler on the demo route"
}
function _op() {
# parse Options
case $1 in
-d | --dir ) shift 1; OPENPILOT_ROOT="$1"; shift 1 ;;
--dry ) shift 1; DRY="1" ;;
-n | --no-verify ) shift 1; NO_VERIFY="1" ;;
-l | --log ) shift 1; LOG_FILE="$1" ; shift 1 ;;
esac
# parse Commands
case $1 in
venv ) shift 1; op_venv "$@" ;;
check ) shift 1; op_check "$@" ;;
setup ) shift 1; op_setup "$@" ;;
build ) shift 1; op_build "$@" ;;
juggle ) shift 1; op_juggle "$@" ;;
cabana ) shift 1; op_cabana "$@" ;;
lint ) shift 1; op_lint "$@" ;;
test ) shift 1; op_test "$@" ;;
replay ) shift 1; op_replay "$@" ;;
sim ) shift 1; op_sim "$@" ;;
install ) shift 1; op_install "$@" ;;
post-commit ) shift 1; op_install_post_commit "$@" ;;
* ) op_default "$@" ;;
esac
}
_op $@