From 5a1bca14f2a82d8b5954e6661be17e1cf3b46438 Mon Sep 17 00:00:00 2001 From: Merlin Ran Date: Sat, 12 Mar 2022 17:59:11 -0500 Subject: [PATCH] try pushing image to ghcr.io --- .github/workflows/test.yaml | 15 +++++++++--- Dockerfile | 3 ++- Makefile | 12 ++++++---- vehicle/hal/GPIO.py | 39 +++++++++++++++++++++++++++++++ vehicle/hal/__init__.py | 1 + vehicle/motors.py | 28 ++++------------------ vehicle/nvidia_power_process.py | 9 +------ vehicle/remote_control_process.py | 26 ++++++++------------- vehicle/requirements.txt | 5 ++++ 9 files changed, 83 insertions(+), 55 deletions(-) create mode 100644 vehicle/hal/GPIO.py create mode 100644 vehicle/hal/__init__.py diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 3b9fca9..6be7b43 100755 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,16 +1,25 @@ name: test -on: [pull_request, push, workflow_dispatch] +on: [pull_request, workflow_dispatch] concurrency: group: test-${{github.ref}} cancel-in-progress: true jobs: + # image: + # runs-on: ubuntu-latest + # steps: + # - name: Checkout source + # uses: actions/checkout@v2 + # + # - name: push image + # run: GITHUB_TOKEN=${{secrets.GITHUB_TOKEN}} make push-image + # test: runs-on: ubuntu-latest # To create and push new image: make push-image - container: docker://merlinran/acorn_docker:latest + container: ghcr.io/twisted-fields/acorn_docker:latest strategy: fail-fast: true @@ -19,7 +28,7 @@ jobs: uses: actions/checkout@v2 - name: Run tests - run: coverage run -m pytest + run: make test - name: Upload Coverage to Codecov uses: codecov/codecov-action@v1 diff --git a/Dockerfile b/Dockerfile index 8941d35..5548b74 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,6 +44,7 @@ RUN apt update && apt install -y libffi-dev \ libxslt1-dev \ gfortran-arm-linux-gnueabi \ libjpeg8-dev \ + libusb-1.0-0-dev \ python3-pip \ python3-scipy \ python3-numpy-dev \ @@ -54,7 +55,7 @@ RUN apt update && apt install -y libffi-dev \ bash \ iputils-ping RUN python3 -m pip install --upgrade pip -RUN python3 -m pip install wheel certifi==2020.06.20 pytest coverage[toml] +RUN python3 -m pip install wheel certifi==2020.06.20 pytest~=7.0.1 coverage[toml]~=6.3.2 COPY server/requirements.txt /install/server/ RUN python3 -m pip install -r /install/server/requirements.txt COPY vehicle/requirements.txt /install/vehicle/ diff --git a/Makefile b/Makefile index a2a06ac..82ce555 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ LOCAL_IMAGE = acorn_docker:1.0 -REMOTE_IMAGE = merlinran/acorn_docker +REMOTE_IMAGE = ghcr.io/twisted-fields/acorn_docker:latest ACORN_NAMES ?= simulation-1 .PHONY: list @@ -40,8 +40,12 @@ docker-test: docker-image @docker-compose -f docker-compose-test.yml up --remove-orphans -d && \ docker exec -it acorn_vehicle make test -.PHONY: push-image # Build and push image to Docker Hub to be used by CI. -push-image: docker-image +.PHONY: push-image # Build and push image to GitHub Container Registry to be used by CI. +push-image: + echo $(GITHUB_TOKEN) | docker login ghcr.io -u twisted-fields --password-stdin && make do-push-image + +.PHONY: do-push-image +do-push-image: docker-image ifeq ($(shell uname -m),arm64) docker buildx build -t $(REMOTE_IMAGE) --platform linux/amd64,linux/arm64 --push . else @@ -50,7 +54,7 @@ endif .PHONY: test # Run tests on Linux (if the Python dependencies are installed) or inside Docker. Otherwise, you probably want to try `make docker-test` instead. test: - coverage run -m pytest --log-cli-level DEBUG && coverage report --skip-covered --skip-empty + python3 -m coverage run -m pytest --log-cli-level DEBUG && python3 -m coverage report --skip-covered --skip-empty .PHONY: docker-vehicle docker-vehicle: docker-image diff --git a/vehicle/hal/GPIO.py b/vehicle/hal/GPIO.py new file mode 100644 index 0000000..a4e4b63 --- /dev/null +++ b/vehicle/hal/GPIO.py @@ -0,0 +1,39 @@ +""" +********************************************************************* + This file is part of: + The Acorn Project + https://wwww.twistedfields.com/research +********************************************************************* +Copyright (c) 2019-2021 Taylor Alexander, Twisted Fields LLC +Copyright (c) 2021 The Acorn Project contributors (cf. AUTHORS.md). + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +********************************************************************* +""" + +try: + import RPi.GPIO as GPIO +except RuntimeError as e: + if str(e) != 'This module can only be run on a Raspberry Pi!': + raise + + class simulated_GPIO(): + def __init__(self): + self.estop_state = True + + def setmode(self, *args): + pass + + def output(self, *args): + pass + GPIO = simulated_GPIO() diff --git a/vehicle/hal/__init__.py b/vehicle/hal/__init__.py new file mode 100644 index 0000000..3903de8 --- /dev/null +++ b/vehicle/hal/__init__.py @@ -0,0 +1 @@ +from .gpio import GPIO diff --git a/vehicle/motors.py b/vehicle/motors.py index 1dfe51f..5e106c1 100644 --- a/vehicle/motors.py +++ b/vehicle/motors.py @@ -34,18 +34,13 @@ import corner_actuator from corner_actuator import OdriveConnection import model - - -# This file gets imported by server but we should only import GPIO on raspi. -if os.uname().machine in ['armv7l','aarch64']: - import RPi.GPIO as GPIO - +from hal import GPIO BOARD_VERSION = 2 -if BOARD_VERSION==1: +if BOARD_VERSION == 1: VOLT_OUT_PIN = 5 -elif BOARD_VERSION==2: +elif BOARD_VERSION == 2: VOLT_OUT_PIN = 23 @@ -59,14 +54,6 @@ _ACCELERATION_COUNTS_SEC = 0.5 -class simulated_GPIO(): - def __init__(self): - self.estop_state = True - - def output(self, *args): - pass - - class AcornMotorInterface(): def __init__(self, manual_control=False, simulated_hardware=False): @@ -88,12 +75,8 @@ def __init__(self, manual_control=False, simulated_hardware=False): self.steering_adjusted = False self.manual_control = manual_control self.simulated_hardware = simulated_hardware - - if self.simulated_hardware: - self.GPIO = simulated_GPIO() - else: - self.GPIO = GPIO - self.setup_GPIO(self.GPIO) + self.GPIO = GPIO + self.setup_GPIO(self.GPIO) def create_socket(self, port=5590): context = zmq.Context() @@ -288,7 +271,6 @@ def run_main(self): abs(vehicle_corner.ibus_0) + abs(vehicle_corner.ibus_1)) temperatures.append(vehicle_corner.temperature_c) - if self.check_odrive_errors(): if not motor_error: # Intentionally break the e-stop loop to stop all motors. diff --git a/vehicle/nvidia_power_process.py b/vehicle/nvidia_power_process.py index 8a1e269..bc43efd 100644 --- a/vehicle/nvidia_power_process.py +++ b/vehicle/nvidia_power_process.py @@ -24,14 +24,7 @@ import time import sys import os - -# This file gets imported by server but we should only import GPIO on raspi. -if os.uname().machine in ['armv7l','aarch64']: - import RPi.GPIO as GPIO - import board - import busio - import digitalio - from adafruit_mcp230xx.mcp23017 import MCP23017 +from hal import GPIO BOARD_VERSION = 2 diff --git a/vehicle/remote_control_process.py b/vehicle/remote_control_process.py index 1ef950c..ad753e0 100644 --- a/vehicle/remote_control_process.py +++ b/vehicle/remote_control_process.py @@ -44,13 +44,6 @@ BOARD_VERSION = 2 -# This file gets imported by server but we should only import GPIO on raspi. -if os.uname().machine in ['armv7l','aarch64']: - import board - import busio - from adafruit_mcp230xx.mcp23017 import MCP23017 - from adafruit_mcp230xx.mcp23016 import MCP23016 - COUNTS_PER_REVOLUTION = corner_actuator.COUNTS_PER_REVOLUTION ACCELERATION_COUNTS_SEC = 0.5 @@ -62,10 +55,10 @@ _DEFAULT_TRAVEL_SPEED = 0.2 _DEFAULT_PATH_END_DISTANCE_METERS = 1 -_DEFAULT_ANGULAR_P=0.9 -_DEFAULT_LATERAL_P=-0.25 -_DEFAULT_ANGULAR_D=0.3 -_DEFAULT_LATERAL_D=-0.05 +_DEFAULT_ANGULAR_P = 0.9 +_DEFAULT_LATERAL_P = -0.25 +_DEFAULT_ANGULAR_D = 0.3 +_DEFAULT_LATERAL_D = -0.05 _DEFAULT_MAXIMUM_VELOCITY = 0.4 _MAXIMUM_ALLOWED_DISTANCE_METERS = 3.5 @@ -225,7 +218,6 @@ def __init__(self, angular_d=_DEFAULT_ANGULAR_D, lateral_d=_DEFAULT_LATERAL_D) - self.nav_path = PathSection(points=[], control_values=self.default_path_control_vals, navigation_parameters=self.default_navigation_parameters, @@ -278,13 +270,17 @@ def __init__(self): self.alarm2 = FakeAlarm() self.alarm3 = FakeAlarm() else: + import busio + import board + from adafruit_mcp230xx.mcp23017 import MCP23017 + from adafruit_mcp230xx.mcp23016 import MCP23016 i2c = busio.I2C(board.SCL, board.SDA) - if BOARD_VERSION==1: + if BOARD_VERSION == 1: mcp = MCP23017(i2c) # , address=0x20) # MCP23017 self.alarm1 = mcp.get_pin(0) self.alarm2 = mcp.get_pin(1) self.alarm3 = mcp.get_pin(2) - elif BOARD_VERSION==2: + elif BOARD_VERSION == 2: mcp = MCP23016(i2c, address=0x20) self.alarm1 = mcp.get_pin(8) self.alarm2 = mcp.get_pin(9) @@ -493,7 +489,6 @@ def run_once(self): autonomy_vel_cmd, autonomy_steer_cmd, autonomy_strafe_cmd ) = self.calc_commands_for_autonomy(calculated_rotation, calculated_strafe, drive_reverse) - time7 = time.time() - debug_time error_messages, fatal_error, zero_output = self.safety_checks(absolute_path_distance, gps_path_angle_error) @@ -617,7 +612,6 @@ def run_once(self): # rather than replacing the object. self.steering_debug[:] = steering_to_numpy(calc)[:] - # If the robot is simulated, estimate movement odometry. if self.simulated_hardware: if abs(steer_cmd) > 0.001 or abs(self.vel_cmd) > 0.001 or abs(strafe_cmd) > 0.001: diff --git a/vehicle/requirements.txt b/vehicle/requirements.txt index 32f27ea..2403329 100644 --- a/vehicle/requirements.txt +++ b/vehicle/requirements.txt @@ -6,3 +6,8 @@ click coloredlogs csaps rpi_ws281x +geopy +psutil +odrive +evdev +fibre