Skip to content

Commit

Permalink
Python virtual environment (paparazzi#3305)
Browse files Browse the repository at this point in the history
* [python] setup venv and update pprzlink.
* [supervision] open terminal in the venv if it exists.
* clean setup.py
* guard venv boostrap
* [install] Use distro instead of lsb_release.

---------

Co-authored-by: Fabien-B <[email protected]>
  • Loading branch information
2 people authored and NoahWe committed Nov 5, 2024
1 parent e2923b4 commit 80beb21
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 18 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
.cache.xml
.directory

# python venv
pprzEnv/

# Eclipse IDE project files
*.cproject
*.project
Expand Down
19 changes: 19 additions & 0 deletions conf/system/term_init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

source ~/.profile

if [ -d "$PAPARAZZI_HOME/pprzEnv" ]; then
source $PAPARAZZI_HOME/pprzEnv/bin/activate
fi

shell=$(echo $SHELL | cut -d / -f 3)

if [ "$shell" = "bash" ]; then
# enter bash specific commands here
echo $shell > /dev/null
elif [ "$shell" = "zsh" ]; then
# enter zsh specific commands here
echo $shell > /dev/null
else
# fallback commands
echo $shell > /dev/null
fi;
56 changes: 55 additions & 1 deletion install.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,60 @@
#!/bin/bash

sudo apt-get install -f -y python3 python3-pyqt5
USE_VENV=true
BASHRC_SOURCE_VENV=false

# exit on error
set -e

for arg in "$@"
do
if [ "$arg" = "-h" ] || [ "$arg" = "--help" ]
then
echo "Usage: ./install.sh [-n|--no-venv] [-h|---help]"
echo " -n, --no-venv Do not use python virtual environment"
echo " -s, --source Add venv source in ~/.bashrc"
echo " -h, --help Print this help"
exit 0
fi

if [ "$arg" = "-n" ] || [ "$arg" = "--no-venv" ]
then
USE_VENV=false
echo "the venv will not be installed!"
fi

if [ "$arg" = "-s" ] || [ "$arg" = "--source" ]
then
BASHRC_SOURCE_VENV=true
fi

done


if [ $VIRTUAL_ENV ]
then
echo "Cannot create venv from itself! Run 'deactivate' first if you want to recreate the venv."
USE_VENV = false
BASHRC_SOURCE_VENV=false
fi


if [ "$USE_VENV" = true ]
then
sudo apt install -y python3 python3-venv
python3 setup.py
source pprzEnv/bin/activate

if [ "$BASHRC_SOURCE_VENV" = true ]
then
echo "venv source will be added to ~/.bashrc"
echo "source $(pwd)/pprzEnv/bin/activate" >> ~/.bashrc
fi

else
sudo apt-get install -f -y python3 python3-pyqt5
fi

python3 ./sw/tools/install.py


11 changes: 11 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
lxml
numpy
scipy
ivy-python
pyserial
PyQt5
PyQtWebEngine
pyqtgraph
unidecode
matplotlib
distro
49 changes: 49 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import venv
import os
import sys
import subprocess
import argparse
import shutil

ENV_NAME = 'pprzEnv'


def run(args):
if args.clean:
if os.path.exists(ENV_NAME):
print("Cleaning previous venv.")
shutil.rmtree(ENV_NAME)
else:
print("No previous venv to clean.")

print("Creating a virtual environment for Paparazzi...")
venv.create(ENV_NAME, with_pip=True, system_site_packages=args.system)

# installing requirements
cmd = [f'./{ENV_NAME}/bin/pip', 'install', '-r' , 'requirements.txt']
result = subprocess.run(cmd, check=False)
if result.returncode:
print("Failed to create venv!")
else:
print("venv successfully created.")

# installing pprzlink
print("Installing pprzlink...")
cmd = [f'./{ENV_NAME}/bin/pip', 'install', '-e' , 'sw/ext/pprzlink/lib/v2.0/python']
result = subprocess.run(cmd, check=False)
if result.returncode:
print("Failed to install pprzlink!")
else:
print("pprzlink successfully installed.")

if not os.path.exists(f'./{ENV_NAME}/bin/calibrate.py'):
os.symlink('../../sw/tools/calibration/calibrate.py', f'./{ENV_NAME}/bin/calibrate.py')


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="This script will setup the python environment for Paparazzi")
parser.add_argument('-s', '--system', action='store_true', help="Use system site packages.")
parser.add_argument('-c', '--clean', action='store_true', help="Delete the previous virtual environment before recreating it.")
args = parser.parse_args()

