Compare commits
93 Commits
b84b05e475
...
station2-c
| Author | SHA1 | Date | |
|---|---|---|---|
| b75e4b270b | |||
| a054e368cb | |||
| db1a261012 | |||
| 7b318831f2 | |||
| 48c532a81c | |||
| c302674958 | |||
| c2df56e15e | |||
| 93fd03e717 | |||
| 3682fc1448 | |||
| f67379f85d | |||
| ac4ff7a657 | |||
| e94f342739 | |||
| e421634432 | |||
| fba81ef345 | |||
| 888ed4db9d | |||
| e89b964d27 | |||
| d74b40b7e2 | |||
| 05e5785fc0 | |||
| 716f01a5be | |||
| 5fad6f294c | |||
| 9a771e8cd4 | |||
| 8a54cedb5b | |||
| 8e3b3abe8a | |||
| b50cfeaac8 | |||
| 8ac68b6ab0 | |||
| 502822a7a1 | |||
| 0d0729cb99 | |||
| 6d7d7cbcfd | |||
| ea5978f4e4 | |||
| 942809c95a | |||
| c2695e1971 | |||
| af4c8f978b | |||
| 046c1f7846 | |||
| 6fbb53b6bd | |||
| f6bb087799 | |||
| 21330c945d | |||
| b5ba5f6f9e | |||
| 32bd0f5b55 | |||
| 13eb27b9c3 | |||
| f34cb81c7a | |||
| 209e15d41f | |||
| de214dfc6b | |||
| 8f7e12ec90 | |||
| 03564ed485 | |||
| 19acde6d43 | |||
| d2f85f6aad | |||
| 6f1e5af90f | |||
| 2ee6bbef90 | |||
| 941b5ac4e8 | |||
| 779127ff73 | |||
| 9e58b2b1af | |||
| 227815ac32 | |||
| 83a33cc202 | |||
| aa575f67a3 | |||
| b902f8a500 | |||
| f38f1ab8ba | |||
| e092a570d1 | |||
| 67daffd667 | |||
| acc5bffb71 | |||
| c0b5d40653 | |||
| db52dbff47 | |||
| 6a74fcb472 | |||
| e8dd3c3fe9 | |||
| 9f0fb82831 | |||
| 049b1a7c5c | |||
| d12c7b64ed | |||
| 8fede6107b | |||
| 75cb115330 | |||
| c2439c8fa1 | |||
| 7cc49a0406 | |||
| f1696dd006 | |||
| 6fd0c249a0 | |||
| 66dfa763d2 | |||
| 3bde28770c | |||
| 4dcb454067 | |||
| 218626d316 | |||
| f9a47e8891 | |||
| c0ec0d141e | |||
| e414f63425 | |||
| 513fe74228 | |||
| 1e98970dc3 | |||
| d13b74ed47 | |||
| 8dcbaded2d | |||
| fe1c4cf389 | |||
| 3ce68231eb | |||
| c33d4c0350 | |||
| 81c442f656 | |||
| f9c7676c92 | |||
| d6e481866a | |||
| 87ec24a074 | |||
| a948335e65 | |||
| 1f0221f5bd | |||
| ba2ef204c9 |
7
.gitignore
vendored
@@ -1,7 +1,14 @@
|
|||||||
# Python
|
# Python
|
||||||
__pycache__
|
__pycache__
|
||||||
|
Pipfile
|
||||||
|
Pipfile.lock
|
||||||
|
|
||||||
# CAD
|
# CAD
|
||||||
*.stl
|
*.stl
|
||||||
*.FCStd1
|
*.FCStd1
|
||||||
|
|
||||||
|
# Artifacts
|
||||||
|
*.png
|
||||||
|
*.jpg
|
||||||
|
*.wav
|
||||||
|
*.pdf
|
||||||
|
|||||||
BIN
CAD/Lewis_CAD/DigiCase/Digi Case Base.FCStd
Normal file
BIN
CAD/Lewis_CAD/DigiCase/Digi Case Lid.FCStd
Normal file
BIN
CAD/Lewis_CAD/Frame.FCStd
Normal file
BIN
CAD/Lewis_CAD/MastCam/9gServo.FCStd
Normal file
BIN
CAD/Lewis_CAD/MastCam/MastCamFace.FCStd
Normal file
BIN
CAD/Lewis_CAD/MastCam/MastCamMount.FCStd
Normal file
BIN
CAD/Lewis_CAD/MastCam/MastCamRear.FCStd
Normal file
BIN
CAD/Lewis_CAD/MastCam/Window Wiper.FCStd
Normal file
BIN
CAD/Lewis_CAD/lewis-crawler.FCStd
Normal file
BIN
CAD/StationA_CAD/StationA_Stack_Base.FCStd
Normal file
7
README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# To install on robot
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone <url>
|
||||||
|
cd lewis-crawler/crawler_software/raspberry_pi
|
||||||
|
make install?
|
||||||
|
```
|
||||||
BIN
companion_software/FreeMono.ttf
Normal file
22
companion_software/README.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Setting up getty override
|
||||||
|
=========================
|
||||||
|
|
||||||
|
```console
|
||||||
|
systemctl edit getty@tty1.service
|
||||||
|
```
|
||||||
|
|
||||||
|
add
|
||||||
|
|
||||||
|
```
|
||||||
|
[Service]
|
||||||
|
ExecStart=
|
||||||
|
ExecStart=-/opt/lewis-crawler/companion_software/dashboard/entrypoint.sh
|
||||||
|
StandardInput=tty
|
||||||
|
StandardOutput=tty
|
||||||
|
```
|
||||||
|
|
||||||
|
then
|
||||||
|
|
||||||
|
```
|
||||||
|
systemctl daemon-reload; systemctl restart getty@tty1.service
|
||||||
|
```
|
||||||
9
companion_software/entrypoint.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd /opt/lewis-crawler/companion_software
|
||||||
|
|
||||||
|
git pull
|
||||||
|
|
||||||
|
pipenv install -r requirements.txt
|
||||||
|
|
||||||
|
pipenv run python -m houston -v
|
||||||
43
companion_software/houston/__main__.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Lewis Crawler
|
||||||
|
# 2021 - 2022
|
||||||
|
# Kitsune Scientific
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import argparse
|
||||||
|
import verboselogs
|
||||||
|
import coloredlogs
|
||||||
|
|
||||||
|
from houston.houston import Houston
|
||||||
|
|
||||||
|
|
||||||
|
# Get debug args
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
'-d', '--debug',
|
||||||
|
help="Print lots of debugging statements",
|
||||||
|
action="store_const", dest="loglevel", const='DEBUG',
|
||||||
|
default='WARNING',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-v', '--verbose',
|
||||||
|
help="Be verbose",
|
||||||
|
action="store_const", dest="loglevel", const='INFO',
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Install verbose logs
|
||||||
|
verboselogs.install()
|
||||||
|
|
||||||
|
# Create a logger object.
|
||||||
|
logger = logging.getLogger('Houston_Log')
|
||||||
|
|
||||||
|
# Install colored logs
|
||||||
|
coloredlogs.install(level=args.loglevel,
|
||||||
|
logger=logger,
|
||||||
|
fmt='%(asctime)s,%(msecs)03d %(hostname)s %(levelname)s %(message)s') # noqa: E501
|
||||||
|
|
||||||
|
logger.info('Lewis Companion Software Started.')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = Houston(logger)
|
||||||
|
app.run()
|
||||||
30
companion_software/houston/houston.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Lewis Crawler
|
||||||
|
# 2021 - 2022
|
||||||
|
# Kitsune Scientific
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
from houston.robotstreamer.streamer import RobotStreamer
|
||||||
|
|
||||||
|
|
||||||
|
class Houston:
|
||||||
|
def __init__(self, logger):
|
||||||
|
# Setup logger
|
||||||
|
self.log = logger
|
||||||
|
|
||||||
|
# Setup robotstreamer
|
||||||
|
self.rs = RobotStreamer(self.log)
|
||||||
|
|
||||||
|
# We're ready to go!
|
||||||
|
self.log.success('Ready to robot!')
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.rs.run()
|
||||||
|
|
||||||
|
# Junk~
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
self.log.debug('Nothing to do.')
|
||||||
|
time.sleep(1)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
break
|
||||||
3
companion_software/houston/robotstreamer/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Lewis Crawler
|
||||||
|
# 2021 - 2022
|
||||||
|
# Kitsune Scientific
|
||||||
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 59 KiB |
@@ -0,0 +1 @@
|
|||||||
|
ffmpeg -f image2 -loop 1 -framerate 25 -video_size 1280x720 -r 25 -i Test-Pattern.jpg -vcodec libx264 -profile:v main -preset:v medium -r 30 -g 60 -keyint_min 60 -sc_threshold 0 -b:v 2500k -maxrate 2500k -bufsize 2500k -sws_flags lanczos+accurate_rnd -acodec aac -b:a 96k -ar 48000 -ac 2 -f flv -maxrate 55k "rtmp://rtmp.robotstreamer.com/live/4619?key=jEquBubjizYDMQNe8nKjLdu88iqFpNe3sVQmGRJ2tzbxd4QJrkSSEZBQhi9UTL3k"
|
||||||
30
companion_software/houston/robotstreamer/streamer.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Lewis Crawler
|
||||||
|
# 2021 - 2022
|
||||||
|
# Kitsune Scientific
|
||||||
|
|
||||||
|
import ffmpeg
|
||||||
|
|
||||||
|
|
||||||
|
class RobotStreamer:
|
||||||
|
def __init__(self, logger):
|
||||||
|
self.log = logger
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.log.debug('Running RobotStreamer')
|
||||||
|
|
||||||
|
stream = ffmpeg.input(
|
||||||
|
'houston/robotstreamer/resources/Test-Pattern.jpg',
|
||||||
|
f='image2',
|
||||||
|
loop='1',
|
||||||
|
framerate=25,
|
||||||
|
video_size='1280x720')
|
||||||
|
|
||||||
|
stream = ffmpeg.output(
|
||||||
|
stream,
|
||||||
|
'http://robotstreamer.com/<secret>/1280/720',
|
||||||
|
f='mpegts',
|
||||||
|
bf=0,
|
||||||
|
muxdelay=0.001,
|
||||||
|
codec='mpeg1video')
|
||||||
|
|
||||||
|
ffmpeg.run(stream)
|
||||||
BIN
companion_software/images/Test-Pattern.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
79
companion_software/images/main.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
|
||||||
|
|
||||||
|
def testScreen(
|
||||||
|
x=1280, y=720,
|
||||||
|
image=None,
|
||||||
|
stripeList=["lightgrey",
|
||||||
|
"yellow",
|
||||||
|
"cyan",
|
||||||
|
"lightgreen",
|
||||||
|
"magenta",
|
||||||
|
"red",
|
||||||
|
"blue"]):
|
||||||
|
|
||||||
|
if image is None:
|
||||||
|
image = Image.new("RGB", (x, y))
|
||||||
|
|
||||||
|
draw = ImageDraw.Draw(image)
|
||||||
|
|
||||||
|
for i, stripe in enumerate(stripeList):
|
||||||
|
draw.rectangle((
|
||||||
|
(x/len(stripeList)) * i, 0,
|
||||||
|
(x/len(stripeList)) * (i + 1), x),
|
||||||
|
fill=stripe)
|
||||||
|
|
||||||
|
draw.rectangle((
|
||||||
|
0, y - (y/3),
|
||||||
|
x, y),
|
||||||
|
fill="black")
|
||||||
|
|
||||||
|
for i, stripe in enumerate(stripeList):
|
||||||
|
if i % 2 != 0:
|
||||||
|
_fill = "black"
|
||||||
|
else:
|
||||||
|
_fill = stripeList[len(stripeList) - i - 1]
|
||||||
|
|
||||||
|
draw.rectangle((
|
||||||
|
(x/len(stripeList)) * i, y - (y/3.1),
|
||||||
|
(x/len(stripeList)) * (i + 1), y - (y/4.9)),
|
||||||
|
fill=_fill)
|
||||||
|
|
||||||
|
draw.rectangle((
|
||||||
|
(x/(len(stripeList)/4)), y - (y/5.3),
|
||||||
|
(0), y),
|
||||||
|
fill="darkblue")
|
||||||
|
|
||||||
|
draw.rectangle((
|
||||||
|
(x/(len(stripeList)/2)), y - (y/5.3),
|
||||||
|
(x/(len(stripeList)/1)), y),
|
||||||
|
fill="white")
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
def drawText(image):
|
||||||
|
# get a font
|
||||||
|
fnt = ImageFont.truetype("FreeMono.ttf", 50)
|
||||||
|
# get a drawing context
|
||||||
|
d = ImageDraw.Draw(image)
|
||||||
|
|
||||||
|
# draw multiline text
|
||||||
|
d.multiline_text((10, 10), str(time.time()), font=fnt, fill=(0, 0, 0))
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
blank_screen = testScreen()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
annotated_image = drawText(blank_screen.copy())
|
||||||
|
|
||||||
|
annotated_image.save('Test-Pattern.png')
|
||||||
|
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# testScreen().save('Test-Pattern.png')
|
||||||
1
companion_software/images/stream.sh
Executable file
@@ -0,0 +1 @@
|
|||||||
|
ffmpeg -re -f image2 -loop 1 -framerate 25 -video_size 1280x720 -r 25 -i Test-Pattern.png -c:v libx264 -b:v 1M -g 50 -bf 0 -muxdelay 0.001 -f flv "rtmp://rtmp.robotstreamer.com/live/4619?key=jEquBubjizYDMQNe8nKjLdu88iqFpNe3sVQmGRJ2tzbxd4QJrkSSEZBQhi9UTL3k"
|
||||||
3
companion_software/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
coloredlogs
|
||||||
|
verboselogs
|
||||||
|
ffmpeg-python
|
||||||
70
crawler_software/arduino/crawler_slave/Makefile
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
### DISCLAIMER
|
||||||
|
### This is an example Makefile and it MUST be configured to suit your needs.
|
||||||
|
### For detailed explanations about all the available options,
|
||||||
|
### please refer to https://github.com/sudar/Arduino-Makefile/blob/master/arduino-mk-vars.md
|
||||||
|
|
||||||
|
### PROJECT_DIR
|
||||||
|
### This is the path to where you have created/cloned your project
|
||||||
|
PROJECT_DIR = $(shell dirname $(shell pwd))
|
||||||
|
|
||||||
|
### ARDMK_DIR
|
||||||
|
### Path to the Arduino-Makefile directory.
|
||||||
|
ARDMK_DIR = $(PROJECT_DIR)/Arduino-Makefile
|
||||||
|
|
||||||
|
### ARDUINO_DIR
|
||||||
|
### Path to the Arduino application and resources directory.
|
||||||
|
ARDUINO_DIR = /usr/share/arduino
|
||||||
|
|
||||||
|
### USER_LIB_PATH
|
||||||
|
### Path to where the your project's libraries are stored.
|
||||||
|
USER_LIB_PATH := $(realpath $(PROJECT_DIR)/lib)
|
||||||
|
|
||||||
|
### BOARD_TAG & BOARD_SUB
|
||||||
|
### For Arduino IDE 1.0.x
|
||||||
|
### Only BOARD_TAG is needed. It must be set to the board you are currently using. (i.e uno, mega2560, etc.)
|
||||||
|
# BOARD_TAG = mega2560
|
||||||
|
### For Arduino IDE 1.6.x
|
||||||
|
### Both BOARD_TAG and BOARD_SUB are needed. They must be set to the board you are currently using. (i.e BOARD_TAG = uno, mega, etc. & BOARD_SUB = atmega2560, etc.)
|
||||||
|
### Note: for the Arduino Uno, only BOARD_TAG is mandatory and BOARD_SUB can be equal to anything
|
||||||
|
BOARD_TAG = mega
|
||||||
|
BOARD_SUB = atmega2560
|
||||||
|
|
||||||
|
### MONITOR_PORT
|
||||||
|
### The port your board is connected to. Using an '*' tries all the ports and finds the right one. Choose one of the two.
|
||||||
|
MONITOR_PORT = /dev/ttyUSB*
|
||||||
|
# MONITOR_PORT = /dev/ttyACM*
|
||||||
|
|
||||||
|
### MONITOR_BAUDRATE
|
||||||
|
### It must be set to Serial baudrate value you are using.
|
||||||
|
MONITOR_BAUDRATE = 115200
|
||||||
|
|
||||||
|
### AVR_TOOLS_DIR
|
||||||
|
### Path to the AVR tools directory such as avr-gcc, avr-g++, etc.
|
||||||
|
AVR_TOOLS_DIR = /usr
|
||||||
|
|
||||||
|
### AVRDUDE
|
||||||
|
### Path to avrdude directory.
|
||||||
|
AVRDUDE = /usr/bin/avrdude
|
||||||
|
|
||||||
|
### CFLAGS_STD
|
||||||
|
CFLAGS_STD = -std=gnu11
|
||||||
|
|
||||||
|
### CXXFLAGS_STD
|
||||||
|
### You can choose wich ever you like
|
||||||
|
# CXXFLAGS_STD = -std=gnu++11
|
||||||
|
CXXFLAGS_STD = -std=gnu++17
|
||||||
|
|
||||||
|
|
||||||
|
### CPPFLAGS
|
||||||
|
### Flags you might want to set for debugging purpose. Comment to stop.
|
||||||
|
CXXFLAGS += -pedantic -Wall -Wextra
|
||||||
|
LDFLAGS += -fdiagnostics-color
|
||||||
|
|
||||||
|
### OBJDIR
|
||||||
|
### Don't touch this!
|
||||||
|
### This is were you put the binaries you just compile using 'make'
|
||||||
|
CURRENT_DIR = $(shell basename $(CURDIR))
|
||||||
|
OBJDIR = $(PROJECT_DIR)/build/$(CURRENT_DIR)/$(BOARD_TAG)
|
||||||
|
|
||||||
|
### path to Arduino.mk, inside the ARDMK_DIR, don't touch.
|
||||||
|
include $(ARDMK_DIR)/Arduino.mk
|
||||||
63
crawler_software/arduino/crawler_slave/crawler_slave.ino
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/* Crawler Slave
|
||||||
|
*
|
||||||
|
* This code runs on the crawler i2c network
|
||||||
|
* and provides a cleaner, less CPU intensive control over PWM devices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Servo.h>
|
||||||
|
|
||||||
|
// This servo is used to wipe and clean the camera lens
|
||||||
|
Servo windowWiperServo;
|
||||||
|
|
||||||
|
// Variables populated over i2c from master
|
||||||
|
int id;
|
||||||
|
int val;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
// For debugging
|
||||||
|
//Serial.begin(115200);
|
||||||
|
|
||||||
|
// Attach the wiper servo to pin 9
|
||||||
|
windowWiperServo.attach(9);
|
||||||
|
|
||||||
|
// This is the address the pi will speak to us at
|
||||||
|
Wire.begin(0x4);
|
||||||
|
|
||||||
|
// Call receiveEvent when data received
|
||||||
|
Wire.onReceive(receiveEvent);
|
||||||
|
|
||||||
|
// Setup LED
|
||||||
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
digitalWrite(LED_BUILTIN, LOW);
|
||||||
|
|
||||||
|
//Serial.println("Started");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just loop to keep the running code alive, and wait for events to happen.
|
||||||
|
void loop() {
|
||||||
|
delay(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method runs when we receive a message
|
||||||
|
void receiveEvent(int n) {
|
||||||
|
Wire.read(); // Remove smbus trash
|
||||||
|
if (true) { // Dont do anything if this is not true
|
||||||
|
id = Wire.read(); // ID of the servo/device to access
|
||||||
|
val = Wire.read(); // Value to assign
|
||||||
|
|
||||||
|
//Serial.println(id);
|
||||||
|
//Serial.println(val);
|
||||||
|
|
||||||
|
switch(id) {
|
||||||
|
case 1:
|
||||||
|
windowWiperServo.write(val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevents a bug where if bytes are left in buffer, arduino crashes.
|
||||||
|
while (Wire.available()) {
|
||||||
|
Wire.read();
|
||||||
|
}
|
||||||
|
}
|
||||||
5
crawler_software/raspberry_pi/config/hardware.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
wiper_servo:
|
||||||
|
pin: 17
|
||||||
|
min_pulse: 0.000544
|
||||||
|
max_pulse: 0.0024
|
||||||
|
|
||||||
11
crawler_software/raspberry_pi/crawler.service
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Crawler service overseer, manages running main crawler software
|
||||||
|
After=multi-user.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
Restart=always
|
||||||
|
ExecStart=/usr/bin/python /srv/crawler/crawler.py
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
2
crawler_software/raspberry_pi/requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
PySSTV
|
||||||
|
picamera
|
||||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
@@ -1,9 +1,15 @@
|
|||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
from PIL import Image, ImageFont, ImageDraw
|
from PIL import Image, ImageFont, ImageDraw
|
||||||
from pysstv import color
|
from pysstv import color
|
||||||
from picamera import PiCamera
|
|
||||||
import logging as log
|
import logging as log
|
||||||
|
|
||||||
|
try:
|
||||||
|
from picamera import PiCamera
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
log.info("Running in simulator mode")
|
||||||
|
|
||||||
|
|
||||||
def take_photo():
|
def take_photo():
|
||||||
# This def is meant to take a photograph from the robot,
|
# This def is meant to take a photograph from the robot,
|
||||||
# it should include all steps and error checking to raise the mast
|
# it should include all steps and error checking to raise the mast
|
||||||
@@ -16,9 +22,12 @@ def take_photo():
|
|||||||
# Software to take the photo should be here
|
# Software to take the photo should be here
|
||||||
#copyfile('photos/camera_latest.jpg', 'working/working.jpg')
|
#copyfile('photos/camera_latest.jpg', 'working/working.jpg')
|
||||||
log.debug('Initalizing camera.')
|
log.debug('Initalizing camera.')
|
||||||
|
try:
|
||||||
camera = PiCamera()
|
camera = PiCamera()
|
||||||
log.info('Saving photo.')
|
log.info('Saving photo.')
|
||||||
camera.capture('working/working.jpg')
|
camera.capture('working/working.jpg')
|
||||||
|
except NameError:
|
||||||
|
log.info("Running in simulator mode, not replacing test pattern")
|
||||||
|
|
||||||
def mark_photo():
|
def mark_photo():
|
||||||
log.info('Opening photo for viewing.')
|
log.info('Opening photo for viewing.')
|
||||||
73
crawler_software/raspberry_pi/tests/discordbot.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
from discord_webhook import DiscordWebhook
|
||||||
|
from picamera import PiCamera
|
||||||
|
from time import sleep
|
||||||
|
from gps import *
|
||||||
|
from smbus import SMBus
|
||||||
|
import time
|
||||||
|
|
||||||
|
addr = 0x4 # bus address
|
||||||
|
bus = SMBus(1) # indicates /dev/ic2-1
|
||||||
|
|
||||||
|
numb = 1
|
||||||
|
|
||||||
|
def writeData(value):
|
||||||
|
byteValue = StringToBytes(value)
|
||||||
|
bus.write_i2c_block_data(addr,0x00,byteValue) #first byte is 0=command byte.. just is.
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
|
def StringToBytes(val):
|
||||||
|
retVal = []
|
||||||
|
for c in val:
|
||||||
|
retVal.append(ord(c))
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
try:
|
||||||
|
for _x in range (0, 2):
|
||||||
|
for i in range(78, 130):
|
||||||
|
writeData("WIPE-" + str(i))
|
||||||
|
time.sleep(0.02)
|
||||||
|
for i in range(130, 78, -1):
|
||||||
|
writeData("WIPE-" + str(i))
|
||||||
|
time.sleep(0.02)
|
||||||
|
except OSError:
|
||||||
|
print("Could not speak to ardujmemo")
|
||||||
|
|
||||||
|
def get_uptime():
|
||||||
|
with open('/proc/uptime', 'r') as f:
|
||||||
|
uptime_seconds = float(f.readline().split()[0])
|
||||||
|
|
||||||
|
return uptime_seconds
|
||||||
|
|
||||||
|
def getPositionData(gps):
|
||||||
|
location = [None]
|
||||||
|
while(location[0] == None):
|
||||||
|
print("Trying again")
|
||||||
|
nx = gpsd.next()
|
||||||
|
# For a list of all supported classes and fields refer to:
|
||||||
|
# https://gpsd.gitlab.io/gpsd/gpsd_json.html
|
||||||
|
if nx['class'] == 'TPV':
|
||||||
|
latitude = getattr(nx,'lat', "Unknown")
|
||||||
|
longitude = getattr(nx,'lon', "Unknown")
|
||||||
|
#print "Your position: lon = " + str(longitude) + ", lat = " + str(latitude)
|
||||||
|
location = [latitude, longitude]
|
||||||
|
return location
|
||||||
|
|
||||||
|
gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE)
|
||||||
|
|
||||||
|
loc = getPositionData(gpsd)
|
||||||
|
|
||||||
|
webhookURL = "https://discord.com/api/webhooks/856609966404534272/TR9tnLq2sIGZoOeADNswmGRNlzBcqM5aKihfU6snVTP9WhSSoVVvi7nT6i-ZfZS7Hcqm"
|
||||||
|
|
||||||
|
print(loc[0])
|
||||||
|
print(loc[1])
|
||||||
|
webhook = DiscordWebhook(url=webhookURL, content="Uptime: " + str( round( ((get_uptime() / 60) / 60 ), 2 )) + " hours. Lat is " + str(loc[0]) + ", long is " + str(loc[1]))
|
||||||
|
|
||||||
|
camera = PiCamera()
|
||||||
|
sleep(3) # let iso settle out
|
||||||
|
camera.capture('still.jpg')
|
||||||
|
|
||||||
|
with open("still.jpg", "rb") as f:
|
||||||
|
webhook.add_file(file=f.read(), filename='still.jpg')
|
||||||
|
response = webhook.execute() # Hit send
|
||||||
|
|
||||||
14
crawler_software/raspberry_pi/tests/otp/Pipfile
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[[source]]
|
||||||
|
url = "https://pypi.org/simple"
|
||||||
|
verify_ssl = true
|
||||||
|
name = "pypi"
|
||||||
|
|
||||||
|
[packages]
|
||||||
|
picamera = "*"
|
||||||
|
PySSTV = "*"
|
||||||
|
pyotp = "*"
|
||||||
|
|
||||||
|
[dev-packages]
|
||||||
|
|
||||||
|
[requires]
|
||||||
|
python_version = "3.9"
|
||||||
88
crawler_software/raspberry_pi/tests/otp/Pipfile.lock
generated
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"_meta": {
|
||||||
|
"hash": {
|
||||||
|
"sha256": "bd19925493e125dc5aa15b339778c61c21e0f1a5574097d1721abf99245fa605"
|
||||||
|
},
|
||||||
|
"pipfile-spec": 6,
|
||||||
|
"requires": {
|
||||||
|
"python_version": "3.9"
|
||||||
|
},
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"name": "pypi",
|
||||||
|
"url": "https://pypi.org/simple",
|
||||||
|
"verify_ssl": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"picamera": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:890815aa01e4d855a6a95dd3ad0953b872a6b954982106407df0c5a31a163e50"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==1.13"
|
||||||
|
},
|
||||||
|
"pillow": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:0b2efa07f69dc395d95bb9ef3299f4ca29bcb2157dc615bae0b42c3c20668ffc",
|
||||||
|
"sha256:114f816e4f73f9ec06997b2fde81a92cbf0777c9e8f462005550eed6bae57e63",
|
||||||
|
"sha256:147bd9e71fb9dcf08357b4d530b5167941e222a6fd21f869c7911bac40b9994d",
|
||||||
|
"sha256:15a2808e269a1cf2131930183dcc0419bc77bb73eb54285dde2706ac9939fa8e",
|
||||||
|
"sha256:196560dba4da7a72c5e7085fccc5938ab4075fd37fe8b5468869724109812edd",
|
||||||
|
"sha256:1c03e24be975e2afe70dfc5da6f187eea0b49a68bb2b69db0f30a61b7031cee4",
|
||||||
|
"sha256:1fd5066cd343b5db88c048d971994e56b296868766e461b82fa4e22498f34d77",
|
||||||
|
"sha256:29c9569049d04aaacd690573a0398dbd8e0bf0255684fee512b413c2142ab723",
|
||||||
|
"sha256:2b6dfa068a8b6137da34a4936f5a816aba0ecc967af2feeb32c4393ddd671cba",
|
||||||
|
"sha256:2cac53839bfc5cece8fdbe7f084d5e3ee61e1303cccc86511d351adcb9e2c792",
|
||||||
|
"sha256:2ee77c14a0299d0541d26f3d8500bb57e081233e3fa915fa35abd02c51fa7fae",
|
||||||
|
"sha256:37730f6e68bdc6a3f02d2079c34c532330d206429f3cee651aab6b66839a9f0e",
|
||||||
|
"sha256:3f08bd8d785204149b5b33e3b5f0ebbfe2190ea58d1a051c578e29e39bfd2367",
|
||||||
|
"sha256:479ab11cbd69612acefa8286481f65c5dece2002ffaa4f9db62682379ca3bb77",
|
||||||
|
"sha256:4bc3c7ef940eeb200ca65bd83005eb3aae8083d47e8fcbf5f0943baa50726856",
|
||||||
|
"sha256:660a87085925c61a0dcc80efb967512ac34dbb256ff7dd2b9b4ee8dbdab58cf4",
|
||||||
|
"sha256:67b3666b544b953a2777cb3f5a922e991be73ab32635666ee72e05876b8a92de",
|
||||||
|
"sha256:70af7d222df0ff81a2da601fab42decb009dc721545ed78549cb96e3a1c5f0c8",
|
||||||
|
"sha256:75e09042a3b39e0ea61ce37e941221313d51a9c26b8e54e12b3ececccb71718a",
|
||||||
|
"sha256:8960a8a9f4598974e4c2aeb1bff9bdd5db03ee65fd1fce8adf3223721aa2a636",
|
||||||
|
"sha256:9364c81b252d8348e9cc0cb63e856b8f7c1b340caba6ee7a7a65c968312f7dab",
|
||||||
|
"sha256:969cc558cca859cadf24f890fc009e1bce7d7d0386ba7c0478641a60199adf79",
|
||||||
|
"sha256:9a211b663cf2314edbdb4cf897beeb5c9ee3810d1d53f0e423f06d6ebbf9cd5d",
|
||||||
|
"sha256:a17ca41f45cf78c2216ebfab03add7cc350c305c38ff34ef4eef66b7d76c5229",
|
||||||
|
"sha256:a2f381932dca2cf775811a008aa3027671ace723b7a38838045b1aee8669fdcf",
|
||||||
|
"sha256:a4eef1ff2d62676deabf076f963eda4da34b51bc0517c70239fafed1d5b51500",
|
||||||
|
"sha256:c088a000dfdd88c184cc7271bfac8c5b82d9efa8637cd2b68183771e3cf56f04",
|
||||||
|
"sha256:c0e0550a404c69aab1e04ae89cca3e2a042b56ab043f7f729d984bf73ed2a093",
|
||||||
|
"sha256:c11003197f908878164f0e6da15fce22373ac3fc320cda8c9d16e6bba105b844",
|
||||||
|
"sha256:c2a5ff58751670292b406b9f06e07ed1446a4b13ffced6b6cab75b857485cbc8",
|
||||||
|
"sha256:c35d09db702f4185ba22bb33ef1751ad49c266534339a5cebeb5159d364f6f82",
|
||||||
|
"sha256:c379425c2707078dfb6bfad2430728831d399dc95a7deeb92015eb4c92345eaf",
|
||||||
|
"sha256:cc866706d56bd3a7dbf8bac8660c6f6462f2f2b8a49add2ba617bc0c54473d83",
|
||||||
|
"sha256:d0da39795049a9afcaadec532e7b669b5ebbb2a9134576ebcc15dd5bdae33cc0",
|
||||||
|
"sha256:f156d6ecfc747ee111c167f8faf5f4953761b5e66e91a4e6767e548d0f80129c",
|
||||||
|
"sha256:f4ebde71785f8bceb39dcd1e7f06bcc5d5c3cf48b9f69ab52636309387b097c8",
|
||||||
|
"sha256:fc214a6b75d2e0ea7745488da7da3c381f41790812988c7a92345978414fad37",
|
||||||
|
"sha256:fd7eef578f5b2200d066db1b50c4aa66410786201669fb76d5238b007918fb24",
|
||||||
|
"sha256:ff04c373477723430dce2e9d024c708a047d44cf17166bf16e604b379bf0ca14"
|
||||||
|
],
|
||||||
|
"markers": "python_version >= '3.6'",
|
||||||
|
"version": "==8.3.1"
|
||||||
|
},
|
||||||
|
"pyotp": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:9d144de0f8a601d6869abe1409f4a3f75f097c37b50a36a3bf165810a6e23f28",
|
||||||
|
"sha256:d28ddfd40e0c1b6a6b9da961c7d47a10261fb58f378cb00f05ce88b26df9c432"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==2.6.0"
|
||||||
|
},
|
||||||
|
"pysstv": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:91f85096591606e774811de8940aef57f30e10cbf81387064f8a686cff0ac3fa"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==0.5.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"develop": {}
|
||||||
|
}
|
||||||
19
crawler_software/raspberry_pi/tests/servo_test.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import RPi.GPIO as GPIO
|
||||||
|
import time
|
||||||
|
|
||||||
|
servoPIN = 17
|
||||||
|
GPIO.setmode(GPIO.BCM)
|
||||||
|
GPIO.setup(servoPIN, GPIO.OUT)
|
||||||
|
|
||||||
|
p = GPIO.PWM(servoPIN, 50) # GPIO 17 for PWM with 50Hz
|
||||||
|
p.start(2.5) # Initialization
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
p.ChangeDutyCycle(10)
|
||||||
|
time.sleep(2)
|
||||||
|
p.ChangeDutyCycle(2.5)
|
||||||
|
time.sleep(2)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
p.stop()
|
||||||
|
GPIO.cleanup()
|
||||||
|
|
||||||
20
crawler_software/raspberry_pi/tests/stack_overflow.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import smbus
|
||||||
|
import time
|
||||||
|
import struct
|
||||||
|
|
||||||
|
# for RPI version 1, use bus = smbus.SMBus(0)
|
||||||
|
bus = smbus.SMBus(1)
|
||||||
|
|
||||||
|
# This is the address we setup in the Arduino Program
|
||||||
|
address = 0x04
|
||||||
|
|
||||||
|
try:
|
||||||
|
for _x in range (0, 2):
|
||||||
|
for i in range(78, 130):
|
||||||
|
bus.write_i2c_block_data(address, 0, [1, i])
|
||||||
|
time.sleep(0.02)
|
||||||
|
for i in range(130, 78, -1):
|
||||||
|
bus.write_i2c_block_data(address, 0, [1, i])
|
||||||
|
time.sleep(0.02)
|
||||||
|
except OSError:
|
||||||
|
print("Could not speak to ardujmemo")
|
||||||
35
crawler_software/raspberry_pi/tests/test_i2c.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Raspberry Pi Master for Arduino Slave
|
||||||
|
# i2c_master_pi.py
|
||||||
|
# Connects to Arduino via I2C
|
||||||
|
|
||||||
|
# DroneBot Workshop 2019
|
||||||
|
# https://dronebotworkshop.com
|
||||||
|
|
||||||
|
from smbus import SMBus
|
||||||
|
import time
|
||||||
|
|
||||||
|
addr = 0x8 # bus address
|
||||||
|
bus = SMBus(1) # indicates /dev/ic2-1
|
||||||
|
|
||||||
|
numb = 1
|
||||||
|
|
||||||
|
print ("Enter num")
|
||||||
|
|
||||||
|
for _x in range (0, 4):
|
||||||
|
for i in range(76, 130):
|
||||||
|
bus.write_byte(addr, i)
|
||||||
|
time.sleep(0.02)
|
||||||
|
for i in range(130, 76, -1):
|
||||||
|
bus.write_byte(addr, i)
|
||||||
|
time.sleep(0.02)
|
||||||
|
|
||||||
|
#while numb == 1:
|
||||||
|
#
|
||||||
|
# ledstate = input(">>>> ")
|
||||||
|
#
|
||||||
|
# if ledstate == "1":
|
||||||
|
# bus.write_byte(addr, 0x1) # switch it on
|
||||||
|
# elif ledstate == "0":
|
||||||
|
# bus.write_byte(addr, 0x0) # switch it on
|
||||||
|
# else:
|
||||||
|
# numb = 0
|
||||||
12
crawler_software/raspberry_pi/tests/test_tx.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library
|
||||||
|
from time import sleep # Import the sleep function from the time module
|
||||||
|
|
||||||
|
GPIO.setwarnings(False) # Ignore warning for now
|
||||||
|
GPIO.setmode(GPIO.BOARD) # Use physical pin numbering
|
||||||
|
GPIO.setup(12, GPIO.OUT, initial=GPIO.LOW) # Set pin 8 to be an output pin and set initial value to low (off)
|
||||||
|
|
||||||
|
while True: # Run forever
|
||||||
|
GPIO.output(12, GPIO.HIGH) # Turn on
|
||||||
|
sleep(1) # Sleep for 1 second
|
||||||
|
GPIO.output(12, GPIO.LOW) # Turn off
|
||||||
|
sleep(1) # Sleep for 1 second
|
||||||
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 86 KiB |
@@ -1,2 +0,0 @@
|
|||||||
PySSTV
|
|
||||||
picamera
|
|
||||||