Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b195fec
added servo class
ethanshry Apr 11, 2021
f413e48
fix PiCar class to use Servo class, and added camera and ultrasonic c…
ethanshry Apr 11, 2021
f56ecff
typos and version update
ethanshry Apr 11, 2021
e1042ad
bugfix
ethanshry Apr 16, 2021
1729f42
servo uses low mid high not left mid right
ethanshry Apr 16, 2021
a0bdad5
set self.servo not servo
ethanshry Apr 16, 2021
8cec1af
update version
ethanshry Apr 16, 2021
d7725cc
fix config format reading
ethanshry Apr 16, 2021
60bca06
maybe no thread warnings
ethanshry Apr 16, 2021
84b3838
shutdown not stop
ethanshry Apr 16, 2021
0ad8077
clean up tasks nicely
ethanshry Apr 16, 2021
e056b59
parallel typing
ethanshry Apr 16, 2021
94bc510
import event
ethanshry Apr 16, 2021
7fc3603
import event
ethanshry Apr 16, 2021
5220f06
version
ethanshry Apr 16, 2021
038f5c2
trig pin
ethanshry Apr 16, 2021
d4f22d8
fix the processes
ethanshry Apr 16, 2021
308af5e
fix the version
ethanshry Apr 16, 2021
d1a0ab5
multiprocess
ethanshry Apr 16, 2021
bc086ce
license
ethanshry Apr 23, 2021
fe98b47
trying to fix imports
ethanshry Apr 30, 2021
d19c894
do the thready business
ethanshry Apr 30, 2021
9af67a1
add self name scope
ethanshry Apr 30, 2021
9c25204
add self name scope
ethanshry Apr 30, 2021
85ae393
join queues
ethanshry Apr 30, 2021
7ea6b44
join queues
ethanshry Apr 30, 2021
4481365
join queues
ethanshry Apr 30, 2021
9fa9e06
join queues
ethanshry Apr 30, 2021
aed8e46
passthrough lambda
ethanshry Apr 30, 2021
e976663
readme update
ethanshry May 1, 2021
d236d23
refactored to use redis to communicate between processes
ethanshry May 11, 2021
d9676f4
minor code cleanup
ethanshry May 11, 2021
8e3fe66
Merge branch 'master' into ethan/refactor
ethanshry May 11, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

203 changes: 144 additions & 59 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.4.13
0.6.0-alpha
63 changes: 0 additions & 63 deletions picar/CarProcesses.py

This file was deleted.

149 changes: 116 additions & 33 deletions picar/ParallelTask.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,128 @@
from multiprocessing import Process, Manager, Queue
from multiprocessing import Process, Event
import redis

import RPi.GPIO as GPIO
from time import time, sleep
from picamera.array import PiRGBArray
from picamera import PiCamera

class ParallelTask:
from typing import Tuple

_process = None

_queue = None
class UltrasonicProcess(Process):
"""
The process function to read ultrasonic values
queue: multiprocessing.Manager.Queue = queue to store ultrasonic data in
ECHO_PIN: GPIO.BOARD Pin = attached to ultrasonic echo pin
TRIG_PIN: GPIO.BOARD Pin = attached to ultrasonic trigger pin
target_sample_rate: Int = target sample rate
"""

@staticmethod
def get_from_queue(queue):
"""
The method to flush the queues and return the most recent result
Args:
queue: multiprocessing.Manager.Queue
return: (data value, time read, datapoints in queue when called)
"""
v = (None, None)
tossed_readings = 0
while not queue.empty():
tossed_readings += 1
# don't block if the queue is busy
v = queue.get_nowait()
# expand the queue 2-tuple (reading, time read) into a flat 3-tuple
return (*v, tossed_readings)
_db = redis.Redis(host="localhost", port=6379, db=0)

def __init__(self, funct, funct_args):
TRIG_TIME = 0.00001

manager = Manager()
sample_rate: int = 10
trig_pin: int = None
echo_pin: int = None

self._queue = manager.Queue()
def __init__(
self,
echo_pin: int,
trig_pin: int,
target_sample_rate: int = 10,
):
Process.__init__(self)

self._process = Process(target=funct, args=(self._queue, *funct_args))
self.sample_rate = target_sample_rate
self.trig_pin = trig_pin
self.echo_pin = echo_pin

self._process.start()
self.kill = Event()

def get_result(self):
"""
Method to return process result
data takes the format (reading, time read, values in queue when read)
"""
# note that get_from_queue empties the queue
data = ParallelTask.get_from_queue(self._queue)
def run(self):

return data
start_time, end_time = (0, 0)

nextTime = time()

while not self.kill.is_set():
if time() > nextTime:
# trigger a reading
GPIO.output(self.trig_pin, True)
sleep(self.TRIG_TIME)
GPIO.output(self.trig_pin, False)

# find the start and end of the ultrasonic pulse
while GPIO.input(self.echo_pin) == 0:
start_time = time()
while GPIO.input(self.echo_pin) == 1:
end_time = time()

# Speed of sound 34300 cm/sec
dist = (end_time - start_time) * 34300 / 2
dist_time = time()
self._db.set("dist_ps_result", dist, time())
self._db.set("dist_update_time", dist_time)

nextTime += 1 / self.sample_rate

def stop(self):
self.kill.set()


class CameraProcess(Process):
"""
The process function to read ultrasonic values
queue: multiprocessing.Manager.Queue = queue to store ultrasonic data in
ECHO_PIN: GPIO.BOARD Pin = attached to ultrasonic echo pin
TRIG_PIN: GPIO.BOARD Pin = attached to ultrasonic trigger pin
target_sample_rate: Int = target sample rate
"""

_db = redis.Redis(host="localhost", port=6379, db=0)

resolution: Tuple[int, int] = None
framerate: int = None
task = None

def __init__(
self,
cam_task=None,
resolution: Tuple[int, int] = (1280, 720),
framerate: int = 30,
):
Process.__init__(self)

self.resolution = resolution
self.framerate = framerate

self.task = cam_task

self.kill = Event()

def run(self):

camera = PiCamera()
camera.resolution = self.resolution
camera.framerate = self.framerate
rawCapture = PiRGBArray(camera, size=self.resolution)
for frame in camera.capture_continuous(
rawCapture, format="bgr", use_video_port=True
):

# TODO test this to make sure it sends fine
res = frame.array
if self.task is not None:
res = self.task(frame.array)
else:
res = bytes(res)
cam_time = time()
self._db.set("cam_ps_result", res)
self._db.set("cam_update_time", cam_time)
rawCapture.truncate(0)
if self.kill.is_set():
break

def stop(self):
self.kill.set()
Loading