python: better imaging management of the raspimjpeg process
This commit is contained in:
parent
d732c8d4ce
commit
cf2f15594d
|
@ -12,10 +12,11 @@ import datetime
|
||||||
import time
|
import time
|
||||||
|
|
||||||
# Libraries manipulate json format, execute bash commands
|
# Libraries manipulate json format, execute bash commands
|
||||||
import json, shutil
|
import json
|
||||||
|
|
||||||
# Library for path and filesystem manipulations
|
# Library for path and filesystem manipulations
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
# Library for starting processes
|
# Library for starting processes
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
@ -166,6 +167,7 @@ class ImagerProcess(multiprocessing.Process):
|
||||||
self.__pump_direction = "FORWARD"
|
self.__pump_direction = "FORWARD"
|
||||||
self.__img_goal = None
|
self.__img_goal = None
|
||||||
self.imager_client = None
|
self.imager_client = None
|
||||||
|
self.__error = 0
|
||||||
|
|
||||||
# Initialise the camera and the process
|
# Initialise the camera and the process
|
||||||
# Also starts the streaming to the temporary file
|
# Also starts the streaming to the temporary file
|
||||||
|
@ -196,7 +198,7 @@ class ImagerProcess(multiprocessing.Process):
|
||||||
self.__white_balance_gain = (
|
self.__white_balance_gain = (
|
||||||
configuration.get("wb_red_gain", 2.00) * 100,
|
configuration.get("wb_red_gain", 2.00) * 100,
|
||||||
configuration.get("wb_blue_gain", 1.40) * 100,
|
configuration.get("wb_blue_gain", 1.40) * 100,
|
||||||
) # Those values were tested on a HQ camera to give a whitish background
|
)
|
||||||
|
|
||||||
self.__base_path = "/home/pi/data/img"
|
self.__base_path = "/home/pi/data/img"
|
||||||
# Let's make sure the base path exists
|
# Let's make sure the base path exists
|
||||||
|
@ -491,7 +493,9 @@ class ImagerProcess(multiprocessing.Process):
|
||||||
self.__imager.change(planktoscope.imager_state_machine.Capture)
|
self.__imager.change(planktoscope.imager_state_machine.Capture)
|
||||||
self.imager_client.client.unsubscribe("status/pump")
|
self.imager_client.client.unsubscribe("status/pump")
|
||||||
else:
|
else:
|
||||||
logger.info(f"The pump is not done yet {payload}")
|
logger.info(
|
||||||
|
f"The pump is not done yet {self.imager_client.msg['payload']}"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error(
|
||||||
"There is an error, we received an unexpected pump message"
|
"There is an error, we received an unexpected pump message"
|
||||||
|
@ -641,39 +645,25 @@ class ImagerProcess(multiprocessing.Process):
|
||||||
# Sleep a duration before to start acquisition
|
# Sleep a duration before to start acquisition
|
||||||
time.sleep(self.__sleep_before)
|
time.sleep(self.__sleep_before)
|
||||||
|
|
||||||
# Capture an image with the proper filename
|
# Capture an image to the temporary file
|
||||||
try:
|
try:
|
||||||
self.__camera.capture(filename_path)
|
self.__camera.capture("", timeout=5)
|
||||||
except TimeoutError as e:
|
except TimeoutError as e:
|
||||||
logger.error("A timeout happened while waiting for a capture to happen")
|
self.__capture_error("timeout during capture")
|
||||||
# Publish the name of the image to via MQTT to Node-RED
|
|
||||||
self.imager_client.client.publish(
|
|
||||||
"status/imager",
|
|
||||||
f'{{"status":"Image {self.__img_done + 1}/{self.__img_goal} WAS NOT CAPTURED! STOPPING THE PROCESS!"}}',
|
|
||||||
)
|
|
||||||
# Reset the counter to 0
|
|
||||||
self.__img_done = 0
|
|
||||||
self.__img_goal = 0
|
|
||||||
self.__imager.change(planktoscope.imager_state_machine.Stop)
|
|
||||||
planktoscope.light.error()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
logger.debug(f"Copying the image from the temp file to {filename_path}")
|
||||||
|
shutil.copy("/dev/shm/mjpeg/image.jpg", filename_path)
|
||||||
|
logger.debug("Syncing the disk")
|
||||||
|
os.sync()
|
||||||
|
|
||||||
# Add the checksum of the captured image to the integrity file
|
# Add the checksum of the captured image to the integrity file
|
||||||
try:
|
try:
|
||||||
planktoscope.integrity.append_to_integrity_file(filename_path)
|
planktoscope.integrity.append_to_integrity_file(filename_path)
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError as e:
|
||||||
logger.error(
|
self.__capture_error(f"{filename_path} was not found")
|
||||||
f"{filename_path} was not found, the camera did not work properly! Trying again"
|
|
||||||
)
|
|
||||||
self.imager_client.client.publish(
|
|
||||||
"status/imager",
|
|
||||||
f'{{"status":"Image {self.__img_done + 1}/{self.__img_goal} was not found, retrying the capture now."}}',
|
|
||||||
)
|
|
||||||
# Let's try again after a tiny delay!
|
|
||||||
time.sleep(1)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Publish the name of the image to via MQTT to Node-RED
|
|
||||||
self.imager_client.client.publish(
|
self.imager_client.client.publish(
|
||||||
"status/imager",
|
"status/imager",
|
||||||
f'{{"status":"Image {self.__img_done + 1}/{self.__img_goal} has been imaged to {filename}"}}',
|
f'{{"status":"Image {self.__img_done + 1}/{self.__img_goal} has been imaged to {filename}"}}',
|
||||||
|
@ -681,6 +671,7 @@ class ImagerProcess(multiprocessing.Process):
|
||||||
|
|
||||||
# Increment the counter
|
# Increment the counter
|
||||||
self.__img_done += 1
|
self.__img_done += 1
|
||||||
|
self.__error = 0
|
||||||
|
|
||||||
# If counter reach the number of frame, break
|
# If counter reach the number of frame, break
|
||||||
if self.__img_done >= self.__img_goal:
|
if self.__img_done >= self.__img_goal:
|
||||||
|
@ -690,7 +681,6 @@ class ImagerProcess(multiprocessing.Process):
|
||||||
|
|
||||||
self.__imager.change(planktoscope.imager_state_machine.Stop)
|
self.__imager.change(planktoscope.imager_state_machine.Stop)
|
||||||
planktoscope.light.ready()
|
planktoscope.light.ready()
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
# We have not reached the final stage, let's keep imaging
|
# We have not reached the final stage, let's keep imaging
|
||||||
self.imager_client.client.subscribe("status/pump")
|
self.imager_client.client.subscribe("status/pump")
|
||||||
|
@ -699,6 +689,27 @@ class ImagerProcess(multiprocessing.Process):
|
||||||
|
|
||||||
self.__imager.change(planktoscope.imager_state_machine.Waiting)
|
self.__imager.change(planktoscope.imager_state_machine.Waiting)
|
||||||
|
|
||||||
|
def __capture_error(self, message=""):
|
||||||
|
logger.error(f"An error occurred during the capture: {message}")
|
||||||
|
planktoscope.light.error()
|
||||||
|
if self.__error:
|
||||||
|
logger.error("This is a repeating problem, stopping the capture now")
|
||||||
|
self.imager_client.client.publish(
|
||||||
|
"status/imager",
|
||||||
|
f'{{"status":"Image {self.__img_done + 1}/{self.__img_goal} WAS NOT CAPTURED! STOPPING THE PROCESS!"}}',
|
||||||
|
)
|
||||||
|
self.__img_done = 0
|
||||||
|
self.__img_goal = 0
|
||||||
|
self.__error = 0
|
||||||
|
self.__imager.change(planktoscope.imager_state_machine.Stop)
|
||||||
|
else:
|
||||||
|
self.__error += 1
|
||||||
|
self.imager_client.client.publish(
|
||||||
|
"status/imager",
|
||||||
|
f'{{"status":"Image {self.__img_done + 1}/{self.__img_goal} was not captured due to this error:{message}! Retrying once!"}}',
|
||||||
|
)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
@logger.catch
|
@logger.catch
|
||||||
def state_machine(self):
|
def state_machine(self):
|
||||||
if self.__imager.state.name == "imaging":
|
if self.__imager.state.name == "imaging":
|
||||||
|
|
|
@ -458,9 +458,10 @@ class raspimjpeg(object):
|
||||||
self.__send_command(f"im")
|
self.__send_command(f"im")
|
||||||
else:
|
else:
|
||||||
self.__send_command(f"im {path}")
|
self.__send_command(f"im {path}")
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
self.__wait_for_output("Capturing image", timeout / 2)
|
self.__wait_for_output("Capturing image", timeout / 2)
|
||||||
self.__wait_for_status("ready", timeout / 2)
|
self.__wait_for_output("Ready", timeout / 2)
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Halt and release the camera. """
|
"""Halt and release the camera. """
|
||||||
|
|
|
@ -354,7 +354,7 @@ class StepperProcess(multiprocessing.Process):
|
||||||
command = self.actuator_client.msg["topic"].split("/", 1)[1]
|
command = self.actuator_client.msg["topic"].split("/", 1)[1]
|
||||||
logger.debug(command)
|
logger.debug(command)
|
||||||
self.actuator_client.read_message()
|
self.actuator_client.read_message()
|
||||||
|
|
||||||
if command == "pump":
|
if command == "pump":
|
||||||
self.__message_pump(last_message)
|
self.__message_pump(last_message)
|
||||||
elif command == "focus":
|
elif command == "focus":
|
||||||
|
|
Binary file not shown.
|
@ -120,9 +120,9 @@ motion_file 0
|
||||||
# image, video and lapse may be configured relative to media_path if first / left out
|
# image, video and lapse may be configured relative to media_path if first / left out
|
||||||
base_path /home/pi/PlanktonScope/scripts/raspimjpeg/
|
base_path /home/pi/PlanktonScope/scripts/raspimjpeg/
|
||||||
preview_path /dev/shm/mjpeg/cam.jpg
|
preview_path /dev/shm/mjpeg/cam.jpg
|
||||||
image_path /home/pi/data/%Y%M%D/im_%i_%h%m%s.jpg
|
image_path /dev/shm/mjpeg/image.jpg
|
||||||
lapse_path /home/pi/media/tl_%i_%t_%Y%M%D_%h%m%s.jpg
|
lapse_path /dev/shm/mjpeg/tl_%i_%t_%Y%M%D_%h%m%s.jpg
|
||||||
video_path /home/pi/media/vi_%v_%Y%M%D_%h%m%s.mp4
|
video_path /dev/shm/mjpeg/vi_%v_%Y%M%D_%h%m%s.mp4
|
||||||
status_file /dev/shm/mjpeg/status_mjpeg.txt
|
status_file /dev/shm/mjpeg/status_mjpeg.txt
|
||||||
control_file /dev/shm/mjpeg/FIFO
|
control_file /dev/shm/mjpeg/FIFO
|
||||||
media_path /home/pi/data/
|
media_path /home/pi/data/
|
||||||
|
@ -165,7 +165,7 @@ watchdog_errors 5
|
||||||
# Set callback_timeout to 0 to disable it
|
# Set callback_timeout to 0 to disable it
|
||||||
callback_timeout 30
|
callback_timeout 30
|
||||||
#optional user_config file to overwrite (persist) changes
|
#optional user_config file to overwrite (persist) changes
|
||||||
user_config /home/pi/PlanktonScope/scripts/raspimjpeg/uconfig
|
user_config
|
||||||
|
|
||||||
#logfile for raspimjpeg, default to merge with scheduler log
|
#logfile for raspimjpeg, default to merge with scheduler log
|
||||||
log_file /home/pi/PlanktonScope/scripts/raspimjpeg/raspimjpeg.log
|
log_file /home/pi/PlanktonScope/scripts/raspimjpeg/raspimjpeg.log
|
||||||
|
|
Loading…
Reference in a new issue