run(args)
16 changes: 9 additions & 7 deletions sw/supervision/python/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from PyQt5.QtWidgets import *
from typing import NamedTuple
from PyQt5.QtCore import QSettings
import subprocess


class GConfEntry(NamedTuple):
Expand Down Expand Up @@ -66,16 +67,17 @@ def get_build_version() -> str:
version = f.readline().strip()
return version

def get_shell():
p = subprocess.run(['getent', 'passwd', os.getenv('LOGNAME')], capture_output=True)
shell = p.stdout.decode().strip().split(':')[6]
return shell

def open_terminal(wd, command=None):
cmd = ""
if command is not None:
cmd = " -- {}".format(command)
def open_terminal(wd):
terminal_emulator = get_settings().value("terminal_emulator", "", str)
if terminal_emulator == "":
terminal_emulator = "gnome-terminal"
os.system("{}".format(terminal_emulator))

terminal_emulator = "x-terminal-emulator"
shell = get_shell()
subprocess.Popen([terminal_emulator, '-e', shell, '--rcfile', 'conf/system/term_init.sh'], cwd=wd)

def get_settings() -> QSettings:
return QSettings(os.path.join(CONF_DIR, "pprz_center_settings.ini"), QSettings.IniFormat)
Expand Down
19 changes: 9 additions & 10 deletions sw/tools/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

import lsb_release
import distro
import subprocess
import webbrowser

release = lsb_release.get_distro_information()
distro_version = float(distro.version())
docs = 'https://paparazzi-uav.readthedocs.io'


Expand Down Expand Up @@ -47,12 +47,12 @@ def cmd_repo(self):
def cmd_dev(self):
self.execute('sudo -E apt-get -f -y install paparazzi-dev')
# Missing
if float(release['RELEASE']) <= 20.04:
if distro_version <= 20.04:
self.execute('sudo -E apt-get install -y python3-lxml python3-numpy')

def cmd_arm(self):
self.execute('sudo -E apt-get -f -y install paparazzi-dev')
if float(release['RELEASE']) >= 20.04:
if distro_version >= 20.04:
self.execute('sudo -E apt-get install -y python-is-python3 gcc-arm-none-eabi gdb-multiarch')
# python3-serial?
else:
Expand All @@ -72,7 +72,7 @@ def cmd_mcu(self):
self.execute('sudo -E cp conf/system/udev/rules/*.rules /etc/udev/rules.d/ && sudo -E udevadm control --reload-rules')

def cmd_gazebo(self):
if float(release['RELEASE']) > 20.04:
if distro_version > 20.04:
self.execute('sudo -E apt-get -f -y install gazebo libgazebo-dev')
else:
self.execute('sudo -E apt-get -f -y install gazebo9 libgazebo9-dev')
Expand Down Expand Up @@ -106,8 +106,7 @@ def __init__(self):
QWidget.__init__(self)
mainlayout = QVBoxLayout()

os = QLabel()
os.setText("OS: " + release['ID'] + ' ' + release['RELEASE'])
os = QLabel(f"OS: {distro.name()} {distro.version()}")
os.setFont(QFont("Times", 18, QFont.Bold))
mainlayout.addWidget(os)

Expand Down Expand Up @@ -143,7 +142,7 @@ def __init__(self):
btn_layout.addWidget(button4)

button5 = QPushButton('5) Binary ground station')
if float(release['RELEASE']) < 20.04:
if distro_version < 20.04:
button5.setDisabled(True)
else:
button5.clicked.connect(self.cmd_gcs)
Expand All @@ -153,7 +152,7 @@ def __init__(self):
button6.clicked.connect(self.cmd_mcu)
btn_layout.addWidget(button6)

if float(release['RELEASE']) <= 20.04:
if distro_version <= 20.04:
button7 = QPushButton('7) Gazebo9')
else:
button7 = QPushButton('7) Gazebo11')
Expand All @@ -162,7 +161,7 @@ def __init__(self):

button8 = QPushButton('8) Bebop Opencv')
button8.clicked.connect(self.cmd_bebopcv)
if float(release['RELEASE']) > 20.04:
if distro_version > 20.04:
button8.setDisabled(True)
btn_layout.addWidget(button8)

Expand Down

0 comments on commit 80beb21

Please sign in to comment.