Skip to content

Commit 1e54567

Browse files
ddd999ddd999
ddd999
authored andcommitted
Photo Mode Skeleton
Enables Rpanion to capture still photos when a button on the frontend is pressed, or when the MavLink MAV_CMD_DO_DIGICAM_CONTROL message is received. Adds ability to send CameraInformation, CameraSettings, and CameraTrigger messages.
1 parent 96f9bae commit 1e54567

8 files changed

+1869
-814
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
# production
1010
/build
1111

12+
# media storage
13+
/media
14+
1215
# misc
1316
.DS_Store
1417
.env
@@ -28,4 +31,4 @@ settingsTest.json
2831
/flightlogs
2932
.nyc_output
3033

31-
/local_modules/long/node_modules
34+
/local_modules/long/node_modules

package-lock.json

+180-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@
7575
"npm-run-all": "^4.1.5",
7676
"pino-colada": "^2.2.2",
7777
"pino-http": "^10.3.0",
78-
"should": "^13.2.3"
78+
"should": "^13.2.3",
79+
"sinon": "^19.0.2",
80+
"sinon-chai": "^3.7.0"
7981
},
8082
"nyc": {
8183
"all": true,

python/photomode.py

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/usr/bin/env python3
2+
# -*- coding:utf-8 vi:ts=4:noexpandtab
3+
4+
from picamera2 import Picamera2
5+
from picamera2.encoders import H264Encoder
6+
7+
import argparse
8+
import time, signal, os
9+
10+
from gi.repository import GLib
11+
12+
# Reset the signal flag
13+
GOT_SIGNAL = False
14+
# Get the PID (for testing/troubleshooting)
15+
pid = os.getpid()
16+
print("PID is : ", pid)
17+
18+
def receive_signal(signum, stack):
19+
global GOT_SIGNAL
20+
GOT_SIGNAL = True
21+
22+
# Register the signal handler function to fire when signals are received
23+
signal.signal(signal.SIGUSR1, receive_signal)
24+
25+
# Reset the video recording flag
26+
VIDEO_ACTIVE = False
27+
28+
if __name__ == '__main__':
29+
parser = argparse.ArgumentParser(description="Camera control server using libcamera")
30+
parser.add_argument("-d", "--destination", dest="mediaPath",
31+
help="Save captured image to PATH. Default: ../media/",
32+
metavar="PATH",
33+
default="../media/"
34+
)
35+
parser.add_argument("-m", "--mode", choices=['photo', 'video'],
36+
dest="captureMode",
37+
help="Capture mode options: photo [default], video", metavar="MODE",
38+
default='photo'
39+
)
40+
parser.add_argument("-b", "--bitrate", metavar = "N",
41+
type = int, dest="vidBitrate",
42+
help="Video bitrate in bits per second. Default: 10000000",
43+
default=10000000
44+
)
45+
args = parser.parse_args()
46+
47+
captureMode = args.captureMode
48+
print("Mode is: ", captureMode)
49+
50+
mediaPath = args.mediaPath
51+
print("Media storage directory is:", mediaPath)
52+
53+
if captureMode == "video":
54+
vidBitrate = args.vidBitrate
55+
print("Video Bitrate is: ", vidBitrate, " (", vidBitrate / 1000000, " MBps)", sep = "")
56+
57+
58+
# Initialize the camera
59+
if captureMode == "photo":
60+
# Initialize the camera
61+
picam2_still = Picamera2()
62+
# By default, use the full resolution of the sensor
63+
config = picam2_still.create_still_configuration(
64+
main={"size": picam2_still.sensor_resolution},
65+
buffer_count=2
66+
)
67+
picam2_still.configure(config)
68+
# Keep the camera active to make responses faster
69+
picam2_still.start()
70+
print("Waiting 2 seconds for camera to stabilize...")
71+
time.sleep(2)
72+
print("Camera is ready")
73+
74+
elif captureMode == "video":
75+
picam2_vid = Picamera2()
76+
video_config = picam2_vid.create_video_configuration()
77+
picam2_vid.configure(video_config)
78+
79+
encoder = H264Encoder(bitrate = vidBitrate)
80+
81+
def startstop_video():
82+
global VIDEO_ACTIVE
83+
84+
if VIDEO_ACTIVE:
85+
picam2_vid.stop_recording()
86+
VIDEO_ACTIVE = False
87+
print ("Video recording stopped.")
88+
else:
89+
filename = time.strftime("RPN%Y%m%d_%H%M%S.h264")
90+
filepath = os.path.join(mediaPath, filename)
91+
print("Recording to ", filepath)
92+
93+
VIDEO_ACTIVE = True
94+
output_video = picam2_vid.start_recording(encoder, filepath)
95+
96+
try:
97+
# Wait for a signal to arrive
98+
while True:
99+
if (GOT_SIGNAL and (captureMode == "photo")):
100+
GOT_SIGNAL = False
101+
print("Received signal.SIGUSR1. Capturing photo.")
102+
filename = time.strftime("/home/pi/Rpanion-server/media/RPN%Y%m%d_%H%M%S.jpg")
103+
print(filename)
104+
output_orig = picam2_still.capture_file(filename)
105+
elif (GOT_SIGNAL and (captureMode == "video")):
106+
GOT_SIGNAL = False
107+
print("Received signal.SIGUSR1.")
108+
startstop_video()
109+
110+
# Wait for a signal
111+
signal.pause()
112+
#loop.run()
113+
except:
114+
print("Exiting Photo/Video Server")

0 commit comments

Comments
 (0)